[PATCH V2 nm-openconnect 2/3] auth-dialog: Add support for NEWGROUP

Kevin Cernekee cernekee at gmail.com
Mon Dec 30 20:49:36 EST 2013


When the user selects a different authgroup, return NEWGROUP to
libopenconnect to allow it to refresh the form.  Different groups may
require different prompts.

Also, if secondary_username is provided by the server, prepopulate the
form field.
---
 auth-dialog/main.c | 112 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 95 insertions(+), 17 deletions(-)

diff --git a/auth-dialog/main.c b/auth-dialog/main.c
index 9253daa..f4c772b 100644
--- a/auth-dialog/main.c
+++ b/auth-dialog/main.c
@@ -71,7 +71,21 @@
 #define __openconnect_set_token_mode openconnect_set_token_mode
 #endif
 
+#if OPENCONNECT_CHECK_VER(3,0)
+#define NEWGROUP_SUPPORTED		1
+#define AUTHGROUP_FIELD(form)		(form)->authgroup_field
+#define AUTHGROUP_SELECTION(form)	(form)->authgroup_selection
+#define FORMCHOICE(sopt, i)		((sopt)->choices[i])
+#else
+#define NEWGROUP_SUPPORTED		0
+#define AUTHGROUP_FIELD(form)		NULL
+#define AUTHGROUP_SELECTION(form)	0
 #define FORMCHOICE(sopt, i)		(&(sopt)->choices[i])
+#define OC_FORM_RESULT_ERR		-1
+#define OC_FORM_RESULT_OK		0
+#define OC_FORM_RESULT_CANCELLED	1
+#define OC_FORM_RESULT_NEWGROUP		2
+#endif
 
 #ifdef OPENCONNECT_OPENSSL
 #include <openssl/ssl.h>
@@ -181,6 +195,9 @@ typedef struct auth_ui_data {
 	GCond form_shown_changed;
 	gboolean form_shown;
 
+	gboolean newgroup;
+	gboolean group_set;
+
 	GCond cert_response_changed;
 	enum certificate_response cert_response;
 } auth_ui_data;
@@ -273,6 +290,7 @@ typedef struct ui_fragment_data {
 #endif
 	struct oc_form_opt *opt;
 	char *entry_text;
+	int initial_selection;
 	int grab_focus;
 } ui_fragment_data;
 
@@ -336,6 +354,12 @@ static void combo_changed(GtkComboBox *combo, ui_fragment_data *data)
 
 	data->entry_text = FORMCHOICE(sopt, entry)->name;
 
+	if (NEWGROUP_SUPPORTED && entry != data->initial_selection) {
+		data->ui_data->newgroup = TRUE;
+		gtk_dialog_response(GTK_DIALOG(data->ui_data->dialog), AUTH_DIALOG_RESPONSE_LOGIN);
+		return;
+	}
+
 	g_queue_foreach(data->ui_data->form_entries, (GFunc)do_override_label,
 			FORMCHOICE(sopt, entry));
 }
@@ -414,7 +438,7 @@ static gboolean ui_add_select (ui_fragment_data *data)
 	auth_ui_data *ui_data = _ui_data; /* FIXME global */
 	GtkWidget *hbox, *text, *combo;
 	struct oc_form_opt_select *sopt = (void *)data->opt;
-	int i;
+	int i, user_selection = -1;
 
 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
 	gtk_box_pack_start(GTK_BOX(data->ui_data->ssl_box), hbox, FALSE, FALSE, 0);
@@ -424,20 +448,21 @@ static gboolean ui_add_select (ui_fragment_data *data)
 
 	combo = gtk_combo_box_text_new();
 	gtk_box_pack_end(GTK_BOX(hbox), combo, FALSE, FALSE, 0);
+
 	for (i = 0; i < sopt->nr_choices; i++) {
 		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), FORMCHOICE(sopt, i)->label);
 		if (data->entry_text &&
-		    !strcmp(data->entry_text, FORMCHOICE(sopt, i)->name)) {
-			gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
-			g_free(data->entry_text);
-			data->entry_text = FORMCHOICE(sopt, i)->name;
-		}
-	}
-	if (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)) < 0) {
-		gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); 
-		data->entry_text = FORMCHOICE(sopt, 0)->name;
+		    !strcmp(data->entry_text, FORMCHOICE(sopt, i)->name))
+			user_selection = i;
 	}
 
+	i = data->initial_selection != -1 ? data->initial_selection :
+	    user_selection != -1 ? user_selection : 0;
+	gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
+	g_free(data->entry_text);
+	data->entry_text = FORMCHOICE(sopt, i)->name;
+	data->initial_selection = i;
+
 	if (g_queue_peek_tail(ui_data->form_entries) == data)
 		gtk_widget_grab_focus (combo);
 	g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(combo_changed), data);
