From 66438abc7cf5d17c1093610266fcc9b8319cd9d6 Mon Sep 17 00:00:00 2001 From: Daniel Lenski Date: Sun, 22 Mar 2020 23:19:21 -0700 Subject: [PATCH] include clientos in output command-lines and environment variables --- README.md | 18 +++++++++++------- gp-saml-gui.py | 20 +++++++++++--------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index aa94778..03d7d66 100644 --- a/README.md +++ b/README.md @@ -32,16 +32,19 @@ $ pip install requests How to use ========== -Specify the GlobalProtect server URL (portal or gateway) and optional arguments. +Specify the GlobalProtect server URL (portal or gateway) and optional +arguments, such as `--clientos=Windows` (because many GlobalProtect +servers don't require SAML login, but apparently omit it in their configuration +for OSes other than Windows). This script will pop up a [GTK WebKit2 WebView](https://webkitgtk.org/) window. After you succesfully complete the SAML login via web forms, the script will output -`HOST`, `USER`, and `COOKIE` variables in a form that can be used by +`HOST`, `USER`, `COOKIE`, and `OS` variables in a form that can be used by [OpenConnect](http://www.infradead.org/openconnect/juniper.html) (similar to the output of `openconnect --authenticate`): ```sh -$ eval $( gp-saml-gui.py -v vpn.company.com ) +$ eval $( gp-saml-gui.py --clientos=Windows vpn.company.com ) Got SAML POST content, opening browser... Finished loading about:blank... Finished loading https://company.okta.com/app/panw_globalprotect/deadbeefFOOBARba1234/sso/saml... @@ -52,14 +55,15 @@ Got SAML relevant headers, done: {'prelogin-cookie': 'blahblahblah', 'saml-usern SAML response converted to OpenConnect command line invocation: echo 'blahblahblah' | - openconnect --protocol=gp --user='foo12345@corp.company.com' --usergroup=prelogin-cookie:gateway --passwd-on-stdin vpn.company.com + 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 $HOST; echo $USER; echo $COOKIE; echo $OS https://vpn.company.com/gateway:prelogin-cookie foo12345@corp.company.com -blahblahblah' +blahblahblah +win -$ echo "$COOKIE" | openconnect --protocol=gp -u "$USER" --passwd-on-stdin "$HOST" +$ echo "$COOKIE" | openconnect --protocol=gp -u "$USER" --os="$OS" --passwd-on-stdin "$HOST" ``` TODO diff --git a/gp-saml-gui.py b/gp-saml-gui.py index 4029a09..09f0faa 100755 --- a/gp-saml-gui.py +++ b/gp-saml-gui.py @@ -122,8 +122,9 @@ class SAMLLoginView: Gtk.main_quit() def parse_args(args = None): - clientos_map = dict(linux='Linux', darwin='Mac', win32='Windows', cygwin='Windows') - default_clientos = clientos_map.get(platform, 'Windows') + pf2clientos = dict(linux='Linux', darwin='Mac', win32='Windows', cygwin='Windows') + clientos2ocos = dict(Linux='linux-64', Mac='mac-intel', Windows='win') + default_clientos = pf2clientos.get(platform, 'Windows') p = argparse.ArgumentParser() p.add_argument('server', help='GlobalProtect server (portal or gateway)') @@ -145,10 +146,11 @@ def parse_args(args = None): g.add_argument('-v','--verbose', default=0, action='count') g.add_argument('-x','--external', action='store_true', help='Launch external browser (for debugging)') g.add_argument('-u','--uri', action='store_true', help='Treat server as the complete URI of the SAML entry point, rather than GlobalProtect server') - g.add_argument('--clientos', choices=set(clientos_map.values()), default=default_clientos, help="clientos value to send (default is %(default)s)") + g.add_argument('--clientos', choices=set(pf2clientos.values()), default=default_clientos, help="clientos value to send (default is %(default)s)") p.add_argument('extra', nargs='*', help='Extra form field(s) to pass to include in the login query string (e.g. "magic-cookie-value=deadbeef01234567")') args = p.parse_args(args = None) + args.ocos = clientos2ocos[args.clientos] args.extra = dict(x.split('=', 1) for x in args.extra) if args.cookies: @@ -261,14 +263,14 @@ if __name__ == "__main__": '''that's associated with the {} interface. You should probably try both.\n'''.format(args.interface, ifh), file=stderr) print('''\nSAML response converted to OpenConnect command line invocation:\n''', file=stderr) - print(''' echo {} |\n openconnect --protocol=gp --user={} --usergroup={}:{} --passwd-on-stdin {}'''.format( - quote(cv), quote(un), quote(ifh), quote(cn), quote(server)), file=stderr) + print(''' echo {} |\n openconnect --protocol=gp --user={} --os={} --usergroup={}:{} --passwd-on-stdin {}'''.format( + quote(cv), quote(un), quote(args.ocos), quote(ifh), quote(cn), quote(server)), file=stderr) print('''\nSAML response converted to test-globalprotect-login.py invocation:\n''', file=stderr) - print(''' test-globalprotect-login.py --user={} -p '' \\\n https://{}/{} {}={}\n'''.format( - quote(un), quote(server), quote(if2auth[ifh]), quote(cn), quote(cv)), file=stderr) + print(''' test-globalprotect-login.py --user={} --clientos={} -p '' \\\n https://{}/{} {}={}\n'''.format( + quote(un), quote(args.clientos), quote(server), quote(if2auth[ifh]), quote(cn), quote(cv)), file=stderr) varvals = { - 'HOST': quote('https://%s/%s:%s' % (server, if2auth[ifh], cn)), - 'USER': quote(un), 'COOKIE': quote(cv), + 'HOST': quote('https://%s/%s:%s' % (server, if2auth[args.interface], cn)), + 'USER': quote(un), 'COOKIE': quote(cv), 'OS': quote(args.ocos), } print('\n'.join('%s=%s' % pair for pair in varvals.items())) -- 2.39.5