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



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4283 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams 2008-11-14 16:55:59 +00:00
parent a2967685db
commit a4d0b07484
11 changed files with 541 additions and 86 deletions

View file

@ -1,3 +1,43 @@
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
2008-11-03 Dan Williams <dcbw@redhat.com>
Patch from Carlos Martín Nieto <carlos@cmartin.tk> (and me) (bgo #547582)

View file

@ -6,6 +6,7 @@ nm_vpnc_auth_dialog_CPPFLAGS = \
$(NM_UTILS_CFLAGS) \
$(GTHREAD_CFLAGS) \
$(GTK_CFLAGS) \
$(GCONF_CFLAGS) \
$(GNOMEKEYRING_CFLAGS) \
-DICONDIR=\""$(datadir)/pixmaps"\" \
-DGLADEDIR=\""$(gladedir)"\" \
@ -24,6 +25,8 @@ nm_vpnc_auth_dialog_SOURCES = \
nm_vpnc_auth_dialog_LDADD = \
$(GTK_LIBS) \
$(GCONF_LIBS) \
$(top_builddir)/common-gnome/libnm-vpnc-common-gnome.la
CLEANFILES = *~

View file

@ -592,6 +592,26 @@ gnome_two_password_dialog_set_show_password_secondary (GnomeTwoPasswordDialog *p
}
}
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)

View file

@ -77,8 +77,10 @@ void gnome_two_password_dialog_set_show_domain (GnomeTwoPasswordDial
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,

View file

@ -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 @@ static gboolean
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);
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);
found = keyring_helpers_lookup_secrets (vpn_uuid, password, group_password, &is_session);
if (!retry && found && *password && *group_password)
return TRUE;
/* 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 @@ get_secrets (const char *vpn_uuid,
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 (*upw) {
gnome_two_password_dialog_set_password (dialog, *upw);
gnome_keyring_memory_free (*upw);
*upw = NULL;
}
if (*group_password) {
gnome_two_password_dialog_set_password_secondary (dialog, *group_password);
gnome_keyring_memory_free (*group_password);
*group_password = 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);
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);
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;
}
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 @@ main (int argc, char *argv[])
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 @@ main (int argc, char *argv[])
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) {

View file

@ -98,6 +98,22 @@ keyring_helpers_lookup_secrets (const char *vpn_uuid,
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,

View file

@ -34,6 +34,11 @@ gboolean keyring_helpers_lookup_secrets (const char *vpn_uuid,
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,

View file

@ -33,12 +33,45 @@
<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>

View file

@ -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 @@ fill_vpn_passwords (VpncPluginUiWidget *self, NMConnection *connection)
}
} 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 @@ show_toggled_cb (GtkCheckButton *button, VpncPluginUiWidget *self)
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 @@ init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **err
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 @@ init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **err
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 @@ get_widget (NMVpnPluginUiWidgetInterface *iface)
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 @@ update_connection (NMVpnPluginUiWidgetInterface *iface,
char *str;
GtkTreeModel *model;
GtkTreeIter iter;
guint32 upw_type, gpw_type;
if (!check_validity (self, error))
return FALSE;
@ -461,13 +599,13 @@ update_connection (NMVpnPluginUiWidgetInterface *iface,
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 @@ update_connection (NMVpnPluginUiWidgetInterface *iface,
}
}
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 @@ update_connection (NMVpnPluginUiWidgetInterface *iface,
/* 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 @@ update_connection (NMVpnPluginUiWidgetInterface *iface,
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 @@ save_secrets (NMVpnPluginUiWidgetInterface *iface,
{
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 @@ save_secrets (NMVpnPluginUiWidgetInterface *iface,
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;
}

View file

@ -55,6 +55,9 @@ static ValidProperty valid_properties[] = {
{ 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 @@ validate_one_property (const char *key, const char *value, gpointer user_data)
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 @@ write_config_option (int fd, const char *format, ...)
typedef struct {
int fd;
GError *error;
gboolean upw_ignored;
gboolean gpw_ignored;
} WriteConfigInfo;
static void
@ -327,6 +334,12 @@ write_one_property (const char *key, const char *value, gpointer user_data)
(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 @@ write_one_property (const char *key, const char *value, gpointer user_data)
"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 @@ nm_vpnc_config_write (gint vpnc_fd,
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 @@ nm_vpnc_config_write (gint vpnc_fd,
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 @@ real_need_secrets (NMVPNPlugin *plugin,
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 @@ real_need_secrets (NMVPNPlugin *plugin,
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;
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;
}
}
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_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;

View file

@ -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;