NetworkManager r4283 - in trunk/vpn-daemons/vpnc: . auth-dialog common-gnome properties src



Author: dcbw
Date: Fri Nov 14 16:55:59 2008
New Revision: 4283
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=4283&view=rev

Log:
2008-11-14  Dan Williams  <dcbw redhat com>

	Add password types to better support OTP/token use-cases, and for people
	who want to be asked every time for one or both passwords (bgo #346547).
	Heavily based on a patch from Mathieu Trudel-Lapierre <mathieu tl gmail com>

	* common-gnome/keyring-helpers.c
	  common-gnome/keyring-helpers.h
		- (keyring_helpers_get_one_secret): accessor to get just one secret

	* auth-dialog/gnome-two-password-dialog.c
	  auth-dialog/gnome-two-password-dialog.h
		- (gnome_two_password_dialog_focus_password,
		   gnome_two_password_dialog_focus_password_secondary): add functions to
			focus specific password entries

	* auth-dialog/Makefile.am
	  auth-dialog/main.c
		- Retrieve password types from GConf, and handle them correctly when
			asking the user for passwords

	* properties/nm-vpnc-dialog.glade
	  properties/nm-vpnc.c
		- Add combo boxes for both passwords with options for saving, asking,
			or not requiring the password
		- (fill_vpn_passwords): handle passwords individually
		- (pw_type_changed_helper): disable the password entry when the user
			picks "Not Required" or "Always Ask"
		- (init_one_pw_combo, init_plugin_ui): set up password combos
		- (handle_one_pw_type, update_connection): save password type
		- (save_one_password): handle saving/clearing passwords based on what
			each password's type is

	* src/nm-vpnc-service.c
	  src/nm-vpnc-service.h
		- (validate_one_property): ignore password type properties
		- (nm_vpnc_config_write, write_one_property): don't write secrets if
			they aren't used
		- (real_need_secrets): only ask for secrets when needed



Modified:
   trunk/vpn-daemons/vpnc/ChangeLog
   trunk/vpn-daemons/vpnc/auth-dialog/Makefile.am
   trunk/vpn-daemons/vpnc/auth-dialog/gnome-two-password-dialog.c
   trunk/vpn-daemons/vpnc/auth-dialog/gnome-two-password-dialog.h
   trunk/vpn-daemons/vpnc/auth-dialog/main.c
   trunk/vpn-daemons/vpnc/common-gnome/keyring-helpers.c
   trunk/vpn-daemons/vpnc/common-gnome/keyring-helpers.h
   trunk/vpn-daemons/vpnc/properties/nm-vpnc-dialog.glade
   trunk/vpn-daemons/vpnc/properties/nm-vpnc.c
   trunk/vpn-daemons/vpnc/src/nm-vpnc-service.c
   trunk/vpn-daemons/vpnc/src/nm-vpnc-service.h

Modified: trunk/vpn-daemons/vpnc/auth-dialog/Makefile.am
==============================================================================
--- trunk/vpn-daemons/vpnc/auth-dialog/Makefile.am	(original)
+++ trunk/vpn-daemons/vpnc/auth-dialog/Makefile.am	Fri Nov 14 16:55:59 2008
@@ -6,6 +6,7 @@
 	$(NM_UTILS_CFLAGS) \
 	$(GTHREAD_CFLAGS) \
 	$(GTK_CFLAGS) \
+	$(GCONF_CFLAGS) \
 	$(GNOMEKEYRING_CFLAGS) \
 	-DICONDIR=\""$(datadir)/pixmaps"\" \
 	-DGLADEDIR=\""$(gladedir)"\" \
@@ -24,6 +25,8 @@
 
 nm_vpnc_auth_dialog_LDADD = \
 	$(GTK_LIBS) \
+	$(GCONF_LIBS) \
 	$(top_builddir)/common-gnome/libnm-vpnc-common-gnome.la
 
 CLEANFILES = *~
+

Modified: trunk/vpn-daemons/vpnc/auth-dialog/gnome-two-password-dialog.c
==============================================================================
--- trunk/vpn-daemons/vpnc/auth-dialog/gnome-two-password-dialog.c	(original)
+++ trunk/vpn-daemons/vpnc/auth-dialog/gnome-two-password-dialog.c	Fri Nov 14 16:55:59 2008
@@ -593,6 +593,26 @@
 }
 
 void
+gnome_two_password_dialog_focus_password (GnomeTwoPasswordDialog *password_dialog)
+{
+	g_return_if_fail (password_dialog != NULL);
+	g_return_if_fail (GNOME_IS_TWO_PASSWORD_DIALOG (password_dialog));
+
+	if (password_dialog->details->show_password)
+		gtk_widget_grab_focus (password_dialog->details->password_entry);
+}
+
+void
+gnome_two_password_dialog_focus_password_secondary (GnomeTwoPasswordDialog *password_dialog)
+{
+	g_return_if_fail (password_dialog != NULL);
+	g_return_if_fail (GNOME_IS_TWO_PASSWORD_DIALOG (password_dialog));
+
+	if (password_dialog->details->show_password_secondary)
+		gtk_widget_grab_focus (password_dialog->details->password_entry_secondary);
+}
+
+void
 gnome_two_password_dialog_set_readonly_username (GnomeTwoPasswordDialog	*password_dialog,
 						gboolean		readonly)
 {

Modified: trunk/vpn-daemons/vpnc/auth-dialog/gnome-two-password-dialog.h
==============================================================================
--- trunk/vpn-daemons/vpnc/auth-dialog/gnome-two-password-dialog.h	(original)
+++ trunk/vpn-daemons/vpnc/auth-dialog/gnome-two-password-dialog.h	Fri Nov 14 16:55:59 2008
@@ -77,8 +77,10 @@
 							    gboolean                show);
 void gnome_two_password_dialog_set_show_password           (GnomeTwoPasswordDialog *password_dialog,
 							    gboolean                show);
