vlaci / openconnect-sso

Wrapper script for OpenConnect supporting Azure AD (SAMLv2) authentication to Cisco SSL-VPNs
GNU General Public License v3.0
280 stars 119 forks source link

Auth finish request not working if CSD is needed #35

Open impynutz opened 3 years ago

impynutz commented 3 years ago

In my company the newest disimprovement for our VPN is to force us to install AV software. Now I need to get openconnect-sso somehow to work with a Cisco Secure Desktop (CSD) wrapper script. I don't know the protocol so not shure what to send when to make the request work. Here is what I get after already going through login and 2FA:

[debug    ] Sending auth finish request    [openconnect_sso.authenticator] content=b'<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n<config-auth client="vpn" type="auth-reply" aggregate-auth-version="2">\n  <version who="vpn">4.7.00136</version>\n  <device-id>linux-64</device-id>\n  <session-token/>\n  <session-id/>\n  <opaque is-for="sg">\n    <tunnel-group>Company</tunnel-group>\n    <auth-method>single-sign-on-v2</auth-method>\n    <config-hash>4589745648123</config-hash>\n  </opaque>\n  <auth>\n    <sso-token>8Z26547815NS92C998874AC</sso-token>\n  </auth>\n</config-auth>\n'
https://vpn.company.com:443 "POST / HTTP/1.1" 200 None
[debug    ] Auth finish response received  [openconnect_sso.authenticator] content=b'<?xml version="1.0" encoding="UTF-8"?>\n<config-auth client="vpn" type="complete" aggregate-auth-version="2">\n<error id="13" param1="" param2="">Unable to complete connection: Cisco Secure Desktop not installed on the client</error>\n</config-auth>\n'
Traceback (most recent call last):
  File "/usr/bin/openconnect-sso", line 33, in <module>
    sys.exit(load_entry_point('openconnect-sso==0.6.0', 'console_scripts', 'openconnect-sso')())
  File "/usr/lib/python3.8/site-packages/openconnect_sso/cli.py", line 169, in main
    return app.run(args)
  File "/usr/lib/python3.8/site-packages/openconnect_sso/app.py", line 34, in run
    auth_response, selected_profile = asyncio.get_event_loop().run_until_complete(
  File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "/usr/lib/python3.8/site-packages/openconnect_sso/app.py", line 137, in _run
    auth_response = await authenticate_to(
  File "/usr/lib/python3.8/site-packages/openconnect_sso/authenticator.py", line 44, in authenticate
    response = self._complete_authentication(auth_request_response, sso_token)
  File "/usr/lib/python3.8/site-packages/openconnect_sso/authenticator.py", line 81, in _complete_authentication
    return parse_response(response)
  File "/usr/lib/python3.8/site-packages/openconnect_sso/authenticator.py", line 142, in parse_response
    return parse_auth_complete_response(xml)
  File "/usr/lib/python3.8/site-packages/openconnect_sso/authenticator.py", line 184, in parse_auth_complete_response
    assert xml.auth.get("id") == "success"
  File "src/lxml/objectify.pyx", line 231, in lxml.objectify.ObjectifiedElement.__getattr__
  File "src/lxml/objectify.pyx", line 450, in lxml.objectify._lookupChildOrRaise
AttributeError: no such child: auth

I tried to somehow pass the sso-token to openconnect, but could not get it to work. I would appreciate if someone who knows this protocol could give me a hint on how to do the final auth step.

vlaci commented 3 years ago

By default csd is not executed by openconnect. You can enable execution of the csd script by e.g passing -- --csd-user <username> option. (arguments passed after -- are passed directly to openconnect.

Unfortunately I have no access to a vpn forcing csd, so cannot investigate this myself.

impynutz commented 3 years ago

Hi @vlaci, yes I already tried this without success :(. Do you have any information or documentation of the cisco protocol? Otherwise I would need to get some MitM setup running where I can sniff the unencrypted traffic. Or maybe I could check out the openconnect source.. Any suggestion?

vlaci commented 3 years ago

I was slow to conenct the dots if the server denies authentication because of the missing csd info, anything we may pass to openconnect after authetnication completes won't help. I just always assumed that csd happens after the authentication.

I personally used mitmproxy dumps to develop this application. Openconnect's source provide some guidance on what to do. Unfortunately it seems that the whole CSD execution stuff would need to happen during authentication:

  1. First, need to parse the CSD related info https://gitlab.com/openconnect/openconnect/-/blob/master/auth.c#L374
  2. CSD needs to be fetched and executed: https://gitlab.com/openconnect/openconnect/-/blob/master/auth.c#L1412, https://gitlab.com/openconnect/openconnect/-/blob/master/auth.c#L1047
  3. The CSD ticket needs to be submitted after authentication https://gitlab.com/openconnect/openconnect/-/blob/master/auth.c#L713
impynutz commented 3 years ago

Thanks, I'll try to get something working. I already have captured some traffic while establishing the connection. My first goal will be to use a csd wrapper script which fakes the result of this process see: https://github.com/Gilks/hostscan-bypass . I'll never install AV snakeoil on my system :)

tysegall commented 3 years ago

I'm also trying to leverage openconnect-sso to call CSD as well, but getting similar errors. Is there anything I can do to help test?

vlaci commented 3 years ago

Sorry for not responding earlier, I haven't got much time lately but hopefully I can start look into it in a few weeks. If me or someone else could submit a PR, then it would be a great help if anyone could actually test it.

@impynutz have you started working on anything?

impynutz commented 3 years ago

Actually I got it to work, but no time to do a proper patch. Basically you can just send the CSD result (extracted with mentioned hostscan-bypass) and add the host-scan-token attribute. But its just hacky and there would need to be more changes to actually run the CSD script, if someone wants this anyway :)

impynutz commented 3 years ago

@vlaci I pushed some code for testing CSD. Like I said we will need some more code to handle CSD wrapper and or for now just add a config option to pass the result of CSD.

@tysegall if you want to test this I added the CSD result which works for me, not sure if it will for you. Your company may have other requirements and if this does not work you will probably need to get your own CSD results or modify some parts of it like changing the AV software.

https://github.com/impynutz/openconnect-sso/commit/3ecfb760219e9df849fcfb6fa75ac89429a689bd

tysegall commented 3 years ago

@impynutz More than happy to test whatever you've hacked together. I haven't checked this in a bit - as you can probably tell - but it's back on my radar now.

@vlaci Happy to be a tester for this.

von-nihil commented 3 years ago

@impynutz Thanks very much for investigating and making a proposal for this.

@vlaci Is there any update on including this as general functionality? My organization is using the CSD functionality so for me it would be very useful (and I suspect many others eventually, as more start using openconnect-sso).

Cheers!

upsatish commented 2 years ago

Hi @impynutz I tested your patch https://github.com/impynutz/openconnect-sso/commit/3ecfb760219e9df849fcfb6fa75ac89429a689bd and it seemed to work. I had to change line 77 to request = open("/usr/libexec/openconnect/csd-wrapper.sh").read(); I'm now getting an error "Your environment does not meet the access criteria defined by your administrator." which I don't think has to do with this patch, but my environment. I am running Ubuntu 20.04 LTS.

impynutz commented 2 years ago

In the file hostscan-data is the result of the CSD scan for my company network. If this does not work for your company network you will need to find out what values are needed in there. Like mentioned there is a small programm which I used to get the values (I used a windows VM for that, where I installed all required programs like antivirus): https://github.com/Gilks/hostscan-bypass Maybe we can collect some values to make this more generic? Like adding all antivirus programs CSD is able to detect :)

vlaci commented 2 years ago

Unfortunately I no longer have access to an anyconnect VPN endpoint so I won't be able to help much implementing this feature :(

upsatish commented 2 years ago

Nice! It works with the hostscan-data file!

LP0101 commented 2 years ago

@impynutz Your patch with my hostscan file just solved the same issue for me, thank you!

Since @vlaci no longer has access to an anyconnect endpoint, can we fork the repo or transfer ownership? This project is pretty much the only way I can continue working from my Linux box :sweat_smile:

dwmw2 commented 2 years ago

The SAML support is merged in OpenConnect v9.01 and the latest version of the GNOME NetworkManager authentication dialog has support for the webview part.

We'd be very interested in hearing if it doesn't work for you. Packages for Fedora are in the COPR repository at https://copr.fedorainfracloud.org/coprs/dwmw2/openconnect/

impynutz commented 2 years ago

Hi, if I try it says "authentication required" in the gnome network systray. In nm-applet it says "No SSO handler". What kind webview is it trying to open here? Currently I have only archlinux on my machines, not sure if the change is already included in gnome there

GNOME NetworkManager authentication dialog

With this you mean nm-applet or is it some separate package?

I have installed

extra/network-manager-applet 1.26.0-1 [installed] extra/openconnect 1:9.01-1 [installed]

Thanks for your work

dwmw2 commented 2 years ago

You need NetworkManager-openconnect from git; it isn't released yet.

impynutz commented 2 years ago

With the git version it does not show any error, it just disables the vpn again after showing the connection animation, not sure where to get some useful log output. journalctl output is not helpful.

dwmw2 commented 2 years ago

journalctl output is not helpful.

Yeah, we should fix that. In the short term since you're building it anyway (thanks) you can try something like this:

diff --git a/auth-dialog/main.c b/auth-dialog/main.c
index 6a3b164..9826f6d 100644
--- a/auth-dialog/main.c
+++ b/auth-dialog/main.c
@@ -1444,6 +1444,8 @@ static void write_progress(void *cbdata, int level, const char *fmt, ...)
        msg = g_strdup_vprintf(fmt, args);
        va_end(args);

+       fprintf(stderr, "%s", msg);
+
        if (level <= PRG_ERR) {
                g_idle_add((GSourceFunc)write_notice_real, g_strdup(msg));
        }

Probably easiest just to run it from the command line for testing.

 $ cat auth-test-input
DATA_KEY=gateway
DATA_VAL=vpn.example.com
DATA_KEY=protocol
DATA_VAL=anyconnect
DATA_KEY=enable_csd_trojan
DATA_VAL=yes
DATA_KEY=csd_wrapper
DATA_VAL=/usr/libexec/openconnect/csd-post.sh
SECRET_KEY=autoconnect
SECRET_VAL=yes
DONE
 $ ./nm-openconnect-auth-dialog -u xxx -n "Some VPN" -s org.freedesktop.NetworkManager.openconnect -i < auth-test-input
dwmw2 commented 2 years ago

Probably best to take further discussion on that to https://gitlab.gnome.org/GNOME/NetworkManager-openconnect/-/issues as it isn't really about openconnect-sso any more. Thanks!

impynutz commented 2 years ago

continued here https://gitlab.gnome.org/GNOME/NetworkManager-openconnect/-/issues/72

Beej126 commented 1 year ago

@vlaci I pushed some code for testing CSD. Like I said we will need some more code to handle CSD wrapper and or for now just add a config option to pass the result of CSD.

impynutz@3ecfb76

thank you @impynutz, this CSD logic worked for me as well!

for anybody interested, i've forked @vlaci's latest main branch (0.8.0) and applied @impynutz' csd_test branch to it, along with publishing a self-contained Windows .exe release & some Windows specific build instructions here => https://github.com/Beej126/openconnect-sso-windows-csd

adminy commented 6 days ago

This should now be fixed with the scan-file flag in https://github.com/vlaci/openconnect-sso/pull/181