@@ -674,10 +699,12 @@ static gboolean ui_form (struct oc_auth_form *form)
 			g_mutex_lock (&ui_data->form_mutex);
 			g_queue_push_head(ui_data->form_entries, data);
 			g_mutex_unlock (&ui_data->form_mutex);
-			if (opt->type != OC_FORM_OPT_PASSWORD)
+			if (opt->type != OC_FORM_OPT_PASSWORD) {
 				data->entry_text = g_strdup (find_form_answer(ui_data->secrets,
 									      form, opt));
-			else {
+				if (!data->entry_text)
+					data->entry_text = g_strdup (opt->value);
+			} else {
 				GHashTable *attrs;
 
 				data->cancel = g_cancellable_new ();
@@ -694,12 +721,19 @@ static gboolean ui_form (struct oc_auth_form *form)
 
 			ui_write_prompt(data);
 		} else if (opt->type == OC_FORM_OPT_SELECT) {
+			char *authgroup_field = AUTHGROUP_FIELD(form);
+
 			g_mutex_lock (&ui_data->form_mutex);
 			g_queue_push_head(ui_data->form_entries, data);
 			g_mutex_unlock (&ui_data->form_mutex);
 			data->entry_text = g_strdup (find_form_answer(ui_data->secrets,
 								      form, opt));
 
+			if (authgroup_field && !strcmp(authgroup_field, opt->name))
+				data->initial_selection = AUTHGROUP_SELECTION(form);
+			else
+				data->initial_selection = -1;
+
 			ui_add_select(data);
 		} else
 			g_slice_free (ui_fragment_data, data);
@@ -708,11 +742,52 @@ static gboolean ui_form (struct oc_auth_form *form)
 	return ui_show(ui_data);
 }
 
+/* If our stored group_list selection differs from the server default, send a
+   NEWGROUP request to try to change it before rendering the form */
+
+static gboolean set_initial_authgroup (auth_ui_data *ui_data, struct oc_auth_form *form)
+{
+	struct oc_form_opt *opt;
+	char *authgroup_field = AUTHGROUP_FIELD(form);
+
+	if (!NEWGROUP_SUPPORTED || ui_data->group_set || authgroup_field)
+		return FALSE;
+	ui_data->group_set = TRUE;
+
+	for (opt = form->opts; opt; opt = opt->next) {
+		int i;
+		char *saved_group;
+		struct oc_form_opt_select *sopt;
+
+		if (opt->type != OC_FORM_OPT_SELECT || strcmp(opt->name, authgroup_field))
+			continue;
+
+		saved_group = find_form_answer(ui_data->secrets, form, opt);
+		if (!saved_group)
+			return FALSE;
+
+		sopt = (struct oc_form_opt_select *)opt;
+		for (i = 0; i < sopt->nr_choices; i++) {
+			struct oc_choice *ch = FORMCHOICE(sopt, i);
+			if (!strcmp(saved_group, ch->name) && i != AUTHGROUP_SELECTION(form)) {
+				free(opt->value);
+				opt->value = g_strdup(saved_group);
+				return TRUE;
+			}
+		}
+	}
+	return FALSE;
+}
+
 static int nm_process_auth_form (void *cbdata, struct oc_auth_form *form)
 {
 	auth_ui_data *ui_data = cbdata;
 	int response;
 
+	if (set_initial_authgroup(ui_data, form))
+		return OC_FORM_RESULT_NEWGROUP;
+
+	ui_data->newgroup = FALSE;
 	g_idle_add((GSourceFunc)ui_form, form);
 
 	g_mutex_lock(&ui_data->form_mutex);
@@ -772,11 +847,14 @@ static int nm_process_auth_form (void *cbdata, struct oc_auth_form *form)
 
 	ui_data->form_grabbed = 0;
 	g_mutex_unlock(&ui_data->form_mutex);
-	
-	/* -1 = cancel,
-	 *  0 = failure,
-	 *  1 = success */
-	return (response == AUTH_DIALOG_RESPONSE_LOGIN ? 0 : 1);
+
+	if (response == AUTH_DIALOG_RESPONSE_LOGIN) {
+		if (ui_data->newgroup)
+			return OC_FORM_RESULT_NEWGROUP;
+		else
+			return OC_FORM_RESULT_OK;
+	} else
+		return OC_FORM_RESULT_CANCELLED;
 
 }
 
-- 
1.8.3.2




More information about the openconnect-devel mailing list