]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
GP auth: give challenge/2FA forms a constant auth_id/name of "_challenge"
authorDaniel Lenski <dlenski@gmail.com>
Thu, 9 Apr 2020 00:35:48 +0000 (17:35 -0700)
committerDaniel Lenski <dlenski@gmail.com>
Thu, 9 Apr 2020 00:59:48 +0000 (17:59 -0700)
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 <dlenski@gmail.com>
auth-globalprotect.c

index 16a3050e1d67fe9ca8a689dd94653700affc0103..a4a9b5840c561a36b99fae0d2a1ed822d5bc09f7 100644 (file)
@@ -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;