From: Benjamin Mako Hill Date: Wed, 28 Jun 2023 18:59:51 +0000 (-0700) Subject: updated to new version fo gp-saml-gui and new api X-Git-Url: https://code.communitydata.science/nu-vpn-proxy.git/commitdiff_plain/2970f2c70235c88029d3248c6c47ac0ecb6718c4?hp=4bb6708dc1c336cd29766d3094bfd053181a6aa3 updated to new version fo gp-saml-gui and new api Apparently new versions of GP hav changed the SAML API some. The openconnect command now requires --gateway so this has been added. I haven't tested the general and http scripts but I assume they work. Someone else should verify. --- diff --git a/README-GP-SAML.md b/README-GP-SAML.md index 1bc0d20..12e851a 100644 --- a/README-GP-SAML.md +++ b/README-GP-SAML.md @@ -1,18 +1,45 @@ -[![Build Status](https://api.travis-ci.org/dlenski/gp-saml-gui.png)](https://travis-ci.org/dlenski/gp-saml-gui) - gp-saml-gui =========== +[![Test Workflow Status](https://github.com/dlenski/gp-saml-gui/workflows/build/badge.svg)](https://github.com/dlenski/gp-saml-gui/actions/workflows/test.yml) + +Table of Contents +================= + + * [Introduction](#introduction) + * [Installation](#installation) + * [First, non-Python Dependencies](#first-non-python-dependencies) + * [Second, gp-saml-gui itself](#second-gp-saml-gui-itself) + * [How to use](#how-to-use) + * [Extra arguments to OpenConnect](#extra-arguments-to-openconnect) + * [License](#license) + +Introduction +============ + This is a helper script to allow you to interactively login to a GlobalProtect VPN -that uses SAML authentication. +that uses [SAML](https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language) +authentication, so that you can subsequently connect with [OpenConnect](https://www.infradead.org/openconnect). +(The GlobalProtect protocol is supported in OpenConnect v8.0 or newer; v8.06+ is recommended.) Interactive login is, unfortunately, sometimes a necessary alternative to automated login via scripts such as [zdave/openconnect-gp-okta](https://github.com/zdave/openconnect-gp-okta). +This script is known to work with many GlobalProtect VPNs using the major single-sign-on (SSO) providers: + +- Okta (sign-in URLs typically `https://.okta.com/login/*`) +- Microsoft (sign-in URLs typically `https://login.microsoftonline.com/*`) + +Please search and file [issues](https://github.com/dlenski/gp-saml-gui/issues) if you can report success +or failure with other SSO SAML providers. + Installation ============ +First, non-Python Dependencies +------------------------------ + gp-saml-gui uses GTK, which requires Python 3 bindings. On Debian / Ubuntu, these are packaged as `python3-gi`, `gir1.2-gtk-3.0`, and @@ -22,13 +49,34 @@ On Debian / Ubuntu, these are packaged as `python3-gi`, `gir1.2-gtk-3.0`, and $ sudo apt install python3-gi gir1.2-gtk-3.0 gir1.2-webkit2-4.0 ``` -Then, set up a virtual environment that can access these system packages, -activate it, and install the Python dependencies: +On Fedora (and possibly RHEL/CentOS) the matching libraries are packaged in +`python3-gobject`, `gtk3-devel`, and `webkit2gtk3-devel`: ``` -$ virtualenv --python=python3 --system-site-packages venv -$ . venv/bin/activate -$ pip install requests +$ sudo dnf install python3-gobject gtk3-devel webkit2gtk3-devel +``` + +On Arch Linux, the libraries are packaged in `gtk3`, `gobject-introspection` +and `webkit2gtk`: + +``` +$ sudo pacman -S gtk3 gobject-introspection webkit2gtk +``` + +Second, gp-saml-gui itself +-------------------------- + +Install gp-saml-gui itself using `pip`: + +``` +$ pip3 install https://github.com/dlenski/gp-saml-gui/archive/master.zip +... +$ gp-saml-gui +usage: gp-saml-gui [-h] [--no-verify] [-C COOKIES | -K] [-p | -g] [-c CERT] + [--key KEY] [-v | -q] [-x | -P | -S] [-u] + [--clientos {Windows,Linux,Mac}] [-f EXTRA] + server [openconnect_extra [openconnect_extra ...]] +gp-saml-gui: error: the following arguments are required: server, openconnect_extra ``` How to use @@ -39,14 +87,15 @@ 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 +This script will pop up a [GTK WebKit2 WebView](https://webkitgtk.org/) window +alongside your terminal window (see this [screenshot](screenshot.png)). +After you successfully complete the SAML login via web forms, the script will output `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 --clientos=Windows vpn.company.com ) +$ eval $( gp-saml-gui --gateway --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... @@ -57,7 +106,7 @@ 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' --os=win --usergroup=prelogin-cookie:gateway --passwd-on-stdin vpn.company.com + openconnect --protocol=gp --user='foo12345@corp.company.com' --os=win --usergroup=gateway:prelogin-cookie --passwd-on-stdin vpn.company.com $ echo $HOST; echo $USER; echo $COOKIE; echo $OS https://vpn.company.com/gateway:prelogin-cookie @@ -68,10 +117,24 @@ win $ echo "$COOKIE" | openconnect --protocol=gp -u "$USER" --os="$OS" --passwd-on-stdin "$HOST" ``` -TODO -==== +If you specify either the `-P`/`--pkexec-openconnect` or `-S`/`--sudo-openconnect` options, the script +will automatically invoke OpenConnect as described, using either [`pkexec` from Polkit](https://www.freedesktop.org/software/polkit/docs/0.106/polkit.8.html) +or [`sudo`](https://www.sudo.ws/), as specified. + +# Extra Arguments to OpenConnect + +Extra arguments needed for OpenConnect can be specified by adding ` -- ` to the command line, and then +appending these. For example: -* Packaging +```sh +$ gp-saml-gui -P --gateway --clientos=Windows vpn.company.com -- --csd-wrapper=hip-report.sh +… +Launching OpenConnect with pkexec, equivalent to: + echo blahblahblahlongrandomcookievalue | + sudo openconnect --protocol=gp --user=foo12345@corp.company.com --os=win --usergroup=gateway:prelogin-cookie --passwd-on-stdin vpn.company.com + + +``` License ======= diff --git a/gp-saml-gui.py b/gp-saml-gui.py index b702d0c..f540a3b 100755 --- a/gp-saml-gui.py +++ b/gp-saml-gui.py @@ -2,34 +2,51 @@ try: import gi + gi.require_version('Gtk', '3.0') + gi.require_version('WebKit2', '4.0') + from gi.repository import Gtk, WebKit2, GLib except ImportError: try: import pgi as gi + gi.require_version('Gtk', '3.0') + gi.require_version('WebKit2', '4.0') + from pgi.repository import Gtk, WebKit2, GLib except ImportError: gi = None if gi is None: raise ImportError("Either gi (PyGObject) or pgi module is required.") import argparse -import pprint -import urllib +import urllib3 import requests import xml.etree.ElementTree as ET import ssl +import tempfile from operator import setitem -from os import path +from os import path, dup2, execvp from shlex import quote from sys import stderr, platform from binascii import a2b_base64, b2a_base64 from urllib.parse import urlparse, urlencode +from html.parser import HTMLParser + + +class CommentHtmlParser(HTMLParser): + def __init__(self): + super().__init__() + self.comments = [] + + def handle_comment(self, data: str) -> None: + self.comments.append(data) + + +COOKIE_FIELDS = ('prelogin-cookie', 'portal-userauthcookie') -gi.require_version('Gtk', '3.0') -gi.require_version('WebKit2', '4.0') -from gi.repository import Gtk, WebKit2, GLib class SAMLLoginView: - def __init__(self, uri, html=None, verbose=False, cookies=None, verify=True): + def __init__(self, uri, html=None, verbose=False, cookies=None, verify=True, user_agent=None): + Gtk.init(None) window = Gtk.Window() # API reference: https://lazka.github.io/pgi-docs/#WebKit2-4.0 @@ -40,20 +57,26 @@ class SAMLLoginView: self.verbose = verbose self.ctx = WebKit2.WebContext.get_default() - if not args.verify: + if not verify: self.ctx.set_tls_errors_policy(WebKit2.TLSErrorsPolicy.IGNORE) self.cookies = self.ctx.get_cookie_manager() - if args.cookies: + if cookies: self.cookies.set_accept_policy(WebKit2.CookieAcceptPolicy.ALWAYS) - self.cookies.set_persistent_storage(args.cookies, WebKit2.CookiePersistentStorage.TEXT) + self.cookies.set_persistent_storage(cookies, WebKit2.CookiePersistentStorage.TEXT) self.wview = WebKit2.WebView() + if user_agent is None: + user_agent = 'PAN GlobalProtect' + settings = self.wview.get_settings() + settings.set_user_agent(user_agent) + self.wview.set_settings(settings) + window.resize(500, 500) window.add(self.wview) window.show_all() window.set_title("SAML Login") window.connect('delete-event', self.close) - self.wview.connect('load-changed', self.get_saml_headers) + self.wview.connect('load-changed', self.on_load_changed) self.wview.connect('resource-load-started', self.log_resources) if html: @@ -93,42 +116,111 @@ class SAMLLoginView: if charset or content_type.startswith('text/'): print(data.decode(charset or 'utf-8'), file=stderr) - def get_saml_headers(self, webview, event): + def on_load_changed(self, webview, event): if event != WebKit2.LoadEvent.FINISHED: return mr = webview.get_main_resource() uri = mr.get_uri() rs = mr.get_response() - h = rs.get_http_headers() + h = rs.get_http_headers() if rs else None + ct = h.get_content_type() + if self.verbose: print('[PAGE ] Finished loading page %s' % uri, file=stderr) - if not h: - return # convert to normal dict d = {} - h.foreach(lambda k, v: setitem(d, k, v)) + h.foreach(lambda k, v: setitem(d, k.lower(), v)) # filter to interesting headers - fd = {name:v for name, v in d.items() if name.startswith('saml-') or name in ('prelogin-cookie', 'portal-userauthcookie')} - if fd and self.verbose: - print("[SAML ] Got SAML result headers: %r" % fd, file=stderr) + fd = {name: v for name, v in d.items() if name.startswith('saml-') or name in COOKIE_FIELDS} + + if fd: + if self.verbose: + print("[SAML ] Got SAML result headers: %r" % fd, file=stderr) + if self.verbose > 1: + # display everything we found + mr.get_data(None, self.log_resource_text, ct[0], ct.params.get('charset'), d) + self.saml_result.update(fd, server=urlparse(uri).netloc) + self.check_done() + + if not self.success: if self.verbose > 1: - # display everything we found - ct = h.get_content_type() - mr.get_data(None, self.log_resource_text, ct[0], ct.params.get('charset'), d) + print("[SAML ] No headers in response, searching body for xml comments", file=stderr) + # asynchronous call to fetch body content, continue processing in callback: + mr.get_data(None, self.response_callback, ct) + + def response_callback(self, resource, result, ct): + data = resource.get_data_finish(result) + content = data.decode(ct.params.get("charset") or "utf-8") + + html_parser = CommentHtmlParser() + html_parser.feed(content) - # check if we're done - self.saml_result.update(fd, server=urlparse(uri).netloc) - GLib.timeout_add(1000, self.check_done) + fd = {} + for comment in html_parser.comments: + if self.verbose > 1: + print("[SAML ] Found comment in response body: '%s'" % comment, file=stderr) + try: + # xml parser requires valid xml with a single root tag, but our expected content + # is just a list of data tags, so we need to improvise + xmlroot = ET.fromstring("%s" % comment) + # search for any valid first level xml tags (inside our fake root) that could contain SAML data + for elem in xmlroot: + if elem.tag.startswith("saml-") or elem.tag in COOKIE_FIELDS: + fd[elem.tag] = elem.text + except ET.ParseError: + pass # silently ignore any comments that don't contain valid xml + + if self.verbose > 1: + print("[SAML ] Finished parsing response body for %s" % resource.get_uri(), file=stderr) + if fd: + if self.verbose: + print("[SAML ] Got SAML result tags: %s" % fd, file=stderr) + self.saml_result.update(fd, server=urlparse(resource.get_uri()).netloc) + + if not self.check_done(): + # Work around timing/race condition by retrying check_done after 1 second + GLib.timeout_add(1000, self.check_done) def check_done(self): d = self.saml_result if 'saml-username' in d and ('prelogin-cookie' in d or 'portal-userauthcookie' in d): - if args.verbose: + if self.verbose: print("[SAML ] Got all required SAML headers, done.", file=stderr) self.success = True Gtk.main_quit() + return True + + +class TLSAdapter(requests.adapters.HTTPAdapter): + '''Adapt to older TLS stacks that would raise errors otherwise. + + We try to work around different issues: + * Enable weak ciphers such as 3DES or RC4, that have been disabled by default + in OpenSSL 3.0 or recent Linux distributions. + * Enable weak Diffie-Hellman key exchange sizes. + * Enable unsafe legacy renegotiation for servers without RFC 5746 support. + + See Also + -------- + https://github.com/psf/requests/issues/4775#issuecomment-478198879 + + Notes + ----- + Python is missing an ssl.OP_LEGACY_SERVER_CONNECT constant. + We have extracted the relevant value from . + + ''' + def init_poolmanager(self, connections, maxsize, block=False): + ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + ssl_context.set_ciphers('DEFAULT:@SECLEVEL=1') + ssl_context.options |= 1<<2 # OP_LEGACY_SERVER_CONNECT + self.poolmanager = urllib3.PoolManager( + num_pools=connections, + maxsize=maxsize, + block=block, + ssl_context=ssl_context) def parse_args(args = None): pf2clientos = dict(linux='Linux', darwin='Mac', win32='Windows', cygwin='Windows') @@ -144,10 +236,10 @@ def parse_args(args = None): x.add_argument('-K', '--no-cookies', dest='cookies', action='store_const', const=None, help="Don't use or store cookies at all") x = p.add_mutually_exclusive_group() - x.add_argument('-p','--portal', dest='interface', action='store_const', const='portal', default='gateway', - help='SAML auth to portal') - x.add_argument('-g','--gateway', dest='interface', action='store_const', const='gateway', - help='SAML auth to gateway (default)') + x.add_argument('-g','--gateway', dest='interface', action='store_const', const='gateway', default='portal', + help='SAML auth to gateway') + x.add_argument('-p','--portal', dest='interface', action='store_const', const='portal', + help='SAML auth to portal (default)') g = p.add_argument_group('Client certificate') g.add_argument('-c','--cert', help='PEM file containing client certificate (and optionally private key)') g.add_argument('--key', help='PEM file containing client private key (if not included in same file as certificate)') @@ -155,11 +247,20 @@ def parse_args(args = None): x = p.add_mutually_exclusive_group() x.add_argument('-v','--verbose', default=1, action='count', help='Increase verbosity of explanatory output to stderr') x.add_argument('-q','--quiet', dest='verbose', action='store_const', const=0, help='Reduce verbosity to a minimum') - g.add_argument('-x','--external', action='store_true', help='Launch external browser (for debugging)') + x = p.add_mutually_exclusive_group() + x.add_argument('-x','--external', action='store_true', help='Launch external browser (for debugging)') + x.add_argument('-P','--pkexec-openconnect', action='store_const', dest='exec', const='pkexec', help='Use PolicyKit to exec openconnect') + x.add_argument('-S','--sudo-openconnect', action='store_const', dest='exec', const='sudo', help='Use sudo to exec openconnect') 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(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) + p.add_argument('-f','--field', dest='extra', action='append', default=[], + help='Extra form field(s) to pass to include in the login query string (e.g. "-f magic-cookie-value=deadbeef01234567")') + p.add_argument('--allow-insecure-crypto', dest='insecure', action='store_true', + help='Allow use of insecure renegotiation or ancient 3DES and RC4 ciphers') + p.add_argument('--user-agent', '--useragent', default='PAN GlobalProtect', + help='Use the provided string as the HTTP User-Agent header (default is %(default)r, as used by OpenConnect)') + p.add_argument('openconnect_extra', nargs='*', help="Extra arguments to include in output OpenConnect command-line") + args = p.parse_args(args) args.ocos = clientos2ocos[args.clientos] args.extra = dict(x.split('=', 1) for x in args.extra) @@ -178,11 +279,13 @@ def parse_args(args = None): return p, args -if __name__ == "__main__": - p, args = parse_args() +def main(args = None): + p, args = parse_args(args) s = requests.Session() - s.headers['User-Agent'] = 'PAN GlobalProtect' + if args.insecure: + s.mount('https://', TLSAdapter()) + s.headers['User-Agent'] = 'PAN GlobalProtect' if args.user_agent is None else args.user_agent s.cert = args.cert if2prelogin = {'portal':'global-protect/prelogin.esp','gateway':'ssl-vpn/prelogin.esp'} @@ -193,7 +296,7 @@ if __name__ == "__main__": sam, uri, html = 'URI', args.server, None else: endpoint = 'https://{}/{}'.format(args.server, if2prelogin[args.interface]) - data = {'tmp':'tmp', 'kerberos-support':'yes', 'ipv6-support':'no', 'clientVer':4100, 'clientos':args.clientos, **args.extra} + data = {'tmp':'tmp', 'kerberos-support':'yes', 'ipv6-support':'yes', 'clientVer':4100, 'clientos':args.clientos, **args.extra} if args.verbose: print("Looking for SAML auth tags in response to %s..." % endpoint, file=stderr) try: @@ -209,12 +312,20 @@ if __name__ == "__main__": if isinstance(rootex, ssl.CertificateError): p.error("SSL certificate error (try --no-verify to ignore): %s" % rootex) elif isinstance(rootex, ssl.SSLError): - p.error("SSL error: %s" % rootex) + p.error("SSL error (try --allow-insecure-crypto to ignore): %s" % rootex) else: raise xml = ET.fromstring(res.content) if xml.tag != 'prelogin-response': p.error("This does not appear to be a GlobalProtect prelogin response\nCheck in browser: {}?{}".format(endpoint, urlencode(data))) + status = xml.find('status') + if status != None and status.text != 'Success': + msg = xml.find('msg') + if msg != None and msg.text == 'GlobalProtect {} does not exist'.format(args.interface): + p.error("{} interface does not exist; specify {} instead".format( + args.interface.title(), '--portal' if args.interface=='gateway' else '--gateway')) + else: + p.error("Error in {} prelogin response: {}".format(args.interface, msg.text)) sam = xml.find('saml-auth-method') sr = xml.find('saml-request') if sam is None or sr is None: @@ -243,7 +354,7 @@ if __name__ == "__main__": # spawn WebKit view to do SAML interactive login if args.verbose: print("Got SAML %s, opening browser..." % sam, file=stderr) - slv = SAMLLoginView(uri, html, verbose=args.verbose, cookies=args.cookies, verify=args.verify) + slv = SAMLLoginView(uri, html, verbose=args.verbose, cookies=args.cookies, verify=args.verify, user_agent=args.user_agent) Gtk.main() if slv.closed: print("Login window closed by user.", file=stderr) @@ -263,6 +374,29 @@ if __name__ == "__main__": cn = ifh = None p.error("Didn't get an expected cookie. Something went wrong.") + urlpath = args.interface + ":" + cn + openconnect_args = [ + "--protocol=gp", + "--user="+un, + "--os="+args.ocos, + "--usergroup="+urlpath, + "--passwd-on-stdin", + server + ] + args.openconnect_extra + + if args.insecure: + openconnect_args.insert(1, "--allow-insecure-crypto") + if args.user_agent: + openconnect_args.insert(1, "--useragent="+args.user_agent) + if args.cert: + cert, key = args.cert + if key: + openconnect_args.insert(1, "--sslkey="+key) + openconnect_args.insert(1, "--certificate="+cert) + + openconnect_command = ''' echo {} |\n sudo openconnect {}'''.format( + quote(cv), " ".join(map(quote, openconnect_args))) + if args.verbose: # Warn about ambiguities if server != args.server and not args.uri: @@ -274,14 +408,33 @@ if __name__ == "__main__": '''that's often 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={} --os={} --usergroup={}:{} --passwd-on-stdin {}'''.format( - quote(cv), quote(un), quote(args.ocos), quote(args.interface), quote(cn), quote(server)), file=stderr) + print(openconnect_command, file=stderr) print('''\nSAML response converted to test-globalprotect-login.py invocation:\n''', file=stderr) print(''' test-globalprotect-login.py --user={} --clientos={} -p '' \\\n https://{}/{} {}={}\n'''.format( quote(un), quote(args.clientos), quote(server), quote(if2auth[args.interface]), quote(cn), quote(cv)), file=stderr) - varvals = { - '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())) + + if args.exec: + print('''Launching OpenConnect with {}, equivalent to:\n{}'''.format(args.exec, openconnect_command), file=stderr) + with tempfile.TemporaryFile('w+') as tf: + tf.write(cv) + tf.flush() + tf.seek(0) + # redirect stdin from this file, before it is closed by the context manager + # (it will remain accessible via the open file descriptor) + dup2(tf.fileno(), 0) + if args.exec == 'pkexec': + cmd = ["pkexec", "--user", "root", "openconnect"] + openconnect_args + elif args.exec == 'sudo': + cmd = ["sudo", "openconnect"] + openconnect_args + execvp(cmd[0], cmd) + + else: + varvals = { + 'HOST': quote('https://%s/%s' % (server, urlpath)), + 'USER': quote(un), 'COOKIE': quote(cv), 'OS': quote(args.ocos), + } + print('\n'.join('%s=%s' % pair for pair in varvals.items())) + +if __name__ == "__main__": + main() diff --git a/openconnect_command-general.sh b/openconnect_command-general.sh index 11d7dab..b7df399 100755 --- a/openconnect_command-general.sh +++ b/openconnect_command-general.sh @@ -4,7 +4,7 @@ cd ~/bin/nu-vpn-proxy ## do the authentication -eval $( ./gp-saml-gui.py -v --clientos=Linux vpn-connect2.northwestern.edu ) +eval $( ./gp-saml-gui.py -v --gateway --clientos=Linux vpn-connect2.northwestern.edu ) echo "$COOKIE" | sudo openconnect --useragent="PAN GlobalConnect" --version-string='5.1.0-101' --protocol=gp -u "$USER" --os="$OS" --passwd-on-stdin "$HOST" --csd-wrapper="hipreport-modified.sh" --reconnect-timeout 60 diff --git a/openconnect_command-http.sh b/openconnect_command-http.sh index 0c519c6..e7821b8 100755 --- a/openconnect_command-http.sh +++ b/openconnect_command-http.sh @@ -9,7 +9,7 @@ exec > $LOG_FILE cd ~/bin/nu-vpn-proxy ## do the authentication -eval $( ./gp-saml-gui.py -v --clientos=Linux vpn-connect2.northwestern.edu ) +eval $( ./gp-saml-gui.py -v --gateway --clientos=Linux vpn-connect2.northwestern.edu ) echo "$COOKIE" | /usr/sbin/openconnect --verbose --useragent="PAN GlobalConnect" --version-string='5.1.0-101' --protocol=gp -u "$USER" --os="$OS" --passwd-on-stdin "$HOST" --csd-wrapper="hipreport-modified.sh" --reconnect-timeout 60 --script-tun --script "ocproxy -D 8181 --keepalive 5 --verbose" -b --pid-file "${PID_FILE}" diff --git a/openconnect_command-ssh.sh b/openconnect_command-ssh.sh index daa1bc0..2a875ff 100755 --- a/openconnect_command-ssh.sh +++ b/openconnect_command-ssh.sh @@ -1,5 +1,6 @@ -#!/bin/bash +#!/bin/bash -x +OS="linux" LOG_FILE=/tmp/nu-globalprotect-saml.log PID_FILE=/tmp/nu-vpn-openconnect.pid @@ -9,7 +10,7 @@ exec > $LOG_FILE cd ~/bin/nu-vpn-proxy ## do the authentication -eval $( ./gp-saml-gui.py -v --clientos=Linux vpn-connect2.northwestern.edu ) +eval $( ./gp-saml-gui.py -v --gateway --clientos=Linux vpn-connect2.northwestern.edu ) echo "$COOKIE" | /usr/sbin/openconnect --useragent="PAN GlobalConnect" --version-string='5.1.0-101' --protocol=gp -u "$USER" --os="$OS" --passwd-on-stdin "$HOST" --csd-wrapper="hipreport-modified.sh" --reconnect-timeout 60 --script-tun --script "ocproxy -D 9052" -b --pid-file "${PID_FILE}"