+void gnome_two_password_dialog_focus_password              (GnomeTwoPasswordDialog *password_dialog);
 void gnome_two_password_dialog_set_show_password_secondary (GnomeTwoPasswordDialog *password_dialog,
 							    gboolean                show);
+void gnome_two_password_dialog_focus_password_secondary    (GnomeTwoPasswordDialog *password_dialog);
 void gnome_two_password_dialog_set_username                (GnomeTwoPasswordDialog  *password_dialog,
 							    const char              *username);
 void gnome_two_password_dialog_set_domain                  (GnomeTwoPasswordDialog  *password_dialog,

Modified: trunk/vpn-daemons/vpnc/auth-dialog/main.c
==============================================================================
--- trunk/vpn-daemons/vpnc/auth-dialog/main.c	(original)
+++ trunk/vpn-daemons/vpnc/auth-dialog/main.c	Fri Nov 14 16:55:59 2008
@@ -29,8 +29,10 @@
 #include <gtk/gtk.h>
 #include <gnome-keyring.h>
 #include <gnome-keyring-memory.h>
+#include <gconf/gconf-client.h>
 
 #include <nm-setting-vpn.h>
+#include <nm-setting-connection.h>
 
 #include "common-gnome/keyring-helpers.h"
 #include "src/nm-vpnc-service.h"
@@ -44,24 +46,61 @@
 get_secrets (const char *vpn_uuid,
              const char *vpn_name,
              gboolean retry,
-             char **password,
-             char **group_password)
+             char **upw,
+             const char *upw_type,
+             char **gpw,
+             const char *gpw_type)
 {
 	GnomeTwoPasswordDialog *dialog;
 	gboolean is_session = TRUE;
-	gboolean found;
+	gboolean found_upw = FALSE;
+	gboolean found_gpw = FALSE;
 	char *prompt;
+	gboolean success = FALSE;
 
 	g_return_val_if_fail (vpn_uuid != NULL, FALSE);
 	g_return_val_if_fail (vpn_name != NULL, FALSE);
-	g_return_val_if_fail (password != NULL, FALSE);
-	g_return_val_if_fail (*password == NULL, FALSE);
-	g_return_val_if_fail (group_password != NULL, FALSE);
-	g_return_val_if_fail (*group_password == NULL, FALSE);
-
-	found = keyring_helpers_lookup_secrets (vpn_uuid, password, group_password, &is_session);
-	if (!retry && found && *password && *group_password)
-		return TRUE;
+	g_return_val_if_fail (upw != NULL, FALSE);
+	g_return_val_if_fail (*upw == NULL, FALSE);
+	g_return_val_if_fail (gpw != NULL, FALSE);
+	g_return_val_if_fail (*gpw == NULL, FALSE);
+
+	/* Default to 'save' to keep same behavior as previous versions before
+	 * password types were added.
+	 */
+	if (!upw_type)
+		upw_type = NM_VPNC_PW_TYPE_SAVE;
+	if (!gpw_type)
+		gpw_type = NM_VPNC_PW_TYPE_SAVE;
+
+	if (strcmp (upw_type, NM_VPNC_PW_TYPE_ASK))
+		found_upw = keyring_helpers_get_one_secret (vpn_uuid, VPNC_USER_PASSWORD, upw, &is_session);
+
+	if (strcmp (gpw_type, NM_VPNC_PW_TYPE_ASK)) 
+		found_gpw = keyring_helpers_get_one_secret (vpn_uuid, VPNC_GROUP_PASSWORD, gpw, &is_session);
+
+	if (!retry) {
+		gboolean need_upw = TRUE, need_gpw = TRUE;
+
+		/* Don't ask if both passwords are either saved and present, or unused */
+		if (   (!strcmp (upw_type, NM_VPNC_PW_TYPE_SAVE) && found_upw && *upw)
+		    || (!upw_type && found_upw && *upw)  /* treat unknown type as "save" */
+		    || !strcmp (upw_type, NM_VPNC_PW_TYPE_UNUSED))
+			need_upw = FALSE;
+
+		if (   (!strcmp (gpw_type, NM_VPNC_PW_TYPE_SAVE) && found_gpw && *gpw)
+		    || (!gpw_type && found_gpw && *gpw)  /* treat unknown type as "save" */
+		    || !strcmp (gpw_type, NM_VPNC_PW_TYPE_UNUSED))
+			need_gpw = FALSE;
+
+		if (!need_upw && !need_gpw)
+			return TRUE;
+	} else {
+		/* Don't ask if both passwords are unused */
+		if (   !strcmp (upw_type, NM_VPNC_PW_TYPE_UNUSED)
+		    && !strcmp (gpw_type, NM_VPNC_PW_TYPE_UNUSED))
+			return TRUE;
+	}
 
 	prompt = g_strdup_printf (_("You need to authenticate to access the Virtual Private Network '%s'."), vpn_name);
 	dialog = GNOME_TWO_PASSWORD_DIALOG (gnome_two_password_dialog_new (_("Authenticate VPN"), prompt, NULL, NULL, FALSE));
@@ -70,56 +109,140 @@
 	gnome_two_password_dialog_set_show_username (dialog, FALSE);
 	gnome_two_password_dialog_set_show_userpass_buttons (dialog, FALSE);
 	gnome_two_password_dialog_set_show_domain (dialog, FALSE);
-	gnome_two_password_dialog_set_show_remember (dialog, TRUE);
+	gnome_two_password_dialog_set_show_remember (dialog, FALSE);
 	gnome_two_password_dialog_set_password_secondary_label (dialog, _("_Group Password:"));
 
-	/* If nothing was found in the keyring, default to not remembering any secrets */
-	if (found) {
-		/* Otherwise set default remember based on which keyring the secrets were found in */
-		if (is_session)
-			gnome_two_password_dialog_set_remember (dialog, GNOME_TWO_PASSWORD_DIALOG_REMEMBER_SESSION);
-		else
-			gnome_two_password_dialog_set_remember (dialog, GNOME_TWO_PASSWORD_DIALOG_REMEMBER_FOREVER);
-	} else
-		gnome_two_password_dialog_set_remember (dialog, GNOME_TWO_PASSWORD_DIALOG_REMEMBER_NOTHING);
+	if (!strcmp (upw_type, NM_VPNC_PW_TYPE_UNUSED))
+		gnome_two_password_dialog_set_show_password (dialog, FALSE);
+	else if (!retry && found_upw && strcmp (upw_type, NM_VPNC_PW_TYPE_ASK))
+		gnome_two_password_dialog_set_show_password (dialog, FALSE);
+
+	if (!strcmp (gpw_type, NM_VPNC_PW_TYPE_UNUSED))
+		gnome_two_password_dialog_set_show_password_secondary (dialog, FALSE);
+	else if (!retry && found_gpw && strcmp (gpw_type, NM_VPNC_PW_TYPE_ASK))
+		gnome_two_password_dialog_set_show_password_secondary (dialog, FALSE);
+
+	/* On reprompt the first entry of type 'ask' gets the focus */
+	if (retry) {
+		if (!strcmp (upw_type, NM_VPNC_PW_TYPE_ASK))
+			gnome_two_password_dialog_focus_password (dialog);
+		else if (!strcmp (gpw_type, NM_VPNC_PW_TYPE_ASK))
+			gnome_two_password_dialog_focus_password_secondary (dialog);
+	}
 
 	/* if retrying, pre-fill dialog with the password */
-	if (*password) {
-		gnome_two_password_dialog_set_password (dialog, *password);
-		gnome_keyring_memory_free (*password);
-		*password = NULL;
-	}
-	if (*group_password) {
-		gnome_two_password_dialog_set_password_secondary (dialog, *group_password);
-		gnome_keyring_memory_free (*group_password);
-		*group_password = NULL;
+	if (*upw) {
+		gnome_two_password_dialog_set_password (dialog, *upw);
+		gnome_keyring_memory_free (*upw);
+		*upw = NULL;
+	}
+	if (*gpw) {
+		gnome_two_password_dialog_set_password_secondary (dialog, *gpw);
+		gnome_keyring_memory_free (*gpw);
+		*gpw = NULL;
 	}
 
 	gtk_widget_show (GTK_WIDGET (dialog));
 
-	if (gnome_two_password_dialog_run_and_block (dialog)) {
-		*password = gnome_two_password_dialog_get_password (dialog);
-		*group_password = gnome_two_password_dialog_get_password_secondary (dialog);
-
-		switch (gnome_two_password_dialog_get_remember (dialog)) {
-		case GNOME_TWO_PASSWORD_DIALOG_REMEMBER_SESSION:
-			keyring_helpers_save_secret (vpn_uuid, vpn_name, "session", VPNC_USER_PASSWORD, *password);
-			keyring_helpers_save_secret (vpn_uuid, vpn_name, "session", VPNC_GROUP_PASSWORD, *group_password);
-			break;
-		case GNOME_TWO_PASSWORD_DIALOG_REMEMBER_FOREVER:
-			keyring_helpers_save_secret (vpn_uuid, vpn_name, NULL, VPNC_USER_PASSWORD, *password);
-			keyring_helpers_save_secret (vpn_uuid, vpn_name, NULL, VPNC_GROUP_PASSWORD, *group_password);
-			break;
-		default:
-			break;
-		}
+	success = gnome_two_password_dialog_run_and_block (dialog);
+	if (success) {
+		*upw = gnome_two_password_dialog_get_password (dialog);
+		*gpw = gnome_two_password_dialog_get_password_secondary (dialog);
+
+		if (!strcmp (upw_type, NM_VPNC_PW_TYPE_SAVE))
+			keyring_helpers_save_secret (vpn_uuid, vpn_name, NULL, VPNC_USER_PASSWORD, *upw);
 
+		if (!strcmp (gpw_type, NM_VPNC_PW_TYPE_SAVE))
+			keyring_helpers_save_secret (vpn_uuid, vpn_name, NULL, VPNC_GROUP_PASSWORD, *gpw);
 	}
 
 	gtk_widget_hide (GTK_WIDGET (dialog));
 	gtk_widget_destroy (GTK_WIDGET (dialog));
 
-	return TRUE;
+	return success;
+}
+
+static gboolean
+get_password_types (const char *vpn_uuid,
+                    char **out_upw_type,
+                    char **out_gpw_type)
+{
+	GConfClient *gconf_client = NULL;
+	GSList *conf_list;
+	GSList *iter;
+	char *key;
+	char *str;
+	char *connection_path = NULL;
+	gboolean success = FALSE;
+	char *upw_type = NULL, *gpw_type = NULL;
+
+	/* FIXME: This whole thing sucks: we should not go around poking gconf
+	   directly, but there's nothing that does it for us right now */
+
+	gconf_client = gconf_client_get_default ();
+
+	conf_list = gconf_client_all_dirs (gconf_client, "/system/networking/connections", NULL);
+	if (!conf_list)
+		goto out;
+
+	for (iter = conf_list; iter; iter = iter->next) {
+		const char *path = (const char *) iter->data;
+
+		key = g_strdup_printf ("%s/%s/%s", 
+		                       path,
+		                       NM_SETTING_CONNECTION_SETTING_NAME,
+		                       NM_SETTING_CONNECTION_TYPE);
+		str = gconf_client_get_string (gconf_client, key, NULL);
+		g_free (key);
+
+		if (!str || strcmp (str, "vpn")) {
+			g_free (str);
+			continue;
+		}
+		g_free (str);
+
+		key = g_strdup_printf ("%s/%s/%s", 
+		                       path,
+		                       NM_SETTING_CONNECTION_SETTING_NAME,
+		                       NM_SETTING_CONNECTION_UUID);
+		str = gconf_client_get_string (gconf_client, key, NULL);
+		g_free (key);
+
+		if (!str || strcmp (str, vpn_uuid)) {
+			g_free (str);
+			continue;
+		}
+		g_free (str);
+
+		/* Woo, found the connection */
+		connection_path = g_strdup (path);
+		break;
+	}
+
+	g_slist_foreach (conf_list, (GFunc) g_free, NULL);
+	g_slist_free (conf_list);
+
+	if (!connection_path)
+		goto out;
+
+	key = g_strdup_printf ("%s/%s/%s", connection_path,
+	                       NM_SETTING_VPN_SETTING_NAME,
+	                       NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
+	*out_upw_type = gconf_client_get_string (gconf_client, key, NULL);
+	g_free (key);
+
+	key = g_strdup_printf ("%s/%s/%s", connection_path,
+	                       NM_SETTING_VPN_SETTING_NAME,
+	                       NM_VPNC_KEY_SECRET_TYPE);
+	*out_gpw_type = gconf_client_get_string (gconf_client, key, NULL);
+	g_free (key);
+	
+	g_free (connection_path);
+	success = TRUE;
+
+out:
+	g_object_unref (gconf_client);
+	return success;
 }
 
 int 
@@ -130,6 +253,7 @@
 	gchar *vpn_uuid = NULL;
 	gchar *vpn_service = NULL;
 	char *password = NULL, *group_password = NULL;
+	char *upw_type = NULL, *gpw_type = NULL;
 	char buf[1];
 	int ret;
 	GError *error = NULL;
@@ -168,12 +292,26 @@
 		return 1;
 	}
 
-	if (!get_secrets (vpn_uuid, vpn_name, retry, &password, &group_password))
+	if (!get_password_types (vpn_uuid, &upw_type, &gpw_type)) {
+		g_free (upw_type);
+		g_free (gpw_type);
+		fprintf (stderr, "This VPN connection '%s' (%s) could not be found in GConf.", vpn_name, vpn_uuid);
 		return 1;
+	}
+
+	if (!get_secrets (vpn_uuid, vpn_name, retry, &password, upw_type, &group_password, gpw_type)) {
+		g_free (upw_type);
+		g_free (gpw_type);
+		return 1;
+	}
+	g_free (upw_type);
+	g_free (gpw_type);
 
 	/* dump the passwords to stdout */
-	printf ("%s\n%s\n", NM_VPNC_KEY_XAUTH_PASSWORD, password);
-	printf ("%s\n%s\n", NM_VPNC_KEY_SECRET, group_password);
+	if (password)
+		printf ("%s\n%s\n", NM_VPNC_KEY_XAUTH_PASSWORD, password);
+	if (group_password)
+		printf ("%s\n%s\n", NM_VPNC_KEY_SECRET, group_password);
 	printf ("\n\n");
 
 	if (password) {

Modified: trunk/vpn-daemons/vpnc/common-gnome/keyring-helpers.c
==============================================================================
--- trunk/vpn-daemons/vpnc/common-gnome/keyring-helpers.c	(original)
+++ trunk/vpn-daemons/vpnc/common-gnome/keyring-helpers.c	Fri Nov 14 16:55:59 2008
@@ -98,6 +98,22 @@
 	return TRUE;
 }
 
+gboolean
+keyring_helpers_get_one_secret (const char *vpn_uuid,
+                                const char *which_secret,
+                                char **password,
+                                gboolean *is_session)
+{
+	g_return_val_if_fail (password != NULL, FALSE);
+	g_return_val_if_fail (*password == NULL, FALSE);
+
+	*password = find_one_password (vpn_uuid, which_secret, is_session);
+	if (!*password)
+		return FALSE;
+
+	return TRUE;
+}
+
 GnomeKeyringResult
 keyring_helpers_save_secret (const char *vpn_uuid,
                              const char *vpn_name,

Modified: trunk/vpn-daemons/vpnc/common-gnome/keyring-helpers.h
==============================================================================
--- trunk/vpn-daemons/vpnc/common-gnome/keyring-helpers.h	(original)
+++ trunk/vpn-daemons/vpnc/common-gnome/keyring-helpers.h	Fri Nov 14 16:55:59 2008
@@ -34,6 +34,11 @@
                                          char **group_password,
                                          gboolean *is_session);
 
+gboolean keyring_helpers_get_one_secret (const char *vpn_uuid,
+                                         const char *which_secret,
+                                         char **password,
+                                         gboolean *is_session);
+
 GnomeKeyringResult keyring_helpers_save_secret (const char *vpn_uuid,
                                                 const char *vpn_name,
                                                 const char *keyring,

Modified: trunk/vpn-daemons/vpnc/properties/nm-vpnc-dialog.glade
==============================================================================
--- trunk/vpn-daemons/vpnc/properties/nm-vpnc-dialog.glade	(original)
+++ trunk/vpn-daemons/vpnc/properties/nm-vpnc-dialog.glade	Fri Nov 14 16:55:59 2008
@@ -33,13 +33,46 @@
                   <widget class="GtkTable" id="table2">
                     <property name="visible">True</property>
                     <property name="n_rows">5</property>
-                    <property name="n_columns">2</property>
+                    <property name="n_columns">3</property>
                     <property name="column_spacing">6</property>
                     <property name="row_spacing">6</property>
                     <child>
                       <placeholder/>
                     </child>
                     <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <widget class="GtkComboBox" id="group_pass_type_combo">
+                        <property name="visible">True</property>
+                        <property name="items" translatable="yes"> </property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">2</property>
+                        <property name="right_attach">3</property>
+                        <property name="top_attach">3</property>
+                        <property name="bottom_attach">4</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkComboBox" id="user_pass_type_combo">
+                        <property name="visible">True</property>
+                        <property name="items" translatable="yes"> </property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">2</property>
+                        <property name="right_attach">3</property>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
+                      </packing>
+                    </child>
+                    <child>
                       <widget class="GtkCheckButton" id="show_passwords_checkbutton">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>

Modified: trunk/vpn-daemons/vpnc/properties/nm-vpnc.c
==============================================================================
--- trunk/vpn-daemons/vpnc/properties/nm-vpnc.c	(original)
+++ trunk/vpn-daemons/vpnc/properties/nm-vpnc.c	Fri Nov 14 16:55:59 2008
@@ -58,6 +58,10 @@
 #define ENC_TYPE_WEAK   1
 #define ENC_TYPE_NONE   2
 
+#define PW_TYPE_SAVE   0
+#define PW_TYPE_ASK	   1
+#define PW_TYPE_UNUSED 2
+
 /************** plugin class **************/
 
 static void vpnc_plugin_ui_interface_init (NMVpnPluginUiInterface *iface_class);
@@ -188,14 +192,21 @@
 			}
 		} else {
 			s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
-			keyring_helpers_lookup_secrets (nm_setting_connection_get_uuid (s_con),
-			                                &password, &group_password, NULL);
 
-			/* If they weren't in the keyring, maybe they are already in the conneciton
-			 * (from import, perhaps).
+			/* Lookup passwords in the keyring, and if they weren't there, try
+			 * the connection itself, which is where they'd be right after import.
 			 */
+			keyring_helpers_get_one_secret (nm_setting_connection_get_uuid (s_con),
+			                                VPNC_USER_PASSWORD,
+			                                &password,
+			                                NULL);
 			if (!password)
 				password = gnome_keyring_memory_strdup (nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD));
+
+			keyring_helpers_get_one_secret (nm_setting_connection_get_uuid (s_con),
+			                                VPNC_GROUP_PASSWORD,
+			                                &group_password,
+			                                NULL);
 			if (!group_password)
 				group_password = gnome_keyring_memory_strdup (nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_SECRET));
 		}
