diff --git a/gp_saml_gui.py b/gp_saml_gui.py index a046e53..35aa729 100755 --- a/gp_saml_gui.py +++ b/gp_saml_gui.py @@ -29,6 +29,9 @@ import xml.etree.ElementTree as ET import ssl import tempfile +import configparser +import itertools +import json from operator import setitem from os import path, dup2, execvp, environ @@ -53,7 +56,6 @@ def handle_comment(self, data: str) -> None: class SAMLLoginView: def __init__(self, uri, html, args): - Gtk.init(None) self.window = window = Gtk.Window() @@ -83,6 +85,19 @@ def __init__(self, uri, html, args): settings.set_user_agent(args.user_agent) self.wview.set_settings(settings) + if args.login: + args.login = path.expanduser(args.login) + self.login = {} + config = configparser.ConfigParser() + try: + config.read(args.login) + except: + print("Error opening or reading '%s'" % args.login) + config = None + if config and config.has_section(args.server): + for x in config[args.server]: + self.login[x] = config[args.server][x] + window.resize(500, 500) window.add(self.wview) window.show_all() @@ -95,7 +110,7 @@ def __init__(self, uri, html, args): self.wview.load_html(html, uri) else: self.wview.load_uri(uri) - + def close(self, window, event): self.closed = True Gtk.main_quit() @@ -129,6 +144,14 @@ def log_resource_text(self, resource, result, content_type, charset=None, show_h if charset or content_type.startswith('text/'): print(data.decode(charset or 'utf-8'), file=stderr) + def setvalue_DOM_element(self, selector, value): + if self.wview: + # name attibute + self.wview.evaluate_javascript("Array.from(document.getElementsByName(%s)).forEach(el => el.value = %s);" % (json.dumps(selector), json.dumps(value)), -1, None, None, None, None, None) + + # id attribute + self.wview.evaluate_javascript("document.getElementById(%s).value = %s;" % (json.dumps(selector), json.dumps(value)), -1, None, None, None, None, None) + def on_load_changed(self, webview, event): if event != WebKit2.LoadEvent.FINISHED: return @@ -149,6 +172,10 @@ def on_load_changed(self, webview, event): if not rs or not h: return + # Set login credentials + for x in self.login: + self.setvalue_DOM_element(x, self.login[x]) + # convert to normal dict d = {} h.foreach(lambda k, v: setitem(d, k.lower(), v)) @@ -290,6 +317,8 @@ def parse_args(args = None): x.add_argument('-E','--exec-openconnect', action='store_const', dest='exec', const='exec', help='Execute openconnect directly (advanced users)') 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('-l','--login', default='~/.gp-saml-gui-credentials', + help='Read login credentials from the file specified (instead of default %(default)s)') 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',