[PATCH/RFC V3 12/13] auth: Hide unused form fields based on the selected authgroup

Kevin Cernekee cernekee at gmail.com
Sun Dec 15 01:43:03 EST 2013


Non-aggregate-auth servers have limited support for customizing the login
form based on which authgroup is currently selected.  Selectively convert
text/password fields to hidden fields, based on the following attributes:

  <input second-auth="1"> (for text/password fields)

  <option                 (for authgroup options)
          second-auth="1"
          secondary_username="foo"
          secondary_username_editable="true"
          noaaa="1" >

Note that implementing secondary_username_editable can cause
libopenconnect to prepopulate the opt->value field, which may be blindly
overwritten (without freeing) by legacy clients.  The other changes
should be backward-compatible, although they are not fully functional
on clients that do not implement OC_FORM_RESULT_NEWGROUP.

Signed-off-by: Kevin Cernekee <cernekee at gmail.com>
---
 auth.c |   36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/auth.c b/auth.c
index 6ff0b01..4f94df4 100644
--- a/auth.c
+++ b/auth.c
@@ -626,6 +626,8 @@ int process_auth_form(struct openconnect_info *vpninfo, struct __oc_auth_form *f
 	int ret;
 	struct __oc_form_opt *opt;
 	struct oc_form_opt **last;
+	struct __oc_form_opt_select *grp = form->authgroup_opt;
+	struct __oc_choice *auth_choice;
 
 	if (!vpninfo->process_auth_form) {
 		vpn_progress(vpninfo, PRG_ERR, _("No form handler; cannot authenticate.\n"));
@@ -633,6 +635,18 @@ int process_auth_form(struct openconnect_info *vpninfo, struct __oc_auth_form *f
 	}
 
 retry:
+	auth_choice = NULL;
+	if (grp && grp->nr_choices && !vpninfo->xmlpost) {
+		if (vpninfo->authgroup) {
+			/* For non-XML-POST, the server doesn't tell us which group is selected */
+			int i;
+			for (i = 0; i < grp->nr_choices; i++)
+				if (!strcmp(grp->choices[i].u.name, vpninfo->authgroup))
+					form->u.authgroup_selection = i;
+		}
+		auth_choice = &grp->choices[form->u.authgroup_selection];
+	}
+
 	/* We have two parallel linked lists of form fields here:
 	   form->u.opts is a linked list of user-visible oc_form_opt's
 	   form->opts is a linked list of internally-visible __oc_form_opt's
@@ -647,10 +661,26 @@ retry:
 				continue;
 			*last = (struct oc_form_opt *)sopt->u;
 			last = &sopt->u->form.next;
-		} else {
-			*last = &opt->u;
-			last = &opt->u.next;
+			continue;
+		} else if (!auth_choice) {
+			/* nothing left to check */
+		} else if (auth_choice->noaaa &&
+			   (opt->u.type == OC_FORM_OPT_TEXT || opt->u.type == OC_FORM_OPT_PASSWORD)) {
+			/* nuke all text fields for noaaa groups */
+			continue;
+		} else if (!auth_choice->second_auth && opt->second_auth) {
+			/* hide second-auth fields if a non-second-auth group is selected */
+			continue;
+		} else if (!strcmp(opt->u.name, "secondary_username") && opt->second_auth) {
+			if (auth_choice->secondary_username) {
+				free(opt->u.value);
+				opt->u.value = strdup(auth_choice->secondary_username);
+			}
+			if (!auth_choice->secondary_username_editable)
+				continue;
 		}
+		*last = &opt->u;
+		last = &opt->u.next;
 	}
 	*last = NULL;
 	ret = vpninfo->process_auth_form(vpninfo->cbdata, &form->u);
-- 
1.7.9.5




More information about the openconnect-devel mailing list