Loss of urlpath through browser-based authentication
OpenConnect loses the urlpath information somewhere along the way in cstp_obtain_cookie() through SSO authentication in an external web browser. This causes the newly updated Cisco AnyConnect VPN at Harvard University to be inaccessible to OpenConnect, because connections to vpn.harvard.edu without a user group end with error 404.
See sample log below. Specifically, I'm connecting to vpn.harvard.edu/gencom, and at the start of cstp_obtain_cookie(), vpninfo->urlpath is set to "gencom" as it should, and the POST connection goes to https://vpn.harvard.edu/gencom, which starts a web browser based SSO sign-on. After we return from handle_auth_form() in Step 5 (line 1632 of auth.c in current master), vpninfo->urlpath no longer contains the necessary information, and the next POST request goes to https://vpn.harvard.edu/ and fails.
I'm able to patch my way around the bug and complete authentication successfully by saving the contents of vpninfo->urlpath at the start of cstp_obtain_cookie() and restoring it to the saved value just before we send the second POST request. I realize this may not be the right way to proceed for compatibility with other VPN setups.
Additionally, when using NetworkManager-openconnect, which uses libopenconnect to complete authentication and then spawns openconnect using the info gleaned from the authentication step, I think I've also hit the same bug that affected users of the PULSE protocol -- we need openconnect_get_connect_url() to return a complete URL, including the urlpath (even though proto is not PROTO_PULSE).
After working around both issues (saving urlpath from the first POST call to the second one in cstp_obtain_cookie(), and making sure that openconnect_get_connect_url() returns the complete URL including urlpath) I am able to connect successfully to this VPN using NetworkManager-openconnect.
I can provide my patch if needed, but my patch is clearly not the right way to do it -- just the outcome of frustrated attempts to get around the immediate issue I had to deal with. I can also try to provide more info about the VPN if needed, but only if it can be done from the end user side -- I'm just an end user, and the university's IT department won't tell me exactly what they changed on their end, they just want me to use Cisco's VPN client.
SAMPLE LOG:
auroux-X1G8 - ~/DL/openconnect-master > ./openconnect --dump-http-traffic -vvv vpn.harvard.edu/gencomPOST https://vpn.harvard.edu/gencom
Attempting to connect to server 128.103.200.147:443
Connected to 128.103.200.147:443
SSL negotiation with vpn.harvard.edu
Connected to HTTPS on vpn.harvard.edu with ciphersuite (TLS1.2)-(RSA)-(AES-128-CBC)-(SHA1)
> POST /gencom HTTP/1.1
> Host: vpn.harvard.edu
> User-Agent: Open AnyConnect VPN Agent v9.12-unknown
> Accept: */*
> Accept-Encoding: identity
> X-Transcend-Version: 1
> X-Aggregate-Auth: 1
> X-Support-HTTP-Auth: true
> X-AnyConnect-STRAP-Pubkey: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVda0dz2xJ+kVkhWyXePdV3TuT9bwuaiCWFzPjDGS8wBcgDl+7MCdjaL72wqepayxnF9QgW8sROPCAUm7M6jx5A==
> X-AnyConnect-STRAP-DH-Pubkey: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEiS7RD8f1HXDXHYq7hpecv39WEOIw3MFkDoT0pqxhiAgrK62GKpin+bND8AWmR8zD8tzoPXrpBJFN4JStcnoqJg==
> X-Pad: 00
> Content-Type: application/xml; charset=utf-8
> Content-Length: 382
>
> <?xml version="1.0" encoding="UTF-8"?>
> <config-auth client="vpn" type="init" aggregate-auth-version="2"><version who="vpn">v9.12-unknown</version><device-id>linux-64</device-id><capabilities><auth-method>single-sign-on-v2</auth-method><auth-method>single-sign-on-external-browser</auth-method></capabilities><group-access>https://vpn.harvard.edu/gencom</group-access></config-auth>
Got HTTP response: HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: no-store
Pragma: no-cache
Connection: Keep-Alive
Date: Sat, 28 Oct 2023 18:35:51 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-XSS-Protection: 1
Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:; frame-ancestors 'self'; base-uri 'self'; block-all-mixed-content
X-Aggregate-Auth: 1
HTTP body chunked (-2)
< <?xml version="1.0" encoding="UTF-8"?>
< <config-auth client="vpn" type="auth-request" aggregate-auth-version="2">
< <opaque is-for="sg">
< <tunnel-group>tunnel-0</tunnel-group>
< <aggauth-handle>1130008442</aggauth-handle>
< <auth-method>single-sign-on-v2</auth-method>
< <auth-method>single-sign-on-external-browser</auth-method>
< <config-hash>1698278328847</config-hash>
< </opaque>
< <auth id="main">
< <title>Login</title>
< <message>Please complete the authentication process in the browser window.</message>
< <banner></banner>
< <sso-v2-login>https://vpn.harvard.edu/+CSCOE+/saml/sp/login?ctx=1704725830%0A&acsamlcap=v2</sso-v2-login>
< <sso-v2-login-final>https://vpn.harvard.edu/+CSCOE+/saml_ac_login.html</sso-v2-login-final>
< <sso-v2-browser-mode>external</sso-v2-browser-mode>
< <sso-v2-token-cookie-name>acSamlv2Token</sso-v2-token-cookie-name>
< <sso-v2-error-cookie-name>acSamlv2Error</sso-v2-error-cookie-name>
< <form>
< <input type="sso" name="sso-token"></input>
< </form>
< </auth>
< </config-auth>
XML POST enabled
Please complete the authentication process in the browser window.
Spawning external browser '/usr/bin/xdg-open'
Accepted incoming external-browser connection on port 29786
< Host: localhost:29786
< User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0
< Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
< Accept-Language: en-US,en;q=0.5
< Accept-Encoding: gzip, deflate, br
< DNT: 1
< Connection: keep-alive
< Upgrade-Insecure-Requests: 1
< Sec-Fetch-Dest: document
< Sec-Fetch-Mode: navigate
< Sec-Fetch-Site: cross-site
Got encrypted SSO token of 157 bytes
POST https://vpn.harvard.edu/
> POST / HTTP/1.1
> Host: vpn.harvard.edu
> User-Agent: Open AnyConnect VPN Agent v9.12-unknown
> Accept: */*
> Accept-Encoding: identity
> X-Transcend-Version: 1
> X-Aggregate-Auth: 1
> X-Support-HTTP-Auth: true
> X-AnyConnect-STRAP-Pubkey: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVda0dz2xJ+kVkhWyXePdV3TuT9bwuaiCWFzPjDGS8wBcgDl+7MCdjaL72wqepayxnF9QgW8sROPCAUm7M6jx5A==
> X-AnyConnect-STRAP-DH-Pubkey: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEiS7RD8f1HXDXHYq7hpecv39WEOIw3MFkDoT0pqxhiAgrK62GKpin+bND8AWmR8zD8tzoPXrpBJFN4JStcnoqJg==
> X-Pad: 0000000000000000000000000000000000000000000000000000000000
> Content-Type: application/xml; charset=utf-8
> Content-Length: 646
>
> <?xml version="1.0" encoding="UTF-8"?>
> <config-auth client="vpn" type="auth-reply" aggregate-auth-version="2"><version who="vpn">v9.12-unknown</version><device-id>linux-64</device-id><capabilities><auth-method>single-sign-on-v2</auth-method><auth-method>single-sign-on-external-browser</auth-method></capabilities><opaque is-for="sg">
> <tunnel-group>tunnel-0</tunnel-group>
> <aggauth-handle>1130008442</aggauth-handle>
> <auth-method>single-sign-on-v2</auth-method>
> <auth-method>single-sign-on-external-browser</auth-method>
> <config-hash>1698278328847</config-hash>
> </opaque><auth><sso-token>4A8BEDEF7CCDEACE731E63C9</sso-token></auth></config-auth>
Got HTTP response: HTTP/1.1 404 Not Found
Cache-Control: no-store
Pragma: no-cache
Connection: Close
Date: Sat, 28 Oct 2023 18:35:58 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-XSS-Protection: 1
Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:; frame-ancestors 'self'; base-uri 'self'; block-all-mixed-content
HTTP body http 1.0 (-1)
TLS/DTLS socket closed uncleanly
Unexpected 404 result from server
Failed to complete authentication
`