@@ -246,6 +257,101 @@
 	gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
 }
 
+static void
+pw_type_changed_helper (VpncPluginUiWidget *self, GtkWidget *combo)
+{
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
+	const char *entry = NULL;
+	GtkWidget *widget;
+	GtkTreeModel *model;
+
+	/* If the user chose "Not required", desensitize and clear the correct
+	 * password entry.
+	 */
+	widget = glade_xml_get_widget (priv->xml, "user_pass_type_combo");
+	if (combo == widget)
+		entry = "user_password_entry";
+	else {
+		widget = glade_xml_get_widget (priv->xml, "group_pass_type_combo");
+		if (combo == widget)
+			entry = "group_password_entry";
+	}
+	if (!entry)
+		return;
+
+	widget = glade_xml_get_widget (priv->xml, entry);
+	g_assert (widget);
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+	switch (gtk_combo_box_get_active (GTK_COMBO_BOX (combo))) {
+	case PW_TYPE_ASK:
+	case PW_TYPE_UNUSED:
+		gtk_entry_set_text (GTK_ENTRY (widget), "");
+		gtk_widget_set_sensitive (widget, FALSE);
+		break;
+	default:
+		gtk_widget_set_sensitive (widget, TRUE);
+		break;
+	}
+}
+
+static void
+pw_type_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+	VpncPluginUiWidget *self = VPNC_PLUGIN_UI_WIDGET (user_data);
+
+	pw_type_changed_helper (self, combo);
+	stuff_changed_cb (combo, self);
+}
+
+static void
+init_one_pw_combo (VpncPluginUiWidget *self,
+                   NMSettingVPN *s_vpn,
+                   const char *combo_name,
+                   const char *key)
+{
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
+	int active = -1;
+	GtkWidget *widget;
+	GtkListStore *store;
+	GtkTreeIter iter;
+	const char *value = NULL;
+
+	store = gtk_list_store_new (1, G_TYPE_STRING);
+	if (s_vpn)
+		value = nm_setting_vpn_get_data_item (s_vpn, key);
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("Saved"), -1);
+	if ((active < 0) && value) {
+		if (!strcmp (value, NM_VPNC_PW_TYPE_SAVE))
+			active = 0;
+	}
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("Always Ask"), -1);
+	if ((active < 0) && value) {
+		if (!strcmp (value, NM_VPNC_PW_TYPE_ASK))
+			active = 1;
+	}
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter, 0, _("Not Required"), -1);
+	if ((active < 0) && value) {
+		if (!strcmp (value, NM_VPNC_PW_TYPE_UNUSED))
+			active = 2;
+	}
+
+	widget = glade_xml_get_widget (priv->xml, combo_name);
+	g_assert (widget);
+	gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (store));
+	g_object_unref (store);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), active < 0 ? 0 : active);
+	pw_type_changed_helper (self, widget);
+
+	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (pw_type_combo_changed_cb), self);
+}
+
 static gboolean
 init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **error)
 {
@@ -254,7 +360,7 @@
 	GtkWidget *widget;
 	GtkListStore *store;
 	GtkTreeIter iter;
-	const char *value;
+	const char *value = NULL;
 	int active = -1;
 	const char *natt_mode = NULL;
 
@@ -312,6 +418,9 @@
 	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), active < 0 ? 0 : active);
 	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
 
