2008-08-11 Dan Williams <dcbw@redhat.com>

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
This commit is contained in:
Dan Williams 2008-08-11 17:15:42 +00:00
parent 9886706ebe
commit 3113ba4bcf
4 changed files with 284 additions and 234 deletions

View file

@ -1,3 +1,8 @@
2008-08-11 Dan Williams <dcbw@redhat.com>
Update to match NM svn3924 vpn setting changes; verify options better;
return more informative errors on VPN launch failures.
2008-08-06 Dan Williams <dcbw@redhat.com>
* src/nm-vpnc-service-vpnc-helper.c

View file

@ -30,7 +30,6 @@
#include <gnome-keyring.h>
#include <nm-setting-vpn.h>
#include <nm-setting-vpn-properties.h>
#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);

View file

@ -40,7 +40,6 @@
#include <nm-vpn-plugin-ui-interface.h>
#include <nm-setting-vpn.h>
#include <nm-setting-vpn-properties.h>
#include <nm-setting-connection.h>
#include <nm-setting-ip4-config.h>
@ -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 : "");

View file

@ -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 <stdio.h>
#include <string.h>
@ -8,9 +8,9 @@
#include <signal.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <nm-setting-vpn.h>
#include <nm-setting-vpn-properties.h>
#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;
}