[PATCH V2 nm-openconnect] Dynamically remove unsupported token_mode entries

Kevin Cernekee cernekee at gmail.com
Sat Jun 8 18:01:30 EDT 2013


Depending on which software token libraries are installed, this could
include stoken options, TOTP options, both, or neither.  Only show the
user the options that are available on his system.
---
 properties/nm-openconnect-dialog.ui |   18 +++++++
 properties/nm-openconnect.c         |   99 ++++++++++++++++++++++-------------
 2 files changed, 80 insertions(+), 37 deletions(-)


V2: Store pref_value, token_type filter, and token_secret_editable
properties in the GtkListStore instead of in a parallel data structure.

Lightly tested.


diff --git a/properties/nm-openconnect-dialog.ui b/properties/nm-openconnect-dialog.ui
index bc38374..b3401db 100644
--- a/properties/nm-openconnect-dialog.ui
+++ b/properties/nm-openconnect-dialog.ui
@@ -734,19 +734,37 @@
         <columns>
           <!-- column-name legible -->
           <column type="gchararray"/>
+          <!-- column-name pref_value -->
+          <column type="gchararray"/>
+          <!-- column-name token_type -->
+          <column type="gchararray"/>
+          <!-- column-name token_secret_editable -->
+          <column type="gboolean"/>
         </columns>
         <data>
           <row>
             <col id="0" translatable="yes">Disabled</col>
+            <col id="1" translatable="no">disabled</col>
+            <col id="2" translatable="no">any</col>
+            <col id="3" translatable="no">False</col>
           </row>
           <row>
             <col id="0" translatable="yes">RSA SecurID - read from ~/.stokenrc</col>
+            <col id="1" translatable="no">stokenrc</col>
+            <col id="2" translatable="no">stoken</col>
+            <col id="3" translatable="no">False</col>
           </row>
           <row>
             <col id="0" translatable="yes">RSA SecurID - manually entered</col>
+            <col id="1" translatable="no">manual</col>
+            <col id="2" translatable="no">stoken</col>
+            <col id="3" translatable="no">True</col>
           </row>
           <row>
             <col id="0" translatable="yes">TOTP - manually entered</col>
+            <col id="1" translatable="no">totp</col>
+            <col id="2" translatable="no">totp</col>
+            <col id="3" translatable="no">True</col>
           </row>
         </data>
       </object>
diff --git a/properties/nm-openconnect.c b/properties/nm-openconnect.c
index 7a60937..9e6d0e7 100644
--- a/properties/nm-openconnect.c
+++ b/properties/nm-openconnect.c
@@ -375,19 +375,49 @@ stuff_changed_cb (GtkWidget *widget, gpointer user_data)
 }
 
 static gboolean
+init_token_mode_options (GtkComboBox *token_mode)
+{
+	GtkListStore *token_mode_list = GTK_LIST_STORE (gtk_combo_box_get_model (token_mode));
+	GtkTreeModel *model = GTK_TREE_MODEL (token_mode_list);
+	GtkTreeIter iter;
+	gboolean iter_valid;
+	int valid_rows = 0;
+
+	if (!gtk_tree_model_get_iter_first (model, &iter))
+		return FALSE;
+	do {
+		char *token_type;
+
+		gtk_tree_model_get (model, &iter, 2, &token_type, -1);
+		if (!strcmp (token_type, "stoken") && !openconnect_has_stoken_support ())
+			iter_valid = gtk_list_store_remove (token_mode_list, &iter);
+		else if (!strcmp (token_type, "totp") && !openconnect_has_oath_support ())
+			iter_valid = gtk_list_store_remove (token_mode_list, &iter);
+		else {
+			iter_valid = gtk_tree_model_iter_next (model, &iter);
+			valid_rows++;
+		}
+		g_free (token_type);
+	} while (iter_valid);
+
+	/* if the only option is "Disabled", don't show the token section at all */
+	return valid_rows > 1;
+}
+
+static gboolean
 init_token_ui (OpenconnectPluginUiWidget *self,
 				OpenconnectPluginUiWidgetPrivate *priv,
 				NMSettingVPN *s_vpn)
 {
 	GtkWidget *widget;
+	GtkComboBox *token_mode;
 	GtkTextBuffer *buffer;
 	const char *value;
 
-	/*
-	 * don't advertise software token properties if we can't use them anyway
-	 * TODO: Fix up the dialog accordingly if e.g. stoken is present but oath is missing
-	 */
-	if (!openconnect_has_stoken_support () && !openconnect_has_oath_support ())
+	token_mode = GTK_COMBO_BOX (gtk_builder_get_object (priv->builder, "token_mode"));
+	if (!token_mode)
+		return FALSE;
+	if (!init_token_mode_options (token_mode))
 		return TRUE;
 
 	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "token_vbox"));