+	init_one_pw_combo (self, s_vpn, "user_pass_type_combo", NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
+	init_one_pw_combo (self, s_vpn, "group_pass_type_combo", NM_VPNC_KEY_SECRET_TYPE);
+
 	widget = glade_xml_get_widget (priv->xml, "user_entry");
 	g_return_val_if_fail (widget != NULL, FALSE);
 	gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget));
@@ -404,6 +513,34 @@
 	return G_OBJECT (priv->widget);
 }
 
+static guint32
+handle_one_pw_type (NMSettingVPN *s_vpn, GladeXML *xml, const char *name, const char *key)
+{
+	GtkWidget *widget;
+	GtkTreeModel *model;
+	guint32 pw_type;
+
+	widget = glade_xml_get_widget (xml, name);
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+
+	pw_type = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+	switch (pw_type) {
+	case PW_TYPE_SAVE:
+		nm_setting_vpn_add_data_item (s_vpn, key, NM_VPNC_PW_TYPE_SAVE);
+		break;
+	case PW_TYPE_UNUSED:
+		nm_setting_vpn_add_data_item (s_vpn, key, NM_VPNC_PW_TYPE_UNUSED);
+		break;
+	case PW_TYPE_ASK:
+	default:
+		pw_type = PW_TYPE_ASK;
+		nm_setting_vpn_add_data_item (s_vpn, key, NM_VPNC_PW_TYPE_ASK);
+		break;
+	}
+
+	return pw_type;
+}
+
 static gboolean
 update_connection (NMVpnPluginUiWidgetInterface *iface,
                    NMConnection *connection,
@@ -416,6 +553,7 @@
 	char *str;
 	GtkTreeModel *model;
 	GtkTreeIter iter;
+	guint32 upw_type, gpw_type;
 
 	if (!check_validity (self, error))
 		return FALSE;
@@ -461,13 +599,13 @@
 	widget = glade_xml_get_widget (priv->xml, "natt_combo");
 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
 	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
-		const char *mode;
+		const char *mode = NULL;
 
 		gtk_tree_model_get (model, &iter, 1, &mode, -1);
 		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_NAT_TRAVERSAL_MODE, mode);
 	} else
 		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_NAT_TRAVERSAL_MODE, NM_VPNC_NATT_MODE_NATT);
