From 3113ba4bcf930a365d68942b7cd629f706551e43 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 11 Aug 2008 17:15:42 +0000 Subject: [PATCH] 2008-08-11 Dan Williams Update to match NM svn3924 vpn setting changes; verify options better; return more informative errors on VPN launch failures. git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3925 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- vpn-daemons/vpnc/ChangeLog | 5 + vpn-daemons/vpnc/auth-dialog/main.c | 7 +- vpn-daemons/vpnc/properties/nm-vpnc.c | 239 +++++++++------------- vpn-daemons/vpnc/src/nm-vpnc-service.c | 267 ++++++++++++++++--------- 4 files changed, 284 insertions(+), 234 deletions(-) diff --git a/vpn-daemons/vpnc/ChangeLog b/vpn-daemons/vpnc/ChangeLog index 0d254c57e6..948591e927 100644 --- a/vpn-daemons/vpnc/ChangeLog +++ b/vpn-daemons/vpnc/ChangeLog @@ -1,3 +1,8 @@ +2008-08-11 Dan Williams + + Update to match NM svn3924 vpn setting changes; verify options better; + return more informative errors on VPN launch failures. + 2008-08-06 Dan Williams * src/nm-vpnc-service-vpnc-helper.c diff --git a/vpn-daemons/vpnc/auth-dialog/main.c b/vpn-daemons/vpnc/auth-dialog/main.c index 451c8c3367..312ed0c897 100644 --- a/vpn-daemons/vpnc/auth-dialog/main.c +++ b/vpn-daemons/vpnc/auth-dialog/main.c @@ -30,7 +30,6 @@ #include #include -#include #include "../src/nm-vpnc-service.h" #include "gnome-two-password-dialog.h" @@ -58,7 +57,7 @@ find_one_password (const char *vpn_id, vpn_id, KEYRING_SN_TAG, GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, - NM_SETTING_VPN_PROPERTIES_SETTING_NAME, + NM_SETTING_VPN_SETTING_NAME, KEYRING_SK_TAG, GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, secret_name, @@ -115,7 +114,7 @@ save_vpn_password (const char *vpn_id, GnomeKeyringAttributeList *attrs = NULL; guint32 id = 0; - display_name = g_strdup_printf ("VPN %s secret for %s/%s/" NM_SETTING_VPN_PROPERTIES_SETTING_NAME, + display_name = g_strdup_printf ("VPN %s secret for %s/%s/" NM_SETTING_VPN_SETTING_NAME, secret_name, vpn_name, vpn_service); @@ -126,7 +125,7 @@ save_vpn_password (const char *vpn_id, vpn_id); gnome_keyring_attribute_list_append_string (attrs, KEYRING_SN_TAG, - NM_SETTING_VPN_PROPERTIES_SETTING_NAME); + NM_SETTING_VPN_SETTING_NAME); gnome_keyring_attribute_list_append_string (attrs, KEYRING_SK_TAG, secret_name); diff --git a/vpn-daemons/vpnc/properties/nm-vpnc.c b/vpn-daemons/vpnc/properties/nm-vpnc.c index 8a97e2f399..2db4f7e8b8 100644 --- a/vpn-daemons/vpnc/properties/nm-vpnc.c +++ b/vpn-daemons/vpnc/properties/nm-vpnc.c @@ -40,7 +40,6 @@ #include #include -#include #include #include @@ -159,15 +158,15 @@ static gboolean init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **error) { VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self); - NMSettingVPNProperties *s_vpn_props; + NMSettingVPN *s_vpn; GtkWidget *widget; GtkListStore *store; GtkTreeIter iter; + char *value; int active = -1; - GValue *value; const char *natt_mode = NULL; - s_vpn_props = (NMSettingVPNProperties *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN_PROPERTIES); + s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN); priv->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); @@ -175,10 +174,10 @@ init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **err if (!widget) return FALSE; gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget)); - if (s_vpn_props) { - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_GATEWAY); - if (value && G_VALUE_HOLDS_STRING (value)) - gtk_entry_set_text (GTK_ENTRY (widget), g_value_get_string (value)); + if (s_vpn) { + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_GATEWAY); + if (value && strlen (value)) + gtk_entry_set_text (GTK_ENTRY (widget), value); } g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self); @@ -186,10 +185,10 @@ init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **err if (!widget) return FALSE; gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget)); - if (s_vpn_props) { - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_ID); - if (value && G_VALUE_HOLDS_STRING (value)) - gtk_entry_set_text (GTK_ENTRY (widget), g_value_get_string (value)); + if (s_vpn) { + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_ID); + if (value && strlen (value)) + gtk_entry_set_text (GTK_ENTRY (widget), value); } g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self); @@ -205,17 +204,17 @@ init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **err gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, _("Weak (use with caution)"), -1); - if ((active < 0) && s_vpn_props) { - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_SINGLE_DES); - if (value && G_VALUE_HOLDS_BOOLEAN (value) && g_value_get_boolean (value)) + if (s_vpn && (active < 0)) { + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_SINGLE_DES); + if (value && !strcmp (value, "yes")) active = 1; } gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, _("None (completely insecure)"), -1); - if ((active < 0) && s_vpn_props) { - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_NO_ENCRYPTION); - if (value && G_VALUE_HOLDS_BOOLEAN (value) && g_value_get_boolean (value)) + if (s_vpn && (active < 0)) { + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_NO_ENCRYPTION); + if (value && !strcmp (value, "yes")) active = 2; } @@ -228,12 +227,10 @@ init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **err if (!widget) return FALSE; gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget)); - if (s_vpn_props) { - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_XAUTH_USER); - if (value && G_VALUE_HOLDS_STRING (value)) - gtk_entry_set_text (GTK_ENTRY (widget), g_value_get_string (value)); - else { - } + if (s_vpn) { + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_XAUTH_USER); + if (value && strlen (value)) + gtk_entry_set_text (GTK_ENTRY (widget), value); } g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self); @@ -241,20 +238,17 @@ init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **err if (!widget) return FALSE; gtk_size_group_add_widget (priv->group, GTK_WIDGET (widget)); - if (s_vpn_props) { - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_DOMAIN); - if (value && G_VALUE_HOLDS_STRING (value)) - gtk_entry_set_text (GTK_ENTRY (widget), g_value_get_string (value)); + if (s_vpn) { + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_DOMAIN); + if (value && strlen (value)) + gtk_entry_set_text (GTK_ENTRY (widget), value); } g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self); active = -1; store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); - if (s_vpn_props) { - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_NAT_TRAVERSAL_MODE); - if (value && G_VALUE_HOLDS_STRING (value)) - natt_mode = g_value_get_string (value); - } + if (s_vpn) + natt_mode = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_NAT_TRAVERSAL_MODE); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, _("NAT-T (default)"), 1, NM_VPNC_NATT_MODE_NATT, -1); @@ -289,10 +283,16 @@ init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **err widget = glade_xml_get_widget (priv->xml, "disable_dpd_checkbutton"); if (!widget) return FALSE; - if (s_vpn_props) { - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_DPD_IDLE_TIMEOUT); - if (value && G_VALUE_HOLDS_INT (value)) { - priv->orig_dpd_timeout = g_value_get_int (value); + if (s_vpn) { + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_DPD_IDLE_TIMEOUT); + if (value) { + long int tmp; + + errno = 0; + tmp = strtol (value, NULL, 10); + if (tmp >= 0 && tmp <= G_MAXUINT32 && errno == 0) + priv->orig_dpd_timeout = (guint32) tmp; + if (priv->orig_dpd_timeout == 0) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE); } @@ -311,42 +311,6 @@ get_widget (NMVpnPluginUiWidgetInterface *iface) return G_OBJECT (priv->widget); } -static GValue * -str_to_gvalue (const char *str) -{ - GValue *value; - - value = g_slice_new0 (GValue); - g_value_init (value, G_TYPE_STRING); - g_value_set_string (value, str); - - return value; -} - -static GValue * -bool_to_gvalue (gboolean b) -{ - GValue *value; - - value = g_slice_new0 (GValue); - g_value_init (value, G_TYPE_BOOLEAN); - g_value_set_boolean (value, b); - - return value; -} - -static GValue * -int_to_gvalue (gint i) -{ - GValue *value; - - value = g_slice_new0 (GValue); - g_value_init (value, G_TYPE_INT); - g_value_set_int (value, i); - - return value; -} - static gboolean update_connection (NMVpnPluginUiWidgetInterface *iface, NMConnection *connection, @@ -355,7 +319,6 @@ update_connection (NMVpnPluginUiWidgetInterface *iface, VpncPluginUiWidget *self = VPNC_PLUGIN_UI_WIDGET (iface); VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (self); NMSettingVPN *s_vpn; - NMSettingVPNProperties *s_vpn_props; GtkWidget *widget; char *str; GtkTreeModel *model; @@ -366,55 +329,52 @@ update_connection (NMVpnPluginUiWidgetInterface *iface, s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); s_vpn->service_type = g_strdup (NM_DBUS_SERVICE_VPNC); - nm_connection_add_setting (connection, NM_SETTING (s_vpn)); - - s_vpn_props = NM_SETTING_VPN_PROPERTIES (nm_setting_vpn_properties_new ()); /* Gateway */ widget = glade_xml_get_widget (priv->xml, "gateway_entry"); str = (char *) gtk_entry_get_text (GTK_ENTRY (widget)); if (str && strlen (str)) { - g_hash_table_insert (s_vpn_props->data, + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_GATEWAY), - str_to_gvalue (str)); + g_strdup (str)); } /* Group name */ widget = glade_xml_get_widget (priv->xml, "group_entry"); str = (char *) gtk_entry_get_text (GTK_ENTRY (widget)); if (str && strlen (str)) { - g_hash_table_insert (s_vpn_props->data, + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_ID), - str_to_gvalue (str)); + g_strdup (str)); } widget = glade_xml_get_widget (priv->xml, "user_entry"); str = (char *) gtk_entry_get_text (GTK_ENTRY (widget)); if (str && strlen (str)) { - g_hash_table_insert (s_vpn_props->data, + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_XAUTH_USER), - str_to_gvalue (str)); + g_strdup (str)); } widget = glade_xml_get_widget (priv->xml, "domain_entry"); str = (char *) gtk_entry_get_text (GTK_ENTRY (widget)); if (str && strlen (str)) { - g_hash_table_insert (s_vpn_props->data, + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_DOMAIN), - str_to_gvalue (str)); + g_strdup (str)); } widget = glade_xml_get_widget (priv->xml, "encryption_combo"); switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget))) { case ENC_TYPE_WEAK: - g_hash_table_insert (s_vpn_props->data, + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_SINGLE_DES), - bool_to_gvalue (TRUE)); + g_strdup ("yes")); break; case ENC_TYPE_NONE: - g_hash_table_insert (s_vpn_props->data, + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_NO_ENCRYPTION), - bool_to_gvalue (TRUE)); + g_strdup ("yes")); break; case ENC_TYPE_SECURE: default: @@ -427,27 +387,27 @@ update_connection (NMVpnPluginUiWidgetInterface *iface, const char *mode; gtk_tree_model_get (model, &iter, 1, &mode, -1); - g_hash_table_insert (s_vpn_props->data, + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_NAT_TRAVERSAL_MODE), - str_to_gvalue (mode)); + g_strdup (mode)); } else { - g_hash_table_insert (s_vpn_props->data, + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_NAT_TRAVERSAL_MODE), - str_to_gvalue (NM_VPNC_NATT_MODE_NATT)); + g_strdup (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))) { - g_hash_table_insert (s_vpn_props->data, + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_DPD_IDLE_TIMEOUT), - int_to_gvalue (0)); + g_strdup ("0")); } else { - g_hash_table_insert (s_vpn_props->data, + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_DPD_IDLE_TIMEOUT), - int_to_gvalue (priv->orig_dpd_timeout)); + g_strdup_printf ("%d", priv->orig_dpd_timeout)); } - nm_connection_add_setting (connection, NM_SETTING (s_vpn_props)); + nm_connection_add_setting (connection, NM_SETTING (s_vpn)); return TRUE; } @@ -591,7 +551,6 @@ import (NMVpnPluginUiInterface *iface, const char *path, GError **error) NMConnection *connection; NMSettingConnection *s_con; NMSettingVPN *s_vpn; - NMSettingVPNProperties *s_vpn_props; GHashTable *pcf; const char *buf; gboolean have_value; @@ -611,9 +570,6 @@ import (NMVpnPluginUiInterface *iface, const char *path, GError **error) s_vpn->service_type = g_strdup (VPNC_PLUGIN_SERVICE); nm_connection_add_setting (connection, NM_SETTING (s_vpn)); - s_vpn_props = NM_SETTING_VPN_PROPERTIES (nm_setting_vpn_properties_new ()); - nm_connection_add_setting (connection, NM_SETTING (s_vpn_props)); - /* Connection name */ if ((buf = pcf_file_lookup_value (pcf, "main", "Description"))) s_con->id = g_strdup (buf); @@ -626,7 +582,7 @@ import (NMVpnPluginUiInterface *iface, const char *path, GError **error) /* Gateway */ if ((buf = pcf_file_lookup_value (pcf, "main", "Host"))) - g_hash_table_insert (s_vpn_props->data, g_strdup (NM_VPNC_KEY_GATEWAY), str_to_gvalue (buf)); + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_GATEWAY), g_strdup (buf)); else { g_set_error (error, 0, 0, "does not look like a %s VPN connection (no Host)", VPNC_PLUGIN_NAME); @@ -636,7 +592,7 @@ import (NMVpnPluginUiInterface *iface, const char *path, GError **error) /* Group name */ if ((buf = pcf_file_lookup_value (pcf, "main", "GroupName"))) - g_hash_table_insert (s_vpn_props->data, g_strdup (NM_VPNC_KEY_ID), str_to_gvalue (buf)); + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_ID), g_strdup (buf)); else { g_set_error (error, 0, 0, "does not look like a %s VPN connection (no GroupName)", VPNC_PLUGIN_NAME); @@ -649,29 +605,34 @@ import (NMVpnPluginUiInterface *iface, const char *path, GError **error) buf = pcf_file_lookup_value (pcf, "main", "UserName"); have_value = buf == NULL ? FALSE : strlen (buf) > 0; if (have_value) - g_hash_table_insert (s_vpn_props->data, g_strdup (NM_VPNC_KEY_XAUTH_USER), str_to_gvalue (buf)); + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_XAUTH_USER), g_strdup (buf)); buf = pcf_file_lookup_value (pcf, "main", "NTDomain"); have_value = buf == NULL ? FALSE : strlen (buf) > 0; if (have_value) - g_hash_table_insert (s_vpn_props->data, g_strdup (NM_VPNC_KEY_DOMAIN), str_to_gvalue (buf)); + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_DOMAIN), g_strdup (buf)); buf = pcf_file_lookup_value (pcf, "main", "SingleDES"); have_value = (buf == NULL ? FALSE : strcmp (buf, "0") != 0); if (have_value) - g_hash_table_insert (s_vpn_props->data, g_strdup (NM_VPNC_KEY_SINGLE_DES), bool_to_gvalue (TRUE)); + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_SINGLE_DES), g_strdup ("yes")); /* Default is enabled, only disabled if explicit EnableNat=0 exists */ buf = pcf_file_lookup_value (pcf, "main", "EnableNat"); have_value = (buf ? strncmp (buf, "0", 1) == 0 : FALSE); if (have_value) - g_hash_table_insert (s_vpn_props->data, g_strdup (NM_VPNC_KEY_NAT_TRAVERSAL_MODE), str_to_gvalue (NM_VPNC_NATT_MODE_NATT)); + g_hash_table_insert (s_vpn->data, g_strdup (NM_VPNC_KEY_NAT_TRAVERSAL_MODE), g_strdup (NM_VPNC_NATT_MODE_NATT)); if ((buf = pcf_file_lookup_value (pcf, "main", "PeerTimeout"))) { - gulong val = strtol (buf, NULL, 10); + long int val; - if ((val == 0) || ((val > 10) && (val < 86400))) - g_hash_table_insert (s_vpn_props->data, g_strdup (NM_VPNC_KEY_DPD_IDLE_TIMEOUT), int_to_gvalue ((gint) val)); + errno = 0; + val = strtol (buf, NULL, 10); + if ((errno == 0) && ((val == 0) || ((val >= 10) && (val <= 86400)))) { + g_hash_table_insert (s_vpn->data, + g_strdup (NM_VPNC_KEY_DPD_IDLE_TIMEOUT), + g_strdup_printf ("%d", (gint) val)); + } } buf = pcf_file_lookup_value (pcf, "main", "X-NM-Routes"); @@ -715,25 +676,25 @@ export (NMVpnPluginUiInterface *iface, GError **error) { NMSettingConnection *s_con; - NMSettingVPNProperties *s_vpn_props; NMSettingIP4Config *s_ip4; + NMSettingVPN *s_vpn; FILE *f; - GValue *value; + const char *value; const char *gateway = NULL; gboolean enablenat = TRUE; gboolean singledes = FALSE; const char *groupname = NULL; const char *username = NULL; const char *domain = NULL; - int peertimeout = 0; + const char *peertimeout = NULL; GString *routes = NULL; gboolean success = FALSE; s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - s_vpn_props = (NMSettingVPNProperties *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN_PROPERTIES); - if (!s_vpn_props || !s_vpn_props->data) { + s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN); + if (!s_vpn || !s_vpn->data) { g_set_error (error, 0, 0, "connection was incomplete"); return FALSE; } @@ -744,43 +705,41 @@ export (NMVpnPluginUiInterface *iface, return FALSE; } - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_GATEWAY); - if (value && G_VALUE_HOLDS_STRING (value)) - gateway = g_value_get_string (value); + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_GATEWAY); + if (value && strlen (value)) + gateway = value; else { g_set_error (error, 0, 0, "connection was incomplete (missing gateway)"); goto done; } - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_ID); - if (value && G_VALUE_HOLDS_STRING (value)) - groupname = g_value_get_string (value); + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_ID); + if (value && strlen (value)) + groupname = value; else { g_set_error (error, 0, 0, "connection was incomplete (missing group)"); goto done; } - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_XAUTH_USER); - if (value && G_VALUE_HOLDS_STRING (value)) - username = g_value_get_string (value); + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_XAUTH_USER); + if (value && strlen (value)) + username = value; - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_DOMAIN); - if (value && G_VALUE_HOLDS_STRING (value)) - domain = g_value_get_string (value); + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_DOMAIN); + if (value && strlen (value)) + domain = value; - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_SINGLE_DES); - if (value && G_VALUE_HOLDS_BOOLEAN (value) && g_value_get_boolean (value)) + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_SINGLE_DES); + if (value && !strcmp (value, "yes")) singledes = TRUE; - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_NAT_TRAVERSAL_MODE); - if (value && G_VALUE_HOLDS_STRING (value)) { - if (strlen (g_value_get_string (value))) - enablenat = TRUE; - } + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_NAT_TRAVERSAL_MODE); + if (value && strlen (value) && strcmp (value, NM_VPNC_NATT_MODE_NONE)) + enablenat = TRUE; - value = g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_DPD_IDLE_TIMEOUT); - if (value && G_VALUE_HOLDS_INT (value)) - peertimeout = g_value_get_int (value); + value = g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_DPD_IDLE_TIMEOUT); + if (value && strlen (value)) + peertimeout = value; routes = g_string_new (""); if (s_ip4 && s_ip4->routes) { @@ -831,7 +790,7 @@ export (NMVpnPluginUiInterface *iface, "MSLogonType=0\n" "TunnelingMode=0\n" "TcpTunnelingPort=10000\n" - "PeerTimeout=%d\n" + "PeerTimeout=%s\n" "EnableLocalLAN=1\n" "SendCertChain=0\n" "VerifyCertDN=\n" @@ -845,7 +804,7 @@ export (NMVpnPluginUiInterface *iface, /* Username */ username != NULL ? username : "", /* EnableNat */ enablenat ? "1" : "0", /* NTDomain */ domain != NULL ? domain : "", - /* PeerTimeout */ peertimeout, + /* PeerTimeout */ peertimeout != NULL ? peertimeout : "0", /* SingleDES */ singledes ? "1" : "0", /* X-NM-Routes */ routes->str ? routes->str : ""); diff --git a/vpn-daemons/vpnc/src/nm-vpnc-service.c b/vpn-daemons/vpnc/src/nm-vpnc-service.c index 65d695cf20..904e900d07 100644 --- a/vpn-daemons/vpnc/src/nm-vpnc-service.c +++ b/vpn-daemons/vpnc/src/nm-vpnc-service.c @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ #include #include @@ -8,9 +8,9 @@ #include #include #include +#include #include -#include #include "nm-vpnc-service.h" #include "nm-utils.h" @@ -36,37 +36,39 @@ static const char *vpnc_binary_paths[] = typedef struct { const char *name; GType type; + gint int_min; + gint int_max; } ValidProperty; #define LEGACY_NAT_KEEPALIVE "NAT-Keepalive packet interval" static ValidProperty valid_properties[] = { - { NM_VPNC_KEY_GATEWAY, G_TYPE_STRING }, - { NM_VPNC_KEY_ID, G_TYPE_STRING }, - { NM_VPNC_KEY_SECRET, G_TYPE_STRING }, - { NM_VPNC_KEY_XAUTH_USER, G_TYPE_STRING }, - { NM_VPNC_KEY_XAUTH_PASSWORD, G_TYPE_STRING }, - { NM_VPNC_KEY_DOMAIN, G_TYPE_STRING }, - { NM_VPNC_KEY_DHGROUP, G_TYPE_STRING }, - { NM_VPNC_KEY_PERFECT_FORWARD, G_TYPE_STRING }, - { NM_VPNC_KEY_APP_VERSION, G_TYPE_STRING }, - { NM_VPNC_KEY_SINGLE_DES, G_TYPE_BOOLEAN }, - { NM_VPNC_KEY_NO_ENCRYPTION, G_TYPE_BOOLEAN }, - { NM_VPNC_KEY_DPD_IDLE_TIMEOUT, G_TYPE_INT }, - { NM_VPNC_KEY_NAT_TRAVERSAL_MODE, G_TYPE_STRING }, - { NM_VPNC_KEY_CISCO_UDP_ENCAPS_PORT, G_TYPE_INT }, + { NM_VPNC_KEY_GATEWAY, G_TYPE_STRING, 0, 0 }, + { NM_VPNC_KEY_ID, G_TYPE_STRING, 0, 0 }, + { NM_VPNC_KEY_SECRET, G_TYPE_STRING, 0, 0 }, + { NM_VPNC_KEY_XAUTH_USER, G_TYPE_STRING, 0, 0 }, + { NM_VPNC_KEY_XAUTH_PASSWORD, G_TYPE_STRING, 0, 0 }, + { NM_VPNC_KEY_DOMAIN, G_TYPE_STRING, 0, 0 }, + { NM_VPNC_KEY_DHGROUP, G_TYPE_STRING, 0, 0 }, + { NM_VPNC_KEY_PERFECT_FORWARD, G_TYPE_STRING, 0, 0 }, + { NM_VPNC_KEY_APP_VERSION, G_TYPE_STRING, 0, 0 }, + { NM_VPNC_KEY_SINGLE_DES, G_TYPE_BOOLEAN, 0, 0 }, + { NM_VPNC_KEY_NO_ENCRYPTION, G_TYPE_BOOLEAN, 0, 0 }, + { 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 }, /* Legacy options that are ignored */ - { LEGACY_NAT_KEEPALIVE, G_TYPE_STRING }, - { NULL, G_TYPE_NONE } + { LEGACY_NAT_KEEPALIVE, G_TYPE_STRING, 0, 0 }, + { NULL, G_TYPE_NONE, 0, 0 } }; static void -validate_one_property (gpointer key, gpointer val, gpointer user_data) +validate_one_property (gpointer key, gpointer value, gpointer user_data) { - gboolean *failed = (gboolean *) user_data; + GError **error = (GError **) user_data; int i; - if (*failed) + if (*error) return; /* 'name' is the setting name; always allowed but unused */ @@ -75,28 +77,71 @@ validate_one_property (gpointer key, gpointer val, gpointer user_data) for (i = 0; valid_properties[i].name; i++) { ValidProperty prop = valid_properties[i]; + long int tmp; - if (!strcmp (prop.name, (char *) key) && prop.type == G_VALUE_TYPE ((GValue *) val)) - /* Property is ok */ - return; + if (strcmp (prop.name, (char *) key)) + continue; + + switch (prop.type) { + case G_TYPE_STRING: + return; /* valid */ + case G_TYPE_INT: + errno = 0; + tmp = strtol ((char *) value, NULL, 10); + if (errno == 0 && tmp >= prop.int_min && tmp <= prop.int_max) + return; /* valid */ + + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "invalid integer property '%s' or out of range [%d -> %d]", + (const char *) key, prop.int_min, prop.int_max); + break; + case G_TYPE_BOOLEAN: + if (!strcmp ((char *) value, "yes") || !strcmp ((char *) value, "no")) + return; /* valid */ + + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "invalid boolean property '%s' (not yes or no)", + (const char *) key); + break; + default: + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "unhandled property '%s' type %d", + (const char *) key, prop.type); + break; + } } /* Did not find the property from valid_properties or the type did not match */ - g_warning ("VPN property '%s' failed validation.", (char *) key); - *failed = TRUE; + if (!valid_properties[i].name) { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "property '%s' invalid or not supported", + (const char *) key); + } } static gboolean -nm_vpnc_properties_validate (GHashTable *properties) +nm_vpnc_properties_validate (GHashTable *properties, GError **error) { - gboolean failed = FALSE; + if (g_hash_table_size (properties) < 1) { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "%s", + "No VPN configuration options."); + return FALSE; + } - if (g_hash_table_size (properties) < 1) - return failed; + g_hash_table_foreach (properties, validate_one_property, error); - g_hash_table_foreach (properties, validate_one_property, &failed); - - return !failed; + return *error ? FALSE : TRUE; } static void @@ -140,7 +185,7 @@ vpnc_watch_cb (GPid pid, gint status, gpointer user_data) } static gint -nm_vpnc_start_vpnc_binary (NMVPNCPlugin *plugin) +nm_vpnc_start_vpnc_binary (NMVPNCPlugin *plugin, GError **error) { GPid pid; const char **vpnc_binary = NULL; @@ -158,7 +203,11 @@ nm_vpnc_start_vpnc_binary (NMVPNCPlugin *plugin) } if (!*vpnc_binary) { - nm_info ("Could not find vpnc binary."); + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, + "%s", + "Could not find vpnc binary."); return -1; } @@ -171,10 +220,9 @@ nm_vpnc_start_vpnc_binary (NMVPNCPlugin *plugin) if (!g_spawn_async_with_pipes (NULL, (char **) vpnc_argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &stdin_fd, - NULL, NULL, &err)) { + NULL, NULL, error)) { g_ptr_array_free (vpnc_argv, TRUE); - nm_warning ("vpnc failed to start. error: '%s'", err->message); - g_error_free (err); + nm_warning ("vpnc failed to start. error: '%s'", (*error)->message); return -1; } g_ptr_array_free (vpnc_argv, TRUE); @@ -204,37 +252,79 @@ write_config_option (int fd, const char *format, ...) va_end (args); } +typedef struct { + int fd; + GError *error; +} WriteConfigInfo; + static void -write_one_property (gpointer key, gpointer val, gpointer user_data) +write_one_property (gpointer key, gpointer value, gpointer user_data) { - gint vpnc_fd = GPOINTER_TO_INT (user_data); - GValue *value = (GValue *) val; - GType type; + WriteConfigInfo *info = (WriteConfigInfo *) user_data; + GType type = G_TYPE_INVALID; + int i; + + if (info->error) + return; + + /* Find the value in the table to get its type */ + for (i = 0; valid_properties[i].name; i++) { + ValidProperty prop = valid_properties[i]; + + if (!strcmp (prop.name, (char *) key)) { + /* Property is ok */ + type = prop.type; + break; + } + } + + if (type == G_TYPE_INVALID) { + g_set_error (&info->error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Config option '%s' invalid or unknown.", + (const char *) key); + } - type = G_VALUE_TYPE (value); if (type == G_TYPE_STRING) - write_config_option (vpnc_fd, "%s %s\n", (char *) key, g_value_get_string (value)); - else if (type == G_TYPE_BOOLEAN) - write_config_option (vpnc_fd, "%s\n", (char *) key); - else if (type == G_TYPE_INT) - write_config_option (vpnc_fd, "%s %d\n", (char *) key, g_value_get_int (value)); - else if (type == DBUS_TYPE_G_UCHAR_ARRAY) { - char *tmp; + write_config_option (info->fd, "%s %s\n", (char *) key, (char *) value); + else if (type == G_TYPE_BOOLEAN) { + if (!strcmp (value, "yes")) + write_config_option (info->fd, "%s\n", (char *) key); + } else if (type == G_TYPE_INT) { + long int tmp_int; + char *tmp_str; - tmp = nm_utils_garray_to_string ((GArray *) g_value_get_boxed (value)); - write_config_option (vpnc_fd, "%s %s\n", tmp); - g_free (tmp); + /* Convert -> int and back to string for security's sake since + * strtol() ignores leading and trailing characters. + */ + errno = 0; + tmp_int = strtol (value, NULL, 10); + if (errno == 0) { + tmp_str = g_strdup_printf ("%ld", tmp_int); + write_config_option (info->fd, "%s %s\n", (char *) key, tmp_str); + g_free (tmp_str); + } else { + g_set_error (&info->error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Config option '%s' not an integer.", + (const char *) key); + } } else { + /* Just ignore unknown properties */ nm_warning ("Don't know how to write property '%s' with type %s", (char *) key, g_type_name (type)); } } -static void +static gboolean nm_vpnc_config_write (gint vpnc_fd, const char *default_user_name, - GHashTable *properties) + GHashTable *properties, + GError **error) { + WriteConfigInfo *info; const char *props_user_name; const char *props_natt_mode; @@ -262,45 +352,42 @@ nm_vpnc_config_write (gint vpnc_fd, NM_VPNC_NATT_MODE_NATT); } - g_hash_table_foreach (properties, write_one_property, GINT_TO_POINTER (vpnc_fd)); + info = g_malloc0 (sizeof (WriteConfigInfo)); + info->fd = vpnc_fd; + g_hash_table_foreach (properties, write_one_property, info); + *error = info->error; + g_free (info); + + return *error ? FALSE : TRUE; } static gboolean real_connect (NMVPNPlugin *plugin, - NMConnection *connection, - GError **err) + NMConnection *connection, + GError **error) { NMSettingVPN *s_vpn; - NMSettingVPNProperties *properties; - gint vpnc_fd; - - properties = NM_SETTING_VPN_PROPERTIES (nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN_PROPERTIES)); - if (!properties || !nm_vpnc_properties_validate (properties->data)) { - g_set_error (err, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, - "%s", - "Invalid arguments."); - return FALSE; - } + gint vpnc_fd = -1; + gboolean success = FALSE; s_vpn = NM_SETTING_VPN (nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN)); g_assert (s_vpn); + if (!nm_vpnc_properties_validate (s_vpn->data, error)) + goto out; - if ((vpnc_fd = nm_vpnc_start_vpnc_binary (NM_VPNC_PLUGIN (plugin))) >= 0) - nm_vpnc_config_write (vpnc_fd, s_vpn->user_name, properties->data); - else { - g_set_error (err, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, - "%s", - "Could not start vpnc binary."); + vpnc_fd = nm_vpnc_start_vpnc_binary (NM_VPNC_PLUGIN (plugin), error); + if (vpnc_fd < 0) + goto out; + + if (!nm_vpnc_config_write (vpnc_fd, s_vpn->user_name, s_vpn->data, error)) + goto out; + + success = TRUE; + +out: + if (vpnc_fd >= 0) close (vpnc_fd); - return FALSE; - } - - close (vpnc_fd); - return TRUE; + return success; } static gboolean @@ -309,13 +396,13 @@ real_need_secrets (NMVPNPlugin *plugin, char **setting_name, GError **error) { - NMSettingVPNProperties *s_vpn_props; + NMSettingVPN *s_vpn; g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE); g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - s_vpn_props = NM_SETTING_VPN_PROPERTIES (nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN_PROPERTIES)); - if (!s_vpn_props) { + s_vpn = NM_SETTING_VPN (nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN)); + if (!s_vpn) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID, @@ -326,12 +413,12 @@ real_need_secrets (NMVPNPlugin *plugin, // FIXME: there are some configurations where both passwords are not // required. Make sure they work somehow. - if (!g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_SECRET)) { - *setting_name = NM_SETTING_VPN_PROPERTIES_SETTING_NAME; + if (!g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_SECRET)) { + *setting_name = NM_SETTING_VPN_SETTING_NAME; return TRUE; } - if (!g_hash_table_lookup (s_vpn_props->data, NM_VPNC_KEY_XAUTH_PASSWORD)) { - *setting_name = NM_SETTING_VPN_PROPERTIES_SETTING_NAME; + if (!g_hash_table_lookup (s_vpn->data, NM_VPNC_KEY_XAUTH_PASSWORD)) { + *setting_name = NM_SETTING_VPN_SETTING_NAME; return TRUE; }