@@ -395,23 +425,31 @@ init_token_ui (OpenconnectPluginUiWidget *self,
 		return FALSE;
 	gtk_box_pack_start (GTK_BOX (priv->widget), widget, FALSE, FALSE, 0);
 
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "token_mode"));
-	if (!widget)
-		return FALSE;
 	if (s_vpn) {
+		GtkTreeModel *model = gtk_combo_box_get_model (token_mode);
+		int active_option = 0;
+
 		value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_TOKEN_MODE);
 		if (value) {
-			if (!strcmp (value, "stokenrc"))
-				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
-			else if (!strcmp (value, "manual"))
-				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2);
-			else if (!strcmp (value, "totp"))
-				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 3);
-			else
-				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+			int i;
+			GtkTreeIter iter;
+
+			if (!gtk_tree_model_get_iter_first (model, &iter))
+				return FALSE;
+			for (i = 0; ; i++) {
+				char *pref_value;
+
+				gtk_tree_model_get (model, &iter, 1, &pref_value, -1);
+				if (!strcmp (value, pref_value))
+					active_option = i;
+				g_free (pref_value);
+				if (!gtk_tree_model_iter_next (model, &iter))
+					break;
+			}
 		}
+		gtk_combo_box_set_active (token_mode, active_option);
 	}
-	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
+	g_signal_connect (G_OBJECT (token_mode), "changed", G_CALLBACK (stuff_changed_cb), self);
 
 	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "token_secret"));
 	if (!widget)
@@ -520,7 +558,8 @@ update_connection (NMVpnPluginUiWidgetInterface *iface,
 	NMSettingVPN *s_vpn;
 	GtkWidget *widget;
 	char *str;
-	gint idx;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
 	gboolean token_secret_editable = FALSE;
 	GtkTextIter iter_start, iter_end;
 	GtkTextBuffer *buffer;
@@ -553,26 +592,12 @@ update_connection (NMVpnPluginUiWidgetInterface *iface,
 		nm_setting_vpn_add_data_item (s_vpn, NM_OPENCONNECT_KEY_CSD_WRAPPER, str);
 
 	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "token_mode"));
-	idx = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
-	str = NULL;
-	switch (idx) {
-	case 0:
-		str = "disabled";
-		break;
-	case 1:
-		str = "stokenrc";
-		break;
-	case 2:
-		str = "manual";
-		token_secret_editable = TRUE;
-		break;
-	case 3:
-		str = "totp";
-		token_secret_editable = TRUE;
-		break;
-	}
-	if (str)
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
+		gtk_tree_model_get (model, &iter, 1, &str, 3, &token_secret_editable, -1);
 		nm_setting_vpn_add_data_item (s_vpn, NM_OPENCONNECT_KEY_TOKEN_MODE, str);
+		g_free(str);
+	}
 
 	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "token_secret_label"));
 	gtk_widget_set_sensitive (widget, token_secret_editable);
-- 
1.7.10.4




More information about the openconnect-devel mailing list