-	
+
 	widget = glade_xml_get_widget (priv->xml, "disable_dpd_checkbutton");
 	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
 		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_DPD_IDLE_TIMEOUT, "0");
@@ -483,6 +621,9 @@
 		}
 	}
 
+	upw_type = handle_one_pw_type (s_vpn, priv->xml, "user_pass_type_combo", NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
+	gpw_type = handle_one_pw_type (s_vpn, priv->xml, "group_pass_type_combo", NM_VPNC_KEY_SECRET_TYPE);
+
 	/* System secrets get stored in the connection, user secrets are saved
 	 * via the save_secrets() hook.
 	 */
@@ -490,13 +631,13 @@
 		/* User password */
 		widget = glade_xml_get_widget (priv->xml, "user_password_entry");
 		str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
-		if (str && strlen (str))
+		if (str && strlen (str) && (upw_type != PW_TYPE_UNUSED))
 			nm_setting_vpn_add_secret (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD, str);
 
 		/* Group password */
 		widget = glade_xml_get_widget (priv->xml, "group_password_entry");
 		str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
-		if (str && strlen (str))
+		if (str && strlen (str) && (gpw_type != PW_TYPE_UNUSED))
 			nm_setting_vpn_add_secret (s_vpn, NM_VPNC_KEY_SECRET, str);
 	}
 
