dlenski / gp-saml-gui

Interactively authenticate to GlobalProtect VPNs that require SAML
GNU General Public License v3.0
306 stars 69 forks source link

Remove "https://" and "/gateway:prelogin-cookie" from HOST variable #50

Closed robin-a-meade closed 1 year ago

robin-a-meade commented 2 years ago

The README.md shows:

SAML response converted to OpenConnect command line invocation:

    echo 'blahblahblah' |
        openconnect --protocol=gp --user='foo12345@corp.company.com' --os=win --usergroup=prelogin-cookie:gateway --passwd-on-stdin vpn.company.com

$ echo $HOST; echo $USER; echo $COOKIE; echo $OS
https://vpn.company.com/gateway:prelogin-cookie
foo12345@corp.company.com
blahblahblah
win

$ echo "$COOKIE" | openconnect --protocol=gp -u "$USER" --os="$OS" --passwd-on-stdin "$HOST"

Notice that the first shown openconnect invocation uses vpn.company.com as the host.

Yet the second invocation uses the $HOST variable which has a different value: https://vpn.company.com/gateway:prelogin-cookie

Recently the "https://" and "/gateway:prelogin-cookie" parts caused my vpn connection script to fail. It was working for many months but then started failing with Failed to parse server response. Failed to complete authentication" error.

In my case, the HOST variable is set to https://vpn.example.edu/ssl-vpn/login.esp:prelogin-cookie.

I fixed my script by changing it from:

#!/bin/bash

eval $(./gp_saml_gui.py -v --gateway --clientos=Linux vpn.example.edu)
echo "$COOKIE" \
  | sudo openconnect --protocol=gp -u "$USER" --usergroup=gateway:prelogin-cookie --os="$OS" --passwd-on-stdin "$HOST"

to:

#!/bin/bash

