From 593df6b1c09ea525a913d4d8401a95ffdb1877db Mon Sep 17 00:00:00 2001 From: Daniel Lenski Date: Wed, 8 Apr 2020 17:35:48 -0700 Subject: [PATCH] GP auth: give challenge/2FA forms a constant auth_id/name of "_challenge" Until now, we've been using the `inputStr` value (hex token that has to accompany challenge form submission) as the `auth_id` for challenge forms, but it appears these values aren't fixed from run-to-run, which makes it impossible to use `--form-entry` to fill them out. This patch makes all challenge forms have `auth_id=_challenge`, so they can be filled with `--form-entry=_challenge:passwd=VALUE`. The `inputStr` value will now be shoehorned into `form->action`. Unless we find a GP VPN that uses multiple independent challenges (3FA?), this should work better. ping #112 Signed-off-by: Daniel Lenski --- auth-globalprotect.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/auth-globalprotect.c b/auth-globalprotect.c index 16a3050e..a4a9b584 100644 --- a/auth-globalprotect.c +++ b/auth-globalprotect.c @@ -60,13 +60,14 @@ const char *gpst_os_name(struct openconnect_info *vpninfo) /* Parse pre-login response ({POST,GET} /{global-protect,ssl-vpn}/pre-login.esp) * * Extracts the relevant arguments from the XML (username-label, password-label) - * and uses them to build an auth form, which always has two visible fields: + * and uses them to build an auth form, which always has 2-3 fields: * - * 1) username + * 1) username (hidden in challenge forms, since it's simply repeated) * 2) one secret value: * - normal account password - * - "challenge" (2FA) password, along with form name in auth_id + * - "challenge" (2FA) password * - cookie from external authentication flow ("alternative secret" INSTEAD OF password) + * 3) inputStr for challenge form (shoehorned into form->action) * */ static int parse_prelogin_xml(struct openconnect_info *vpninfo, xmlNode *xml_node, void *cb_data) @@ -173,11 +174,10 @@ static int parse_prelogin_xml(struct openconnect_info *vpninfo, xmlNode *xml_nod else opt2->type = OC_FORM_OPT_PASSWORD; - vpn_progress(vpninfo, PRG_TRACE, "%s%s: \"%s\" %s(%s)=%s, \"%s\" %s(%s)\n", - form->auth_id[0] == '_' ? "Login form" : "Challenge form ", - form->auth_id[0] != '_' ? form->auth_id : "", - opt->label, opt->name, opt->type == OC_FORM_OPT_TEXT ? "TEXT" : "HIDDEN", opt->_value, - opt2->label, opt2->name, opt2->type == OC_FORM_OPT_PASSWORD ? "PASSWORD" : "TOKEN"); + vpn_progress(vpninfo, PRG_TRACE, "Prelogin form %s: \"%s\" %s(%s)=%s, \"%s\" %s(%s)\n", + form->auth_id, + opt->label, opt->name, opt->type == OC_FORM_OPT_TEXT ? "TEXT" : "HIDDEN", opt->_value, + opt2->label, opt2->name, opt2->type == OC_FORM_OPT_PASSWORD ? "PASSWORD" : "TOKEN"); out: free(prompt); @@ -202,21 +202,23 @@ static int challenge_cb(struct openconnect_info *vpninfo, char *prompt, char *in */ free(form->message); free(form->auth_id); + free(form->action); free(opt2->label); free(opt2->_value); opt2->_value = NULL; opt->type = OC_FORM_OPT_HIDDEN; if ( !(form->message = strdup(prompt)) - || !(form->auth_id = strdup(inputStr)) + || !(form->action = strdup(inputStr)) + || !(form->auth_id = strdup("_challenge")) || !(opt2->label = strdup(_("Challenge: "))) ) return -ENOMEM; - vpn_progress(vpninfo, PRG_TRACE, "%s%s: \"%s\" %s(%s)=%s, \"%s\" %s(%s)\n", - form->auth_id[0] == '_' ? "Login form" : "Challenge form ", - form->auth_id[0] != '_' ? form->auth_id : "", - opt->label, opt->name, opt->type == OC_FORM_OPT_TEXT ? "TEXT" : "HIDDEN", opt->_value, - opt2->label, opt2->name, opt2->type == OC_FORM_OPT_PASSWORD ? "PASSWORD" : "TOKEN"); + vpn_progress(vpninfo, PRG_TRACE, "Challenge form %s: \"%s\" %s(%s)=%s, \"%s\" %s(%s), inputStr=%s\n", + form->auth_id, + opt->label, opt->name, opt->type == OC_FORM_OPT_TEXT ? "TEXT" : "HIDDEN", opt->_value, + opt2->label, opt2->name, opt2->type == OC_FORM_OPT_PASSWORD ? "PASSWORD" : "TOKEN", + inputStr); return -EAGAIN; } @@ -571,8 +573,8 @@ static int gpst_login(struct openconnect_info *vpninfo, int portal, struct login append_opt(request_body, "computer", vpninfo->localname); if (vpninfo->ip_info.addr) append_opt(request_body, "preferred-ip", vpninfo->ip_info.addr); - if (ctx->form->auth_id && ctx->form->auth_id[0]!='_') - append_opt(request_body, "inputStr", ctx->form->auth_id); + if (ctx->form->action) + append_opt(request_body, "inputStr", ctx->form->action); append_form_opts(vpninfo, ctx->form, request_body); if ((result = buf_error(request_body))) goto out; -- 2.50.1