@@ -504,6 +645,41 @@
 	return TRUE;
 }
 
+static void
+save_one_password (GladeXML *xml,
+                   const char *keyring_tag,
+                   const char *uuid,
+                   const char *id,
+                   const char *entry,
+                   const char *combo,
+                   const char *desc)
+{
+	GnomeKeyringResult ret;
+	GtkWidget *widget;
+	const char *password;
+	GtkTreeModel *model;
+	gboolean saved = FALSE;
+
+	widget = glade_xml_get_widget (xml, combo);
+	g_assert (widget);
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == PW_TYPE_SAVE) {
+		widget = glade_xml_get_widget (xml, entry);
+		g_assert (widget);
+		password = gtk_entry_get_text (GTK_ENTRY (widget));
+		if (password && strlen (password)) {
+			ret = keyring_helpers_save_secret (uuid, id, NULL, keyring_tag, password);
+			if (ret == GNOME_KEYRING_RESULT_OK)
+				saved = TRUE;
+			else
+				g_warning ("%s: failed to save %s to keyring.", __func__, desc);
+		}
+	}
+
+	if (!saved)
+		keyring_helpers_delete_secret (uuid, keyring_tag);
+}
+
 static gboolean
 save_secrets (NMVpnPluginUiWidgetInterface *iface,
               NMConnection *connection,
@@ -511,9 +687,7 @@
 {
 	VpncPluginUiWidget *self = VPNC_PLUGIN_UI_WIDGET (iface);
 	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
-	GnomeKeyringResult ret;
 	NMSettingConnection *s_con;
-	GtkWidget *widget;
 	const char *str, *id, *uuid;
 
 	s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
@@ -528,25 +702,10 @@
 	id = nm_setting_connection_get_id (s_con);
 	uuid = nm_setting_connection_get_uuid (s_con);
 
-	widget = glade_xml_get_widget (priv->xml, "user_password_entry");
-	g_assert (widget);
-	str = gtk_entry_get_text (GTK_ENTRY (widget));
-	if (str && strlen (str)) {
-		ret = keyring_helpers_save_secret (uuid, id, NULL, VPNC_USER_PASSWORD, str);
-		if (ret != GNOME_KEYRING_RESULT_OK)
-			g_warning ("%s: failed to save user password to keyring.", __func__);
-	} else
-		keyring_helpers_delete_secret (uuid, VPNC_USER_PASSWORD);
-
-	widget = glade_xml_get_widget (priv->xml, "group_password_entry");
-	g_assert (widget);
-	str = gtk_entry_get_text (GTK_ENTRY (widget));
-	if (str && strlen (str)) {
-		ret = keyring_helpers_save_secret (uuid, id, NULL, VPNC_GROUP_PASSWORD, str);
-		if (ret != GNOME_KEYRING_RESULT_OK)
-			g_warning ("%s: failed to save group password to keyring.", __func__);
-	} else
-		keyring_helpers_delete_secret (uuid, VPNC_GROUP_PASSWORD);
+	save_one_password (priv->xml, VPNC_USER_PASSWORD, uuid, id,
+	                   "user_password_entry", "user_pass_type_combo", "user password");
+	save_one_password (priv->xml, VPNC_GROUP_PASSWORD, uuid, id,
+	                   "group_password_entry", "group_pass_type_combo", "group password");
 
 	return TRUE;
 }

Modified: trunk/vpn-daemons/vpnc/src/nm-vpnc-service.c
==============================================================================
--- trunk/vpn-daemons/vpnc/src/nm-vpnc-service.c	(original)
+++ trunk/vpn-daemons/vpnc/src/nm-vpnc-service.c	Fri Nov 14 16:55:59 2008
@@ -55,6 +55,9 @@
 	{ NM_VPNC_KEY_DPD_IDLE_TIMEOUT,      G_TYPE_INT, 0, 86400 },
 	{ NM_VPNC_KEY_NAT_TRAVERSAL_MODE,    G_TYPE_STRING, 0, 0 },
 	{ NM_VPNC_KEY_CISCO_UDP_ENCAPS_PORT, G_TYPE_INT, 0, 65535 },
+	/* Ignored option for internal use */
+	{ NM_VPNC_KEY_SECRET_TYPE,           G_TYPE_NONE, 0, 0 },
+	{ NM_VPNC_KEY_XAUTH_PASSWORD_TYPE,   G_TYPE_NONE, 0, 0 },
 	/* Legacy options that are ignored */
 	{ LEGACY_NAT_KEEPALIVE,              G_TYPE_STRING, 0, 0 },
 	{ NULL,                              G_TYPE_NONE, 0, 0 }
@@ -95,6 +98,8 @@
 			continue;
 
 		switch (prop.type) {
+		case G_TYPE_NONE:
+			return; /* technically valid, but unused */
 		case G_TYPE_STRING:
 			return; /* valid */
 		case G_TYPE_INT:
@@ -285,6 +290,8 @@
 typedef struct {
 	int fd;
 	GError *error;
+	gboolean upw_ignored;
+	gboolean gpw_ignored;
 } WriteConfigInfo;
 
 static void
@@ -327,6 +334,12 @@
 		             (const char *) key);
 	}	
 