eval $(./gp_saml_gui.py -v --gateway --clientos=Linux vpn.example.edu)
: "${HOST#*//}"          # Chop off https:// from the beginning. Result will be in $_ variable
ADJUSTED_HOST=${_%%/*}   # Chop off path from the end
echo "$COOKIE" \
  | sudo openconnect --protocol=gp -u "$USER" --usergroup=gateway:prelogin-cookie --os="$OS" --passwd-on-stdin "$ADJUSTED_HOST"

So, I'm wondering if the HOST variable shouldn't have the "https://" and "/gateway:prelogin-cookie" parts.

dlenski commented 1 year ago

The README.md shows:

SAML response converted to OpenConnect command line invocation:

    echo 'blahblahblah' |
        openconnect --protocol=gp --user='foo12345@corp.company.com' --os=win --usergroup=prelogin-cookie:gateway --passwd-on-stdin vpn.company.com

Thanks, this was backwards :man_facepalming:. Should've been gateway:prelogin-cookie rather than prelogin-cookie:gateway.

(Note that this is entirely equivalent to appending /gateway:prelogin-cookie to the server address/URL, or /ssl-vpn/prelogin.esp:prelogin-cookie for that matter. You can read the OpenConnect manual for why, or look at the code for the gory details.)

dlenski commented 1 year ago

Your new script and your old script as written above should be entirely equivalent. I suspect that you may have actually had the order/contents of --usergroup backwards based on the mistake in the README, which I just fixed in 18bbf11.

robin-a-meade commented 1 year ago

Thanks. I'm testing now.

In this commit:

https://github.com/dlenski/gp-saml-gui/commit/f33444375822f5c025b1d5ffa5b26afafa4ec6ab

the [0] should be removed from this line in setup.py:

if sys.version_info[0] <= (3, 5):

I'll test further later.

dlenski commented 1 year ago

Thanks @robin-a-meade, force-pushed to de15c2c8f366b5700c8bec5e8162b50a9d8ed2ca :man_facepalming:

robin-a-meade commented 1 year ago

Scenario 1: I copy and paste the suggested command line invocation that is logged to the terminal

I do the first step at https://github.com/dlenski/gp-saml-gui#how-to-use :

eval $( gp-saml-gui --allow-insecure-crypto --gateway --clientos=Linux vpn.example.edu -- -v)

(I added the --allow-insecure-crypto because I needed it on Fedora 38 beta and the -- -v part for verbose openconnect logging.)

In the log output I see:

SAML response converted to OpenConnect command line invocation:

    echo EwUAi8mlu/NAHSKU+qln6gToWi1lP+oOoKlK+p9LuIYweWHtURVKVNaOyVodXd/0 |
        sudo openconnect --protocol=gp '--useragent=PAN GlobalProtect' --allow-insecure-crypto --user=robin --os=linux-64 --usergroup=gateway:prelogin-cookie --passwd-on-stdin vpn.example.edu -v

I paste that into my terminal and it works.

$ echo EwUAi8mlu/NAHSKU+qln6gToWi1lP+oOoKlK+p9LuIYweWHtURVKVNaOyVodXd/0 |
        sudo openconnect --protocol=gp '--useragent=PAN GlobalProtect' --allow-insecure-crypto --user=robin --os=linux-64 --usergroup=gateway:prelogin-cookie --passwd-on-stdin vpn.example.edu -v
[sudo] password for robin:
POST https://vpn.example.edu/ssl-vpn/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Linux
Attempting to connect to server yyy.yyy.yyy.yyy:443
Connected to yyy.yyy.yyy.yyy:443
SSL negotiation with vpn.example.edu
Connected to HTTPS on vpn.example.edu with ciphersuite (TLS1.2)-(RSA)-(AES-256-GCM)
Got HTTP response: HTTP/1.1 200 OK
Date: Wed, 12 Apr 2023 05:14:53 GMT
Content-Type: application/xml; charset=UTF-8
Content-Length: 2092
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
X-FRAME-OPTIONS: DENY
Set-Cookie: CLIENTOS=TGludXg%3D; expires=Thu, 13-Apr-2023 05:14:53 GMT; Max-Age=86400; path=/
Set-Cookie: PHPSESSID=c96e1f21f3b2f09b55853ddd504e33e1; secure; HttpOnly
Set-Cookie: PHPSESSID=c96e1f21f3b2f09b55853ddd504e33e1; secure; HttpOnly
Set-Cookie: PHPSESSID=c96e1f21f3b2f09b55853ddd504e33e1; secure; HttpOnly
Set-Cookie: PHPSESSID=c96e1f21f3b2f09b55853ddd504e33e1; secure; HttpOnly
Set-Cookie: PHPSESSID=c96e1f21f3b2f09b55853ddd504e33e1; secure; HttpOnly
Set-Cookie: PHPSESSID=c96e1f21f3b2f09b55853ddd504e33e1; secure; HttpOnly
Set-Cookie: PHPSESSID=c96e1f21f3b2f09b55853ddd504e33e1; secure; HttpOnly
Set-Cookie: PHPSESSID=c96e1f21f3b2f09b55853ddd504e33e1; secure; HttpOnly
Set-Cookie: PHPSESSID=c96e1f21f3b2f09b55853ddd504e33e1; secure; HttpOnly
Set-Cookie: PHPSESSID=c96e1f21f3b2f09b55853ddd504e33e1; secure; HttpOnly
Strict-Transport-Security: max-age=31536000;
X-XSS-Protection: 1; mode=block;
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (2092)
Destination form field prelogin-cookie was specified; assuming SAML POST authentication is complete.
Enter login credentials
POST https://vpn.example.edu/ssl-vpn/login.esp
Got HTTP response: HTTP/1.1 200 OK
Date: Wed, 12 Apr 2023 05:14:53 GMT
Content-Type: application/xml; charset=UTF-8
Content-Length: 710
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
X-FRAME-OPTIONS: DENY
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=1edd5f01bc8b8e4d408b1ca1b1dc3864; path=/; secure; HttpOnly
Strict-Transport-Security: max-age=31536000;
X-XSS-Protection: 1; mode=block;
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (710)
GlobalProtect login returned authentication-source=UU-Shib-2022-10-16
GlobalProtect login returned usually-equals-4=4
GlobalProtect login returned usually-equals-unknown=unknown
POST https://vpn.example.edu/ssl-vpn/getconfig.esp
Got HTTP response: HTTP/1.1 200 OK
Date: Wed, 12 Apr 2023 05:14:53 GMT
Content-Type: application/xml; charset=UTF-8
Content-Length: 1598
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
X-FRAME-OPTIONS: DENY
Strict-Transport-Security: max-age=31536000;
X-XSS-Protection: 1; mode=block;
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (1598)
Tunnel timeout (rekey interval) is 600 minutes.
Idle timeout is 600 minutes.
TCP_INFO rcv mss 1460, snd mss 1460, adv mss 1460, pmtu 1500
No MTU received. Calculated 1422 for ESP tunnel
POST https://vpn.example.edu/ssl-vpn/hipreportcheck.esp
Got HTTP response: HTTP/1.1 200 OK
Date: Wed, 12 Apr 2023 05:14:53 GMT
Content-Type: application/xml; charset=UTF-8
Content-Length: 107
Connection: keep-alive
X-Content-Type-Options: nosniff
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Security-Policy: default-src 'self'
Expires: Thu, 19 Nov 1981 08:52:00 GMT
X-FRAME-OPTIONS: DENY
Strict-Transport-Security: max-age=31536000;
X-XSS-Protection: 1; mode=block;
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (107)
Gateway says HIP report submission is needed.
WARNING: Server asked us to submit HIP report with md5sum e1de480752cda1113aa2a513022e646a.
    VPN connectivity may be disabled or limited without HIP report submission.
    You need to provide a --csd-wrapper argument with the HIP report submission script.
Send ESP probes
UDP SO_SNDBUF: 28440
ESP session established with server
ESP tunnel connected; exiting HTTPS mainloop.
Configured as xxx.xxx.xxx.xxx, with SSL disconnected and ESP established
Session authentication will expire at Thu May 11 19:14:53 2023

✔️ Scenario 1 is successful.

Scenario 2: I follow the additional steps in the README.md

Instead of pasting the invocation shown in the logs into my terminal, I carry out the additional steps in the README.md

echo $HOST; echo $USER; echo $COOKIE; echo $OS
echo "$COOKIE" | openconnect --protocol=gp -u "$USER" --os="$OS" --passwd-on-stdin "$HOST" -v
$ echo $HOST; echo $USER; echo $COOKIE; echo $OS
https://vpn.example.edu/ssl-vpn/login.esp:prelogin-cookie
robin
msCCBpDc6xha3wZzDgOfAWY3kxQrtLG5ENMYzW8bMN6L1WQdwNC37GudKwJY2yDy
linux-64
$ echo "$COOKIE" | sudo openconnect --protocol=gp -u "$USER" --os="$OS" --usergroup=gateway:prelogin-cookie --passwd-on-stdin "$HOST" -v
POST https://vpn.example.edu/ssl-vpn/login.esp
Attempting to connect to server yyy.yyy.yyy.yyy:443
Connected to yyy.yyy.yyy.yyy:443
SSL negotiation with vpn.example.edu
Connected to HTTPS on vpn.example.edu with ciphersuite (TLS1.2)-(RSA)-(AES-256-GCM)
Got HTTP response: HTTP/1.1 200 OK
Date: Wed, 12 Apr 2023 07:01:27 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 71
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
X-FRAME-OPTIONS: DENY
Set-Cookie: PHPSESSID=ffa92726a98acffa7f7f0e3bb18a3a77; secure; HttpOnly
Strict-Transport-Security: max-age=31536000;
X-XSS-Protection: 1; mode=block;
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (71)
Failed to parse server response
Response was: 
var respStatus = "";
var respMsg = "";
thisForm.inputStr.value = "";

Failed to complete authentication

It does not work at my institution's VPN.

I think the 2nd scenario failed because it results in a different openconnect command line invocation.

Here I just echo the invocation to the terminal so I can see it:

$ echo "$COOKIE | openconnect --protocol=gp -u $USER --os=$OS --passwd-on-stdin $HOST -v"
msCCBpDc6xha3wZzDgOfAWY3kxQrtLG5ENMYzW8bMN6L1WQdwNC37GudKwJY2yDy | openconnect --protocol=gp -u robin --os=linux-64 --passwd-on-stdin https://vpn.example.edu/ssl-vpn/login.esp:prelogin-cookie -v

Maybe, as you say, this invocation should be equivalent to the Scenario 1 invocation, but, at least at my institution's vpn, it doesn't seem to be so.

I can make it work by modifying the command sequence to make the openconnect invocation like Scenario 1:

eval $( gp-saml-gui --allow-insecure-crypto --gateway --clientos=Linux vpn.example.edu -- -v)
HOST=vpn.example.edu # Change 1: Simplify the HOST variable
echo $HOST; echo $USER; echo $COOKIE; echo $OS
# Change 2:  Added --usergroup=gateway:prelogin-cookie to the following invocation:
echo "$COOKIE" | sudo openconnect --protocol=gp -u "$USER" --os="$OS" --usergroup=gateway:prelogin-cookie --passwd-on-stdin "$HOST" -v

I made two changes:

  1. Simplified the HOST variable by chopping off "https://" from the beginning and /ssl-vpn/login.esp:prelogin-cookie from the end.
  2. Added the --usergroup=gateway:prelogin-cookie option

Maybe my institution's VPN is an anomalous deviation from the standard, and the two changes I made should not have been necessary.

If, on the other hand, my institution's VPN behavior is typical, then I would (1) change this line:

'HOST': quote('https://%s/%s:%s' % (server, if2auth[args.interface], cn)),

to:

'HOST': quote(server),

and change the last line of the code block in section https://github.com/dlenski/gp-saml-gui#how-to-use from:

$ echo "$COOKIE" | openconnect --protocol=gp -u "$USER" --os="$OS" --passwd-on-stdin "$HOST"

to:

$ echo "$COOKIE" | openconnect --protocol=gp -u "$USER" --os="$OS" --usergroup=gateway:prelogin-cookie --passwd-on-stdin "$HOST"

That is, add the --usergroup=gateway:prelogin-cookie option.

I concede that it is possible that my institution's VPN's behavior is deviating from expected behavior. If you feel that might be the case, I don't mind if we close this issue. I'm been using gp-saml-gui effectively for about 3 years. (Thanks!) In fact, with the -S option, I no longer need the "fix" I showed in my initial description of this issue.

dlenski commented 1 year ago

Most important question: what openconnect --version are you using? Older versions do not support SAML correctly, or at all. Make sure it's a recent version (v9.01, or a newer unreleased build).

Also, you can use --dump-http-traffic to see the exact details of what OpenConnect is sending to the servers.


This whole thing can be boiled down to "what is the difference between the Scenario 1 command-line, and the Scenario 2 command-line"…

Which comes down to the following…

diff --git a/tmp/scenario1.txt b/tmp/scenario2.txt
index 8043ca2..0453fea 100644
--- a/tmp/scenario1.txt
+++ b/tmp/scenario2.txt
@@ -1 +1 @@
-echo "$COOKIE" | openconnect --protocol=gp --useragent='PAN GlobalProtect' --allow-insecure-crypto --user="$USERNAME" --os=linux-64 --usergroup=gateway:prelogin-cookie --passwd-on-stdin -v "$HOSTNAME"
+echo "$COOKIE" | openconnect --protocol=gp --user="$USERNAME" --os=linux-64 --passwd-on-stdin "https://$HOSTNAME/ssl-vpn/login.esp:prelogin-cookie" -v

In other words…

Specifics:

  1. The --allow-insecure-crypto option is clearly not making a difference here, but it's also pretty tangential so let's not get into why.
  2. The --useragent='PAN GlobalProtect' option is not making a difference here, because every version of OpenConnect v8.04+ that supports the GP protocol sends it unconditionally (see https://gitlab.com/openconnect/openconnect/-/commit/92e534bd1656ffbdcf00621f3472cd5dfcd459fe)
  3. As we've already discussed, the usergroup/URL-path distinction should not matter, and this should not be dependent on the server in any way.

However, I see a puzzling difference between your Scenario 1 and your Scenario 2. Namely, in Scenario 1, OpenConnect starts off with a request to https://vpn.example.edu/ssl-vpn/login.esp, whereas in Scenario 2 it starts off with a request to https://vpn.example.edu/ssl-vpn/prelogin.esp.

This difference makes no sense. These two command lines:

  1. openconnect --prot=gp --dump -u test --usergroup gateway:prelogin-cookie https://localhost
  2. openconnect --prot=gp --dump -u test https://localhost/gateway:prelogin-cookie

… should result in the exact same initial request to the server, namely:

POST https://localhost/ssl-vpn/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Linux
Attempting to connect to server 127.0.0.1:443
Connected to 127.0.0.1:443
SSL negotiation with localhost
Server certificate verify failed: signer not found
Connected to HTTPS on localhost with ciphersuite (TLS1.2)-(ECDHE-SECP256R1)-(RSA-SHA256)-(AES-256-GCM)
> POST /ssl-vpn/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Linux HTTP/1.1
> Host: localhost
> User-Agent: PAN GlobalProtect
> 

@robin-a-meade, my strong suspicion is that _you're invoking a different openconnect executable in the two cases, due to some PATH difference with/without sudo/pkexec/etc.

In one case, you're probably running a new openconnect with the latest-and-greatest-ish PAN GP SAML support, in another, you're running an old openconnect.

So that brings us back to the top: what version(s) of openconnect are you running?

robin-a-meade commented 1 year ago

Thanks. This time I tried to include all possible logs.

Version of openconnect

$ sudo dnf list installed \*openconnect\*
Installed Packages
NetworkManager-openconnect.x86_64          1.2.8-4.fc38               @fedora
NetworkManager-openconnect-gnome.x86_64    1.2.8-4.fc38               @fedora
openconnect.x86_64                         9.01-4.fc38                @fedora

$ openconnect -V
OpenConnect version v9.01
Using GnuTLS 3.8.0. Features present: TPM, TPMv2, PKCS#11, RSA software token, HOTP software token, TOTP software token, Yubikey OATH, System keys, DTLS, ESP
Supported protocols: anyconnect (default), nc, gp, pulse, f5, fortinet, array
Default vpnc-script (override with --script): /etc/vpnc/vpnc-script

$ sudo openconnect -V
(Same output)

Source files for the Fedora 38 openconnect package: https://src.fedoraproject.org/rpms/openconnect/tree/f38

Scenario 1: I copy and paste the openconnect invocation shown in the gp-saml-gui output

First the call to gp-saml-gui:

$ eval $( gp-saml-gui -v --allow-insecure-crypto --gateway --clientos=Linux vpn.example.edu -- -v --dump-http-traffic)
Looking for SAML auth tags in response to https://vpn.example.edu/ssl-vpn/prelogin.esp...
Got SAML POST, opening browser...
[REQUEST] Request for resource about:blank
[PAGE   ] Finished loading page about:blank
[REQUEST] POST for resource https://idp.example.edu/idp/profile/SAML2/POST/SSO
[REQUEST] GET for resource https://idp.example.edu/idp/css/main.css
[PAGE   ] Finished loading page https://idp.example.edu/idp/profile/SAML2/POST/SSO?execution=e1s1
[REQUEST] POST for resource https://idp.example.edu/idp/profile/SAML2/POST/SSO?execution=e1s1
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/normalize.css/8.0.1/normalize.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/bootstrap/5.1.3/css/bootstrap-grid.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/material-components-web/13.0.0/dist/material-components-web.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/mdi__font/6.2.95/css/materialdesignicons.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/css/cas.css
[REQUEST] GET for resource https://cdnjs.cloudflare.com/ajax/libs/core-js/3.21.1/minified.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/jquery/3.6.0/jquery.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/es5-shim/4.5.9/es5-shim.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/css-vars-ponyfill/2.4.7/dist/css-vars-ponyfill.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/material-components-web/13.0.0/dist/material-components-web.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/js/cas.js
[REQUEST] GET for resource https://authn.example.edu/cas/images/useal.png
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/mdi__font/6.2.95/fonts/materialdesignicons-webfont.woff2?v=6.2.95
[PAGE   ] Finished loading page https://authn.example.edu/cas/login?service=https%3A%2F%2Fidp.example.edu%2Fidp%2FAuthn%2FExternal%3Fconversation%3De1s2&entityId=https%3A%2F%2Fvpn.example.edu%3A443%2FSAML20%2FSP
[REQUEST] POST for resource https://authn.example.edu/cas/login?service=https%3A%2F%2Fidp.example.edu%2Fidp%2FAuthn%2FExternal%3Fconversation%3De1s2&entityId=https%3A%2F%2Fvpn.example.edu%3A443%2FSAML20%2FSP
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/normalize.css/8.0.1/normalize.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/bootstrap/5.1.3/css/bootstrap-grid.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/material-components-web/13.0.0/dist/material-components-web.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/mdi__font/6.2.95/css/materialdesignicons.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/css/cas.css
[REQUEST] GET for resource https://cdnjs.cloudflare.com/ajax/libs/core-js/3.21.1/minified.js
[REQUEST] GET for resource https://authn.example.edu/cas/js/duo/Duo-Web-v2.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/jquery/3.6.0/jquery.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/es5-shim/4.5.9/es5-shim.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/css-vars-ponyfill/2.4.7/dist/css-vars-ponyfill.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/material-components-web/13.0.0/dist/material-components-web.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/js/cas.js
[PAGE   ] Finished loading page https://authn.example.edu/cas/login?service=https%3A%2F%2Fidp.example.edu%2Fidp%2FAuthn%2FExternal%3Fconversation%3De1s2&entityId=https%3A%2F%2Fvpn.example.edu%3A443%2FSAML20%2FSP
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/web/v1/auth?tx=TX|bWVhZGVyfERJUjNYRTA0WEY2UEtJVFdVOEJFfDE2ODEzMzE5MTQ=|a9b47805eaf4662b2ec801f7a9902211f014735b&parent=https%3A%2F%2Fauthn.example.edu%2Fcas%2Flogin%3Fservice%3Dhttps%253A%252F%252Fidp.example.edu%252Fidp%252FAuthn%252FExternal%253Fconversation%253De1s2%26entityId%3Dhttps%253A%252F%252Fvpn.example.edu%253A443%252FSAML20%252FSP&v=2.6
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/css/v3/base.css?v=39c22
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/plugin-detect/plugin-detect.min.css?v=01376
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery-prologue.js?v=400dc
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery.min.js?v=ff152
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/lib/jquery-postmessage.min.js?v=98c73
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/plugin-detect/plugin-detect.min.js?v=6a394
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/page/preauth.js?v=154e6
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery-epilogue.js?v=c4ac5
[REQUEST] POST for resource https://api-16a593a9.duosecurity.com/frame/web/v1/auth?tx=TX|bWVhZGVyfERJUjNYRTA0WEY2UEtJVFdVOEJFfDE2ODEzMzE5MTQ=|a9b47805eaf4662b2ec801f7a9902211f014735b&parent=https%3A%2F%2Fauthn.example.edu%2Fcas%2Flogin%3Fservice%3Dhttps%253A%252F%252Fidp.example.edu%252Fidp%252FAuthn%252FExternal%253Fconversation%253De1s2%26entityId%3Dhttps%253A%252F%252Fvpn.example.edu%253A443%252FSAML20%252FSP&v=2.6
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/css/normalize.css?v=a674e
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/fonts/ss-standard/ss-standard.css?v=a8885
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/css/fonts/duo-admin.css?v=50a8a
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/css/v3/base.css?v=39c22
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/css/tipsy.css?v=4217a
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/logo?sid=Y2MzYmQ3MDUyMTMzNDFjNGFhOWViNWY4MmQzZGNmYTI=|1681331615|512cc8a0e4f43bdf1cd2457810b7389c4e7868e4
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery-prologue.js?v=400dc
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery.min.js?v=ff152
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/he/he.min.js?v=aaa33
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/lib/jquery-postmessage.min.js?v=98c73
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/lodash/lodash.min.js?v=6585f
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/backbone/backbone-min.js?v=e0ff6
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/page/v3/frame.js?v=4baee
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/page/v3/base.js?v=a2248
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/validator/validator.min.js?v=9a068
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery-epilogue.js?v=c4ac5
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/js/errors.js?v=d10d2
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/lib/jquery.tipsy.js?v=c0432
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/page/v3/prompt.js?v=72a73
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/fonts/duo-admin/duo-admin.woff
[REQUEST] POST for resource https://api-16a593a9.duosecurity.com/frame/prompt
[REQUEST] POST for resource https://api-16a593a9.duosecurity.com/frame/status
[REQUEST] POST for resource https://api-16a593a9.duosecurity.com/frame/status
[REQUEST] POST for resource https://api-16a593a9.duosecurity.com/frame/status/692053ce-e9b0-4783-8079-c66a565f57f2
[REQUEST] POST for resource https://authn.example.edu/cas/login?service=https%3A%2F%2Fidp.example.edu%2Fidp%2FAuthn%2FExternal%3Fconversation%3De1s2&entityId=https%3A%2F%2Fvpn.example.edu%3A443%2FSAML20%2FSP
[PAGE   ] Finished loading page https://idp.example.edu/idp/profile/SAML2/POST/SSO?execution=e1s2&_eventId_proceed=1
[REQUEST] POST for resource https://vpn.example.edu/SAML20/SP/ACS
[PAGE   ] Finished loading page https://vpn.example.edu/SAML20/SP/ACS
[SAML   ] Got SAML result headers: {'saml-username': 'robin', 'prelogin-cookie': 'IozAXDCYvM0cAUJl8GgqtMD5t6cyRhO+uqfBzPw7cuWaxP8AA9IoenDTKut1Dw0p', 'saml-slo': 'no', 'saml-auth-status': '1'}
[DATA   ] 249 bytes of text/html; charset=UTF-8 for resource https://vpn.example.edu/SAML20/SP/ACS
Date: Wed, 12 Apr 2023 20:33:44 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 249
Connection: keep-alive
ETag: "1c86624bf152"
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block;
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
saml-username: robin
prelogin-cookie: IozAXdCYvM0cAUJl8GgqtMD5t6cyRhO+uqfBzPw7cuWaxP8AA9IoenDTKut1Dw0p
saml-slo: no
saml-auth-status: 1
Strict-Transport-Security: max-age=31536000;

<html><body>Login Successful!</body><!-- <saml-auth-status>1</saml-auth-status><prelogin-cookie>IozAXDCYvM0cAUJl8GgqtMD5t6cyRhO+uqfBzPw7cuWaxP8AA9IoenDTKut1Dw0p</prelogin-cookie><saml-username>robin</saml-username><saml-slo>no</saml-slo> --></html>
[SAML   ] Got all required SAML headers, done.

SAML response converted to OpenConnect command line invocation:

    echo IozAXdCYvM0cAUJl8GgqtMD5t6cyRhO+uqfBzPw7cuWaxP8AA9IoenDTKut1Dw0p |
        sudo openconnect --protocol=gp '--useragent=PAN GlobalProtect' --allow-insecure-crypto --user=robin --os=linux-64 --usergroup=gateway:prelogin-cookie --passwd-on-stdin vpn.example.edu -v --dump-http-traffic

SAML response converted to test-globalprotect-login.py invocation:

    test-globalprotect-login.py --user=robin --clientos=Linux -p '' \
        https://vpn.example.edu/ssl-vpn/login.esp prelogin-cookie=IozAXdCYvM0cAUJl8GgqtMD5t6cyRhO+uqfBzPw7cuWaxP8AA9IoenDTKut1Dw0p

Then I copy the above reported openconnect command line invocation, adding --dump-http-traffic and -v options:

$ echo IozAXdCYvM0cAUJl8GgqtMD5t6cyRhO+uqfBzPw7cuWaxP8AA9IoenDTKut1Dw0p |
        sudo openconnect --protocol=gp '--useragent=PAN GlobalProtect' --allow-insecure-crypto --user=robin --os=linux-64 --usergroup=gateway:prelogin-cookie --passwd-on-stdin vpn.example.edu -v --dump-http-traffic
[sudo] password for robin:
POST https://vpn.example.edu/ssl-vpn/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Linux
Attempting to connect to server xxx.xxx.xxx.131:443
Connected to xxx.xxx.xxx.131:443
SSL negotiation with vpn.example.edu
Connected to HTTPS on vpn.example.edu with ciphersuite (TLS1.2)-(RSA)-(AES-256-GCM)
> POST /ssl-vpn/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Linux HTTP/1.1
> Host: vpn.example.edu
> User-Agent: PAN GlobalProtect
>
Got HTTP response: HTTP/1.1 200 OK
Date: Wed, 12 Apr 2023 20:34:48 GMT
Content-Type: application/xml; charset=UTF-8
Content-Length: 2115
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
X-FRAME-OPTIONS: DENY
Set-Cookie: CLIENTOS=TGludXg%3D; expires=Thu, 13-Apr-2023 20:34:48 GMT; Max-Age=86400; path=/
Set-Cookie: PHPSESSID=73f1ec0d96340c1d9b25bec26fd5483a; secure; HttpOnly
Set-Cookie: PHPSESSID=73f1ec0d96340c1d9b25bec26fd5483a; secure; HttpOnly
Set-Cookie: PHPSESSID=73f1ec0d96340c1d9b25bec26fd5483a; secure; HttpOnly
Set-Cookie: PHPSESSID=73f1ec0d96340c1d9b25bec26fd5483a; secure; HttpOnly
Set-Cookie: PHPSESSID=73f1ec0d96340c1d9b25bec26fd5483a; secure; HttpOnly
Set-Cookie: PHPSESSID=73f1ec0d96340c1d9b25bec26fd5483a; secure; HttpOnly
Set-Cookie: PHPSESSID=73f1ec0d96340c1d9b25bec26fd5483a; secure; HttpOnly
Set-Cookie: PHPSESSID=73f1ec0d96340c1d9b25bec26fd5483a; secure; HttpOnly
Set-Cookie: PHPSESSID=73f1ec0d96340c1d9b25bec26fd5483a; secure; HttpOnly
Set-Cookie: PHPSESSID=73f1ec0d96340c1d9b25bec26fd5483a; secure; HttpOnly
Strict-Transport-Security: max-age=31536000;
X-XSS-Protection: 1; mode=block;
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (2115)
< <?xml version="1.0" encoding="UTF-8" ?>
< <prelogin-response>
< <status>Success</status>
< <ccusername></ccusername>
< <autosubmit>false</autosubmit>
< <msg></msg>
< <newmsg></newmsg>
< <license>yes</license>
< <authentication-message>Enter login credentials</authentication-message>
< <username-label>Username</username-label>
< <password-label>Password</password-label>
< <panos-version>1</panos-version>
< <saml-default-browser>yes</saml-default-browser><saml-auth-status>0</saml-auth-status>
< <saml-auth-method>POST</saml-auth-method>
< <saml-request-timeout>600</saml-request-timeout>
< <saml-request-id>0</saml-request-id><saml-request>PGh0bWw+Cjxib2R5Pgo8Zm9ybSBpZD0ibXlmb3JtIiBtZXRob2Q9IlBPU1QiIGFjdGlvbj0iaHR0cHM6Ly9pZHAuaGF3YWlpLmVkdS9pZHAvcHJvZmlsZS9TQU1MMi9QT1NUL1NTTyI+CjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9IlNBTUxSZXF1ZXN0IiB2YWx1ZT0iUEhOaGJXeHdPa0YxZEdodVVtVnhkV1Z6ZENCNGJXeHVjenB6WVcxc2NEMGlkWEp1T205aGMybHpPbTVoYldWek9uUmpPbE5CVFV3Nk1pNHdPbkJ5YjNSdlkyOXNJaUJCYzNObGNuUnBiMjVEYjI1emRXMWxjbE5sY25acFkyVlZVa3c5SW1oMGRIQnpPaTh2WjJGc2FXeGxieTVsYm5SbGNuQnlhWE5sTG1sMGN5NW9ZWGRoYVdrdVpXUjFPalEwTXk5VFFVMU1NakF2VTFBdlFVTlRJaUJFWlhOMGFXNWhkR2x2YmowaWFIUjBjSE02THk5cFpIQXVhR0YzWVdscExtVmtkUzlwWkhBdmNISnZabWxzWlM5VFFVMU1NaTlRVDFOVUwxTlRUeUlnU1VROUlsOWlOVFJoTldRd1ltUXpOV1k0T1dVek1HVTVPV0U0WTJFeFpqZ3lPR0kwTXlJZ1NYTnpkV1ZKYm5OMFlXNTBQU0l5TURJekxUQTBMVEV5VkRJd09qTTBPalE0V2lJZ1VISnZkRzlqYjJ4Q2FXNWthVzVuUFNKMWNtNDZiMkZ6YVhNNmJtRnRaWE02ZEdNNlUwRk5URG95TGpBNlltbHVaR2x1WjNNNlNGUlVVQzFRVDFOVUlpQldaWEp6YVc5dVBTSXlMakFpUGp4ellXMXNPa2x6YzNWbGNpQjRiV3h1Y3pwellXMXNQU0oxY200NmIyRnphWE02Ym1GdFpYTTZkR002VTBGTlREb3lMakE2WVhOelpYSjBhVzl1SWo1b2RIUndjem92TDJkaGJHbHNaVzh1Wlc1MFpYSndjbWx6WlM1cGRITXVhR0YzWVdscExtVmtkVG8wTkRNdlUwRk5UREl3TDFOUVBDOXpZVzFzT2tsemMzVmxjajQ4TDNOaGJXeHdPa0YxZEdodVVtVnhkV1Z6ZEQ0PSIgLz4KPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iUmVsYXlTdGF0ZSIgdmFsdWU9IkUzVURBRTlQZ1dJM00yWXhaV013WkRrMk16UXdZekZrT1dJeU5XSmxZekkyWm1RMU5EZ3pZUT09IiAvPgo8L2Zvcm0+CjxzY3JpcHQ+CiAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ215Zm9ybScpLnN1Ym1pdCgpOwo8L3NjcmlwdD4KPC9ib2R5Pgo8L2h0bWw+DQo=</saml-request><region>172.16.0.0-172.31.255.255</region>
< </prelogin-response>
Destination form field prelogin-cookie was specified; assuming SAML POST authentication is complete.
Enter login credentials
POST https://vpn.example.edu/ssl-vpn/login.esp
> POST /ssl-vpn/login.esp HTTP/1.1
> Host: vpn.example.edu
> User-Agent: PAN GlobalProtect
> Cookie: CLIENTOS=TGludXg%3D; PHPSESSID=73f1ec0d96340c1d9b25bec26fd5483a
> X-Pad: 000000000000000000000000000000
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 290
>
> jnlpReady=jnlpReady&ok=Login&direct=yes&clientVer=4100&prot=https:&internal=no&ipv6-support=yes&clientos=Linux&os-version=linux-64&server=vpn.example.edu&computer=localhost-live&user=robin&prelogin-cookie=IozAXdCYvM0cAUJl8GgqtMD5t6cyRhO%2buqfBzPw7cuWaxP8AA9IoenDTKut1Dw0p
Got HTTP response: HTTP/1.1 200 OK
Date: Wed, 12 Apr 2023 20:34:48 GMT
Content-Type: application/xml; charset=UTF-8
Content-Length: 710
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
X-FRAME-OPTIONS: DENY
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Set-Cookie: PHPSESSID=4faa227a5ff5c9d541ee4f5298119102; path=/; secure; HttpOnly
Strict-Transport-Security: max-age=31536000;
X-XSS-Protection: 1; mode=block;
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (710)
< <?xml version="1.0" encoding="utf-8"?><jnlp><application-desc><argument>(null)</argument><argument>f5b078bdf420aad8307cce66cef960a8</argument><argument>c0a66a946ac8525989dbf9a53c78fe69c55dcb5f</argument><argument>Galileo-N</argument><argument>robin</argument><argument>UU-Shib-2022-10-16</argument><argument>vsys1</argument><argument>%28empty_domain%29</argument><argument>(null)</argument><argument></argument><argument></argument><argument></argument><argument>tunnel</argument><argument>-1</argument><argument>4100</argument><argument></argument><argument></argument><argument></argument><argument></argument><argument>4</argument><argument>unknown</argument><argument></argument></application-desc></jnlp>
GlobalProtect login returned authentication-source=UU-Shib-2022-10-16
GlobalProtect login returned usually-equals-4=4
GlobalProtect login returned usually-equals-unknown=unknown
POST https://vpn.example.edu/ssl-vpn/getconfig.esp
> POST /ssl-vpn/getconfig.esp HTTP/1.1
> Host: vpn.example.edu
> User-Agent: PAN GlobalProtect
> Cookie: CLIENTOS=TGludXg%3D; PHPSESSID=4faa227a5ff5c9d541ee4f5298119102
> X-Pad: 000000000000000
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 305
>
> client-type=1&protocol-version=p1&internal=no&app-version=5.1.5-8&ipv6-support=yes&clientos=Linux&os-version=linux-64&hmac-algo=sha1%2cmd5%2csha256&enc-algo=aes-128-cbc%2caes-256-cbc&authcookie=f5b078bDf420aad8307cce66cef960a8&portal=Galileo-N&user=robin&domain=%28empty_domain%29&computer=localhost-live
Got HTTP response: HTTP/1.1 200 OK
Date: Wed, 12 Apr 2023 20:34:48 GMT
Content-Type: application/xml; charset=UTF-8
Content-Length: 1598
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
X-FRAME-OPTIONS: DENY
Strict-Transport-Security: max-age=31536000;
X-XSS-Protection: 1; mode=block;
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (1598)
<
<     <response status="success">
<        <need-tunnel>yes</need-tunnel>
<        <ssl-tunnel-url>/ssl-tunnel-connect.sslvpn</ssl-tunnel-url>
<        <portal>Galileo-N</portal>
<        <user>robin</user>
<        <lifetime>2592000</lifetime>
<        <timeout>36000</timeout>
<        <disconnect-on-idle>36000</disconnect-on-idle>
<        <bw-c2s>1000</bw-c2s>
<        <bw-s2c>1000</bw-s2c>
<        <gw-address>xxx.xxx.xxx.131</gw-address>
<        <ipv6-connection>no</ipv6-connection>
<        <ip-address>172.19.100.218</ip-address>
<        <netmask>255.255.255.255</netmask>
<        <ip-address-preferred>yes</ip-address-preferred>
<        <dns>
<            <member>192.168.10.115</member>
<            <member>192.168.10.116</member>
<        </dns>
<        <wins>
<        </wins>
<        <dns-suffix>
<        </dns-suffix>
<        <default-gateway>172.19.100.218</default-gateway>
<        <mtu>0</mtu>
<        <no-direct-access-to-local-network>yes</no-direct-access-to-local-network>
<        <access-routes>
<            <member>0.0.0.0/0</member>
<        </access-routes>
<        <exclude-access-routes>
<        </exclude-access-routes>
<        <ipsec>
<            <udp-port>4501</udp-port>
<            <ipsec-mode>esp-tunnel</ipsec-mode>
<            <enc-algo>aes-128-cbc</enc-algo>
<            <hmac-algo>sha1</hmac-algo>
<            <c2s-spi>0x7B7BEC5C</c2s-spi>
<            <s2c-spi>0x3CD52B75</s2c-spi>
<            <akey-s2c>
<                <bits>160</bits>
<                <val>ae440bb83e19b53179a6ef554b19594ab8887c3e</val>
<            </akey-s2c>
<            <ekey-s2c>
<                <bits>128</bits>
<                <val>5eead07485fa9a3c5de93689074055d0</val>
<            </ekey-s2c>
<            <akey-c2s>
<                <bits>160</bits>
<                <val>8f1b533b94460bd88893fee11237064bf87add65</val>
<            </akey-c2s>
<            <ekey-c2s>
<                <bits>128</bits>
<                <val>c6eab7ece614546913ab2a3945a1ee8a</val>
<            </ekey-c2s>
<        </ipsec>
<     </response>
Tunnel timeout (rekey interval) is 600 minutes.
Idle timeout is 600 minutes.
TCP_INFO rcv mss 1460, snd mss 1460, adv mss 1460, pmtu 1500
No MTU received. Calculated 1422 for ESP tunnel
POST https://vpn.example.edu/ssl-vpn/hipreportcheck.esp
> POST /ssl-vpn/hipreportcheck.esp HTTP/1.1
> Host: vpn.example.edu
> User-Agent: PAN GlobalProtect
> Cookie: CLIENTOS=TGludXg%3D; PHPSESSID=4faa227a5ff5c9d541ee4f5298119102
> X-Pad: 0000000000000000000000000000000000000000
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 216
>
> client-role=global-protect-full&authcookie=f5b078bdf420aad8307cce66cef960a8&portal=Galileo-N&user=robin&domain=%28empty_domain%29&computer=localhost-live&client-ip=172.19.100.218&md5=e1de480752cda1113aa2a513022e646a
Got HTTP response: HTTP/1.1 200 OK
Date: Wed, 12 Apr 2023 20:34:48 GMT
Content-Type: application/xml; charset=UTF-8
Content-Length: 107
Connection: keep-alive
X-Content-Type-Options: nosniff
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Security-Policy: default-src 'self'
Expires: Thu, 19 Nov 1981 08:52:00 GMT
X-FRAME-OPTIONS: DENY
Strict-Transport-Security: max-age=31536000;
X-XSS-Protection: 1; mode=block;
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (107)
<
<     <response status="success">
<        <hip-report-needed>yes</hip-report-needed>
<        <delay>0</delay>
<     </response>
Gateway says HIP report submission is needed.
WARNING: Server asked us to submit HIP report with md5sum e1de480752cda1113aa2a513022e646a.
    VPN connectivity may be disabled or limited without HIP report submission.
    You need to provide a --csd-wrapper argument with the HIP report submission script.
Send ESP probes
UDP SO_SNDBUF: 28440
ESP session established with server
ESP tunnel connected; exiting HTTPS mainloop.
Configured as 172.19.100.218, with SSL disconnected and ESP established
Session authentication will expire at Fri May 12 10:34:48 2023

Not using vhost-net due to low queue length 10
Send ESP probes for DPD
Send ESP probes for DPD
[...]

✔️ Scenario 1 is successful.

Scenario 2: I instead follow the additional steps in the README.md

I perform this sequence of commands:

eval $( gp-saml-gui -v --allow-insecure-crypto --gateway --clientos=Linux vpn.example.edu -- -v --dump-http-traffic)
echo $HOST; echo $USER; echo $COOKIE; echo $OS
echo "$COOKIE" | sudo openconnect --protocol=gp -u "$USER" --os="$OS" --passwd-on-stdin "$HOST" -v --dump-http-traffic
$ eval $( gp-saml-gui -v --allow-insecure-crypto --gateway --clientos=Linux vpn.example.edu -- -v --dump-http-traffic)
Looking for SAML auth tags in response to https://vpn.example.edu/ssl-vpn/prelogin.esp...
Got SAML POST, opening browser...
[REQUEST] Request for resource about:blank
[PAGE   ] Finished loading page about:blank
[REQUEST] POST for resource https://idp.example.edu/idp/profile/SAML2/POST/SSO
[REQUEST] GET for resource https://idp.example.edu/idp/css/main.css
[PAGE   ] Finished loading page https://idp.example.edu/idp/profile/SAML2/POST/SSO?execution=e1s1
[REQUEST] POST for resource https://idp.example.edu/idp/profile/SAML2/POST/SSO?execution=e1s1
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/normalize.css/8.0.1/normalize.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/bootstrap/5.1.3/css/bootstrap-grid.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/material-components-web/13.0.0/dist/material-components-web.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/mdi__font/6.2.95/css/materialdesignicons.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/css/cas.css
[REQUEST] GET for resource https://cdnjs.cloudflare.com/ajax/libs/core-js/3.21.1/minified.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/jquery/3.6.0/jquery.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/es5-shim/4.5.9/es5-shim.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/css-vars-ponyfill/2.4.7/dist/css-vars-ponyfill.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/material-components-web/13.0.0/dist/material-components-web.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/js/cas.js
[REQUEST] GET for resource https://authn.example.edu/cas/images/uh_seal.png
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/mdi__font/6.2.95/fonts/materialdesignicons-webfont.woff2?v=6.2.95
[PAGE   ] Finished loading page https://authn.example.edu/cas/login?service=https%3A%2F%2Fidp.example.edu%2Fidp%2FAuthn%2FExternal%3Fconversation%3De1s2&entityId=https%3A%2F%2Fvpn.example.edu%3A443%2FSAML20%2FSP
[REQUEST] POST for resource https://authn.example.edu/cas/login?service=https%3A%2F%2Fidp.example.edu%2Fidp%2FAuthn%2FExternal%3Fconversation%3De1s2&entityId=https%3A%2F%2Fvpn.example.edu%3A443%2FSAML20%2FSP
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/normalize.css/8.0.1/normalize.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/bootstrap/5.1.3/css/bootstrap-grid.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/material-components-web/13.0.0/dist/material-components-web.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/mdi__font/6.2.95/css/materialdesignicons.min.css
[REQUEST] GET for resource https://authn.example.edu/cas/css/cas.css
[REQUEST] GET for resource https://cdnjs.cloudflare.com/ajax/libs/core-js/3.21.1/minified.js
[REQUEST] GET for resource https://authn.example.edu/cas/js/duo/Duo-Web-v2.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/jquery/3.6.0/jquery.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/es5-shim/4.5.9/es5-shim.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/css-vars-ponyfill/2.4.7/dist/css-vars-ponyfill.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/webjars/material-components-web/13.0.0/dist/material-components-web.min.js
[REQUEST] GET for resource https://authn.example.edu/cas/js/cas.js
[PAGE   ] Finished loading page https://authn.example.edu/cas/login?service=https%3A%2F%2Fidp.example.edu%2Fidp%2FAuthn%2FExternal%3Fconversation%3De1s2&entityId=https%3A%2F%2Fvpn.example.edu%3A443%2FSAML20%2FSP
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/web/v1/auth?tx=TX|bWVhZGVyfERJUjNYRTA0WEY2UEtJVFdVOEJFfDE2ODEzMzE1NjA=|54a73ba8e71ad618e3c24dd1562370cd4b52740e&parent=https%3A%2F%2Fauthn.example.edu%2Fcas%2Flogin%3Fservice%3Dhttps%253A%252F%252Fidp.example.edu%252Fidp%252FAuthn%252FExternal%253Fconversation%253De1s2%26entityId%3Dhttps%253A%252F%252Fvpn.example.edu%253A443%252FSAML20%252FSP&v=2.6
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/css/v3/base.css?v=39c22
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/plugin-detect/plugin-detect.min.css?v=01376
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery-prologue.js?v=400dc
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery.min.js?v=ff152
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/lib/jquery-postmessage.min.js?v=98c73
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/plugin-detect/plugin-detect.min.js?v=6a394
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/page/preauth.js?v=154e6
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery-epilogue.js?v=c4ac5
[REQUEST] POST for resource https://api-16a593a9.duosecurity.com/frame/web/v1/auth?tx=TX|bWVhZGVyfERJUjNYRTA0WEY2UEtJVFdVOEJFfDE2ODEzMzE1NjA=|54a73ba8e71ad618e3c24dd1562370cd4b52740e&parent=https%3A%2F%2Fauthn.example.edu%2Fcas%2Flogin%3Fservice%3Dhttps%253A%252F%252Fidp.example.edu%252Fidp%252FAuthn%252FExternal%253Fconversation%253De1s2%26entityId%3Dhttps%253A%252F%252Fvpn.example.edu%253A443%252FSAML20%252FSP&v=2.6
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/css/normalize.css?v=a674e
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/fonts/ss-standard/ss-standard.css?v=a8885
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/css/fonts/duo-admin.css?v=50a8a
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/css/v3/base.css?v=39c22
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/css/tipsy.css?v=4217a
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/logo?sid=NDdhZWEyZTIzM2JhNGY2YWE2ZmRlZjViYWFkMmI2ZmU=|1681331261|5c92744d25ced35870eb7f27e1fdedb93ee8eb55
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery-prologue.js?v=400dc
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery.min.js?v=ff152
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/he/he.min.js?v=aaa33
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/lib/jquery-postmessage.min.js?v=98c73
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/lodash/lodash.min.js?v=6585f
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/backbone/backbone-min.js?v=e0ff6
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/page/v3/frame.js?v=4baee
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/page/v3/base.js?v=a2248
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/validator/validator.min.js?v=9a068
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/lib/jquery/jquery-epilogue.js?v=c4ac5
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/shared/js/errors.js?v=d10d2
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/lib/jquery.tipsy.js?v=c0432
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/js/page/v3/prompt.js?v=72a73
[REQUEST] GET for resource https://api-16a593a9.duosecurity.com/frame/static/fonts/duo-admin/duo-admin.woff
[REQUEST] POST for resource https://api-16a593a9.duosecurity.com/frame/prompt
[REQUEST] POST for resource https://api-16a593a9.duosecurity.com/frame/status
[REQUEST] POST for resource https://api-16a593a9.duosecurity.com/frame/status
[REQUEST] POST for resource https://api-16a593a9.duosecurity.com/frame/status/f2709a8a-74ec-4364-abee-72a10f868cab
[REQUEST] POST for resource https://authn.example.edu/cas/login?service=https%3A%2F%2Fidp.example.edu%2Fidp%2FAuthn%2FExternal%3Fconversation%3De1s2&entityId=https%3A%2F%2Fvpn.example.edu%3A443%2FSAML20%2FSP
[PAGE   ] Finished loading page https://idp.example.edu/idp/profile/SAML2/POST/SSO?execution=e1s2&_eventId_proceed=1
[REQUEST] POST for resource https://vpn.example.edu/SAML20/SP/ACS
[PAGE   ] Finished loading page https://vpn.example.edu/SAML20/SP/ACS
[SAML   ] Got SAML result headers: {'saml-username': 'robin', 'prelogin-cookie': 'nwVS4PPxKnf27rwRK7BS0GE7qaDoKT9aJprkOc2Ks1cPWYbAXWZdSO7BjUV68v0j', 'saml-slo': 'no', 'saml-auth-status': '1'}
[DATA   ] 249 bytes of text/html; charset=UTF-8 for resource https://vpn.example.edu/SAML20/SP/ACS
Date: Wed, 12 Apr 2023 20:27:48 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 249
Connection: keep-alive
ETag: "1c86624bf152"
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block;
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
saml-username: robin
prelogin-cookie: nwVS4pPxKnf27rwRK7BS0GE7qaDoKT9aJprkOc2Ks1cPWYbAXWZdSO7BjUV68v0j
saml-slo: no
saml-auth-status: 1
Strict-Transport-Security: max-age=31536000;

<html><body>Login Successful!</body><!-- <saml-auth-status>1</saml-auth-status><prelogin-cookie>nwVS4pPxKnf27rwRK7BS0GE7qaDoKT9aJprkOc2Ks1cPWYbAXWZdSO7BjUV68v0j</prelogin-cookie><saml-username>robin</saml-username><saml-slo>no</saml-slo> --></html>
[SAML   ] Got all required SAML headers, done.

SAML response converted to OpenConnect command line invocation:

    echo nwVS4pPxKnf27rwRK7BS0GE7qaDoKT9aJprkOc2Ks1cPWYbAXWZdSO7BjUV68v0j |
        sudo openconnect --protocol=gp '--useragent=PAN GlobalProtect' --allow-insecure-crypto --user=robin --os=linux-64 --usergroup=gateway:prelogin-cookie --passwd-on-stdin vpn.example.edu -v --dump-http-traffic

SAML response converted to test-globalprotect-login.py invocation:

    test-globalprotect-login.py --user=robin --clientos=Linux -p '' \
        https://vpn.example.edu/ssl-vpn/login.esp prelogin-cookie=nwVS4PPxKnf27rwRK7BS0GE7qaDoKT9aJprkOc2Ks1cPWYbAXWZdSO7BjUV68v0j
$ echo $HOST; echo $USER; echo $COOKIE; echo $OS
https://vpn.example.edu/ssl-vpn/login.esp:prelogin-cookie
robin
nwVS4PPxKnf27rwRK7BS0GE7qaDoKT9aJprkOc2Ks1cPWYbAXWZdSO7BjUV68v0j
linux-64
$ echo "$COOKIE" | sudo openconnect --protocol=gp -u "$USER" --os="$OS" --passwd-on-stdin "$HOST" -v --dump-http-traffic
[sudo] password for robin:                                                     
POST https://vpn.example.edu/ssl-vpn/login.esp                                 
Attempting to connect to server xxx.xxx.xxx.131:443                            
Connected to xxx.xxx.xxx.131:443                                               
SSL negotiation with vpn.example.edu                                           
Connected to HTTPS on vpn.example.edu with ciphersuite (TLS1.2)-(RSA)-(AES-256-GCM)
> POST /ssl-vpn/login.esp HTTP/1.1                                             
> Host: vpn.example.edu                                                        
> User-Agent: PAN GlobalProtect                                                
>                                                                              
Got HTTP response: HTTP/1.1 200 OK                                             
Date: Wed, 12 Apr 2023 20:29:33 GMT                                            
Content-Type: text/html; charset=UTF-8                                         
Content-Length: 71                                                             
Connection: keep-alive                                                         
Pragma: no-cache                                                               
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0  
Expires: Thu, 19 Nov 1981 08:52:00 GMT                                         
X-FRAME-OPTIONS: DENY                                                          
Set-Cookie: PHPSESSID=929009082e6cd5a88ac0b619a743d815; secure; HttpOnly       
Strict-Transport-Security: max-age=31536000;                                   
X-XSS-Protection: 1; mode=block;                                               
X-Content-Type-Options: nosniff                                                
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (71)                                                        
<                                                                              
< var respStatus = "";                                                         
< var respMsg = "";                                                            
< thisForm.inputStr.value = "";                                                
<                                                                              
Failed to parse server response                                                
Response was:                                                                  
var respStatus = "";                                                           
var respMsg = "";                                                              
thisForm.inputStr.value = "";                                                  

Failed to complete authentication                                              
robin-a-meade commented 1 year ago

My openconnect agrees with your statement that these two command invocations should result in the same output:

openconnect --prot=gp --dump -u test --usergroup gateway:prelogin-cookie https://localhost
openconnect --prot=gp --dump -u test https://localhost/gateway:prelogin-cookie
$ openconnect --prot=gp --dump -u test --usergroup gateway:prelogin-cookie https://localhost
POST https://localhost/ssl-vpn/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Linux
Attempting to connect to server [::1]:443
Failed to connect to [::1]:443: Connection refused
Attempting to connect to server 127.0.0.1:443
Failed to connect to 127.0.0.1:443: Connection refused
Failed to connect to host localhost
Failed to open HTTPS connection to localhost
Failed to complete authentication

$ openconnect --prot=gp --dump -u test https://localhost/gateway:prelogin-cookie
POST https://localhost/ssl-vpn/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Linux
Attempting to connect to server [::1]:443
Failed to connect to [::1]:443: Connection refused
Attempting to connect to server 127.0.0.1:443
Failed to connect to 127.0.0.1:443: Connection refused
Failed to connect to host localhost
Failed to open HTTPS connection to localhost
Failed to complete authentication
robin-a-meade commented 1 year ago

If I modify the HOST variable, replacing ssl-vpn/login.esp with gateway, it works:

eval $( gp-saml-gui -v --allow-insecure-crypto --gateway --clientos=Linux vpn.example.edu -- -v --dump-http-traffic)
echo $HOST # https://vpn.example.edu/ssl-vpn/login.esp:prelogin-cookie
HOST=https://vpn.example.edu/gateway:prelogin-cookie
echo "$COOKIE" | sudo openconnect --protocol=gp -u "$USER" --os="$OS" --passwd-on-stdin "$HOST" -v --dump-http-traffic
dlenski commented 1 year ago

:man_facepalming:

@robin-a-meade Here is the problem/difference:

So, basically, gp-saml-gui's "scenario 2" output has been incompatible with OpenConnect since v8.20 :sweat:

dlenski commented 1 year ago

70b4c9a should fix this, and thank you for the doggedly detailed diffs… which finally got through my thick skull to show me what had been wrong. :grimacing:

robin-a-meade commented 1 year ago

Oh, interesting! Thank you @dlenski ! I successfully tested. It works great!

dlenski commented 1 year ago

Thanks for making this software better :muscle:

We have a fake GlobalProtect server written in Python which we test OpenConnect against. Not only can it do most of the non-SAML authentication modes (of which there are waaaay too many :dizzy_face:), but as of 64a0ba69 it can also do SAML:

This allows authenticating to the fake server with https://github.com/dlenski/gp-saml-gui

# Start fake server
$ ./fake-gp-server localhost 8080 certs/server-{cert,key}.pem 2>&1 >/dev/null &

# Configure fake server for SAML on the portal interface
$ curl -sk https://localhost:8080/CONFIGURE -d portal_saml=portal-userauthcookie -d portal_cookie=portal-userauthcookie

# Use gp-saml-gui to authenticate to it
$ gp-saml-gui --no-verify localhost:8080
...
... pops up window
... fills out login form
...
HOST=https://localhost:8080/global-protect/getconfig.esp:portal-userauthcookie
USER=nobody
COOKIE=FAKE_username_nobody_password_whatever
OS=linux-64

If anyone wants to improve this repository to pull in the fake-gp-server.py and automatically test against it, I'd be grateful for that contribution :grimacing: