[PATCH] Juniper: support password and 2FA fields in the same form

Ash Holland ash at sorrel.sh
Wed Jun 24 17:26:28 EDT 2020

Juniper login forms typically ask for the password in the first form,
then put the 2FA field in a later form. However, some use a second
password field in the first form (usually frmLogin) for the 2FA token.
We now assume password fields after the first in a frmLogin to be 2FA
fields to cope with this case.

Signed-off-by: Ash Holland <ash at sorrel.sh>
I've tested this against the VPN I mentioned in [1], and it seems to
work well (it doesn't work properly with the NetworkManager integration,
I get "Unexpected 302 result from server" followed by "Creating SSL
connection failed", but I think that's a result of the way I've
installed my compiled version rather than anything else, and the
credential-entry UI works properly regardless).

Obviously it's possible that this could break currently-working setups?
I could believe that there exists a login form out there where you have
to type the password twice, or (more realistically) that there's a form
with a second password field into which you have to type something other
than a 2FA code. OTOH, that's fine if they don't also need 2FA.

[1]: https://lists.infradead.org/pipermail/openconnect-devel/2020-June/004870.html

 auth-juniper.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/auth-juniper.c b/auth-juniper.c
index 19d439784..f4d9733fa 100644
--- a/auth-juniper.c
+++ b/auth-juniper.c
@@ -74,6 +74,18 @@ static int oncp_can_gen_tokencode(struct openconnect_info *vpninfo,
 		return -EINVAL;
+	if (!strcmp(form->auth_id, "frmLogin")) {
+		// The first "password" input in frmLogin is likely to be a password, not 2FA token
+		struct oc_form_opt **p = &form->opts;
+		while (*p) {
+			if ((*p)->type == OC_FORM_OPT_PASSWORD) {
+				return can_gen_tokencode(vpninfo, form, opt);
+			}
+			p = &(*p)->next;
+		}
+		return -EINVAL;
+	}
 	if (strcmp(form->auth_id, "frmDefender") &&
 	    strcmp(form->auth_id, "frmNextToken") &&
 	    strcmp(form->auth_id, "frmTotpToken"))

More information about the openconnect-devel mailing list