+	/* Don't write ignored secrets */
+	if (!strcmp (key, NM_VPNC_KEY_XAUTH_PASSWORD) && info->upw_ignored)
+		return;
+	if (!strcmp (key, NM_VPNC_KEY_SECRET) && info->gpw_ignored)
+		return;
+
 	if (type == G_TYPE_STRING)
 		write_config_option (info->fd, "%s %s\n", (char *) key, (char *) value);
 	else if (type == G_TYPE_BOOLEAN) {
@@ -352,6 +365,8 @@
 			             "Config option '%s' not an integer.",
 			             (const char *) key);
 		}
+	} else if (type == G_TYPE_NONE) {
+		/* ignored */
 	} else {
 		/* Just ignore unknown properties */
 		nm_warning ("Don't know how to write property '%s' with type %s",
@@ -368,6 +383,7 @@
 	const char *props_username;
 	const char *props_natt_mode;
 	const char *default_username;
+	const char *pw_type;
 
 	default_username = nm_setting_vpn_get_user_name (s_vpn);
 
@@ -397,6 +413,17 @@
 
 	info = g_malloc0 (sizeof (WriteConfigInfo));
 	info->fd = vpnc_fd;
+
+	/* Check for ignored user password */
+	pw_type = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
+	if (pw_type && !strcmp (pw_type, NM_VPNC_PW_TYPE_UNUSED))
+		info->upw_ignored = TRUE;
+
+	/* Check for ignored group password */
+	pw_type = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_SECRET_TYPE);
+	if (pw_type && !strcmp (pw_type, NM_VPNC_PW_TYPE_UNUSED))
+		info->gpw_ignored = TRUE;
+
 	nm_setting_vpn_foreach_data_item (s_vpn, write_one_property, info);
 	nm_setting_vpn_foreach_secret (s_vpn, write_one_property, info);
 	*error = info->error;
@@ -444,6 +471,7 @@
                    GError **error)
 {
 	NMSettingVPN *s_vpn;
+	const char *pw_type;
 
 	g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
@@ -458,15 +486,20 @@
 		return FALSE;
 	}
 
-	// FIXME: there are some configurations where both passwords are not
-	// required.  Make sure they work somehow.
-	if (!nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_SECRET)) {
-		*setting_name = NM_SETTING_VPN_SETTING_NAME;
-		return TRUE;
-	}
-	if (!nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD)) {
-		*setting_name = NM_SETTING_VPN_SETTING_NAME;
-		return TRUE;
+	pw_type = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_SECRET_TYPE);
+	if (!pw_type || strcmp (pw_type, NM_VPNC_PW_TYPE_UNUSED)) {
+		if (!nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_SECRET)) {
+			*setting_name = NM_SETTING_VPN_SETTING_NAME;
+			return TRUE;
+		}
+	}
+
+	pw_type = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
+	if (!pw_type || strcmp (pw_type, NM_VPNC_PW_TYPE_UNUSED)) {
+		if (!nm_setting_vpn_get_secret (s_vpn, NM_VPNC_KEY_XAUTH_PASSWORD)) {
+			*setting_name = NM_SETTING_VPN_SETTING_NAME;
+			return TRUE;
+		}
 	}
 
 	return FALSE;

Modified: trunk/vpn-daemons/vpnc/src/nm-vpnc-service.h
==============================================================================
--- trunk/vpn-daemons/vpnc/src/nm-vpnc-service.h	(original)
+++ trunk/vpn-daemons/vpnc/src/nm-vpnc-service.h	Fri Nov 14 16:55:59 2008
@@ -21,8 +21,10 @@
 #define NM_VPNC_KEY_GATEWAY "IPSec gateway"
 #define NM_VPNC_KEY_ID "IPSec ID"
 #define NM_VPNC_KEY_SECRET "IPSec secret"
+#define NM_VPNC_KEY_SECRET_TYPE "ipsec-secret-type"
 #define NM_VPNC_KEY_XAUTH_USER "Xauth username"
 #define NM_VPNC_KEY_XAUTH_PASSWORD "Xauth password"
+#define NM_VPNC_KEY_XAUTH_PASSWORD_TYPE "xauth-password-type"
 #define NM_VPNC_KEY_DOMAIN "Domain"
 #define NM_VPNC_KEY_DHGROUP "IKE DH Group"
 #define NM_VPNC_KEY_PERFECT_FORWARD "Perfect Forward Secrecy"
@@ -37,6 +39,10 @@
 #define NM_VPNC_NATT_MODE_NONE "none"
 #define NM_VPNC_NATT_MODE_CISCO "cisco-udp"
 
+#define NM_VPNC_PW_TYPE_SAVE   "save"
+#define NM_VPNC_PW_TYPE_ASK    "ask"
+#define NM_VPNC_PW_TYPE_UNUSED "unused"
+
 typedef struct {
 	NMVPNPlugin parent;
 } NMVPNCPlugin;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]