diff --git a/vpn-daemons/openvpn/ChangeLog b/vpn-daemons/openvpn/ChangeLog index 26253495a2..0de46c13ee 100644 --- a/vpn-daemons/openvpn/ChangeLog +++ b/vpn-daemons/openvpn/ChangeLog @@ -1,3 +1,7 @@ +2007-10-08 Tambet Ingo + + * Update everything to work with the 0.7 branch NetworkManager. + 2007-08-15 Tambet Ingo * nm-openvpn-service.name.in: Use uppercase macros so that they get replaced diff --git a/vpn-daemons/openvpn/auth-dialog/Makefile.am b/vpn-daemons/openvpn/auth-dialog/Makefile.am index 6bc2a6804b..a3fb535ec8 100644 --- a/vpn-daemons/openvpn/auth-dialog/Makefile.am +++ b/vpn-daemons/openvpn/auth-dialog/Makefile.am @@ -1,5 +1,3 @@ -INCLUDES = -I${top_srcdir} -I${top_srcdir}/utils - libexec_PROGRAMS = nm-openvpn-auth-dialog nm_openvpn_auth_dialog_CPPFLAGS = \ @@ -7,6 +5,7 @@ nm_openvpn_auth_dialog_CPPFLAGS = \ $(GTK_CFLAGS) \ $(LIBGNOMEUI_CFLAGS) \ $(GNOMEKEYRING_CFLAGS) \ + $(NETWORK_MANAGER_CFLAGS) \ -DICONDIR=\""$(datadir)/pixmaps"\" \ -DGLADEDIR=\""$(gladedir)"\" \ -DBINDIR=\""$(bindir)"\" \ diff --git a/vpn-daemons/openvpn/auth-dialog/main.c b/vpn-daemons/openvpn/auth-dialog/main.c index a58c72691f..cda288cc90 100644 --- a/vpn-daemons/openvpn/auth-dialog/main.c +++ b/vpn-daemons/openvpn/auth-dialog/main.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ /* NetworkManager Wireless Applet -- Display wireless access points and allow user control * * Dan Williams @@ -32,109 +33,94 @@ #include #include +#include "../src/nm-openvpn-service.h" #include "gnome-two-password-dialog.h" -#define VPN_SERVICE "org.freedesktop.NetworkManager.openvpn" -// MUST be the same as in gnome/applet/applet.h -// A real fix for this is needed by giving more information to auth apps -#define GCONF_PATH_VPN_CONNECTIONS "/system/networking/vpn_connections" +typedef struct { + char *vpn_name; + char *vpn_service; -static GSList * -lookup_pass (const char *vpn_name, const char *vpn_service, gboolean *is_session) + gboolean need_password; + char *password; + + gboolean need_certpass; + char *certpass; +} PasswordsInfo; + +static gboolean +lookup_pass (PasswordsInfo *info, gboolean *is_session) { - GSList *passwords; - GList *keyring_result; - GList *keyring_i; + int status; + GList *list = NULL; + GList *iter; - char *password = NULL; - char *certpass = NULL; + status = gnome_keyring_find_network_password_sync (g_get_user_name (), /* user */ + NULL, /* domain */ + info->vpn_name, /* server */ + NULL, /* object */ + info->vpn_service, /* protocol */ + NULL, /* authtype */ + 0, /* port */ + &list); - passwords = NULL; + if (status != GNOME_KEYRING_RESULT_OK || list == NULL) + return FALSE; - if (gnome_keyring_find_network_password_sync (g_get_user_name (), /* user */ - NULL, /* domain */ - vpn_name, /* server */ - NULL, /* object */ - vpn_service, /* protocol */ - NULL, /* authtype */ - 0, /* port */ - &keyring_result) != GNOME_KEYRING_RESULT_OK) - return FALSE; + *is_session = FALSE; - *is_session = FALSE; - - // Go through all passwords and assign to appropriate variable - for (keyring_i = keyring_result; keyring_i != NULL; keyring_i = g_list_next (keyring_i)) { - - GnomeKeyringNetworkPasswordData *data = keyring_i->data; + /* Go through all passwords and assign to appropriate variable */ + for (iter = list; iter; iter = iter->next) { + GnomeKeyringNetworkPasswordData *data = iter->data; - if (strcmp (data->object, "password") == 0) { - password = data->password; - } else if (strcmp (data->object, "certpass") == 0) { - certpass = data->password; - } + if (!strcmp (data->object, "password") && data->password) + info->password = g_strdup (data->password); + else if (strcmp (data->object, "certpass") == 0) + info->certpass = g_strdup (data->password); - if (strcmp (data->keyring, "session") == 0) - *is_session = TRUE; - - } + if (strcmp (data->keyring, "session") == 0) + *is_session = TRUE; + } + gnome_keyring_network_password_list_free (list); - if (password != NULL) { - passwords = g_slist_append (passwords, g_strdup (password)); - } else { - passwords = g_slist_append (passwords, g_strdup ("")); - } - - if (certpass != NULL) { - passwords = g_slist_append (passwords, g_strdup (certpass)); - } else { - passwords = g_slist_append (passwords, g_strdup ("")); - } - - gnome_keyring_network_password_list_free (keyring_result); - - return passwords; + return TRUE; } -static void save_vpn_password (const char *vpn_name, const char *vpn_service, const char *keyring, - const char *password, const char *certpass) +static void +save_vpn_password (PasswordsInfo *info, const char *keyring) { - guint32 item_id; - GnomeKeyringResult keyring_result; + guint32 item_id; + GnomeKeyringResult keyring_result; - if ( password != NULL) { - keyring_result = gnome_keyring_set_network_password_sync (keyring, - g_get_user_name (), - NULL, - vpn_name, - "password", - vpn_service, - NULL, - 0, - password, - &item_id); - if (keyring_result != GNOME_KEYRING_RESULT_OK) { - g_warning ("Couldn't store password in keyring, code %d", (int) keyring_result); - } - } - - if ( certpass != NULL) { - keyring_result = gnome_keyring_set_network_password_sync (keyring, - g_get_user_name (), - NULL, - vpn_name, - "certpass", - vpn_service, - NULL, - 0, - certpass, - &item_id); - if (keyring_result != GNOME_KEYRING_RESULT_OK) { - g_warning ("Couldn't store certpass in keyring, code %d", (int) keyring_result); - } - } + if (info->password) { + keyring_result = gnome_keyring_set_network_password_sync (keyring, + g_get_user_name (), + NULL, + info->vpn_name, + "password", + info->vpn_service, + NULL, + 0, + info->password, + &item_id); + if (keyring_result != GNOME_KEYRING_RESULT_OK) + g_warning ("Couldn't store password in keyring, code %d", (int) keyring_result); + } + if (info->certpass) { + keyring_result = gnome_keyring_set_network_password_sync (keyring, + g_get_user_name (), + NULL, + info->vpn_name, + "certpass", + info->vpn_service, + NULL, + 0, + info->certpass, + &item_id); + if (keyring_result != GNOME_KEYRING_RESULT_OK) + g_warning ("Couldn't store certpass in keyring, code %d", (int) keyring_result); + } } @@ -146,308 +132,281 @@ static void save_vpn_password (const char *vpn_name, const char *vpn_service, co * @return returns true if the key is encrypted, false otherwise */ static gboolean -pem_is_encrypted(const char *filename) +pem_is_encrypted (const char *filename) { - GIOChannel *pem_chan; - char *str = NULL; - gboolean encrypted = FALSE; + GIOChannel *pem_chan; + char *str = NULL; + gboolean encrypted = FALSE; - pem_chan = g_io_channel_new_file (filename, "r", NULL); + pem_chan = g_io_channel_new_file (filename, "r", NULL); - if ( pem_chan == NULL ) { - // We don't know - return FALSE; - } + if ( pem_chan == NULL ) { + // We don't know + return FALSE; + } - while ( ! encrypted && (g_io_channel_read_line (pem_chan, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) ) { - if ( strstr (str, "Proc-Type: 4,ENCRYPTED") == str ) { - // encrypted! - encrypted = TRUE; - } + while ( ! encrypted && (g_io_channel_read_line (pem_chan, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) ) { + if ( strstr (str, "Proc-Type: 4,ENCRYPTED") == str ) { + // encrypted! + encrypted = TRUE; + } - g_free (str); - } + g_free (str); + } - return encrypted; + return encrypted; } -static GSList * -get_passwords (const char *vpn_name, - const char *vpn_service, - gboolean retry, - gboolean need_password, - gboolean need_certpass) +static gboolean +get_passwords (PasswordsInfo *info, gboolean retry) { - GSList *result; - char *prompt; - GtkWidget *dialog; - char *keyring_password; - char *keyring_certpass; - gboolean keyring_is_session; - GSList *keyring_result; - GnomeTwoPasswordDialogRemember remember; - int num_passwords = 0; + char *prompt; + GtkWidget *dialog; + gboolean keyring_is_session; + GnomeTwoPasswordDialogRemember remember = GNOME_TWO_PASSWORD_DIALOG_REMEMBER_NOTHING; + gboolean success = FALSE; - result = NULL; - keyring_password = NULL; - keyring_certpass = NULL; - keyring_result = NULL; + if (lookup_pass (info, &keyring_is_session)) { + if (!retry) + return TRUE; - g_return_val_if_fail (vpn_name != NULL, NULL); + if (keyring_is_session) + remember = GNOME_TWO_PASSWORD_DIALOG_REMEMBER_SESSION; + else + remember = GNOME_TWO_PASSWORD_DIALOG_REMEMBER_FOREVER; + } - /* Use the system user name, since the VPN might have a different user name */ - if (!retry) { - if ((result = lookup_pass (vpn_name, vpn_service, &keyring_is_session)) != NULL) { - return result; - } - } else { - if ((keyring_result = lookup_pass (vpn_name, vpn_service, &keyring_is_session)) != NULL) { - keyring_password = g_strdup ((char *) keyring_result->data); - keyring_certpass = g_strdup ((char *) (g_slist_next (keyring_result))->data); - } - g_slist_foreach (keyring_result, (GFunc)g_free, NULL); - g_slist_free (keyring_result); - } + prompt = g_strdup_printf (_("You need to authenticate to access the Virtual Private Network '%s'."), info->vpn_name); + dialog = gnome_two_password_dialog_new (_("Authenticate VPN"), prompt, NULL, NULL, FALSE); + g_free (prompt); - prompt = g_strdup_printf (_("You need to authenticate to access the Virtual Private Network '%s'."), vpn_name); - dialog = gnome_two_password_dialog_new (_("Authenticate VPN"), prompt, NULL, NULL, FALSE); - g_free (prompt); + gnome_two_password_dialog_set_remember (GNOME_TWO_PASSWORD_DIALOG (dialog), remember); + gnome_two_password_dialog_set_show_username (GNOME_TWO_PASSWORD_DIALOG (dialog), FALSE); + gnome_two_password_dialog_set_show_userpass_buttons (GNOME_TWO_PASSWORD_DIALOG (dialog), FALSE); + gnome_two_password_dialog_set_show_domain (GNOME_TWO_PASSWORD_DIALOG (dialog), FALSE); + gnome_two_password_dialog_set_show_remember (GNOME_TWO_PASSWORD_DIALOG (dialog), TRUE); - gnome_two_password_dialog_set_show_username (GNOME_TWO_PASSWORD_DIALOG (dialog), FALSE); - gnome_two_password_dialog_set_show_userpass_buttons (GNOME_TWO_PASSWORD_DIALOG (dialog), FALSE); - gnome_two_password_dialog_set_show_domain (GNOME_TWO_PASSWORD_DIALOG (dialog), FALSE); - gnome_two_password_dialog_set_show_remember (GNOME_TWO_PASSWORD_DIALOG (dialog), TRUE); + if (info->need_password && info->need_certpass) { + gnome_two_password_dialog_set_show_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog), + TRUE); + gnome_two_password_dialog_set_password_secondary_label (GNOME_TWO_PASSWORD_DIALOG (dialog), + _("Certificate pass_word:") ); - if (need_password && need_certpass) { - gnome_two_password_dialog_set_show_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog), - TRUE); - gnome_two_password_dialog_set_password_secondary_label (GNOME_TWO_PASSWORD_DIALOG (dialog), - _("Certificate pass_word:") ); + /* if retrying, put in the passwords from the keyring */ + if (info->password) + gnome_two_password_dialog_set_password (GNOME_TWO_PASSWORD_DIALOG (dialog), info->password); + if (info->certpass) + gnome_two_password_dialog_set_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog), info->certpass); + } else { + gnome_two_password_dialog_set_show_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog), FALSE); + if (info->need_password) { + /* if retrying, put in the passwords from the keyring */ + if (info->password) + gnome_two_password_dialog_set_password (GNOME_TWO_PASSWORD_DIALOG (dialog), info->password); + } else if (info->need_certpass) { + gnome_two_password_dialog_set_password_primary_label (GNOME_TWO_PASSWORD_DIALOG (dialog), + _("Certificate password:")); + /* if retrying, put in the passwords from the keyring */ + if (info->certpass) + gnome_two_password_dialog_set_password (GNOME_TWO_PASSWORD_DIALOG (dialog), info->certpass); + } + } - /* if retrying, put in the passwords from the keyring */ - if (keyring_password != NULL) { - gnome_two_password_dialog_set_password (GNOME_TWO_PASSWORD_DIALOG (dialog), - keyring_password); - } - if (keyring_certpass != NULL) { - gnome_two_password_dialog_set_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog), - keyring_certpass); - } - } else { - gnome_two_password_dialog_set_show_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog), - FALSE); - if (need_password) { - // defaults for label are ok + gtk_widget_show (dialog); + if (gnome_two_password_dialog_run_and_block (GNOME_TWO_PASSWORD_DIALOG (dialog))) { + success = TRUE; - /* if retrying, put in the passwords from the keyring */ - if (keyring_password != NULL) { - gnome_two_password_dialog_set_password (GNOME_TWO_PASSWORD_DIALOG (dialog), - keyring_password); - } + if (info->need_password) + info->password = g_strdup (gnome_two_password_dialog_get_password (GNOME_TWO_PASSWORD_DIALOG (dialog))); + if (info->need_certpass) + info->certpass = g_strdup (info->need_password ? + gnome_two_password_dialog_get_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog)) : + gnome_two_password_dialog_get_password (GNOME_TWO_PASSWORD_DIALOG (dialog))); - } else if (need_certpass) { - gnome_two_password_dialog_set_password_primary_label (GNOME_TWO_PASSWORD_DIALOG (dialog), - _("Certificate password:") ); - /* if retrying, put in the passwords from the keyring */ - if (keyring_certpass != NULL) { - gnome_two_password_dialog_set_password (GNOME_TWO_PASSWORD_DIALOG (dialog), - keyring_certpass); - } - } - } - /* use the same keyring storage options as from the items we put in the entry boxes */ - remember = GNOME_TWO_PASSWORD_DIALOG_REMEMBER_NOTHING; - if (keyring_result != NULL) { - if (keyring_is_session) - remember = GNOME_TWO_PASSWORD_DIALOG_REMEMBER_SESSION; - else - remember = GNOME_TWO_PASSWORD_DIALOG_REMEMBER_FOREVER; - } - gnome_two_password_dialog_set_remember (GNOME_TWO_PASSWORD_DIALOG (dialog), remember); + switch (gnome_two_password_dialog_get_remember (GNOME_TWO_PASSWORD_DIALOG (dialog))) { + case GNOME_TWO_PASSWORD_DIALOG_REMEMBER_SESSION: + save_vpn_password (info, "session"); + break; + case GNOME_TWO_PASSWORD_DIALOG_REMEMBER_FOREVER: + save_vpn_password (info, NULL); + break; + default: + break; + } + } - gtk_widget_show (dialog); + gtk_widget_destroy (dialog); - if (gnome_two_password_dialog_run_and_block (GNOME_TWO_PASSWORD_DIALOG (dialog))) { - char *password = "unused"; - char *certpass = "unused"; + return success; +} - if (need_password && need_certpass) { - password = gnome_two_password_dialog_get_password (GNOME_TWO_PASSWORD_DIALOG (dialog)); - certpass = gnome_two_password_dialog_get_password_secondary (GNOME_TWO_PASSWORD_DIALOG (dialog)); - } else { - if (need_password) { - password = gnome_two_password_dialog_get_password (GNOME_TWO_PASSWORD_DIALOG (dialog)); - } else if (need_certpass) { - certpass = gnome_two_password_dialog_get_password (GNOME_TWO_PASSWORD_DIALOG (dialog)); - } - } +static gboolean +get_password_types (PasswordsInfo *info) +{ + GConfClient *gconf_client = NULL; + GSList *conf_list; + GSList *iter; + char *key; + char *str; + char *connection_path = NULL; + gboolean success = FALSE; - result = g_slist_append (result, g_strdup (password)); - result = g_slist_append (result, g_strdup (certpass)); + /* FIXME: This whole thing sucks: we should not go around poking gconf + directly, but there's nothing that does it for us right now */ - switch (gnome_two_password_dialog_get_remember (GNOME_TWO_PASSWORD_DIALOG (dialog))) { - case GNOME_TWO_PASSWORD_DIALOG_REMEMBER_SESSION: - save_vpn_password (vpn_name, vpn_service, "session", password, certpass); - break; - case GNOME_TWO_PASSWORD_DIALOG_REMEMBER_FOREVER: - save_vpn_password (vpn_name, vpn_service, NULL, password, certpass); - break; - default: - break; - } - } + gconf_client = gconf_client_get_default (); - g_free (keyring_password); - g_free (keyring_certpass); + conf_list = gconf_client_all_dirs (gconf_client, "/system/networking/connections", NULL); + if (!conf_list) + return FALSE; - gtk_widget_destroy (dialog); + for (iter = conf_list; iter; iter = iter->next) { + key = g_strconcat ((char *) iter->data, "connection/type", NULL); + str = gconf_client_get_string (gconf_client, key, NULL); + g_free (key); - return result; + if (!str || strcmp (str, "vpn")) { + g_free (str); + continue; + } + + key = g_strconcat ((char *) iter->data, "connection/name", NULL); + str = gconf_client_get_string (gconf_client, key, NULL); + g_free (key); + + if (!str || strcmp (str, info->vpn_name)) { + g_free (str); + continue; + } + + /* Woo, found the connection */ + connection_path = g_strdup ((char *) iter->data); + break; + } + + g_slist_foreach (conf_list, (GFunc) g_free, NULL); + g_slist_free (conf_list); + + if (connection_path) { + int connection_type; + + key = g_strconcat (connection_path, "vpn-properties/connection-type", NULL); + connection_type = gconf_client_get_int (gconf_client, key, NULL); + g_free (key); + + switch (connection_type) { + case NM_OPENVPN_CONTYPE_X509USERPASS: + info->need_password = TRUE; + /* Fall through */ + case NM_OPENVPN_CONTYPE_X509: + success = TRUE; + + key = g_strconcat (connection_path, "vpn-properties/", NM_OPENVPN_KEY_KEY, NULL); + str = gconf_client_get_string (gconf_client, key, NULL); + g_free (key); + if (str) { + info->need_certpass = pem_is_encrypted (str); + g_free (str); + } + break; + case NM_OPENVPN_CONTYPE_SHAREDKEY: + success = TRUE; + break; + case NM_OPENVPN_CONTYPE_PASSWORD: + success = TRUE; + info->need_password = TRUE; + break; + default: + /* Invalid connection type */ + break; + } + + info->need_password = TRUE; + info->need_certpass = TRUE; + + g_free (connection_path); + } + + g_object_unref (gconf_client); + + return success; } int main (int argc, char *argv[]) { - GConfClient *gconf_client = NULL; - GConfValue *gconf_val = NULL; - gchar *gconf_key = NULL; - char *escaped_name; - gboolean needs_password = FALSE; - gboolean needs_certpass = FALSE; - gboolean valid_conn = FALSE; - GSList *i; - GSList *passwords; - gchar *key = NULL; - gchar *connection_type = NULL; - static gboolean retry = FALSE; - static gchar *vpn_name = NULL; - static gchar *vpn_service = NULL; - GError *error = NULL; - GOptionContext *context; - GnomeProgram *program = NULL; - int bytes_read; - GOptionEntry entries[] = - { - { "reprompt", 'r', 0, G_OPTION_ARG_NONE, &retry, "Reprompt for passwords", NULL}, - { "name", 'n', 0, G_OPTION_ARG_STRING, &vpn_name, "Name of VPN connection", NULL}, - { "service", 's', 0, G_OPTION_ARG_STRING, &vpn_service, "VPN service type", NULL}, - { NULL } - }; - char buf[1]; + PasswordsInfo info; + int exit_status = 1; + static gboolean retry = FALSE; + static gchar *vpn_name = NULL; + static gchar *vpn_service = NULL; + GOptionContext *context; + GnomeProgram *program = NULL; + int bytes_read; + GOptionEntry entries[] = + { + { "reprompt", 'r', 0, G_OPTION_ARG_NONE, &retry, "Reprompt for passwords", NULL}, + { "name", 'n', 0, G_OPTION_ARG_STRING, &vpn_name, "Name of VPN connection", NULL}, + { "service", 's', 0, G_OPTION_ARG_STRING, &vpn_service, "VPN service type", NULL}, + { NULL } + }; + char buf[1]; - bindtextdomain (GETTEXT_PACKAGE, NULL); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); + bindtextdomain (GETTEXT_PACKAGE, NULL); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); - passwords = NULL; + context = g_option_context_new ("- openvpn auth dialog"); + g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); - context = g_option_context_new ("- openvpn auth dialog"); - g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); + program = gnome_program_init ("nm-openvpn-auth-dialog", VERSION, + LIBGNOMEUI_MODULE, + argc, argv, + GNOME_PARAM_GOPTION_CONTEXT, context, + GNOME_PARAM_NONE); - program = gnome_program_init ("nm-openvpn-auth-dialog", VERSION, - LIBGNOMEUI_MODULE, - argc, argv, - GNOME_PARAM_GOPTION_CONTEXT, context, - GNOME_PARAM_NONE); - - if (vpn_name == NULL || vpn_service == NULL) { - fprintf (stderr, "Have to supply both name and service\n"); - goto out; - } - - if (strcmp (vpn_service, VPN_SERVICE) != 0) { - fprintf (stderr, "This dialog only works with the '%s' service\n", VPN_SERVICE); - goto out; - } - - gconf_client = gconf_client_get_default(); - escaped_name = gconf_escape_key (vpn_name, strlen (vpn_name)); - gconf_key = g_strdup_printf ("%s/%s/vpn_data", GCONF_PATH_VPN_CONNECTIONS, escaped_name); - if ( !(gconf_val = gconf_client_get (gconf_client, gconf_key, NULL)) || - !(gconf_val->type == GCONF_VALUE_LIST) || - !(gconf_value_get_list_type (gconf_val) == GCONF_VALUE_STRING)) { - - if (gconf_val) - gconf_value_free (gconf_val); - g_free (gconf_key); - goto out; - } - g_free (gconf_key); - - valid_conn = TRUE; - - for (i = gconf_value_get_list (gconf_val); i != NULL; i = g_slist_next (i)) { - const char *gkey = gconf_value_get_string ((GConfValue *)i->data); - const char *gval = NULL; - - i = g_slist_next (i); - if (i != NULL) { - gval = gconf_value_get_string ((GConfValue *)i->data); - } - - if ( gkey != NULL ) { - if ( strcmp (gkey, "connection-type") == 0 ) { - connection_type = g_strdup (gval); - if ( (strcmp (gval, "password") == 0) || - (strcmp (gval, "x509userpass") == 0) ) { - needs_password = TRUE; + if (vpn_name == NULL || vpn_service == NULL) { + fprintf (stderr, "Have to supply both name and service\n"); + goto out; } - } else if ( strcmp (gkey, "key") == 0 ) { - key = g_strdup (gval); - } - } - } - gconf_value_free (gconf_val); - if ( (connection_type != NULL) && (key != NULL) ) { - if ( (strcmp (connection_type, "x509") == 0) || - (strcmp (connection_type, "x509userpass") == 0) ) { - needs_certpass = pem_is_encrypted (key); - } - } + if (strcmp (vpn_service, NM_DBUS_SERVICE_OPENVPN) != 0) { + fprintf (stderr, "This dialog only works with the '%s' service\n", NM_DBUS_SERVICE_OPENVPN); + goto out; + } - if ( needs_password || needs_certpass ) { - passwords = get_passwords (vpn_name, vpn_service, retry, needs_password, needs_certpass); - if (passwords == NULL) - goto out; + memset (&info, 0, sizeof (PasswordsInfo)); + info.vpn_name = vpn_name; + info.vpn_service = vpn_service; - /* dump the passwords to stdout */ - for (i = passwords; i != NULL; i = g_slist_next (i)) { - char *password = (char *) i->data; - printf ("%s\n", password); - } + if (!get_password_types (&info)) { + fprintf (stderr, "Invalid connection"); + goto out; + } - g_slist_foreach (passwords, (GFunc)g_free, NULL); - g_slist_free (passwords); + exit_status = 0; - } else { - printf ("No password needed\nNo certpass needed\n"); - } + if (!info.need_password && !info.need_certpass) + goto out; - printf ("\n\n"); - /* for good measure, flush stdout since Kansas is going Bye-Bye */ - fflush (stdout); + if (get_passwords (&info, retry)) { + if (info.need_password) + printf ("%s\n", info.password); + if (info.need_certpass) + printf ("%s\n", info.certpass); + } + printf ("\n\n"); + /* for good measure, flush stdout since Kansas is going Bye-Bye */ + fflush (stdout); - /* wait for data on stdin */ - bytes_read = fread (buf, sizeof (char), sizeof (buf), stdin); + /* wait for data on stdin */ + bytes_read = fread (buf, sizeof (char), sizeof (buf), stdin); out: - if (gconf_client) - g_object_unref (gconf_client); + g_object_unref (program); - g_object_unref (program); - - g_free (connection_type); - g_free (key); - - if ( ! valid_conn ) { - return 1; - } else if ( needs_password ) { - return (passwords != NULL) ? 0 : 1; - } else { - return 0; - } + return exit_status; } diff --git a/vpn-daemons/openvpn/configure.in b/vpn-daemons/openvpn/configure.in index a7961bbff7..678c9c80fe 100644 --- a/vpn-daemons/openvpn/configure.in +++ b/vpn-daemons/openvpn/configure.in @@ -56,7 +56,7 @@ PKG_CHECK_MODULES(DBUS, dbus-glib-1 >= 0.30) AC_SUBST(DBUS_CFLAGS) AC_SUBST(DBUS_LIBS) -PKG_CHECK_MODULES(NETWORK_MANAGER, NetworkManager >= 0.4.1 libnm-util >= 0.7.0) +PKG_CHECK_MODULES(NETWORK_MANAGER, NetworkManager >= 0.7.0 libnm-util >= 0.7.0 libnm_glib) AC_SUBST(NETWORK_MANAGER_CFLAGS) AC_SUBST(NETWORK_MANAGER_LIBS) diff --git a/vpn-daemons/openvpn/properties/nm-openvpn.c b/vpn-daemons/openvpn/properties/nm-openvpn.c index d857cf638e..0895415d69 100644 --- a/vpn-daemons/openvpn/properties/nm-openvpn.c +++ b/vpn-daemons/openvpn/properties/nm-openvpn.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ /* nm-openvpn.c : GNOME UI dialogs for configuring OpenVPN connections * * Copyright (C) 2005 Tim Niemueller @@ -27,6 +28,7 @@ #include #include +#include #include #define NM_VPN_API_SUBJECT_TO_CHANGE @@ -34,65 +36,64 @@ #include #include "../src/nm-openvpn-service.h" -#include "../src/nm-utils.h" typedef struct _NetworkManagerVpnUIImpl NetworkManagerVpnUIImpl; struct _NetworkManagerVpnUIImpl { - NetworkManagerVpnUI parent; + NetworkManagerVpnUI parent; - NetworkManagerVpnUIDialogValidityCallback callback; - gpointer callback_user_data; + NetworkManagerVpnUIDialogValidityCallback callback; + gpointer callback_user_data; - gchar *last_fc_dir; + gchar *last_fc_dir; - GladeXML *xml; + GladeXML *xml; - GtkWidget *widget; - GtkDialog *advanced; + GtkWidget *widget; + GtkDialog *advanced; - GtkEntry *w_connection_name; - GtkEntry *w_remote; - GtkEntry *w_port; - GtkEntry *w_ca; - GtkEntry *w_cert; - GtkEntry *w_key; - GtkCheckButton *w_use_routes; - GtkEntry *w_routes; - GtkCheckButton *w_use_lzo; - GtkCheckButton *w_use_tap; - GtkCheckButton *w_use_tcp; - GtkExpander *w_opt_info_expander; - GtkButton *w_advanced_button; - GtkButton *w_import_button; - GtkButton *w_button_ca; - GtkButton *w_button_cert; - GtkButton *w_button_key; - GtkComboBox *w_connection_type; - GtkNotebook *w_settings_notebook; - GtkButton *w_button_shared_key; - GtkEntry *w_shared_key; - GtkEntry *w_local_ip; - GtkEntry *w_remote_ip; - GtkEntry *w_username; - GtkEntry *w_password_ca; - GtkButton *w_button_password_ca; - GtkEntry *w_x509userpass_ca; - GtkEntry *w_x509userpass_cert; - GtkEntry *w_x509userpass_key; - GtkEntry *w_x509userpass_username; - GtkButton *w_button_x509userpass_ca; - GtkButton *w_button_x509userpass_cert; - GtkButton *w_button_x509userpass_key; - GtkCheckButton *w_use_cipher; - GtkComboBox *w_cipher; - GtkCheckButton *w_use_ta; - GtkEntry *w_ta; - GtkButton *w_button_ta; - GtkLabel *w_ta_dir_label; - GtkRadioButton *w_ta_dir_none; - GtkRadioButton *w_ta_dir_zero; - GtkRadioButton *w_ta_dir_one; + GtkEntry *w_connection_name; + GtkEntry *w_remote; + GtkEntry *w_port; + GtkEntry *w_ca; + GtkEntry *w_cert; + GtkEntry *w_key; + GtkCheckButton *w_use_routes; + GtkEntry *w_routes; + GtkCheckButton *w_use_lzo; + GtkCheckButton *w_use_tap; + GtkCheckButton *w_use_tcp; + GtkExpander *w_opt_info_expander; + GtkButton *w_advanced_button; + GtkButton *w_import_button; + GtkButton *w_button_ca; + GtkButton *w_button_cert; + GtkButton *w_button_key; + GtkComboBox *w_connection_type; + GtkNotebook *w_settings_notebook; + GtkButton *w_button_shared_key; + GtkEntry *w_shared_key; + GtkEntry *w_local_ip; + GtkEntry *w_remote_ip; + GtkEntry *w_username; + GtkEntry *w_password_ca; + GtkButton *w_button_password_ca; + GtkEntry *w_x509userpass_ca; + GtkEntry *w_x509userpass_cert; + GtkEntry *w_x509userpass_key; + GtkEntry *w_x509userpass_username; + GtkButton *w_button_x509userpass_ca; + GtkButton *w_button_x509userpass_cert; + GtkButton *w_button_x509userpass_key; + GtkCheckButton *w_use_cipher; + GtkComboBox *w_cipher; + GtkCheckButton *w_use_ta; + GtkEntry *w_ta; + GtkButton *w_button_ta; + GtkLabel *w_ta_dir_label; + GtkRadioButton *w_ta_dir_none; + GtkRadioButton *w_ta_dir_zero; + GtkRadioButton *w_ta_dir_one; }; static void connection_type_changed(GtkComboBox *box, gpointer user_data); @@ -101,334 +102,365 @@ static void connection_type_changed(GtkComboBox *box, gpointer user_data); static void openvpn_clear_widget (NetworkManagerVpnUIImpl *impl) { - gtk_entry_set_text (impl->w_connection_name, ""); - gtk_entry_set_text (impl->w_remote, ""); - gtk_entry_set_text (impl->w_port, "1194"); - gtk_entry_set_text (impl->w_ca, ""); - gtk_entry_set_text (impl->w_cert, ""); - gtk_entry_set_text (impl->w_key, ""); - gtk_entry_set_text (impl->w_shared_key, ""); - gtk_entry_set_text (impl->w_local_ip, ""); - gtk_entry_set_text (impl->w_remote_ip, ""); - gtk_entry_set_text (impl->w_username, ""); - gtk_entry_set_text (impl->w_password_ca, ""); - gtk_entry_set_text (impl->w_x509userpass_ca, ""); - gtk_entry_set_text (impl->w_x509userpass_cert, ""); - gtk_entry_set_text (impl->w_x509userpass_key, ""); - gtk_entry_set_text (impl->w_x509userpass_username, ""); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_routes), FALSE); - gtk_entry_set_text (impl->w_routes, ""); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_routes), FALSE); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_lzo), FALSE); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tap), FALSE); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tcp), FALSE); - gtk_combo_box_set_active (GTK_COMBO_BOX (impl->w_connection_type), 0); - connection_type_changed (GTK_COMBO_BOX (impl->w_connection_type), impl); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_cipher), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_cipher), FALSE); - gtk_combo_box_set_active (GTK_COMBO_BOX (impl->w_cipher), 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_ta), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_button_ta), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_label), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_none), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_zero), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_one), FALSE); - gtk_entry_set_text (impl->w_ta, ""); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_none), TRUE); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_zero), FALSE); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_one), FALSE); + gtk_entry_set_text (impl->w_connection_name, ""); + gtk_entry_set_text (impl->w_remote, ""); + gtk_entry_set_text (impl->w_port, "1194"); + gtk_entry_set_text (impl->w_ca, ""); + gtk_entry_set_text (impl->w_cert, ""); + gtk_entry_set_text (impl->w_key, ""); + gtk_entry_set_text (impl->w_shared_key, ""); + gtk_entry_set_text (impl->w_local_ip, ""); + gtk_entry_set_text (impl->w_remote_ip, ""); + gtk_entry_set_text (impl->w_username, ""); + gtk_entry_set_text (impl->w_password_ca, ""); + gtk_entry_set_text (impl->w_x509userpass_ca, ""); + gtk_entry_set_text (impl->w_x509userpass_cert, ""); + gtk_entry_set_text (impl->w_x509userpass_key, ""); + gtk_entry_set_text (impl->w_x509userpass_username, ""); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_routes), FALSE); + gtk_entry_set_text (impl->w_routes, ""); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_routes), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_lzo), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tap), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tcp), FALSE); + gtk_combo_box_set_active (GTK_COMBO_BOX (impl->w_connection_type), 0); + connection_type_changed (GTK_COMBO_BOX (impl->w_connection_type), impl); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_cipher), FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_cipher), FALSE); + gtk_combo_box_set_active (GTK_COMBO_BOX (impl->w_cipher), 0); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_ta), FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta), FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_button_ta), FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_label), FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_none), FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_zero), FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_one), FALSE); + gtk_entry_set_text (impl->w_ta, ""); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_none), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_zero), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_one), FALSE); } static const char * impl_get_display_name (NetworkManagerVpnUI *self) { - return _("OpenVPN Client"); + return _("OpenVPN Client"); } static const char * impl_get_service_name (NetworkManagerVpnUI *self) { - return "org.freedesktop.NetworkManager.openvpn"; -} - -static void -set_cipher(GtkComboBox *box, GtkCheckButton *button, const char *value) -{ - GtkTreeModel *tree = gtk_combo_box_get_model(box); - GtkTreeIter iter; - gboolean valid; - - valid = gtk_tree_model_get_iter_first(tree, &iter); - - while (valid) { - gchar *alg; - - gtk_tree_model_get (tree, &iter, 0, &alg, -1); - -/* printf("set_cipher: %s %s\n", alg, value); */ - - if (strcmp(value, alg) == 0) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (box), TRUE); - gtk_combo_box_set_active_iter (box, &iter); - valid = FALSE; - } else - valid = gtk_tree_model_iter_next (tree, &iter); - - g_free (alg); - } -} - -static GtkWidget * -impl_get_widget (NetworkManagerVpnUI *self, GSList *properties, GSList *routes, const char *connection_name) -{ - GSList *i; - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; - gboolean should_expand; - - openvpn_clear_widget (impl); - - should_expand = FALSE; - - if (connection_name != NULL) - gtk_entry_set_text (impl->w_connection_name, connection_name); - - for (i = properties; i != NULL && g_slist_next (i) != NULL; i = g_slist_next (g_slist_next (i))) { - const char *key; - const char *value; - - key = i->data; - value = (g_slist_next (i))->data; - - if (strcmp (key, "remote") == 0) { - gtk_entry_set_text (impl->w_remote, value); - } else if (strcmp (key, "port") == 0) { - gtk_entry_set_text (impl->w_port, value); - } else if (strcmp (key, "ca") == 0) { - gtk_entry_set_text (impl->w_ca, value); - } else if (strcmp (key, "cert") == 0) { - gtk_entry_set_text (impl->w_cert, value); - } else if (strcmp (key, "key") == 0) { - gtk_entry_set_text (impl->w_key, value); - } else if ( (strcmp (key, "comp-lzo") == 0) && - (strcmp (value, "yes") == 0) ) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_lzo), TRUE); - should_expand = TRUE; - } else if ( strcmp (key, "connection-type") == 0) { - gint type_cbox_sel = 0; - - if ( strcmp (value, "x509") == 0 ) { - type_cbox_sel = NM_OPENVPN_CONTYPE_X509; - } else if ( strcmp (value, "shared-key") == 0 ) { - type_cbox_sel = NM_OPENVPN_CONTYPE_SHAREDKEY; - } else if ( strcmp (value, "password") == 0 ) { - type_cbox_sel = NM_OPENVPN_CONTYPE_PASSWORD; - } else if ( strcmp (value, "x509userpass") == 0 ) { - type_cbox_sel = NM_OPENVPN_CONTYPE_X509USERPASS; - } - - gtk_combo_box_set_active (GTK_COMBO_BOX (impl->w_connection_type), type_cbox_sel); - connection_type_changed (GTK_COMBO_BOX (impl->w_connection_type), impl); - } else if ( strcmp (key, "local-ip") == 0 ) { - gtk_entry_set_text (impl->w_local_ip, value); - } else if ( strcmp (key, "remote-ip") == 0 ) { - gtk_entry_set_text (impl->w_remote_ip, value); - } else if ( strcmp (key, "shared-key") == 0 ) { - gtk_entry_set_text (impl->w_shared_key, value); - } else if ( strcmp (key, "username") == 0 ) { - gtk_entry_set_text (impl->w_username, value); - } else if ( (strcmp (key, "dev") == 0) && - (strcmp (value, "tap") == 0) ) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tap), TRUE); - should_expand = TRUE; - } else if ( (strcmp (key, "proto") == 0) && - (strcmp (value, "tcp-client") == 0) ) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tcp), TRUE); - should_expand = TRUE; - } else if (strcmp (key, "cipher") == 0) { - set_cipher(impl->w_cipher, impl->w_use_cipher, value); - } else if (strcmp (key, "ta") == 0) { - gtk_entry_set_text (impl->w_ta, value); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_ta), TRUE); - } else if (strcmp (key, "ta-dir") == 0) { -/* printf("ta_dir='%s'\n", value); */ - if (strcmp (value, "0") == 0) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_zero), TRUE); - else if (strcmp (value, "1") == 0) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_one), TRUE); - } - } - - if (routes != NULL) { - GString *route_str; - char *str; - - route_str = g_string_new (""); - for (i = routes; i != NULL; i = g_slist_next (i)) { - const char *route; - - if (i != routes) - g_string_append_c(route_str, ' '); - - route = (const char *) i->data; - g_string_append(route_str, route); - } - - str = g_string_free (route_str, FALSE); - gtk_entry_set_text (impl->w_routes, str); - g_free (str); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_routes), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_routes), TRUE); - - should_expand = TRUE; - } - - gtk_container_resize_children (GTK_CONTAINER (impl->widget)); - - return impl->widget; -} - -static GSList * -impl_get_properties (NetworkManagerVpnUI *self) -{ - GSList *data; - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; - const char *connectionname; - const char *remote; - const char *port; - const char *ca; - const char *cert; - const char *key; - const char *shared_key; - const char *local_ip; - const char *remote_ip; - const char *username; - gboolean use_lzo; - gboolean use_tap; - gboolean use_tcp; - gboolean use_cipher; - gboolean use_ta; - - connectionname = gtk_entry_get_text (impl->w_connection_name); - remote = gtk_entry_get_text (impl->w_remote); - port = gtk_entry_get_text (impl->w_port); - ca = gtk_entry_get_text (impl->w_ca); - cert = gtk_entry_get_text (impl->w_cert); - key = gtk_entry_get_text (impl->w_key); - use_lzo = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_lzo)); - use_tap = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_tap)); - use_tcp = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_tcp)); - shared_key = gtk_entry_get_text (impl->w_shared_key); - local_ip = gtk_entry_get_text (impl->w_local_ip); - remote_ip = gtk_entry_get_text (impl->w_remote_ip); - username = gtk_entry_get_text (impl->w_username); - use_cipher = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_cipher)); - use_ta = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_ta)); - - data = NULL; - data = g_slist_append (data, g_strdup ("connection-type")); - switch ( gtk_combo_box_get_active (GTK_COMBO_BOX (impl->w_connection_type)) ) { - case NM_OPENVPN_CONTYPE_SHAREDKEY: - data = g_slist_append (data, g_strdup ("shared-key")); - break; - case NM_OPENVPN_CONTYPE_PASSWORD: - data = g_slist_append (data, g_strdup ("password")); - break; - case NM_OPENVPN_CONTYPE_X509USERPASS: - data = g_slist_append (data, g_strdup ("x509userpass")); - break; - default: // NM_OPENVPN_CONTYPE_X509 - data = g_slist_append (data, g_strdup ("x509")); - break; - } - data = g_slist_append (data, g_strdup ("dev")); - data = g_slist_append (data, use_tap ? g_strdup ("tap") : g_strdup("tun")); - data = g_slist_append (data, g_strdup ("remote")); - data = g_slist_append (data, g_strdup (remote)); - data = g_slist_append (data, g_strdup ("port")); - data = g_slist_append (data, g_strdup (port)); - data = g_slist_append (data, g_strdup ("proto")); - data = g_slist_append (data, use_tcp ? g_strdup ("tcp-client") : g_strdup("udp")); - data = g_slist_append (data, g_strdup ("ca")); - data = g_slist_append (data, g_strdup (ca)); - data = g_slist_append (data, g_strdup ("cert")); - data = g_slist_append (data, g_strdup (cert)); - data = g_slist_append (data, g_strdup ("key")); - data = g_slist_append (data, g_strdup (key)); - data = g_slist_append (data, g_strdup ("comp-lzo")); - data = g_slist_append (data, use_lzo ? g_strdup ("yes") : g_strdup("no")); - data = g_slist_append (data, g_strdup ("shared-key")); - data = g_slist_append (data, g_strdup (shared_key)); - data = g_slist_append (data, g_strdup ("local-ip")); - data = g_slist_append (data, g_strdup (local_ip)); - data = g_slist_append (data, g_strdup ("remote-ip")); - data = g_slist_append (data, g_strdup (remote_ip)); - data = g_slist_append (data, g_strdup ("username")); - data = g_slist_append (data, g_strdup (username)); - if (use_cipher) { - const gchar *cipher = gtk_combo_box_get_active_text(impl->w_cipher); - if (cipher != NULL) { - data = g_slist_append (data, g_strdup ("cipher")); - data = g_slist_append (data, g_strdup (cipher)); - } - } - if (use_ta) { - const gchar* dir; - - data = g_slist_append (data, g_strdup ("ta")); - data = g_slist_append (data, g_strdup (gtk_entry_get_text (impl->w_ta))); - data = g_slist_append (data, g_strdup ("ta-dir")); - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_zero))) - dir = "0"; - else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_one))) - dir = "1"; - else - dir = ""; -/* printf("ta_dir='%s'\n", dir); */ - data = g_slist_append (data, g_strdup(dir)); - } - return data; + return "org.freedesktop.NetworkManager.openvpn"; } static GSList * get_routes (NetworkManagerVpnUIImpl *impl) { - GSList *routes; - const char *routes_entry; - gboolean use_routes; - char **substrs; - unsigned int i; + GSList *routes; + const char *routes_entry; + gboolean use_routes; + char **substrs; + unsigned int i; - routes = NULL; + routes = NULL; - routes_entry = gtk_entry_get_text (impl->w_routes); - use_routes = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_routes)); + routes_entry = gtk_entry_get_text (impl->w_routes); + use_routes = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_routes)); - if (!use_routes) - goto out; + if (!use_routes) + goto out; - substrs = g_strsplit (routes_entry, " ", 0); - for (i = 0; substrs[i] != NULL; i++) { - char *route; + substrs = g_strsplit (routes_entry, " ", 0); + for (i = 0; substrs[i] != NULL; i++) { + char *route; - route = substrs[i]; - if (strlen (route) > 0) - routes = g_slist_append (routes, g_strdup (route)); - } + route = substrs[i]; + if (strlen (route) > 0) + routes = g_slist_append (routes, g_strdup (route)); + } - g_strfreev (substrs); + g_strfreev (substrs); out: - return routes; + return routes; } -static GSList * -impl_get_routes (NetworkManagerVpnUI *self) +static GValue * +str_to_gvalue (const char *str) { - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; + GValue *value; - return get_routes (impl); + 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 (int i) +{ + GValue *value; + + value = g_slice_new0 (GValue); + g_value_init (value, G_TYPE_INT); + g_value_set_int (value, i); + + return value; +} + +static GValue * +uint_to_gvalue (guint u) +{ + GValue *value; + + value = g_slice_new0 (GValue); + g_value_init (value, G_TYPE_UINT); + g_value_set_uint (value, u); + + return value; +} + +static void +impl_fill_connection (NetworkManagerVpnUI *self, NMConnection *connection) +{ + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; + NMSettingConnection *s_con; + NMSettingVPN *s_vpn; + NMSettingVPNProperties *s_vpn_props; + GHashTable *properties; + const char *connectionname; + const char *remote; + const char *port; + const char *ca; + const char *cert; + const char *key; + const char *shared_key; + const char *local_ip; + const char *remote_ip; + const char *username; + gboolean use_lzo; + gboolean use_tap; + gboolean use_tcp; + gboolean use_cipher; + gboolean use_ta; + + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_SETTING_CONNECTION); + g_assert (s_con); + + s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_SETTING_VPN); + g_assert (s_vpn); + + s_vpn_props = (NMSettingVPNProperties *) nm_connection_get_setting (connection, NM_SETTING_VPN_PROPERTIES); + g_assert (s_vpn_props); + properties = s_vpn_props->data; + + /* Connection name */ + connectionname = gtk_entry_get_text (impl->w_connection_name); + g_assert (connectionname); + s_con->name = g_strdup (connectionname); + + /* Populate routes */ + if (s_vpn->routes) { + g_slist_foreach (s_vpn->routes, (GFunc) g_free, NULL); + g_slist_free (s_vpn->routes); + } + s_vpn->routes = get_routes (impl); + + remote = gtk_entry_get_text (impl->w_remote); + port = gtk_entry_get_text (impl->w_port); + ca = gtk_entry_get_text (impl->w_ca); + cert = gtk_entry_get_text (impl->w_cert); + key = gtk_entry_get_text (impl->w_key); + use_lzo = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_lzo)); + use_tap = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_tap)); + use_tcp = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_tcp)); + shared_key = gtk_entry_get_text (impl->w_shared_key); + local_ip = gtk_entry_get_text (impl->w_local_ip); + remote_ip = gtk_entry_get_text (impl->w_remote_ip); + username = gtk_entry_get_text (impl->w_username); + use_cipher = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_cipher)); + use_ta = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_ta)); + + g_hash_table_insert (properties, NM_OPENVPN_KEY_CONNECTION_TYPE, + int_to_gvalue (gtk_combo_box_get_active (GTK_COMBO_BOX (impl->w_connection_type)))); + + g_hash_table_insert (properties, NM_OPENVPN_KEY_TAP_DEV, bool_to_gvalue (use_tap)); + g_hash_table_insert (properties, NM_OPENVPN_KEY_REMOTE, str_to_gvalue (remote)); + g_hash_table_insert (properties, NM_OPENVPN_KEY_PORT, uint_to_gvalue ((guint) atoi (port))); + g_hash_table_insert (properties, NM_OPENVPN_KEY_PROTO_TCP, bool_to_gvalue (use_tcp)); + g_hash_table_insert (properties, NM_OPENVPN_KEY_CA, str_to_gvalue (ca)); + g_hash_table_insert (properties, NM_OPENVPN_KEY_CERT, str_to_gvalue (cert)); + g_hash_table_insert (properties, NM_OPENVPN_KEY_KEY, str_to_gvalue (key)); + g_hash_table_insert (properties, NM_OPENVPN_KEY_COMP_LZO, bool_to_gvalue (use_lzo)); + g_hash_table_insert (properties, NM_OPENVPN_KEY_SHARED_KEY, str_to_gvalue (shared_key)); + g_hash_table_insert (properties, NM_OPENVPN_KEY_LOCAL_IP, str_to_gvalue (local_ip)); + g_hash_table_insert (properties, NM_OPENVPN_KEY_REMOTE_IP, str_to_gvalue (remote_ip)); + g_hash_table_insert (properties, NM_OPENVPN_KEY_USERNAME, str_to_gvalue (username)); + + if (use_cipher) { + const gchar *cipher = gtk_combo_box_get_active_text (impl->w_cipher); + if (cipher != NULL) + g_hash_table_insert (properties, NM_OPENVPN_KEY_CIPHER, str_to_gvalue (cipher)); + } + if (use_ta) { + const gchar* dir; + + g_hash_table_insert (properties, NM_OPENVPN_KEY_TA, + str_to_gvalue (gtk_entry_get_text (impl->w_ta))); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_zero))) + dir = "0"; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_one))) + dir = "1"; + else + dir = ""; + + g_hash_table_insert (properties, NM_OPENVPN_KEY_TA, str_to_gvalue (dir)); + } +} + +static void +set_cipher (GtkComboBox *box, GtkCheckButton *button, const char *value) +{ + GtkTreeModel *tree = gtk_combo_box_get_model(box); + GtkTreeIter iter; + gboolean valid; + + valid = gtk_tree_model_get_iter_first(tree, &iter); + + while (valid) { + gchar *alg; + + gtk_tree_model_get (tree, &iter, 0, &alg, -1); + + /* printf("set_cipher: %s %s\n", alg, value); */ + + if (strcmp(value, alg) == 0) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (box), TRUE); + gtk_combo_box_set_active_iter (box, &iter); + valid = FALSE; + } else + valid = gtk_tree_model_iter_next (tree, &iter); + + g_free (alg); + } +} + +static void +set_property (gpointer key, gpointer val, gpointer user_data) +{ + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) user_data; + const char *name = (const char *) key; + GValue *value = (GValue *) val; + + if (!strcmp (name, NM_OPENVPN_KEY_REMOTE)) + gtk_entry_set_text (impl->w_remote, g_value_get_string (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_PORT)) { + char *port = g_strdup_printf ("%u", g_value_get_uint (value)); + gtk_entry_set_text (impl->w_port, port); + g_free (port); + } else if (!strcmp (name, NM_OPENVPN_KEY_CA)) + gtk_entry_set_text (impl->w_ca, g_value_get_string (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_CERT)) + gtk_entry_set_text (impl->w_cert, g_value_get_string (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_KEY)) + gtk_entry_set_text (impl->w_key, g_value_get_string (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_COMP_LZO)) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_lzo), g_value_get_boolean (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_CONNECTION_TYPE)) { + gtk_combo_box_set_active (GTK_COMBO_BOX (impl->w_connection_type), g_value_get_int (value)); + connection_type_changed (GTK_COMBO_BOX (impl->w_connection_type), impl); + } else if (!strcmp (name, NM_OPENVPN_KEY_LOCAL_IP)) + gtk_entry_set_text (impl->w_local_ip, g_value_get_string (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_REMOTE_IP)) + gtk_entry_set_text (impl->w_remote_ip, g_value_get_string (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_SHARED_KEY)) + gtk_entry_set_text (impl->w_shared_key, g_value_get_string (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_USERNAME)) + gtk_entry_set_text (impl->w_username, g_value_get_string (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_TAP_DEV)) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tap), g_value_get_boolean (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_PROTO_TCP)) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tcp), g_value_get_boolean (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_CIPHER)) + set_cipher(impl->w_cipher, impl->w_use_cipher, g_value_get_string (value)); + else if (!strcmp (name, NM_OPENVPN_KEY_TA)) { + gtk_entry_set_text (impl->w_ta, g_value_get_string (value)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_ta), TRUE); + } else if (!strcmp (name, NM_OPENVPN_KEY_TA_DIR)) { + const char *dir = g_value_get_string (value); + + if (!strcmp (dir, "0")) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_zero), TRUE); + else if (!strcmp (dir, "1")) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_ta_dir_one), TRUE); + } +} + +static GtkWidget * +impl_get_widget (NetworkManagerVpnUI *self, NMConnection *connection) +{ + GSList *i; + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; + NMSettingConnection *s_con; + NMSettingVPN *s_vpn; + NMSettingVPNProperties *s_vpn_props; + + openvpn_clear_widget (impl); + if (!connection) + goto out; + + /* Populate UI bits from the NMConnection */ + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_SETTING_CONNECTION); + g_assert (s_con); + g_assert (s_con->name); + gtk_entry_set_text (impl->w_connection_name, s_con->name); + + s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_SETTING_VPN); + g_assert (s_vpn); + + s_vpn_props = (NMSettingVPNProperties *) nm_connection_get_setting (connection, NM_SETTING_VPN_PROPERTIES); + g_assert (s_vpn_props); + + if (s_vpn_props->data) + g_hash_table_foreach (s_vpn_props->data, set_property, self); + + if (s_vpn->routes != NULL) { + GString *route_str; + char *str; + + route_str = g_string_new (""); + for (i = s_vpn->routes; i; i = i->next) { + if (i != s_vpn->routes) + g_string_append_c (route_str, ' '); + g_string_append (route_str, (char *) i->data); + } + + str = g_string_free (route_str, FALSE); + gtk_entry_set_text (impl->w_routes, str); + g_free (str); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_routes), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_routes), TRUE); + } + + gtk_container_resize_children (GTK_CONTAINER (impl->widget)); + + out: + return impl->widget; } @@ -438,17 +470,17 @@ impl_get_routes (NetworkManagerVpnUI *self) static gboolean check_port (const char *port) { - int d; + int d; - if (sscanf (port, "%d", &d) != 1) { - return FALSE; - } + if (sscanf (port, "%d", &d) != 1) { + return FALSE; + } - if (d < 1 || d > 65536 ) { - return FALSE; - } + if (d < 1 || d > 65536 ) { + return FALSE; + } - return TRUE; + return TRUE; } @@ -458,22 +490,22 @@ check_port (const char *port) static gboolean check_ip (const char *ip) { - int d1, d2, d3, d4; + int d1, d2, d3, d4; - if (sscanf (ip, "%d.%d.%d.%d", &d1, &d2, &d3, &d4) != 4) { - return FALSE; - } + if (sscanf (ip, "%d.%d.%d.%d", &d1, &d2, &d3, &d4) != 4) { + return FALSE; + } - /* TODO: this can be improved a bit */ - if (d1 < 0 || d1 > 255 || - d2 < 0 || d2 > 255 || - d3 < 0 || d3 > 255 || - d4 < 0 || d4 > 255 ) { + /* TODO: this can be improved a bit */ + if (d1 < 0 || d1 > 255 || + d2 < 0 || d2 > 255 || + d3 < 0 || d3 > 255 || + d4 < 0 || d4 > 255 ) { - return FALSE; - } + return FALSE; + } - return TRUE; + return TRUE; } /** Checks if net cidr is in notation @@ -483,1237 +515,1293 @@ check_ip (const char *ip) static gboolean check_net_cidr (const char *net) { - int d1, d2, d3, d4, mask; + int d1, d2, d3, d4, mask; - if (sscanf (net, "%d.%d.%d.%d/%d", &d1, &d2, &d3, &d4, &mask) != 5) { - return FALSE; - } + if (sscanf (net, "%d.%d.%d.%d/%d", &d1, &d2, &d3, &d4, &mask) != 5) { + return FALSE; + } - /* TODO: this can be improved a bit */ - if (d1 < 0 || d1 > 255 || - d2 < 0 || d2 > 255 || - d3 < 0 || d3 > 255 || - d4 < 0 || d4 > 255 || - mask < 0 || mask > 32) { - return FALSE; - } + /* TODO: this can be improved a bit */ + if (d1 < 0 || d1 > 255 || + d2 < 0 || d2 > 255 || + d3 < 0 || d3 > 255 || + d4 < 0 || d4 > 255 || + mask < 0 || mask > 32) { + return FALSE; + } - return TRUE; -} - - -static char * -impl_get_connection_name (NetworkManagerVpnUI *self) -{ - const char *name; - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; - - name = gtk_entry_get_text (impl->w_connection_name); - if (name != NULL) - return g_strdup (name); - else - return NULL; + return TRUE; } static gboolean impl_is_valid (NetworkManagerVpnUI *self) { - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; - gboolean is_valid; - gboolean use_routes; - const char *routes_entry; - const char *connectionname; - const char *remote; - const char *port; - gint connection_type = gtk_combo_box_get_active (GTK_COMBO_BOX (impl->w_connection_type)); + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; + gboolean is_valid; + gboolean use_routes; + const char *routes_entry; + const char *connectionname; + const char *remote; + const char *port; + gint connection_type = gtk_combo_box_get_active (GTK_COMBO_BOX (impl->w_connection_type)); - connectionname = gtk_entry_get_text (impl->w_connection_name); - remote = gtk_entry_get_text (impl->w_remote); - port = gtk_entry_get_text (impl->w_port); - use_routes = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_routes)); - routes_entry = gtk_entry_get_text (impl->w_routes); + connectionname = gtk_entry_get_text (impl->w_connection_name); + remote = gtk_entry_get_text (impl->w_remote); + port = gtk_entry_get_text (impl->w_port); + use_routes = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_routes)); + routes_entry = gtk_entry_get_text (impl->w_routes); - is_valid = FALSE; + is_valid = FALSE; - if ( (strlen (connectionname) == 0) || - (strlen (remote) == 0) || - (strstr (remote, " ") != NULL) || - (strstr (remote, "\t") != NULL) || - (strlen (port) == 0) || - (strstr (port, " ") != NULL) || - (strstr (port, "\t") != NULL) || - (!check_port (port)) ) { + if ( (strlen (connectionname) == 0) || + (strlen (remote) == 0) || + (strstr (remote, " ") != NULL) || + (strstr (remote, "\t") != NULL) || + (strlen (port) == 0) || + (strstr (port, " ") != NULL) || + (strstr (port, "\t") != NULL) || + (!check_port (port)) ) { - is_valid = FALSE; + is_valid = FALSE; - } else if ( connection_type == NM_OPENVPN_CONTYPE_SHAREDKEY ) { - const char *shared_key; - const char *local_ip; - const char *remote_ip; + } else if ( connection_type == NM_OPENVPN_CONTYPE_SHAREDKEY ) { + const char *shared_key; + const char *local_ip; + const char *remote_ip; - shared_key = gtk_entry_get_text (impl->w_shared_key); - local_ip = gtk_entry_get_text (impl->w_local_ip); - remote_ip = gtk_entry_get_text (impl->w_remote_ip); + shared_key = gtk_entry_get_text (impl->w_shared_key); + local_ip = gtk_entry_get_text (impl->w_local_ip); + remote_ip = gtk_entry_get_text (impl->w_remote_ip); - if ( (strlen (shared_key) > 0) && - (strlen (local_ip) > 0) && - (strlen (remote_ip) > 0) && - check_ip (local_ip) && - check_ip (remote_ip) && - g_file_test( shared_key, G_FILE_TEST_IS_REGULAR) ) { + if ( (strlen (shared_key) > 0) && + (strlen (local_ip) > 0) && + (strlen (remote_ip) > 0) && + check_ip (local_ip) && + check_ip (remote_ip) && + g_file_test( shared_key, G_FILE_TEST_IS_REGULAR) ) { - is_valid = TRUE; - } + is_valid = TRUE; + } - } else if ( connection_type == NM_OPENVPN_CONTYPE_PASSWORD ) { + } else if ( connection_type == NM_OPENVPN_CONTYPE_PASSWORD ) { - const char *username; - const char *ca; + const char *username; + const char *ca; - username = gtk_entry_get_text (impl->w_username); - ca = gtk_entry_get_text (impl->w_password_ca); + username = gtk_entry_get_text (impl->w_username); + ca = gtk_entry_get_text (impl->w_password_ca); - if (strlen (username) > 0 && - strlen (ca) > 0 && - g_file_test( ca, G_FILE_TEST_IS_REGULAR) ) { + if (strlen (username) > 0 && + strlen (ca) > 0 && + g_file_test( ca, G_FILE_TEST_IS_REGULAR) ) { - is_valid = TRUE; - } + is_valid = TRUE; + } - } else if ( connection_type == NM_OPENVPN_CONTYPE_X509USERPASS ) { + } else if ( connection_type == NM_OPENVPN_CONTYPE_X509USERPASS ) { - const char *ca; - const char *cert; - const char *key; - const char *username; + const char *ca; + const char *cert; + const char *key; + const char *username; - ca = gtk_entry_get_text (impl->w_x509userpass_ca); - cert = gtk_entry_get_text (impl->w_x509userpass_cert); - key = gtk_entry_get_text (impl->w_x509userpass_key); - username = gtk_entry_get_text (impl->w_x509userpass_username); + ca = gtk_entry_get_text (impl->w_x509userpass_ca); + cert = gtk_entry_get_text (impl->w_x509userpass_cert); + key = gtk_entry_get_text (impl->w_x509userpass_key); + username = gtk_entry_get_text (impl->w_x509userpass_username); - if (strlen (username) > 0 && - strlen (ca) > 0 && - strlen (cert) > 0 && - strlen (key) > 0 && - ((!use_routes) || (use_routes && strlen (routes_entry) > 0)) && - /* validate ca/cert/key files */ - g_file_test( ca, G_FILE_TEST_IS_REGULAR) && - g_file_test( cert, G_FILE_TEST_IS_REGULAR) && - g_file_test( key, G_FILE_TEST_IS_REGULAR) ) { + if (strlen (username) > 0 && + strlen (ca) > 0 && + strlen (cert) > 0 && + strlen (key) > 0 && + ((!use_routes) || (use_routes && strlen (routes_entry) > 0)) && + /* validate ca/cert/key files */ + g_file_test( ca, G_FILE_TEST_IS_REGULAR) && + g_file_test( cert, G_FILE_TEST_IS_REGULAR) && + g_file_test( key, G_FILE_TEST_IS_REGULAR) ) { - is_valid = TRUE; - } + is_valid = TRUE; + } - } else { - // default to NM_OPENVPN_CONTYPE_X509 - const char *ca; - const char *cert; - const char *key; + } else { + // default to NM_OPENVPN_CONTYPE_X509 + const char *ca; + const char *cert; + const char *key; - ca = gtk_entry_get_text (impl->w_ca); - cert = gtk_entry_get_text (impl->w_cert); - key = gtk_entry_get_text (impl->w_key); + ca = gtk_entry_get_text (impl->w_ca); + cert = gtk_entry_get_text (impl->w_cert); + key = gtk_entry_get_text (impl->w_key); - /* initial sanity checking */ - if (strlen (ca) > 0 && - strlen (cert) > 0 && - strlen (key) > 0 && - ((!use_routes) || (use_routes && strlen (routes_entry) > 0)) && - /* validate ca/cert/key files */ - g_file_test( ca, G_FILE_TEST_IS_REGULAR) && - g_file_test( cert, G_FILE_TEST_IS_REGULAR) && - g_file_test( key, G_FILE_TEST_IS_REGULAR) ) { + /* initial sanity checking */ + if (strlen (ca) > 0 && + strlen (cert) > 0 && + strlen (key) > 0 && + ((!use_routes) || (use_routes && strlen (routes_entry) > 0)) && + /* validate ca/cert/key files */ + g_file_test( ca, G_FILE_TEST_IS_REGULAR) && + g_file_test( cert, G_FILE_TEST_IS_REGULAR) && + g_file_test( key, G_FILE_TEST_IS_REGULAR) ) { - is_valid = TRUE; - } + is_valid = TRUE; + } - } + } - /* validate routes: each entry must be of the form 'a.b.c.d/mask' */ - if (is_valid) { - GSList *i; - GSList *routes; + /* validate routes: each entry must be of the form 'a.b.c.d/mask' */ + if (is_valid) { + GSList *i; + GSList *routes; - routes = get_routes (impl); + routes = get_routes (impl); - for (i = routes; is_valid && (i != NULL); i = g_slist_next (i)) { - is_valid = (is_valid && check_net_cidr ( i->data )); - } + for (i = routes; is_valid && (i != NULL); i = g_slist_next (i)) { + is_valid = (is_valid && check_net_cidr ( i->data )); + } - if (routes != NULL) { - g_slist_foreach (routes, (GFunc)g_free, NULL); - g_slist_free (routes); - } - } + if (routes != NULL) { + g_slist_foreach (routes, (GFunc)g_free, NULL); + g_slist_free (routes); + } + } - return is_valid; + return is_valid; } static void use_editable_toggled (GtkToggleButton *togglebutton, gpointer user_data) { - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) user_data; + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) user_data; - if (GTK_CHECK_BUTTON(togglebutton) == impl->w_use_routes) - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_routes), - gtk_toggle_button_get_active (togglebutton)); - else if (GTK_CHECK_BUTTON(togglebutton) == impl->w_use_cipher) - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_cipher), - gtk_toggle_button_get_active (togglebutton)); - else if (GTK_CHECK_BUTTON(togglebutton) == impl->w_use_ta) { - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta), - gtk_toggle_button_get_active (togglebutton)); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_button_ta), - gtk_toggle_button_get_active (togglebutton)); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_label), - gtk_toggle_button_get_active (togglebutton)); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_none), - gtk_toggle_button_get_active (togglebutton)); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_zero), - gtk_toggle_button_get_active (togglebutton)); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_one), - gtk_toggle_button_get_active (togglebutton)); - } + if (GTK_CHECK_BUTTON(togglebutton) == impl->w_use_routes) + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_routes), + gtk_toggle_button_get_active (togglebutton)); + else if (GTK_CHECK_BUTTON(togglebutton) == impl->w_use_cipher) + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_cipher), + gtk_toggle_button_get_active (togglebutton)); + else if (GTK_CHECK_BUTTON(togglebutton) == impl->w_use_ta) { + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta), + gtk_toggle_button_get_active (togglebutton)); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_button_ta), + gtk_toggle_button_get_active (togglebutton)); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_label), + gtk_toggle_button_get_active (togglebutton)); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_none), + gtk_toggle_button_get_active (togglebutton)); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_zero), + gtk_toggle_button_get_active (togglebutton)); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_one), + gtk_toggle_button_get_active (togglebutton)); + } - if (impl->callback != NULL) { - gboolean is_valid; + if (impl->callback != NULL) { + gboolean is_valid; - is_valid = impl_is_valid (&(impl->parent)); - impl->callback (&(impl->parent), is_valid, impl->callback_user_data); - } + is_valid = impl_is_valid (&(impl->parent)); + impl->callback (&(impl->parent), is_valid, impl->callback_user_data); + } } static void editable_changed (GtkEditable *editable, gpointer user_data) { - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) user_data; + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) user_data; - if (impl->callback != NULL) { - gboolean is_valid; + if (impl->callback != NULL) { + gboolean is_valid; - is_valid = impl_is_valid (&(impl->parent)); - impl->callback (&(impl->parent), is_valid, impl->callback_user_data); - } + is_valid = impl_is_valid (&(impl->parent)); + impl->callback (&(impl->parent), is_valid, impl->callback_user_data); + } - // Sync X.509 and password CA, we save the same for both. Since this is ONE - // connection we do not expect the value to change - if ( GTK_ENTRY (editable) == impl->w_ca ) { - gtk_entry_set_text ( impl->w_password_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_ca))); - gtk_entry_set_text ( impl->w_x509userpass_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_ca))); - } else if ( GTK_ENTRY (editable) == impl->w_password_ca ) { - gtk_entry_set_text ( impl->w_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_password_ca))); - gtk_entry_set_text ( impl->w_x509userpass_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_password_ca))); - } else if ( GTK_ENTRY (editable) == impl->w_x509userpass_ca ) { - gtk_entry_set_text ( impl->w_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_x509userpass_ca))); - gtk_entry_set_text ( impl->w_password_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_x509userpass_ca))); - } + // Sync X.509 and password CA, we save the same for both. Since this is ONE + // connection we do not expect the value to change + if ( GTK_ENTRY (editable) == impl->w_ca ) { + gtk_entry_set_text ( impl->w_password_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_ca))); + gtk_entry_set_text ( impl->w_x509userpass_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_ca))); + } else if ( GTK_ENTRY (editable) == impl->w_password_ca ) { + gtk_entry_set_text ( impl->w_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_password_ca))); + gtk_entry_set_text ( impl->w_x509userpass_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_password_ca))); + } else if ( GTK_ENTRY (editable) == impl->w_x509userpass_ca ) { + gtk_entry_set_text ( impl->w_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_x509userpass_ca))); + gtk_entry_set_text ( impl->w_password_ca, gtk_entry_get_text (GTK_ENTRY (impl->w_x509userpass_ca))); + } - if ( GTK_ENTRY (editable) == impl->w_cert ) { - gtk_entry_set_text ( impl->w_x509userpass_cert, gtk_entry_get_text (GTK_ENTRY (impl->w_cert))); - } else if ( GTK_ENTRY (editable) == impl->w_x509userpass_cert ) { - gtk_entry_set_text ( impl->w_cert, gtk_entry_get_text (GTK_ENTRY (impl->w_x509userpass_cert))); - } + if ( GTK_ENTRY (editable) == impl->w_cert ) { + gtk_entry_set_text ( impl->w_x509userpass_cert, gtk_entry_get_text (GTK_ENTRY (impl->w_cert))); + } else if ( GTK_ENTRY (editable) == impl->w_x509userpass_cert ) { + gtk_entry_set_text ( impl->w_cert, gtk_entry_get_text (GTK_ENTRY (impl->w_x509userpass_cert))); + } - if ( GTK_ENTRY (editable) == impl->w_key ) { - gtk_entry_set_text ( impl->w_x509userpass_key, gtk_entry_get_text (GTK_ENTRY (impl->w_key))); - } else if ( GTK_ENTRY (editable) == impl->w_x509userpass_key ) { - gtk_entry_set_text ( impl->w_key, gtk_entry_get_text (GTK_ENTRY (impl->w_x509userpass_key))); - } + if ( GTK_ENTRY (editable) == impl->w_key ) { + gtk_entry_set_text ( impl->w_x509userpass_key, gtk_entry_get_text (GTK_ENTRY (impl->w_key))); + } else if ( GTK_ENTRY (editable) == impl->w_x509userpass_key ) { + gtk_entry_set_text ( impl->w_key, gtk_entry_get_text (GTK_ENTRY (impl->w_x509userpass_key))); + } - if ( GTK_ENTRY (editable) == impl->w_username ) { - gtk_entry_set_text ( impl->w_x509userpass_username, gtk_entry_get_text (GTK_ENTRY (impl->w_username))); - } else if ( GTK_ENTRY (editable) == impl->w_x509userpass_username ) { - gtk_entry_set_text ( impl->w_username, gtk_entry_get_text (GTK_ENTRY (impl->w_x509userpass_username))); - } + if ( GTK_ENTRY (editable) == impl->w_username ) { + gtk_entry_set_text ( impl->w_x509userpass_username, gtk_entry_get_text (GTK_ENTRY (impl->w_username))); + } else if ( GTK_ENTRY (editable) == impl->w_x509userpass_username ) { + gtk_entry_set_text ( impl->w_username, gtk_entry_get_text (GTK_ENTRY (impl->w_x509userpass_username))); + } } static void impl_set_validity_changed_callback (NetworkManagerVpnUI *self, - NetworkManagerVpnUIDialogValidityCallback callback, - gpointer user_data) + NetworkManagerVpnUIDialogValidityCallback callback, + gpointer user_data) { - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; - impl->callback = callback; - impl->callback_user_data = user_data; + impl->callback = callback; + impl->callback_user_data = user_data; } static void impl_get_confirmation_details (NetworkManagerVpnUI *self, gchar **retval) { - GString *buf; - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; - const char *connectionname; - const char *remote; - const char *port; - const char *ca; - const char *cert; - const char *key; - const char *shared_key; - const char *local_ip; - const char *remote_ip; - const char *username; - gboolean use_routes; - const char *routes; - gboolean use_lzo; - gboolean use_tap; - gboolean use_tcp; - gint connection_type; - gboolean use_cipher; - const gchar *cipher; - gboolean use_ta; - const char *ta; - const char *ta_dir; + GString *buf; + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; + const char *connectionname; + const char *remote; + const char *port; + const char *ca; + const char *cert; + const char *key; + const char *shared_key; + const char *local_ip; + const char *remote_ip; + const char *username; + gboolean use_routes; + const char *routes; + gboolean use_lzo; + gboolean use_tap; + gboolean use_tcp; + gint connection_type; + gboolean use_cipher; + const gchar *cipher; + gboolean use_ta; + const char *ta; + const char *ta_dir; - connectionname = gtk_entry_get_text (impl->w_connection_name); - connection_type = gtk_combo_box_get_active (impl->w_connection_type); - remote = gtk_entry_get_text (impl->w_remote); - port = gtk_entry_get_text (impl->w_port); - cert = gtk_entry_get_text (impl->w_cert); - key = gtk_entry_get_text (impl->w_key); - shared_key = gtk_entry_get_text (impl->w_shared_key); - local_ip = gtk_entry_get_text (impl->w_local_ip); - remote_ip = gtk_entry_get_text (impl->w_remote_ip); - username = gtk_entry_get_text (impl->w_username); - use_routes = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_routes)); - routes = gtk_entry_get_text (impl->w_routes); - use_lzo = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_lzo)); - use_tap = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_tap)); - use_tcp = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_tcp)); - use_cipher = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_cipher)); - cipher = gtk_combo_box_get_active_text(impl->w_cipher); - use_ta = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_ta)); - ta = gtk_entry_get_text (impl->w_ta); - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(impl->w_ta_dir_zero))) - ta_dir = "0"; - else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(impl->w_ta_dir_one))) - ta_dir = "1"; - else - ta_dir = ""; + connectionname = gtk_entry_get_text (impl->w_connection_name); + connection_type = gtk_combo_box_get_active (impl->w_connection_type); + remote = gtk_entry_get_text (impl->w_remote); + port = gtk_entry_get_text (impl->w_port); + cert = gtk_entry_get_text (impl->w_cert); + key = gtk_entry_get_text (impl->w_key); + shared_key = gtk_entry_get_text (impl->w_shared_key); + local_ip = gtk_entry_get_text (impl->w_local_ip); + remote_ip = gtk_entry_get_text (impl->w_remote_ip); + username = gtk_entry_get_text (impl->w_username); + use_routes = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_routes)); + routes = gtk_entry_get_text (impl->w_routes); + use_lzo = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_lzo)); + use_tap = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_tap)); + use_tcp = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_tcp)); + use_cipher = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_cipher)); + cipher = gtk_combo_box_get_active_text(impl->w_cipher); + use_ta = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_ta)); + ta = gtk_entry_get_text (impl->w_ta); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(impl->w_ta_dir_zero))) + ta_dir = "0"; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(impl->w_ta_dir_one))) + ta_dir = "1"; + else + ta_dir = ""; - // This is risky, should be variable length depending on actual data! - buf = g_string_sized_new (512); + // This is risky, should be variable length depending on actual data! + buf = g_string_sized_new (512); - g_string_append (buf, _("The following OpenVPN connection will be created:")); - g_string_append (buf, "\n\n\t"); - g_string_append_printf (buf, _("Name: %s"), connectionname); - g_string_append (buf, "\n\n\t"); + g_string_append (buf, _("The following OpenVPN connection will be created:")); + g_string_append (buf, "\n\n\t"); + g_string_append_printf (buf, _("Name: %s"), connectionname); + g_string_append (buf, "\n\n\t"); - switch ( connection_type ) { + switch ( connection_type ) { - case NM_OPENVPN_CONTYPE_X509: - ca = gtk_entry_get_text (impl->w_ca); + case NM_OPENVPN_CONTYPE_X509: + ca = gtk_entry_get_text (impl->w_ca); - g_string_append (buf, _("Connection Type: X.509 Certificates")); + g_string_append (buf, _("Connection Type: X.509 Certificates")); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("CA: %s"), ca); + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("CA: %s"), ca); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Cert: %s"), cert); + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Cert: %s"), cert); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Key: %s"), key); - break; + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Key: %s"), key); + break; - case NM_OPENVPN_CONTYPE_SHAREDKEY: - g_string_append (buf, _("Connection Type: Shared Key")); + case NM_OPENVPN_CONTYPE_SHAREDKEY: + g_string_append (buf, _("Connection Type: Shared Key")); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Shared Key: %s"), shared_key); + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Shared Key: %s"), shared_key); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Local IP: %s"), local_ip); + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Local IP: %s"), local_ip); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Remote IP: %s"), remote_ip); - break; + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Remote IP: %s"), remote_ip); + break; - case NM_OPENVPN_CONTYPE_PASSWORD: - ca = gtk_entry_get_text (impl->w_password_ca); - g_string_append (buf, _("Connection Type: Password")); + case NM_OPENVPN_CONTYPE_PASSWORD: + ca = gtk_entry_get_text (impl->w_password_ca); + g_string_append (buf, _("Connection Type: Password")); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("CA: %s"), ca); + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("CA: %s"), ca); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Username: %s"), username); - break; + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Username: %s"), username); + break; - case NM_OPENVPN_CONTYPE_X509USERPASS: - ca = gtk_entry_get_text (impl->w_x509userpass_ca); + case NM_OPENVPN_CONTYPE_X509USERPASS: + ca = gtk_entry_get_text (impl->w_x509userpass_ca); - g_string_append (buf, _("Connection Type: X.509 with Password Authentication")); + g_string_append (buf, _("Connection Type: X.509 with Password Authentication")); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("CA: %s"), ca); + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("CA: %s"), ca); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Cert: %s"), cert); + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Cert: %s"), cert); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Key: %s"), key); + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Key: %s"), key); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Username: %s"), username); - break; + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Username: %s"), username); + break; - } + } - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Remote: %s"), remote); + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Remote: %s"), remote); - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Port: %s"), port); + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Port: %s"), port); - g_string_append (buf, "\n\t"); - g_string_append_printf( buf, _("Device: %s"), ((use_tap) ? _("TAP") : _("TUN"))); + g_string_append (buf, "\n\t"); + g_string_append_printf( buf, _("Device: %s"), ((use_tap) ? _("TAP") : _("TUN"))); - g_string_append (buf, "\n\t"); - g_string_append_printf( buf, _("Protocol: %s"), ((use_tcp) ? _("TCP") : _("UDP"))); + g_string_append (buf, "\n\t"); + g_string_append_printf( buf, _("Protocol: %s"), ((use_tcp) ? _("TCP") : _("UDP"))); - if (use_routes) { - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Routes: %s"), routes); - } + if (use_routes) { + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Routes: %s"), routes); + } - g_string_append (buf, "\n\t"); - g_string_append_printf( buf, _("Use LZO Compression: %s"), ((use_lzo) ? _("Yes") : _("No"))); + g_string_append (buf, "\n\t"); + g_string_append_printf( buf, _("Use LZO Compression: %s"), ((use_lzo) ? _("Yes") : _("No"))); - if (use_cipher && (cipher != NULL)) { - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("Cipher: %s"), cipher); - } + if (use_cipher && (cipher != NULL)) { + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("Cipher: %s"), cipher); + } - if (use_ta) { - g_string_append (buf, "\n\t"); - g_string_append_printf (buf, _("TLS auth: %s %s"), ta, ta_dir); - } + if (use_ta) { + g_string_append (buf, "\n\t"); + g_string_append_printf (buf, _("TLS auth: %s %s"), ta, ta_dir); + } - g_string_append (buf, "\n\n"); - g_string_append (buf, _("The connection details can be changed using the \"Edit\" button.")); - g_string_append (buf, "\n"); + g_string_append (buf, "\n\n"); + g_string_append (buf, _("The connection details can be changed using the \"Edit\" button.")); + g_string_append (buf, "\n"); - *retval = g_string_free (buf, FALSE); + *retval = g_string_free (buf, FALSE); } static gboolean -import_from_file (NetworkManagerVpnUIImpl *impl, const char *path) +import_from_file (NetworkManagerVpnUI *self, + const char *path, + NMConnection *connection) { - char *basename; - GKeyFile *keyfile; - gboolean file_is_good; + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; + char *basename; + GKeyFile *keyfile; + gboolean file_is_good; - file_is_good = TRUE; - basename = g_path_get_basename (path); + file_is_good = TRUE; + basename = g_path_get_basename (path); - keyfile = g_key_file_new (); - if (g_key_file_load_from_file (keyfile, path, 0, NULL)) { - char *connectionname = NULL; - char *remote = NULL; - char *port = NULL; - char *ca = NULL; - char *cert = NULL; - char *key = NULL; - char *routes = NULL; - char *lzo = NULL; - char *dev = NULL; - char *proto = NULL; - char *connection_type = NULL; - char *shared_key = NULL; - char *local_ip = NULL; - char *remote_ip = NULL; - char *username = NULL; - char *cipher = NULL; - char *ta = NULL; - char *ta_dir = NULL; - gint connection_type_sel = 0; - gboolean should_expand; + keyfile = g_key_file_new (); + if (g_key_file_load_from_file (keyfile, path, 0, NULL)) { + char *connectionname = NULL; + char *remote = NULL; + char *port = NULL; + char *ca = NULL; + char *cert = NULL; + char *key = NULL; + char *routes = NULL; + char *lzo = NULL; + char *dev = NULL; + char *proto = NULL; + char *connection_type = NULL; + char *shared_key = NULL; + char *local_ip = NULL; + char *remote_ip = NULL; + char *username = NULL; + char *cipher = NULL; + char *ta = NULL; + char *ta_dir = NULL; + gint connection_type_sel = 0; + gboolean should_expand; - connectionname = g_key_file_get_string (keyfile, "openvpn", "description", NULL); - connection_type = g_key_file_get_string (keyfile, "openvpn", "connection-type", NULL); - remote = g_key_file_get_string (keyfile, "openvpn", "remote", NULL); - port = g_key_file_get_string (keyfile, "openvpn", "port", NULL); - dev = g_key_file_get_string (keyfile, "openvpn", "dev", NULL); - proto = g_key_file_get_string (keyfile, "openvpn", "proto", NULL); - ca = g_key_file_get_string (keyfile, "openvpn", "ca", NULL); - cert = g_key_file_get_string (keyfile, "openvpn", "cert", NULL); - key = g_key_file_get_string (keyfile, "openvpn", "key", NULL); - lzo = g_key_file_get_string (keyfile, "openvpn", "comp-lzo", NULL); - shared_key = g_key_file_get_string (keyfile, "openvpn", "shared-key", NULL); - local_ip = g_key_file_get_string (keyfile, "openvpn", "local-ip", NULL); - remote_ip = g_key_file_get_string (keyfile, "openvpn", "remote-ip", NULL); - username = g_key_file_get_string (keyfile, "openvpn", "username", NULL); - cipher = g_key_file_get_string (keyfile, "openvpn", "cipher", NULL); - ta = g_key_file_get_string (keyfile, "openvpn", "ta", NULL); - ta_dir = g_key_file_get_string (keyfile, "openvpn", "ta_dir", NULL); + connectionname = g_key_file_get_string (keyfile, "openvpn", "description", NULL); + connection_type = g_key_file_get_string (keyfile, "openvpn", "connection-type", NULL); + remote = g_key_file_get_string (keyfile, "openvpn", "remote", NULL); + port = g_key_file_get_string (keyfile, "openvpn", "port", NULL); + dev = g_key_file_get_string (keyfile, "openvpn", "dev", NULL); + proto = g_key_file_get_string (keyfile, "openvpn", "proto", NULL); + ca = g_key_file_get_string (keyfile, "openvpn", "ca", NULL); + cert = g_key_file_get_string (keyfile, "openvpn", "cert", NULL); + key = g_key_file_get_string (keyfile, "openvpn", "key", NULL); + lzo = g_key_file_get_string (keyfile, "openvpn", "comp-lzo", NULL); + shared_key = g_key_file_get_string (keyfile, "openvpn", "shared-key", NULL); + local_ip = g_key_file_get_string (keyfile, "openvpn", "local-ip", NULL); + remote_ip = g_key_file_get_string (keyfile, "openvpn", "remote-ip", NULL); + username = g_key_file_get_string (keyfile, "openvpn", "username", NULL); + cipher = g_key_file_get_string (keyfile, "openvpn", "cipher", NULL); + ta = g_key_file_get_string (keyfile, "openvpn", "ta", NULL); + ta_dir = g_key_file_get_string (keyfile, "openvpn", "ta_dir", NULL); - /* may not exist */ - if ((routes = g_key_file_get_string (keyfile, "openvpn", "routes", NULL)) == NULL) - routes = g_strdup (""); + /* may not exist */ + if ((routes = g_key_file_get_string (keyfile, "openvpn", "routes", NULL)) == NULL) + routes = g_strdup (""); - /* sanity check data */ - if ( (connectionname != NULL) && - (remote != NULL ) && - (port != NULL ) && - (dev != NULL) && - (proto != NULL) && - (connection_type != NULL) && - (strlen (remote) > 0) && - (strlen (port) > 0) && - (strlen (dev) > 0) && - (strlen (proto) > 0) && - (strlen (connectionname) > 0) ) { + /* sanity check data */ + if ( (connectionname != NULL) && + (remote != NULL ) && + (port != NULL ) && + (dev != NULL) && + (proto != NULL) && + (connection_type != NULL) && + (strlen (remote) > 0) && + (strlen (port) > 0) && + (strlen (dev) > 0) && + (strlen (proto) > 0) && + (strlen (connectionname) > 0) ) { - // Basics ok, now check per poosible mode + // Basics ok, now check per poosible mode - if (strcmp (connection_type, "x509") == 0) { - if ( (ca != NULL ) && - (cert != NULL ) && - (key != NULL ) && - (strlen(ca) > 0) && - (strlen(cert) > 0) && - (strlen(key) > 0) ) { + if (strcmp (connection_type, "x509") == 0) { + if ( (ca != NULL ) && + (cert != NULL ) && + (key != NULL ) && + (strlen(ca) > 0) && + (strlen(cert) > 0) && + (strlen(key) > 0) ) { - gtk_entry_set_text (impl->w_ca, ca); - gtk_entry_set_text (impl->w_password_ca, ca); - gtk_entry_set_text (impl->w_x509userpass_ca, ca); - gtk_entry_set_text (impl->w_cert, cert); - gtk_entry_set_text (impl->w_x509userpass_cert, cert); - gtk_entry_set_text (impl->w_key, key); - gtk_entry_set_text (impl->w_x509userpass_key, key); - connection_type_sel = NM_OPENVPN_CONTYPE_X509; - } else { - file_is_good = FALSE; + gtk_entry_set_text (impl->w_ca, ca); + gtk_entry_set_text (impl->w_password_ca, ca); + gtk_entry_set_text (impl->w_x509userpass_ca, ca); + gtk_entry_set_text (impl->w_cert, cert); + gtk_entry_set_text (impl->w_x509userpass_cert, cert); + gtk_entry_set_text (impl->w_key, key); + gtk_entry_set_text (impl->w_x509userpass_key, key); + connection_type_sel = NM_OPENVPN_CONTYPE_X509; + } else { + file_is_good = FALSE; + } + } else if (strcmp (connection_type, "shared-key") == 0) { + if ( (shared_key != NULL ) && + (local_ip != NULL ) && + (remote_ip != NULL ) && + (strlen(shared_key) > 0) && + (strlen(local_ip) > 0) && + (strlen(remote_ip) > 0) && + check_ip (local_ip) && + check_ip (remote_ip) ) { + + gtk_entry_set_text (impl->w_shared_key, shared_key); + gtk_entry_set_text (impl->w_local_ip, local_ip); + gtk_entry_set_text (impl->w_remote_ip, remote_ip); + connection_type_sel = NM_OPENVPN_CONTYPE_SHAREDKEY; + } else { + file_is_good = FALSE; + } + } else if (strcmp (connection_type, "password") == 0) { + if ( (username != NULL ) && + (strlen(username) > 0) ) { + + gtk_entry_set_text (impl->w_username, username); + gtk_entry_set_text (impl->w_x509userpass_username, username); + gtk_entry_set_text (impl->w_ca, ca); + gtk_entry_set_text (impl->w_password_ca, ca); + gtk_entry_set_text (impl->w_x509userpass_ca, ca); + connection_type_sel = NM_OPENVPN_CONTYPE_PASSWORD; + } else { + file_is_good = FALSE; + } + } else if (strcmp (connection_type, "x509userpass") == 0) { + if ( (ca != NULL ) && + (cert != NULL ) && + (key != NULL ) && + (username != NULL ) && + (strlen(ca) > 0) && + (strlen(cert) > 0) && + (strlen(key) > 0) && + (strlen(username) > 0) ) { + + gtk_entry_set_text (impl->w_ca, ca); + gtk_entry_set_text (impl->w_password_ca, ca); + gtk_entry_set_text (impl->w_x509userpass_ca, ca); + gtk_entry_set_text (impl->w_cert, cert); + gtk_entry_set_text (impl->w_x509userpass_cert, cert); + gtk_entry_set_text (impl->w_key, key); + gtk_entry_set_text (impl->w_x509userpass_key, key); + gtk_entry_set_text (impl->w_username, username); + gtk_entry_set_text (impl->w_x509userpass_username, username); + connection_type_sel = NM_OPENVPN_CONTYPE_X509USERPASS; + } else { + file_is_good = FALSE; + } + } else { + // no connection type given in config + file_is_good = FALSE; + } + } else { + // invlid basic data + file_is_good = FALSE; + } + + if ((cipher != NULL) && (strlen (cipher) > 0)) { + set_cipher(impl->w_cipher, impl->w_use_cipher, cipher); + } + + if ((ta != NULL) && (strlen (ta) > 0)) { + gtk_entry_set_text (impl->w_ta, ta); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_ta), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_button_ta), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_label), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_none), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_zero), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_one), TRUE); + } + + if ((ta_dir != NULL) && (strlen (ta_dir) > 0)) { + if (strcmp(ta_dir, "0") == 0) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(impl->w_ta_dir_zero), TRUE); + else if (strcmp(ta_dir, "1") == 0) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(impl->w_ta_dir_one), TRUE); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(impl->w_ta_dir_none), TRUE); + } + + if (file_is_good) { + should_expand = FALSE; + + gtk_entry_set_text (impl->w_connection_name, connectionname); + gtk_entry_set_text (impl->w_remote, remote); + + if ( check_port (port) ) { + gtk_entry_set_text (impl->w_port, port); + } else { + gtk_entry_set_text (impl->w_port, "1194"); + } + + gtk_combo_box_set_active (GTK_COMBO_BOX (impl->w_connection_type), connection_type_sel); + connection_type_changed (GTK_COMBO_BOX (impl->w_connection_type), impl); + + if ( (lzo != NULL) && (strcmp(lzo, "yes") == 0) ) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_lzo), TRUE); + should_expand = TRUE; + } + + if ( strcmp (dev, "tap") == 0 ) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tap), TRUE); + should_expand = TRUE; + } + + if ( strcmp (proto, "tcp-client") == 0 ) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tcp), TRUE); + should_expand = TRUE; + } + + if ( strlen (routes) > 0 ) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_routes), TRUE); + should_expand = TRUE; + gtk_entry_set_text (impl->w_routes, routes); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_routes), TRUE); + } + + if (connection) + impl_fill_connection (self, connection); + } else { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_CLOSE, + _("Cannot import settings")); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + _("The VPN settings file '%s' does not contain valid data."), basename); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + } + + g_key_file_free (keyfile); + + g_free (connectionname); + g_free (connection_type); + g_free (remote); + g_free (port); + g_free (dev); + g_free (proto); + g_free (ca); + g_free (cert); + g_free (key); + g_free (lzo); + g_free (shared_key); + g_free (local_ip); + g_free (remote_ip); + g_free (username); + g_free (cipher); + g_free (ta); + g_free (ta_dir); } - } else if (strcmp (connection_type, "shared-key") == 0) { - if ( (shared_key != NULL ) && - (local_ip != NULL ) && - (remote_ip != NULL ) && - (strlen(shared_key) > 0) && - (strlen(local_ip) > 0) && - (strlen(remote_ip) > 0) && - check_ip (local_ip) && - check_ip (remote_ip) ) { - gtk_entry_set_text (impl->w_shared_key, shared_key); - gtk_entry_set_text (impl->w_local_ip, local_ip); - gtk_entry_set_text (impl->w_remote_ip, remote_ip); - connection_type_sel = NM_OPENVPN_CONTYPE_SHAREDKEY; - } else { - file_is_good = FALSE; - } - } else if (strcmp (connection_type, "password") == 0) { - if ( (username != NULL ) && - (strlen(username) > 0) ) { + g_free (basename); - gtk_entry_set_text (impl->w_username, username); - gtk_entry_set_text (impl->w_x509userpass_username, username); - gtk_entry_set_text (impl->w_ca, ca); - gtk_entry_set_text (impl->w_password_ca, ca); - gtk_entry_set_text (impl->w_x509userpass_ca, ca); - connection_type_sel = NM_OPENVPN_CONTYPE_PASSWORD; - } else { - file_is_good = FALSE; - } - } else if (strcmp (connection_type, "x509userpass") == 0) { - if ( (ca != NULL ) && - (cert != NULL ) && - (key != NULL ) && - (username != NULL ) && - (strlen(ca) > 0) && - (strlen(cert) > 0) && - (strlen(key) > 0) && - (strlen(username) > 0) ) { - - gtk_entry_set_text (impl->w_ca, ca); - gtk_entry_set_text (impl->w_password_ca, ca); - gtk_entry_set_text (impl->w_x509userpass_ca, ca); - gtk_entry_set_text (impl->w_cert, cert); - gtk_entry_set_text (impl->w_x509userpass_cert, cert); - gtk_entry_set_text (impl->w_key, key); - gtk_entry_set_text (impl->w_x509userpass_key, key); - gtk_entry_set_text (impl->w_username, username); - gtk_entry_set_text (impl->w_x509userpass_username, username); - connection_type_sel = NM_OPENVPN_CONTYPE_X509USERPASS; - } else { - file_is_good = FALSE; - } - } else { - // no connection type given in config - file_is_good = FALSE; - } - } else { - // invlid basic data - file_is_good = FALSE; - } - - if ((cipher != NULL) && (strlen (cipher) > 0)) { - set_cipher(impl->w_cipher, impl->w_use_cipher, cipher); - } - - if ((ta != NULL) && (strlen (ta) > 0)) { - gtk_entry_set_text (impl->w_ta, ta); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_ta), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_button_ta), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_label), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_none), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_zero), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_ta_dir_one), TRUE); - } - - if ((ta_dir != NULL) && (strlen (ta_dir) > 0)) { - if (strcmp(ta_dir, "0") == 0) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(impl->w_ta_dir_zero), TRUE); - else if (strcmp(ta_dir, "1") == 0) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(impl->w_ta_dir_one), TRUE); - else - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(impl->w_ta_dir_none), TRUE); - } - - if (file_is_good) { - should_expand = FALSE; - - gtk_entry_set_text (impl->w_connection_name, connectionname); - gtk_entry_set_text (impl->w_remote, remote); - - if ( check_port (port) ) { - gtk_entry_set_text (impl->w_port, port); - } else { - gtk_entry_set_text (impl->w_port, "1194"); - } - - gtk_combo_box_set_active (GTK_COMBO_BOX (impl->w_connection_type), connection_type_sel); - connection_type_changed (GTK_COMBO_BOX (impl->w_connection_type), impl); - - if ( (lzo != NULL) && (strcmp(lzo, "yes") == 0) ) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_lzo), TRUE); - should_expand = TRUE; - } - - if ( strcmp (dev, "tap") == 0 ) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tap), TRUE); - should_expand = TRUE; - } - - if ( strcmp (proto, "tcp-client") == 0 ) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_tcp), TRUE); - should_expand = TRUE; - } - - if ( strlen (routes) > 0 ) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_routes), TRUE); - should_expand = TRUE; - gtk_entry_set_text (impl->w_routes, routes); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_routes), TRUE); - } - } else { - GtkWidget *dialog; - - dialog = gtk_message_dialog_new (NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_CLOSE, - _("Cannot import settings")); - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), - _("The VPN settings file '%s' does not contain valid data."), basename); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - } - - g_key_file_free (keyfile); - - g_free (connectionname); - g_free (connection_type); - g_free (remote); - g_free (port); - g_free (dev); - g_free (proto); - g_free (ca); - g_free (cert); - g_free (key); - g_free (lzo); - g_free (shared_key); - g_free (local_ip); - g_free (remote_ip); - g_free (username); - g_free (cipher); - g_free (ta); - g_free (ta_dir); - } - - g_free (basename); - - return file_is_good; + return file_is_good; } static void advanced_button_clicked (GtkButton *button, gpointer user_data) { - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) user_data; + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) user_data; - gtk_dialog_run (impl->advanced); - gtk_widget_hide (GTK_WIDGET(impl->advanced)); + gtk_dialog_run (impl->advanced); + gtk_widget_hide (GTK_WIDGET(impl->advanced)); } static void import_button_clicked (GtkButton *button, gpointer user_data) { - char *filename = NULL; - GtkWidget *dialog; - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) user_data; + char *filename = NULL; + GtkWidget *dialog; + NetworkManagerVpnUI *self = (NetworkManagerVpnUI *) user_data; - dialog = gtk_file_chooser_dialog_new (_("Select file to import"), - NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); + dialog = gtk_file_chooser_dialog_new (_("Select file to import"), + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - /*printf ("User selected '%s'\n", filename);*/ + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + /*printf ("User selected '%s'\n", filename);*/ - } + } - gtk_widget_destroy (dialog); + gtk_widget_destroy (dialog); - if (filename != NULL) { - import_from_file (impl, filename); - g_free (filename); - } + if (filename != NULL) { + import_from_file (self, filename, NULL); + g_free (filename); + } } static void connection_type_changed (GtkComboBox *box, gpointer user_data) { - int i; - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) user_data; - gint sel = gtk_combo_box_get_active( box ); + int i; + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) user_data; + gint sel = gtk_combo_box_get_active( box ); - switch ( sel ) { - case NM_OPENVPN_CONTYPE_X509: - case NM_OPENVPN_CONTYPE_SHAREDKEY: - case NM_OPENVPN_CONTYPE_PASSWORD: - case NM_OPENVPN_CONTYPE_X509USERPASS: - { - gtk_notebook_set_current_page( impl->w_settings_notebook, sel ); - for (i = NM_OPENVPN_CONTYPE_X509; i <= NM_OPENVPN_CONTYPE_X509USERPASS; ++i) { - GtkWidget *tab = GTK_WIDGET ( gtk_notebook_get_nth_page( GTK_NOTEBOOK (impl->w_settings_notebook), i)); - gtk_widget_set_sensitive( tab, (i == sel)); - gtk_widget_set_sensitive( GTK_WIDGET ( gtk_notebook_get_tab_label( GTK_NOTEBOOK (impl->w_settings_notebook), tab) ), (i == sel)); - } - } - break; - } + switch ( sel ) { + case NM_OPENVPN_CONTYPE_X509: + case NM_OPENVPN_CONTYPE_SHAREDKEY: + case NM_OPENVPN_CONTYPE_PASSWORD: + case NM_OPENVPN_CONTYPE_X509USERPASS: + { + gtk_notebook_set_current_page( impl->w_settings_notebook, sel ); + for (i = NM_OPENVPN_CONTYPE_X509; i <= NM_OPENVPN_CONTYPE_X509USERPASS; ++i) { + GtkWidget *tab = GTK_WIDGET ( gtk_notebook_get_nth_page( GTK_NOTEBOOK (impl->w_settings_notebook), i)); + gtk_widget_set_sensitive( tab, (i == sel)); + gtk_widget_set_sensitive( GTK_WIDGET ( gtk_notebook_get_tab_label( GTK_NOTEBOOK (impl->w_settings_notebook), tab) ), (i == sel)); + } + } + break; + } } static void open_button_clicked (GtkButton *button, gpointer user_data) { - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *)user_data; - GtkWidget *dialog; + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *)user_data; + GtkWidget *dialog; - const char *msg; - GtkEntry *entry; + const char *msg; + GtkEntry *entry; - gchar *dir; + gchar *dir; - if ( button == impl->w_button_ca ) { - msg = _("Select CA to use"); - entry = impl->w_ca; - } else if ( button == impl->w_button_cert ) { - msg = _("Select certificate to use"); - entry = impl->w_cert; - } else if ( button == impl->w_button_key ) { - msg = _("Select key to use"); - entry = impl->w_key; - } else if ( button == impl->w_button_shared_key ) { - msg = _("Select shared key to use"); - entry = impl->w_shared_key; - } else if ( button == impl->w_button_password_ca ) { - msg = _("Select CA to use"); - entry = impl->w_password_ca; - } else if ( button == impl->w_button_x509userpass_ca ) { - msg = _("Select CA to use"); - entry = impl->w_x509userpass_ca; - } else if ( button == impl->w_button_x509userpass_cert ) { - msg = _("Select certificate to use"); - entry = impl->w_x509userpass_cert; - } else if ( button == impl->w_button_x509userpass_key ) { - msg = _("Select key to use"); - entry = impl->w_x509userpass_key; - } else if ( button == impl->w_button_ta ) { - msg = _("Select TA to use"); - entry = impl->w_ta; - } else { - return; - } + if ( button == impl->w_button_ca ) { + msg = _("Select CA to use"); + entry = impl->w_ca; + } else if ( button == impl->w_button_cert ) { + msg = _("Select certificate to use"); + entry = impl->w_cert; + } else if ( button == impl->w_button_key ) { + msg = _("Select key to use"); + entry = impl->w_key; + } else if ( button == impl->w_button_shared_key ) { + msg = _("Select shared key to use"); + entry = impl->w_shared_key; + } else if ( button == impl->w_button_password_ca ) { + msg = _("Select CA to use"); + entry = impl->w_password_ca; + } else if ( button == impl->w_button_x509userpass_ca ) { + msg = _("Select CA to use"); + entry = impl->w_x509userpass_ca; + } else if ( button == impl->w_button_x509userpass_cert ) { + msg = _("Select certificate to use"); + entry = impl->w_x509userpass_cert; + } else if ( button == impl->w_button_x509userpass_key ) { + msg = _("Select key to use"); + entry = impl->w_x509userpass_key; + } else if ( button == impl->w_button_ta ) { + msg = _("Select TA to use"); + entry = impl->w_ta; + } else { + return; + } - dialog = gtk_file_chooser_dialog_new (msg, - NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); + dialog = gtk_file_chooser_dialog_new (msg, + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); - if ( impl->last_fc_dir != NULL ) { - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), impl->last_fc_dir); - } + if ( impl->last_fc_dir != NULL ) { + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), impl->last_fc_dir); + } - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { - gtk_entry_set_text (entry, gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog))); - dir = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); - g_free( impl->last_fc_dir ); - impl->last_fc_dir = dir; - } + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { + gtk_entry_set_text (entry, gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog))); + dir = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); + g_free( impl->last_fc_dir ); + impl->last_fc_dir = dir; + } - gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - gtk_widget_destroy (dialog); + gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + gtk_widget_destroy (dialog); } static gboolean impl_can_export (NetworkManagerVpnUI *self) { - return TRUE; + return TRUE; } static gboolean -impl_import_file (NetworkManagerVpnUI *self, const char *path) +impl_import_file (NetworkManagerVpnUI *self, + const char *path, + NMConnection *connection) { - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; - - return import_from_file (impl, path); + return import_from_file (self, path, connection); } static gboolean -export_to_file (NetworkManagerVpnUIImpl *impl, const char *path, - GSList *properties, GSList *routes, const char *connection_name) +export_to_file (NetworkManagerVpnUIImpl *impl, + const char *path, + NMConnection *connection) { - FILE *f; - GSList *i; - const char *connection_type = ""; - const char *remote = ""; - const char *port = ""; - const char *dev = ""; - const char *proto = ""; - const char *ca = ""; - const char *cert = ""; - const char *key = ""; - const char *lzo = ""; - const char *shared_key = ""; - const char *local_ip = ""; - const char *remote_ip = ""; - const char *username = ""; - const char *cipher = ""; - const char *ta = ""; - const char *ta_dir = ""; - char *routes_str = NULL; - gboolean ret; + NMSettingConnection *s_con; + NMSettingVPN *s_vpn; + NMSettingVPNProperties *s_vpn_props; + GValue *val; + FILE *f; + const char *connection_type = ""; + const char *remote = ""; + guint port; + gboolean tap_dev; + gboolean proto_tcp; + const char *ca = ""; + const char *cert = ""; + const char *key = ""; + gboolean lzo; + const char *shared_key = ""; + const char *local_ip = ""; + const char *remote_ip = ""; + const char *username = ""; + const char *cipher = ""; + const char *ta = ""; + const char *ta_dir = ""; + char *routes_str = NULL; + gboolean ret; - /*printf ("in export_to_file; path='%s'\n", path);*/ + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_SETTING_CONNECTION); + g_assert (s_con); - for (i = properties; i != NULL && g_slist_next (i) != NULL; i = g_slist_next (g_slist_next (i))) { - const char *k; - const char *value; + s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_SETTING_VPN); + g_assert (s_vpn); - k = i->data; - value = (g_slist_next (i))->data; + s_vpn_props = (NMSettingVPNProperties *) nm_connection_get_setting (connection, NM_SETTING_VPN_PROPERTIES); + g_assert (s_vpn_props); - if (strcmp (k, "remote") == 0) { - remote = value; - } else if (strcmp (k, "port") == 0) { - port = value; - } else if (strcmp (k, "dev") == 0) { - dev = value; - } else if (strcmp (k, "proto") == 0) { - proto = value; - } else if (strcmp (k, "ca") == 0) { - ca = value; - } else if (strcmp (k, "cert") == 0) { - cert = value; - } else if (strcmp (k, "key") == 0) { - key = value; - } else if (strcmp (k, "comp-lzo") == 0) { - lzo = value; - } else if (strcmp (k, "shared-key") == 0) { - shared_key = value; - } else if (strcmp (k, "local-ip") == 0) { - local_ip = value; - } else if (strcmp (k, "remote-ip") == 0) { - remote_ip = value; - } else if (strcmp (k, "username") == 0) { - username = value; - } else if (strcmp (k, "connection-type") == 0) { - connection_type = value; - } else if (strcmp (k, "cipher") == 0) { - cipher = value; - } else if (strcmp (k, "ta") == 0) { - ta = value; - } else if (strcmp (k, "ta-dir") == 0) { - ta_dir = value; - } - } + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_REMOTE); + if (val) + remote = g_value_get_string (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_PORT); + if (val) + port = g_value_get_uint (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_TAP_DEV); + if (val) + tap_dev = g_value_get_boolean (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_PROTO_TCP); + if (val) + proto_tcp = g_value_get_boolean (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_CA); + if (val) + ca = g_value_get_string (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_CERT); + if (val) + cert = g_value_get_string (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_KEY); + if (val) + key = g_value_get_string (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_COMP_LZO); + if (val) + lzo = g_value_get_boolean (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_SHARED_KEY); + if (val) + shared_key = g_value_get_string (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_LOCAL_IP); + if (val) + local_ip = g_value_get_string (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_REMOTE_IP); + if (val) + remote_ip = g_value_get_string (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_USERNAME); + if (val) + username = g_value_get_string (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_CONNECTION_TYPE); + if (val) { + switch (g_value_get_int (val)) { + case NM_OPENVPN_CONTYPE_X509: + connection_type = "x509"; + break; + case NM_OPENVPN_CONTYPE_SHAREDKEY: + connection_type = "shared-key"; + break; + case NM_OPENVPN_CONTYPE_PASSWORD: + connection_type = "password"; + break; + case NM_OPENVPN_CONTYPE_X509USERPASS: + connection_type = "x509userpass"; + break; + default: + break; + } + } + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_CIPHER); + if (val) + cipher = g_value_get_string (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_TA); + if (val) + ta = g_value_get_string (val); + + val = (GValue *) g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_TA_DIR); + if (val) + ta_dir = g_value_get_string (val); - if (routes != NULL) { - GString *str; + if (s_vpn->routes != NULL) { + GSList *i; + GString *str; - str = g_string_new (""); - for (i = routes; i != NULL; i = g_slist_next (i)) { - const char *route; + str = g_string_new (""); + for (i = s_vpn->routes; i != NULL; i = g_slist_next (i)) { + if (i != s_vpn->routes) + g_string_append_c (str, ' '); + g_string_append (str, (const char *) i->data); + } - if (i != routes) - g_string_append_c (str, ' '); + g_string_append_c (str, '\n'); - route = (const char *) i->data; - g_string_append (str, route); - } + routes_str = g_string_free (str, FALSE); + } - g_string_append_c (str, '\n'); + f = fopen (path, "w"); + if (f != NULL) { - routes_str = g_string_free (str, FALSE); - } + fprintf (f, + "[openvpn]\n" + "description=%s\n" + "connection-type=%s\n" + "remote=%s\n" + "port=%u\n" + "dev=%s\n" + "proto=%s\n" + "ca=%s\n" + "cert=%s\n" + "key=%s\n" + "comp-lzo=%s\n" + "shared-key=%s\n" + "local-ip=%s\n" + "remote-ip=%s\n" + "username=%s\n" + "cipher=%s\n" + "ta=%s\n" + "ta_dir=%s\n" + "routes=%s\n", + /* Description */ s_con->name, + /* conn type */ connection_type, + /* Host */ remote, + /* Port */ port, + /* TUN or TAP */ tap_dev ? "tap" : "tun", + /* TCP or UDP */ proto_tcp ? "tcp-client" : "udp", + /* CA */ ca, + /* Cert */ cert, + /* Key */ key, + /* Comp-LZO */ lzo ? "yes" : "", + /* Shared key */ shared_key, + /* local ip */ local_ip, + /* remote ip */ remote_ip, + /* username */ username, + /* cipher */ cipher, + /* TA */ ta, + /* TA direction*/ ta_dir, + /* X-NM-Routes */ routes_str != NULL ? routes_str : ""); - f = fopen (path, "w"); - if (f != NULL) { + fclose (f); + ret = TRUE; + } + else + ret = FALSE; - fprintf (f, - "[openvpn]\n" - "description=%s\n" - "connection-type=%s\n" - "remote=%s\n" - "port=%s\n" - "dev=%s\n" - "proto=%s\n" - "ca=%s\n" - "cert=%s\n" - "key=%s\n" - "comp-lzo=%s\n" - "shared-key=%s\n" - "local-ip=%s\n" - "remote-ip=%s\n" - "username=%s\n" - "cipher=%s\n" - "ta=%s\n" - "ta_dir=%s\n" - "routes=%s\n", - /* Description */ connection_name, - /* conn type */ connection_type, - /* Host */ remote, - /* Port */ port, - /* TUN or TAP */ dev, - /* TCP or UDP */ proto, - /* CA */ ca, - /* Cert */ cert, - /* Key */ key, - /* Comp-LZO */ lzo, - /* Shared key */ shared_key, - /* local ip */ local_ip, - /* remote ip */ remote_ip, - /* username */ username, - /* cipher */ cipher, - /* TA */ ta, - /* TA direction*/ ta_dir, - /* X-NM-Routes */ routes_str != NULL ? routes_str : ""); - - fclose (f); - ret = TRUE; - } - else - ret = FALSE; - g_free (routes_str); - return ret; + g_free (routes_str); + return ret; } static gboolean -impl_export (NetworkManagerVpnUI *self, GSList *properties, GSList *routes, const char *connection_name) +impl_export (NetworkManagerVpnUI *self, NMConnection *connection) { - char *suggested_name; - char *path = NULL; - GtkWidget *dialog; - NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; + NMSettingConnection *s_con; + char *suggested_name; + char *path = NULL; + GtkWidget *dialog; + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; - /*printf ("in impl_export\n");*/ + /*printf ("in impl_export\n");*/ - dialog = gtk_file_chooser_dialog_new (_("Save as..."), - NULL, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL); + dialog = gtk_file_chooser_dialog_new (_("Save as..."), + NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); - suggested_name = g_strdup_printf ("%s.pcf", connection_name); - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), suggested_name); - g_free (suggested_name); + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_SETTING_CONNECTION); + g_assert (s_con); + g_assert (s_con->name); - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) - { + suggested_name = g_strdup_printf ("%s.pcf", s_con->name); + gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), suggested_name); + g_free (suggested_name); - path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); -/* printf ("User selected '%s'\n", path); */ + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - } + gtk_widget_destroy (dialog); - gtk_widget_destroy (dialog); + if (path != NULL) { + if (g_file_test (path, G_FILE_TEST_EXISTS)) { + int response; + GtkWidget *dialog; - if (path != NULL) { - if (g_file_test (path, G_FILE_TEST_EXISTS)) { - int response; - GtkWidget *dialog; + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_CANCEL, + _("A file named \"%s\" already exists."), path); + gtk_dialog_add_buttons (GTK_DIALOG (dialog), "_Replace", GTK_RESPONSE_OK, NULL); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + _("Do you want to replace it with the one you are saving?")); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + if (response != GTK_RESPONSE_OK) + goto out; + } - dialog = gtk_message_dialog_new (NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_CANCEL, - _("A file named \"%s\" already exists."), path); - gtk_dialog_add_buttons (GTK_DIALOG (dialog), "_Replace", GTK_RESPONSE_OK, NULL); - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), - _("Do you want to replace it with the one you are saving?")); - response = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - if (response != GTK_RESPONSE_OK) - goto out; - } + if (!export_to_file (impl, path, connection)) { + GtkWidget *dialog; - if (!export_to_file (impl, path, properties, routes, connection_name)) { - GtkWidget *dialog; + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_CLOSE, + _("Failed to export configuration")); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + _("Failed to save file %s"), path); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + } + } - dialog = gtk_message_dialog_new (NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_CLOSE, - _("Failed to export configuration")); - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), - _("Failed to save file %s"), path); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - } - } + out: + g_free (path); -out: - g_free (path); + return TRUE; +} - return TRUE; +static const char * +nm_find_openvpn (void) +{ + static const char *openvpn_binary_paths[] = { + "/usr/sbin/openvpn", + "/sbin/openvpn", + NULL + }; + const char **openvpn_binary = openvpn_binary_paths; + + while (*openvpn_binary != NULL) { + if (g_file_test (*openvpn_binary, G_FILE_TEST_EXISTS)) + break; + openvpn_binary++; + } + + return *openvpn_binary; } static void -populate_cipher(GtkComboBox *box) +populate_cipher (GtkComboBox *box) { - const char *openvpn_binary = NULL; - gchar *cmdline, *tmp, *token; + const char *openvpn_binary = NULL; + gchar *cmdline, *tmp, *token; - openvpn_binary = nm_find_openvpn(); - if (!openvpn_binary) - return; + openvpn_binary = nm_find_openvpn (); + if (!openvpn_binary) + return; - cmdline = g_strdup_printf("/bin/sh -c \"%s --show-ciphers | /bin/awk '/^[A-Z][A-Z0-9]+-/ { print $1 }'\"", openvpn_binary); - if (!g_spawn_command_line_sync(cmdline, &tmp, NULL, NULL, NULL)) - goto end; + cmdline = g_strdup_printf("/bin/sh -c \"%s --show-ciphers | /bin/awk '/^[A-Z][A-Z0-9]+-/ { print $1 }'\"", openvpn_binary); + if (!g_spawn_command_line_sync(cmdline, &tmp, NULL, NULL, NULL)) + goto end; - token = strtok(tmp, "\n"); + token = strtok(tmp, "\n"); - while (token) { - if (strlen(token)) - gtk_combo_box_append_text(box, token); - token = strtok(NULL, "\n"); - } + while (token) { + if (strlen(token)) + gtk_combo_box_append_text(box, token); + token = strtok(NULL, "\n"); + } -end: - g_free(tmp); + end: + g_free(tmp); } static NetworkManagerVpnUI* impl_get_object (void) { - char *glade_file; - NetworkManagerVpnUIImpl *impl; + char *glade_file; + NetworkManagerVpnUIImpl *impl; - impl = g_new0 (NetworkManagerVpnUIImpl, 1); + impl = g_new0 (NetworkManagerVpnUIImpl, 1); - impl->last_fc_dir = NULL; + impl->last_fc_dir = NULL; - glade_file = g_strdup_printf ("%s/%s", GLADEDIR, "nm-openvpn-dialog.glade"); - impl->xml = glade_xml_new (glade_file, NULL, GETTEXT_PACKAGE); - g_free( glade_file ); - if (impl->xml != NULL) { + glade_file = g_strdup_printf ("%s/%s", GLADEDIR, "nm-openvpn-dialog.glade"); + impl->xml = glade_xml_new (glade_file, NULL, GETTEXT_PACKAGE); + g_free( glade_file ); + if (impl->xml != NULL) { - impl->widget = glade_xml_get_widget(impl->xml, "nm-openvpn-widget"); - impl->advanced = GTK_DIALOG (glade_xml_get_widget(impl->xml, "nm-openvpn-advanced-dialog")); + impl->widget = glade_xml_get_widget(impl->xml, "nm-openvpn-widget"); + impl->advanced = GTK_DIALOG (glade_xml_get_widget(impl->xml, "nm-openvpn-advanced-dialog")); - impl->w_connection_name = GTK_ENTRY (glade_xml_get_widget (impl->xml, "openvpn-connection-name")); - impl->w_remote = GTK_ENTRY (glade_xml_get_widget (impl->xml, "openvpn-remote")); - impl->w_port = GTK_ENTRY (glade_xml_get_widget (impl->xml, "openvpn-port")); - impl->w_use_routes = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-routes")); - impl->w_routes = GTK_ENTRY (glade_xml_get_widget (impl->xml, "openvpn-routes")); - impl->w_opt_info_expander = GTK_EXPANDER (glade_xml_get_widget (impl->xml, - "openvpn-optional-information-expander")); - impl->w_advanced_button = GTK_BUTTON (glade_xml_get_widget (impl->xml, - "openvpn-advanced-button")); + impl->w_connection_name = GTK_ENTRY (glade_xml_get_widget (impl->xml, "openvpn-connection-name")); + impl->w_remote = GTK_ENTRY (glade_xml_get_widget (impl->xml, "openvpn-remote")); + impl->w_port = GTK_ENTRY (glade_xml_get_widget (impl->xml, "openvpn-port")); + impl->w_use_routes = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-routes")); + impl->w_routes = GTK_ENTRY (glade_xml_get_widget (impl->xml, "openvpn-routes")); + impl->w_opt_info_expander = GTK_EXPANDER (glade_xml_get_widget (impl->xml, + "openvpn-optional-information-expander")); + impl->w_advanced_button = GTK_BUTTON (glade_xml_get_widget (impl->xml, + "openvpn-advanced-button")); - impl->w_import_button = GTK_BUTTON (glade_xml_get_widget (impl->xml, - "openvpn-import-button")); + impl->w_import_button = GTK_BUTTON (glade_xml_get_widget (impl->xml, + "openvpn-import-button")); - impl->w_ca = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-ca" ) ); - impl->w_cert = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-cert" ) ); - impl->w_key = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-key" ) ); + impl->w_ca = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-ca" ) ); + impl->w_cert = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-cert" ) ); + impl->w_key = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-key" ) ); - impl->w_button_ca = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-but-ca" ) ); - impl->w_button_cert = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-but-cert" ) ); - impl->w_button_key = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-but-key" ) ); + impl->w_button_ca = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-but-ca" ) ); + impl->w_button_cert = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-but-cert" ) ); + impl->w_button_key = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-but-key" ) ); - impl->w_use_lzo = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-lzo")); - impl->w_use_tap = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-tap")); - impl->w_use_tcp = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-tcp")); + impl->w_use_lzo = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-lzo")); + impl->w_use_tap = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-tap")); + impl->w_use_tcp = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-tcp")); - impl->w_connection_type = GTK_COMBO_BOX (glade_xml_get_widget (impl->xml, "openvpn-connection-type")); - impl->w_settings_notebook = GTK_NOTEBOOK (glade_xml_get_widget (impl->xml, "openvpn-settings")); + impl->w_connection_type = GTK_COMBO_BOX (glade_xml_get_widget (impl->xml, "openvpn-connection-type")); + impl->w_settings_notebook = GTK_NOTEBOOK (glade_xml_get_widget (impl->xml, "openvpn-settings")); - impl->w_button_shared_key = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-but-shared-key" ) ); - impl->w_shared_key = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-shared-key" ) ); - impl->w_local_ip = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-local-ip" ) ); - impl->w_remote_ip = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-remote-ip" ) ); + impl->w_button_shared_key = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-but-shared-key" ) ); + impl->w_shared_key = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-shared-key" ) ); + impl->w_local_ip = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-local-ip" ) ); + impl->w_remote_ip = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-remote-ip" ) ); - impl->w_username = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-username" ) ); - impl->w_password_ca = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-password-ca" ) ); - impl->w_button_password_ca = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-password-but-ca" ) ); + impl->w_username = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-username" ) ); + impl->w_password_ca = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-password-ca" ) ); + impl->w_button_password_ca = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-password-but-ca" ) ); - impl->w_x509userpass_ca = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-ca" ) ); - impl->w_x509userpass_cert = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-cert" ) ); - impl->w_x509userpass_key = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-key" ) ); - impl->w_x509userpass_username = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-username" ) ); + impl->w_x509userpass_ca = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-ca" ) ); + impl->w_x509userpass_cert = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-cert" ) ); + impl->w_x509userpass_key = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-key" ) ); + impl->w_x509userpass_username = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-username" ) ); - impl->w_button_x509userpass_ca = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-but-ca" ) ); - impl->w_button_x509userpass_cert = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-but-cert" ) ); - impl->w_button_x509userpass_key = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-but-key" ) ); + impl->w_button_x509userpass_ca = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-but-ca" ) ); + impl->w_button_x509userpass_cert = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-but-cert" ) ); + impl->w_button_x509userpass_key = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-x509userpass-but-key" ) ); - impl->w_use_cipher = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-cipher")); - impl->w_cipher = GTK_COMBO_BOX( glade_xml_get_widget( impl->xml, "openvpn-cipher" ) ); - populate_cipher(impl->w_cipher); + impl->w_use_cipher = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-cipher")); + impl->w_cipher = GTK_COMBO_BOX( glade_xml_get_widget( impl->xml, "openvpn-cipher" ) ); + populate_cipher(impl->w_cipher); - impl->w_use_ta = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-ta")); - impl->w_ta = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-ta" ) ); - impl->w_button_ta = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-but-ta" ) ); - impl->w_ta_dir_label = GTK_LABEL( glade_xml_get_widget( impl->xml, "openvpn-ta-dir-label" ) ); - impl->w_ta_dir_none = GTK_RADIO_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-ta-dir-none" ) ); - impl->w_ta_dir_zero = GTK_RADIO_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-ta-dir-zero" ) ); - impl->w_ta_dir_one = GTK_RADIO_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-ta-dir-one" ) ); + impl->w_use_ta = GTK_CHECK_BUTTON (glade_xml_get_widget (impl->xml, "openvpn-use-ta")); + impl->w_ta = GTK_ENTRY( glade_xml_get_widget( impl->xml, "openvpn-ta" ) ); + impl->w_button_ta = GTK_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-but-ta" ) ); + impl->w_ta_dir_label = GTK_LABEL( glade_xml_get_widget( impl->xml, "openvpn-ta-dir-label" ) ); + impl->w_ta_dir_none = GTK_RADIO_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-ta-dir-none" ) ); + impl->w_ta_dir_zero = GTK_RADIO_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-ta-dir-zero" ) ); + impl->w_ta_dir_one = GTK_RADIO_BUTTON( glade_xml_get_widget( impl->xml, "openvpn-ta-dir-one" ) ); - impl->callback = NULL; + impl->callback = NULL; - gtk_signal_connect (GTK_OBJECT (impl->w_use_routes), - "toggled", GTK_SIGNAL_FUNC (use_editable_toggled), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_use_cipher), - "toggled", GTK_SIGNAL_FUNC (use_editable_toggled), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_use_ta), - "toggled", GTK_SIGNAL_FUNC (use_editable_toggled), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_use_routes), + "toggled", GTK_SIGNAL_FUNC (use_editable_toggled), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_use_cipher), + "toggled", GTK_SIGNAL_FUNC (use_editable_toggled), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_use_ta), + "toggled", GTK_SIGNAL_FUNC (use_editable_toggled), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_connection_name), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_remote), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_port), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_routes), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_ca), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_cert), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_key), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_shared_key), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_local_ip), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_remote_ip), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_username), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_password_ca), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_x509userpass_ca), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_x509userpass_cert), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_x509userpass_key), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_x509userpass_username), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_ta), - "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_connection_name), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_remote), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_port), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_routes), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_ca), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_cert), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_key), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_shared_key), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_local_ip), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_remote_ip), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_username), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_password_ca), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_x509userpass_ca), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_x509userpass_cert), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_x509userpass_key), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_x509userpass_username), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_ta), + "changed", GTK_SIGNAL_FUNC (editable_changed), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_button_ca), - "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_button_cert), - "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_button_key), - "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_button_shared_key), - "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_button_password_ca), - "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_button_x509userpass_ca), - "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_button_x509userpass_cert), - "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_button_x509userpass_key), - "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_button_ta), - "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_button_ca), + "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_button_cert), + "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_button_key), + "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_button_shared_key), + "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_button_password_ca), + "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_button_x509userpass_ca), + "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_button_x509userpass_cert), + "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_button_x509userpass_key), + "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_button_ta), + "clicked", GTK_SIGNAL_FUNC (open_button_clicked), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_advanced_button), - "clicked", GTK_SIGNAL_FUNC (advanced_button_clicked), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_advanced_button), + "clicked", GTK_SIGNAL_FUNC (advanced_button_clicked), impl); - gtk_signal_connect (GTK_OBJECT (impl->w_import_button), - "clicked", GTK_SIGNAL_FUNC (import_button_clicked), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_import_button), + "clicked", GTK_SIGNAL_FUNC (import_button_clicked), &(impl->parent)); - gtk_signal_connect (GTK_OBJECT (impl->w_connection_type), - "changed", GTK_SIGNAL_FUNC (connection_type_changed), impl); + gtk_signal_connect (GTK_OBJECT (impl->w_connection_type), + "changed", GTK_SIGNAL_FUNC (connection_type_changed), impl); - /* make the widget reusable */ - gtk_signal_connect (GTK_OBJECT (impl->widget), "delete-event", - GTK_SIGNAL_FUNC (gtk_widget_hide_on_delete), NULL); - gtk_signal_connect (GTK_OBJECT (impl->advanced), "delete-event", - GTK_SIGNAL_FUNC (gtk_widget_hide_on_delete), NULL); + /* make the widget reusable */ + gtk_signal_connect (GTK_OBJECT (impl->widget), "delete-event", + GTK_SIGNAL_FUNC (gtk_widget_hide_on_delete), NULL); + gtk_signal_connect (GTK_OBJECT (impl->advanced), "delete-event", + GTK_SIGNAL_FUNC (gtk_widget_hide_on_delete), NULL); - openvpn_clear_widget (impl); + openvpn_clear_widget (impl); - impl->parent.get_display_name = impl_get_display_name; - impl->parent.get_service_name = impl_get_service_name; - impl->parent.get_widget = impl_get_widget; - impl->parent.get_connection_name = impl_get_connection_name; - impl->parent.get_properties = impl_get_properties; - impl->parent.get_routes = impl_get_routes; - impl->parent.set_validity_changed_callback = impl_set_validity_changed_callback; - impl->parent.is_valid = impl_is_valid; - impl->parent.get_confirmation_details = impl_get_confirmation_details; - impl->parent.can_export = impl_can_export; - impl->parent.import_file = impl_import_file; - impl->parent.export = impl_export; - impl->parent.data = impl; + impl->parent.get_display_name = impl_get_display_name; + impl->parent.get_service_name = impl_get_service_name; + impl->parent.fill_connection = impl_fill_connection; + impl->parent.get_widget = impl_get_widget; + impl->parent.set_validity_changed_callback = impl_set_validity_changed_callback; + impl->parent.is_valid = impl_is_valid; + impl->parent.get_confirmation_details = impl_get_confirmation_details; + impl->parent.can_export = impl_can_export; + impl->parent.import_file = impl_import_file; + impl->parent.export = impl_export; + impl->parent.data = impl; - return &(impl->parent); - } else { - g_free (impl); - return NULL; - } + return &(impl->parent); + } else { + g_free (impl); + return NULL; + } } NetworkManagerVpnUI* nm_vpn_properties_factory (void) { - return impl_get_object(); + return impl_get_object (); } diff --git a/vpn-daemons/openvpn/src/Makefile.am b/vpn-daemons/openvpn/src/Makefile.am index 16a2354261..f19c144c6a 100644 --- a/vpn-daemons/openvpn/src/Makefile.am +++ b/vpn-daemons/openvpn/src/Makefile.am @@ -1,8 +1,5 @@ -INCLUDES = -I${top_srcdir} -I${top_srcdir}/utils -I${top_srcdir}/vpn-daemons/openvpn - AM_CPPFLAGS = \ $(DBUS_CFLAGS) \ - $(GTHREAD_CFLAGS) \ $(NETWORK_MANAGER_CFLAGS) \ -Wall \ -DDBUS_API_SUBJECT_TO_CHANGE \ @@ -20,15 +17,10 @@ bin_PROGRAMS = nm-openvpn-service nm-openvpn-service-openvpn-helper nm_openvpn_service_SOURCES = \ nm-openvpn-service.c \ - nm-openvpn-service.h \ - nm-utils.c \ - nm-utils.h + nm-openvpn-service.h -nm_openvpn_service_LDADD = \ - $(DBUS_LIBS) \ - $(GTHREAD_LIBS) \ - $(NETWORK_MANAGER_LIBS) +nm_openvpn_service_LDADD = $(NETWORK_MANAGER_LIBS) -lnm_glib_vpn nm_openvpn_service_openvpn_helper_SOURCES = \ @@ -36,7 +28,6 @@ nm_openvpn_service_openvpn_helper_SOURCES = \ nm_openvpn_service_openvpn_helper_LDADD = \ $(DBUS_LIBS) \ - $(GTHREAD_LIBS) \ $(NETWORK_MANAGER_LIBS) CLEANFILES = *~ diff --git a/vpn-daemons/openvpn/src/nm-openvpn-service-openvpn-helper.c b/vpn-daemons/openvpn/src/nm-openvpn-service-openvpn-helper.c index 6d106123aa..831d90af39 100644 --- a/vpn-daemons/openvpn/src/nm-openvpn-service-openvpn-helper.c +++ b/vpn-daemons/openvpn/src/nm-openvpn-service-openvpn-helper.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ /* nm-openvpn-service-openvpn-helper - helper called after OpenVPN established * a connection, uses DBUS to send information back to nm-openvpn-service * @@ -38,389 +39,226 @@ #include #include #include -#include #include "nm-openvpn-service.h" #include "nm-utils.h" static void -nm_log_handler (const gchar * log_domain, - GLogLevelFlags log_level, - const gchar * message, - gpointer ignored) +helper_failed (DBusGConnection *connection, const char *reason) { - int syslog_priority; + DBusGProxy *proxy; + GError *err = NULL; - switch (log_level) - { - case G_LOG_LEVEL_ERROR: - syslog_priority = LOG_CRIT; - break; + nm_warning ("nm-openvpn-service-openvpn-helper did not receive a valid %s from openvpn", reason); - case G_LOG_LEVEL_CRITICAL: - syslog_priority = LOG_ERR; - break; + proxy = dbus_g_proxy_new_for_name (connection, + NM_DBUS_SERVICE_OPENVPN, + NM_VPN_DBUS_PLUGIN_PATH, + NM_VPN_DBUS_PLUGIN_INTERFACE); - case G_LOG_LEVEL_WARNING: - syslog_priority = LOG_WARNING; - break; + dbus_g_proxy_call (proxy, "SetFailure", &err, + G_TYPE_STRING, reason, + G_TYPE_INVALID, + G_TYPE_INVALID); - case G_LOG_LEVEL_MESSAGE: - syslog_priority = LOG_NOTICE; - break; + if (err) { + nm_warning ("Could not send failure information: %s", err->message); + g_error_free (err); + } - case G_LOG_LEVEL_DEBUG: - syslog_priority = LOG_DEBUG; - break; + g_object_unref (proxy); - case G_LOG_LEVEL_INFO: - default: - syslog_priority = LOG_INFO; - break; - } - - syslog (syslog_priority, "%s", message); + exit (1); } -void -nm_logging_setup () -{ - openlog (G_LOG_DOMAIN, LOG_CONS, LOG_DAEMON); - g_log_set_handler (G_LOG_DOMAIN, - G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, - nm_log_handler, - NULL); -} - -void -nm_logging_shutdown (void) -{ - closelog (); -} - -void -cleanup_and_exit(int n) -{ - nm_logging_shutdown(); - exit(n); -} -/* - * send_config_error - * - * Notify nm-openvpn-service of a config error from 'openvpn'. - * - */ -static void send_config_error (DBusConnection *con, const char *item) -{ - DBusMessage *message; - - g_return_if_fail (con != NULL); - g_return_if_fail (item != NULL); - - if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE_OPENVPN, NM_DBUS_PATH_OPENVPN, NM_DBUS_INTERFACE_OPENVPN, "signalConfigError"))) - { - nm_warning ("send_config_error(): Couldn't allocate the dbus message"); - return; - } - - dbus_message_append_args (message, DBUS_TYPE_STRING, &item, DBUS_TYPE_INVALID); - if (!dbus_connection_send (con, message, NULL)) - nm_warning ("send_config_error(): could not send dbus message"); - - dbus_message_unref (message); -} - - - /* - * gpa_to_uint32arr - * - * Convert GPtrArray of uint32 to a uint32* array - * - */ static void -gpa_to_uint32arr (const GPtrArray *gpa, - guint32 **uia, - guint32 *uia_len) +send_ip4_config (DBusGConnection *connection, GHashTable *config) { - - guint32 num_valid = 0, i = 0; - struct in_addr temp_addr; + DBusGProxy *proxy; + GError *err = NULL; - *uia = NULL; + proxy = dbus_g_proxy_new_for_name (connection, + NM_DBUS_SERVICE_OPENVPN, + NM_VPN_DBUS_PLUGIN_PATH, + NM_VPN_DBUS_PLUGIN_INTERFACE); - if ( gpa->len > 0 ) { - /* Pass over the array first to determine how many valid entries there are */ - num_valid = 0; - for (i = 0; i < gpa->len; ++i) { - if (inet_aton ((char *)gpa->pdata[i], &temp_addr)) { - num_valid++; - } - } - - /* Do the actual string->int conversion and assign to the array. */ - if (num_valid > 0) { - *uia = g_new0 (guint32, num_valid); - for (i = 0; i < gpa->len; ++i) { - if (inet_aton ((char *)gpa->pdata[i], &temp_addr)) { - (*uia)[i] = temp_addr.s_addr; + dbus_g_proxy_call (proxy, "SetIp4Config", &err, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + config, + G_TYPE_INVALID, + G_TYPE_INVALID); + + if (err) { + nm_warning ("Could not send failure information: %s", err->message); + g_error_free (err); } - } - } - - *uia_len = num_valid; - } - if (*uia == NULL) { - *uia = g_malloc0 (sizeof (guint32)); - *uia_len = 1; - } + + g_object_unref (proxy); } -static gboolean -ipstr_to_uint32 (const char *ip_str, guint32 *ip) +static GValue * +str_to_gvalue (const char *str, gboolean try_convert) { - struct in_addr temp_addr; + GValue *val; - /* Convert IPv4 address arguments from strings into numbers */ - if (!inet_aton (ip_str, &temp_addr)) - return FALSE; - *ip = temp_addr.s_addr; - return TRUE; -} + /* Empty */ + if (!str || strlen (str) < 1) + return NULL; + if (!g_utf8_validate (str, -1, NULL)) { + if (try_convert && !(str = g_convert (str, -1, "ISO-8859-1", "UTF-8", NULL, NULL, NULL))) + str = g_convert (str, -1, "C", "UTF-8", NULL, NULL, NULL); -/* - * send_config_info - * - * Send IP config info to nm-openvpn-service - * - */ -static gboolean -send_config_info (DBusConnection *con, - const char *str_vpn_gateway, - const char *str_tundev, - const char *str_ip4_address, - const char *str_ip4_ptpaddr, - const char *str_ip4_netmask, - const GPtrArray *gpa_ip4_dns, - const GPtrArray *gpa_ip4_nbns - ) -{ - DBusMessage * message; - struct in_addr temp_addr; - guint32 uint_vpn_gateway = 0; - guint32 uint_ip4_address = 0; - guint32 uint_ip4_ptpaddr = 0; - guint32 uint_ip4_netmask = 0xFFFFFFFF; /* Default mask of 255.255.255.255 */ - guint32 * uint_ip4_dns = NULL; - guint32 uint_ip4_dns_len = 0; - guint32 * uint_ip4_nbns = NULL; - guint32 uint_ip4_nbns_len = 0; - gboolean success = FALSE; - - g_return_val_if_fail (con != NULL, FALSE); - - if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE_OPENVPN, NM_DBUS_PATH_OPENVPN, NM_DBUS_INTERFACE_OPENVPN, "signalIP4Config"))) - { - nm_warning ("send_config_error(): Couldn't allocate the dbus message"); - return FALSE; - } - - if (! ipstr_to_uint32 (str_vpn_gateway, &uint_vpn_gateway) ) { - nm_warning ("nm-openvpn-service-openvpn-helper didn't receive a valid VPN Gateway from openvpn."); - send_config_error (con, "VPN Gateway"); - goto out; - } - - if (! ipstr_to_uint32 (str_ip4_address, &uint_ip4_address) ) { - nm_warning ("nm-openvpn-service-openvpn-helper didn't receive a valid Internal IP4 Address from openvpn."); - send_config_error (con, "IP4 Address"); - goto out; - } - - if (str_ip4_ptpaddr && ! ipstr_to_uint32 (str_ip4_ptpaddr, &uint_ip4_ptpaddr) ) { - nm_warning ("nm-openvpn-service-openvpn-helper didn't receive a valid PtP IP4 Address from openvpn."); - send_config_error (con, "IP4 PtP Address"); - goto out; - } - - if (strlen (str_ip4_netmask) > 0) { - ipstr_to_uint32 (str_ip4_netmask, &uint_ip4_netmask); - } - - gpa_to_uint32arr (gpa_ip4_dns, &uint_ip4_dns, &uint_ip4_dns_len); - gpa_to_uint32arr (gpa_ip4_nbns, &uint_ip4_nbns, &uint_ip4_nbns_len); - - dbus_message_append_args (message, DBUS_TYPE_UINT32, &uint_vpn_gateway, - DBUS_TYPE_STRING, &str_tundev, - DBUS_TYPE_UINT32, &uint_ip4_address, - DBUS_TYPE_UINT32, &uint_ip4_ptpaddr, - DBUS_TYPE_UINT32, &uint_ip4_netmask, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &uint_ip4_dns, uint_ip4_dns_len, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &uint_ip4_nbns, uint_ip4_nbns_len, - DBUS_TYPE_INVALID); - if (dbus_connection_send (con, message, NULL)) - success = TRUE; - else - nm_warning ("send_config_error(): could not send dbus message"); - - dbus_message_unref (message); - - g_free (uint_ip4_dns); - g_free (uint_ip4_nbns); - - out: - return success; -} - - -/* - * See the OpenVPN man page for available environment variables. - * - * - */ - -#if 0 /* FIXME: Nothing uses this and it is static */ -/** Prints all environment variables to /tmp/environ - */ -static void -print_env() -{ - FILE *f = fopen("/tmp/environ", "w"); - int env = 0; - while ( __environ[env] != NULL ) { - fprintf(f, "%s\n", __environ[env++]); - } - fclose(f); -} -#endif - - -/* - * main - * - */ -int main( int argc, char *argv[] ) -{ - DBusConnection *con; - DBusError error; - char *vpn_gateway = NULL; - char *tundev = NULL; - char *ip4_address = NULL; - char *ip4_ptp = NULL; - char *ip4_netmask = NULL; - GPtrArray *ip4_dns = NULL; - GPtrArray *ip4_nbns = NULL; - - char **split = NULL; - char **item; - - char *tmp; - // max(length(envname)) = length("foreign_option_") + length(to_string(MAX_INT)) + 1; - // = 15 = 10 for 4 byte int - // (which should be enough for quite some time) - char envname[26]; - int i = 1; - int exit_code = 0; - - g_type_init (); - if (!g_thread_supported ()) - g_thread_init (NULL); - - nm_logging_setup(); - - dbus_error_init (&error); - con = dbus_bus_get (DBUS_BUS_SYSTEM, &error); - if ((con == NULL) || dbus_error_is_set (&error)) - { - nm_warning ("Could not get the system bus. Make sure the message bus daemon is running?"); - cleanup_and_exit (1); - } - dbus_connection_set_exit_on_disconnect (con, FALSE); - - // print_env(); - - vpn_gateway = getenv( "trusted_ip" ); - tundev = getenv ("dev"); - ip4_ptp = getenv("ifconfig_remote"); - ip4_address = getenv("ifconfig_local"); - ip4_netmask = getenv("route_netmask_1"); - - ip4_dns = g_ptr_array_new(); - ip4_nbns = g_ptr_array_new(); - - while (1) { - sprintf(envname, "foreign_option_%i", i++); - tmp = getenv( envname ); - - if ( (tmp == NULL) || (strlen(tmp) == 0) ) { - break; - } else { - - if ((split = g_strsplit( tmp, " ", -1))) { - int size = 0; - for( item = split; *item; item++) { - ++size; + if (!str) + /* Invalid */ + return NULL; } - if ( size != 3 ) continue; - - if (strcmp( split[0], "dhcp-option") == 0) { - // Interesting, now check if DNS or NBNS/WINS - if (strcmp( split[1], "DNS") == 0) { - // DNS, push it! - g_ptr_array_add( ip4_dns, (gpointer) split[2] ); - } else if (strcmp( split[1], "WINS") == 0) { - // WINS, push it! - g_ptr_array_add( ip4_nbns, (gpointer) split[2] ); - } - } - } - } - } -#if 0 - { - FILE *file = fopen ("/tmp/vpnstuff", "w"); - fprintf (file, "VPNGATEWAY: '%s'\n", vpn_gateway); - fprintf (file, "TUNDEV: '%s'\n", tundev); - fprintf (file, "IP4_ADDRESS: '%s'\n", ip4_address); - fprintf (file, "IP4_NETMASK: '%s'\n", ip4_netmask); - fclose (file); - } -#endif - - if (!vpn_gateway) { - nm_warning ("nm-openvpn-service-openvpn-helper didn't receive a VPN Gateway from openvpn."); - send_config_error (con, "VPN Gateway"); - exit (1); - } - if (!tundev || !g_utf8_validate (tundev, -1, NULL)) { - nm_warning ("nm-openvpn-service-openvpn-helper didn't receive a Tunnel Device from openvpn, or the tunnel device was not valid UTF-8."); - send_config_error (con, "Tunnel Device"); - cleanup_and_exit (1); - } - if (!ip4_address) { - nm_warning ("nm-openvpn-service-openvpn-helper didn't receive an Internal IP4 Address from openvpn."); - send_config_error (con, "IP4 Address"); - cleanup_and_exit (1); - } + val = g_slice_new0 (GValue); + g_value_init (val, G_TYPE_STRING); + g_value_set_string (val, str); - if (!ip4_netmask) { - ip4_netmask = g_strdup (""); - } - - if (!send_config_info (con, vpn_gateway, tundev, - ip4_address, ip4_ptp, ip4_netmask, - ip4_dns, ip4_nbns)) { - exit_code = 1; - } - - g_strfreev( split ); - g_ptr_array_free( ip4_dns, TRUE ); - g_ptr_array_free( ip4_nbns, TRUE ); - - cleanup_and_exit (exit_code); - - // Dummy return; cleanup_and_exit() takes care of exit() - return 0; + return val; } +static GValue * +addr_to_gvalue (const char *str) +{ + struct in_addr temp_addr; + GValue *val; + + /* Empty */ + if (!str || strlen (str) < 1) + return NULL; + + if (!inet_aton (str, &temp_addr)) + return NULL; + + val = g_slice_new0 (GValue); + g_value_init (val, G_TYPE_UINT); + g_value_set_uint (val, temp_addr.s_addr); + + return val; +} + +static GValue * +parse_addr_list (GValue *value_array, const char *str) +{ + char **split; + int i; + struct in_addr temp_addr; + GArray *array; + + /* Empty */ + if (!str || strlen (str) < 1) + return value_array; + + if (value_array) + array = (GArray *) g_value_get_boxed (value_array); + else + array = g_array_new (FALSE, FALSE, sizeof (guint)); + + split = g_strsplit (str, " ", -1); + for (i = 0; split[i]; i++) { + if (inet_aton (split[i], &temp_addr)) + g_array_append_val (array, temp_addr.s_addr); + } + + g_strfreev (split); + + if (!value_array && array->len > 1) { + value_array = g_slice_new0 (GValue); + g_value_init (value_array, DBUS_TYPE_G_UINT_ARRAY); + g_value_set_boxed (value_array, array); + } + + return value_array; +} + +int +main (int argc, char *argv[]) +{ + DBusGConnection *connection; + GHashTable *config; + char *tmp; + GValue *val; + int i; + GError *err = NULL; + GValue *dns_list = NULL; + GValue *nbns_list = NULL; + + g_type_init (); + + connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); + if (!connection) { + nm_warning ("Could not get the system bus: %s", err->message); + exit (1); + } + + config = g_hash_table_new (g_str_hash, g_str_equal); + + /* Gateway */ + val = addr_to_gvalue (getenv ("trusted_ip")); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY, val); + else + helper_failed (connection, "VPN Gateway"); + + /* Tunnel device */ + val = str_to_gvalue (getenv ("dev"), FALSE); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val); + else + helper_failed (connection, "Tunnel Device"); + + /* IP address */ + val = addr_to_gvalue (getenv ("ipconfig_local")); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val); + else + helper_failed (connection, "IP4 Address"); + + /* PTP address; for vpnc PTP address == internal IP4 address */ + val = addr_to_gvalue (getenv ("ifconfig_remote")); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_PTP, val); + else + helper_failed (connection, "IP4 PTP Address"); + + /* Netmask */ + val = addr_to_gvalue (getenv ("route_netmask_1")); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_NETMASK, val); + + /* DNS and WINS servers */ + for (i = 1; i < 256; i++) { + char *env_name; + + env_name = g_strdup_printf ("foreign_option_%d", i); + tmp = getenv (env_name); + g_free (env_name); + + if (!tmp || strlen (tmp) < 1) + break; + + if (!g_str_has_prefix (tmp, "dhcp-option ")) + continue; + + tmp += 12; /* strlen ("dhcp-option ") */ + + if (g_str_has_prefix (tmp, "DNS ")) + dns_list = parse_addr_list (dns_list, tmp + 4); + else if (g_str_has_prefix (tmp, "WINS ")) + nbns_list = parse_addr_list (nbns_list, tmp + 5); + } + + if (dns_list) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_DNS, dns_list); + if (nbns_list) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, nbns_list); + + /* Send the config info to nm-openvpn-service */ + send_ip4_config (connection, config); + + return 0; +} diff --git a/vpn-daemons/openvpn/src/nm-openvpn-service.c b/vpn-daemons/openvpn/src/nm-openvpn-service.c index b522f0c363..9d5e10fc90 100644 --- a/vpn-daemons/openvpn/src/nm-openvpn-service.c +++ b/vpn-daemons/openvpn/src/nm-openvpn-service.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ /* nm-openvpn-service - openvpn integration with NetworkManager * * Tim Niemueller @@ -52,1548 +53,724 @@ #define NM_OPENVPN_HELPER_PATH BINDIR"/nm-openvpn-service-openvpn-helper" -typedef struct _NmOpenVPN_IOData -{ - char *username; - char *password; - char *certpass; - gint child_stdin_fd; - gint child_stdout_fd; - gint child_stderr_fd; - GIOChannel *socket_channel; - guint socket_channel_eventid; -} NmOpenVPN_IOData; +G_DEFINE_TYPE (NMOpenvpnPlugin, nm_openvpn_plugin, NM_TYPE_VPN_PLUGIN) -typedef struct NmOpenVPNData -{ - GMainLoop *loop; - DBusConnection *con; - NMVPNServiceState state; - GPid pid; - guint quit_timer; - guint helper_timer; - gint connection_type; - guint connect_timer; - guint connect_count; - NmOpenVPN_IOData *io_data; -} NmOpenVPNData; +#define NM_OPENVPN_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OPENVPN_PLUGIN, NMOpenvpnPluginPrivate)) -static gboolean nm_openvpn_dbus_handle_stop_vpn (NmOpenVPNData *data); +typedef struct { + char *username; + char *password; + char *certpass; + gint child_stdin_fd; + gint child_stdout_fd; + gint child_stderr_fd; + GIOChannel *socket_channel; + guint socket_channel_eventid; +} NMOpenvpnPluginIOData; +typedef struct { + GPid pid; + guint connect_timer; + guint connect_count; + NMOpenvpnPluginIOData *io_data; +} NMOpenvpnPluginPrivate; -/* - * nm_dbus_create_error_message - * - * Make a DBus error message - * - */ -static DBusMessage * -nm_dbus_create_error_message (DBusMessage *message, const char *exception_namespace, - const char *exception, const char *format, ...) -{ - char *exception_text; - DBusMessage *reply; - va_list args; - char error_text[512]; +typedef struct { + const char *name; + GType type; +} ValidProperty; - va_start (args, format); - vsnprintf (error_text, 512, format, args); - va_end (args); +static ValidProperty valid_properties[] = { + { NM_OPENVPN_KEY_CA, G_TYPE_STRING }, + { NM_OPENVPN_KEY_CERT, G_TYPE_STRING }, + { NM_OPENVPN_KEY_CIPHER, G_TYPE_STRING }, + { NM_OPENVPN_KEY_COMP_LZO, G_TYPE_BOOLEAN }, + { NM_OPENVPN_KEY_CONNECTION_TYPE, G_TYPE_INT }, + { NM_OPENVPN_KEY_TAP_DEV, G_TYPE_BOOLEAN }, + { NM_OPENVPN_KEY_KEY, G_TYPE_STRING }, + { NM_OPENVPN_KEY_LOCAL_IP, G_TYPE_STRING }, + { NM_OPENVPN_KEY_PORT, G_TYPE_UINT }, + { NM_OPENVPN_KEY_PROTO_TCP, G_TYPE_BOOLEAN }, + { NM_OPENVPN_KEY_REMOTE, G_TYPE_STRING }, + { NM_OPENVPN_KEY_REMOTE_IP, G_TYPE_STRING }, + { NM_OPENVPN_KEY_SHARED_KEY, G_TYPE_STRING }, + { NM_OPENVPN_KEY_TA, G_TYPE_STRING }, + { NM_OPENVPN_KEY_TA_DIR, G_TYPE_STRING }, + { NM_OPENVPN_KEY_USERNAME, G_TYPE_STRING }, + { NULL, G_TYPE_NONE } +}; - exception_text = g_strdup_printf ("%s.%s", exception_namespace, exception); - reply = dbus_message_new_error (message, exception_text, error_text); - g_free (exception_text); - - return (reply); -} - - -/* - * nm_openvpn_dbus_signal_failure - * - * Signal the bus that some VPN operation failed. - * - */ static void -nm_openvpn_dbus_signal_failure (NmOpenVPNData *data, const char *signal) +validate_one_property (gpointer key, gpointer val, gpointer user_data) { - DBusMessage *message; - const char *error_msg = NULL; + gboolean *failed = (gboolean *) user_data; + int i; - g_return_if_fail (data != NULL); - g_return_if_fail (signal != NULL); + if (*failed) + return; - if ( strcmp (signal, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED) == 0 ) - error_msg = _("The VPN login failed because the user name and password were not accepted or the certificate password was wrong."); - else if (strcmp (signal, NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED) == 0 ) - error_msg = _("The VPN login failed because the VPN program could not be started."); - else if (strcmp (signal, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED) == 0 ) - error_msg = _("The VPN login failed because the VPN program could not connect to the VPN server."); - else if (strcmp (signal, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD) == 0 ) - error_msg = _("The VPN login failed because the VPN configuration options were invalid."); - else if (strcmp (signal, NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD) == 0 ) - error_msg = _("The VPN login failed because the VPN program received an invalid configuration from the VPN server."); - else - error_msg = _("VPN connection failed"); + for (i = 0; valid_properties[i].name; i++) { + ValidProperty prop = valid_properties[i]; - if (!error_msg) - return; + if (!strcmp (prop.name, (char *) key) && prop.type == G_VALUE_TYPE ((GValue *) val)) + /* Property is ok */ + return; + } - if (!(message = dbus_message_new_signal (NM_DBUS_PATH_OPENVPN, NM_DBUS_INTERFACE_OPENVPN, signal))) - { - nm_warning ("Not enough memory for new dbus message!"); - return; - } - - dbus_message_append_args (message, DBUS_TYPE_STRING, &error_msg, DBUS_TYPE_INVALID); - if (!dbus_connection_send (data->con, message, NULL)) - nm_warning ("Could not raise the signal!"); - - dbus_message_unref (message); + /* Did not find the property from valid_properties or the type did not match */ + *failed = TRUE; } - -/* - * nm_openvpn_dbus_signal_state_change - * - * Signal the bus that our state changed. - * - */ -static void -nm_openvpn_dbus_signal_state_change (NmOpenVPNData *data, NMVPNServiceState old_state) -{ - DBusMessage *message; - - g_return_if_fail (data != NULL); - - if (!(message = dbus_message_new_signal (NM_DBUS_PATH_OPENVPN, NM_DBUS_INTERFACE_OPENVPN, NM_DBUS_VPN_SIGNAL_STATE_CHANGE))) - { - nm_warning ("nm_openvpn_dbus_signal_state_change(): Not enough memory for new dbus message!"); - return; - } - - dbus_message_append_args (message, DBUS_TYPE_UINT32, &old_state, DBUS_TYPE_UINT32, &(data->state), DBUS_TYPE_INVALID); - - if (!dbus_connection_send (data->con, message, NULL)) - nm_warning ("nm_openvpn_dbus_signal_state_change(): Could not raise the signal!"); - - dbus_message_unref (message); -} - - -/* - * nm_openvpn_set_state - * - * Set our state and make sure to signal the bus. - * - */ -static void -nm_openvpn_set_state (NmOpenVPNData *data, NMVPNServiceState new_state) -{ - NMVPNServiceState old_state; - - g_return_if_fail (data != NULL); - - old_state = data->state; - - if (old_state != new_state) - { - data->state = new_state; - nm_openvpn_dbus_signal_state_change (data, old_state); - } -} - - -/* - * nm_openvpn_quit_timer_cb - * - * Callback to quit nm-openvpn-service after a certain period of time. - * - */ static gboolean -nm_openvpn_quit_timer_cb (NmOpenVPNData *data) +nm_openvpn_properties_validate (GHashTable *properties) { - data->quit_timer = 0; + gboolean failed = FALSE; - g_return_val_if_fail (data != NULL, FALSE); + if (g_hash_table_size (properties) < 1) + return failed; - g_main_loop_quit (data->loop); + g_hash_table_foreach (properties, validate_one_property, &failed); - return FALSE; + return !failed; } - -/* - * nm_openvpn_schedule_quit_timer - * - * If openvpn isn't running, and we haven't been asked to do anything in a while, - * then we just exit since NetworkManager will re-launch us later. - * - */ -static void -nm_openvpn_schedule_quit_timer (NmOpenVPNData *data, guint interval) -{ - g_return_if_fail (data != NULL); - - if (data->quit_timer == 0) - data->quit_timer = g_timeout_add (interval, (GSourceFunc) nm_openvpn_quit_timer_cb, data); -} - - -/* - * nm_openvpn_cancel_quit_timer - * - * Cancel a quit timer that we've scheduled before. - * - */ -static void -nm_openvpn_cancel_quit_timer (NmOpenVPNData *data) -{ - g_return_if_fail (data != NULL); - - if (data->quit_timer > 0) - g_source_remove (data->quit_timer); -} - - - - static void -nm_openvpn_disconnect_management_socket (NmOpenVPNData *data) +nm_openvpn_disconnect_management_socket (NMOpenvpnPlugin *plugin) { - g_return_if_fail (data != NULL); + NMOpenvpnPluginPrivate *priv = NM_OPENVPN_PLUGIN_GET_PRIVATE (plugin); + NMOpenvpnPluginIOData *io_data = priv->io_data; - // This should no throw a warning since this can happen in - // non-password modes - if ( data->io_data == NULL) return; + /* This should no throw a warning since this can happen in + non-password modes */ + if (!io_data) + return; - g_source_remove (data->io_data->socket_channel_eventid); - g_io_channel_shutdown (data->io_data->socket_channel, FALSE, NULL); - g_io_channel_unref (data->io_data->socket_channel); + g_source_remove (io_data->socket_channel_eventid); + g_io_channel_shutdown (io_data->socket_channel, FALSE, NULL); + g_io_channel_unref (io_data->socket_channel); - if (data->io_data->username) g_free (data->io_data->username); - if (data->io_data->password) g_free (data->io_data->password); + g_free (io_data->username); + g_free (io_data->password); - g_free (data->io_data); - data->io_data = NULL; + g_free (priv->io_data); + priv->io_data = NULL; } - -/* - * nm_openvpn_helper_timer_cb - * - * If we haven't received the IP4 config info from the helper before the timeout - * occurs, we kill openvpn - * - */ -static gboolean -nm_openvpn_helper_timer_cb (NmOpenVPNData *data) -{ - data->helper_timer = 0; - - g_return_val_if_fail (data != NULL, FALSE); - - nm_openvpn_disconnect_management_socket (data); - - nm_openvpn_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED); - nm_openvpn_dbus_handle_stop_vpn (data); - - return FALSE; -} - - -/* - * nm_openvpn_schedule_helper_timer - * - * Once openvpn is running, we wait for the helper to return the IP4 configuration - * information to us. If we don't receive that information within 7 seconds, - * we kill openvpn - * - */ -static void -nm_openvpn_schedule_helper_timer (NmOpenVPNData *data) -{ - g_return_if_fail (data != NULL); - - if (data->helper_timer == 0) - data->helper_timer = g_timeout_add (10000, (GSourceFunc) nm_openvpn_helper_timer_cb, data); -} - - -/* - * nm_openvpn_cancel_helper_timer - * - * Cancel a helper timer that we've scheduled before. - * - */ -static void -nm_openvpn_cancel_helper_timer (NmOpenVPNData *data) -{ - g_return_if_fail (data != NULL); - - if (data->helper_timer > 0) - g_source_remove (data->helper_timer); -} - - -/* - * nm_openvpn_csocket_data_cb - * - * Called if data is available on the management connection, if asked for user or - * password it is sent. After password has been sent associated data will be freed - * and channel closed by returning FALSE. - * - */ static gboolean nm_openvpn_socket_data_cb (GIOChannel *source, GIOCondition condition, gpointer user_data) { - NmOpenVPNData *data = (NmOpenVPNData *)user_data; - NmOpenVPN_IOData *io_data = data->io_data; - char *str = NULL; + NMOpenvpnPlugin *plugin = NM_OPENVPN_PLUGIN (user_data); + NMOpenvpnPluginIOData *io_data = NM_OPENVPN_PLUGIN_GET_PRIVATE (plugin)->io_data; + gboolean again = TRUE; + char *str = NULL; + char *auth; + gsize written; + char *buf; - if (! (condition & G_IO_IN)) - return TRUE; + if (!(condition & G_IO_IN)) + return TRUE; - if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) { - int len; + if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) != G_IO_STATUS_NORMAL) + goto out; - len = strlen (str); - if ( len > 0 ) { - char *auth; + if (strlen (str) < 1) + goto out; - // printf("Read: %s\n", str); + if (sscanf (str, ">PASSWORD:Need '%a[^']'", &auth) > 0 ) { + if (strcmp (auth, "Auth") == 0) { + if (io_data->username != NULL && io_data->password != NULL) { + buf = g_strdup_printf ("username \"%s\" %s\n" + "password \"%s\" %s\n", + auth, io_data->username, + auth, io_data->password); + /* Will always write everything in blocking channels (on success) */ + g_io_channel_write_chars (source, buf, strlen (buf), &written, NULL); + g_io_channel_flush (source, NULL); + g_free (buf); + } + } else if (!strcmp (auth, "Private Key")) { + if (io_data->certpass) { + buf = g_strdup_printf ("password \"%s\" %s\n", auth, io_data->certpass); + /* Will always write everything in blocking channels (on success) */ + g_io_channel_write_chars (source, buf, strlen (buf), &written, NULL); + g_io_channel_flush (source, NULL); + g_free (buf); + } else { + nm_warning ("Certificate password requested but certpass == NULL"); + } + } else { + nm_warning ("No clue what to send for username/password request for '%s'", auth); + nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); + nm_openvpn_disconnect_management_socket (plugin); + } - if ( sscanf(str, ">PASSWORD:Need '%a[^']'", &auth) > 0 ) { - - if ( strcmp (auth, "Auth") == 0) { - - if ( (io_data->username != NULL) && - (io_data->password != NULL) ) { - gsize written; - char *buf = g_strdup_printf ("username \"%s\" %s\n" - "password \"%s\" %s\n", - auth, io_data->username, - auth, io_data->password); - /* Will always write everything in blocking channels (on success) */ - g_io_channel_write_chars (source, buf, strlen (buf), &written, NULL); - g_io_channel_flush (source, NULL); - g_free (buf); - } - } else if ( strcmp (auth, "Private Key") == 0 ) { - if ( io_data->certpass != NULL ) { - gsize written; - char *buf = g_strdup_printf ("password \"%s\" %s\n", - auth, io_data->certpass); - // printf("1: sending: %s\n", buf); - /* Will always write everything in blocking channels (on success) */ - g_io_channel_write_chars (source, buf, strlen (buf), &written, NULL); - g_io_channel_flush (source, NULL); - g_free (buf); - } else { - nm_warning("Certificate password requested but certpass == NULL"); - } - } else { - nm_warning("No clue what to send for username/password request for '%s'", auth); - nm_openvpn_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED); - nm_openvpn_disconnect_management_socket (data); + } else if (strstr (str, ">PASSWORD:Verification Failed: ") == str) { + nm_warning ("Password verification failed"); + nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); + nm_openvpn_disconnect_management_socket (plugin); + again = FALSE; } - g_free (auth); - return TRUE; - - } else if ( strstr(str, ">PASSWORD:Verification Failed: ") == str ) { - - nm_warning("Password verification failed"); - - nm_openvpn_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED); - nm_openvpn_disconnect_management_socket (data); - - return FALSE; - } - } - } - - g_free (str); - - return TRUE; + out: + g_free (str); + return again; } - -/* - * nm_openvpn_connect_timer_cb - * - * We need to wait until OpenVPN has started the management socket - * - */ static gboolean -nm_openvpn_connect_timer_cb (NmOpenVPNData *data) +nm_openvpn_connect_timer_cb (gpointer data) { - struct sockaddr_in serv_addr; - gboolean connected = FALSE; - gint socket_fd = -1; - NmOpenVPN_IOData *io_data; + NMOpenvpnPlugin *plugin = NM_OPENVPN_PLUGIN (data); + NMOpenvpnPluginPrivate *priv = NM_OPENVPN_PLUGIN_GET_PRIVATE (plugin); + struct sockaddr_in serv_addr; + gboolean connected = FALSE; + gint socket_fd = -1; + NMOpenvpnPluginIOData *io_data = priv->io_data; - g_return_val_if_fail (data != NULL, FALSE); + priv->connect_timer = 0; + priv->connect_count++; - io_data = data->io_data; - g_return_val_if_fail (io_data != NULL, FALSE); + /* open socket and start listener */ + socket_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (socket_fd < 0) + return FALSE; - data->connect_timer = 0; - data->connect_count++; - - // open socket and start listener - socket_fd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ); - if ( socket_fd < 0 ) { - // we failed - return FALSE; - } - - serv_addr.sin_family = AF_INET; - inet_aton("127.0.0.1", &(serv_addr.sin_addr)); - serv_addr.sin_port = htons( 1194 ); + serv_addr.sin_family = AF_INET; + inet_aton ("127.0.0.1", &(serv_addr.sin_addr)); + serv_addr.sin_port = htons (1194); - connected = ( connect (socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0 ); + connected = (connect (socket_fd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) == 0); + if (!connected) { + close (socket_fd); + if (priv->connect_count <= 30) { + return TRUE; + } else { + nm_warning ("Could not open management socket"); + nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); + nm_vpn_plugin_set_state (NM_VPN_PLUGIN (plugin), NM_VPN_SERVICE_STATE_STOPPED); + return FALSE; + } + } else { + GIOChannel *openvpn_socket_channel; + guint openvpn_socket_channel_eventid; - if ( ! connected ) { - close ( socket_fd ); - if ( data->connect_count <= 30 ) { - return TRUE; - } else { - nm_warning ("Could not open management socket"); - nm_openvpn_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED); - return FALSE; - } - } else { - GIOChannel *openvpn_socket_channel; - guint openvpn_socket_channel_eventid; - - openvpn_socket_channel = g_io_channel_unix_new (socket_fd); - openvpn_socket_channel_eventid = g_io_add_watch (openvpn_socket_channel, G_IO_IN, nm_openvpn_socket_data_cb, data); - g_io_channel_set_encoding (openvpn_socket_channel, NULL, NULL); + openvpn_socket_channel = g_io_channel_unix_new (socket_fd); + openvpn_socket_channel_eventid = g_io_add_watch (openvpn_socket_channel, + G_IO_IN, + nm_openvpn_socket_data_cb, + plugin); - io_data->socket_channel = openvpn_socket_channel; - io_data->socket_channel_eventid = openvpn_socket_channel_eventid; + g_io_channel_set_encoding (openvpn_socket_channel, NULL, NULL); + io_data->socket_channel = openvpn_socket_channel; + io_data->socket_channel_eventid = openvpn_socket_channel_eventid; - return FALSE; - } + return FALSE; + } } - -/* - * nm_openvpn_schedule_helper_timer - * - * Once openvpn is running, we wait for the helper to return the IP4 configuration - * information to us. If we don't receive that information within 7 seconds, - * we kill openvpn - * - */ static void -nm_openvpn_schedule_connect_timer (NmOpenVPNData *data) +nm_openvpn_schedule_connect_timer (NMOpenvpnPlugin *plugin) { - g_return_if_fail (data != NULL); - g_return_if_fail (data->io_data != NULL); + NMOpenvpnPluginPrivate *priv = NM_OPENVPN_PLUGIN_GET_PRIVATE (plugin); - if (data->connect_timer == 0) - data->connect_timer = g_timeout_add (200, (GSourceFunc) nm_openvpn_connect_timer_cb, data); + if (priv->connect_timer == 0) + priv->connect_timer = g_timeout_add (200, nm_openvpn_connect_timer_cb, plugin); } - -/* - * nm_openvpn_cancel_helper_timer - * - * Cancel a helper timer that we've scheduled before. - * - */ -static void -nm_openvpn_cancel_connect_timer (NmOpenVPNData *data) -{ - g_return_if_fail (data != NULL); - - if (data->connect_timer > 0) { - g_source_remove (data->connect_timer); - data->connect_timer = 0; - data->connect_count = 0; - } -} - - - - -/* - * openvpn_watch_cb - * - * Watch our child openvpn process and get notified of events from it. - * - */ static void openvpn_watch_cb (GPid pid, gint status, gpointer user_data) { - guint error = -1; + NMVPNPlugin *plugin = NM_VPN_PLUGIN (user_data); + NMOpenvpnPluginPrivate *priv = NM_OPENVPN_PLUGIN_GET_PRIVATE (plugin); + guint error; - NmOpenVPNData *data = (NmOpenVPNData *)user_data; - - if (WIFEXITED (status)) - { - error = WEXITSTATUS (status); - if (error != 0) - nm_warning ("openvpn exited with error code %d", error); + if (WIFEXITED (status)) { + error = WEXITSTATUS (status); + if (error != 0) + nm_warning ("openvpn exited with error code %d", error); } - else if (WIFSTOPPED (status)) - nm_warning ("openvpn stopped unexpectedly with signal %d", WSTOPSIG (status)); - else if (WIFSIGNALED (status)) - nm_warning ("openvpn died with signal %d", WTERMSIG (status)); - else - nm_warning ("openvpn died from an unknown cause"); + else if (WIFSTOPPED (status)) + nm_warning ("openvpn stopped unexpectedly with signal %d", WSTOPSIG (status)); + else if (WIFSIGNALED (status)) + nm_warning ("openvpn died with signal %d", WTERMSIG (status)); + else + nm_warning ("openvpn died from an unknown cause"); - /* Reap child if needed. */ - waitpid (data->pid, NULL, WNOHANG); - data->pid = 0; - - /* Must be after data->state is set since signals use data->state */ - /* This is still code from vpnc, openvpn does not supply useful exit codes :-/ */ - switch (error) - { - case 2: /* Couldn't log in due to bad user/pass */ - nm_openvpn_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED); - break; - - case 1: /* Other error (couldn't bind to address, etc) */ - nm_openvpn_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED); - break; - - default: - break; - } - - nm_openvpn_set_state (data, NM_VPN_SERVICE_STATE_STOPPED); - nm_openvpn_schedule_quit_timer (data, 10000); -} - - - -/* - * nm_openvpn_start_vpn_binary - * - * Start the openvpn binary with a set of arguments and a config file. - * - */ -static gint -nm_openvpn_start_openvpn_binary (NmOpenVPNData *data, - char **data_items, const int num_items, - char **passwords, const int num_passwords - ) -{ - GPid pid; - const char *openvpn_binary = NULL; - GPtrArray *openvpn_argv; - GError *error = NULL; - GSource *openvpn_watch; - gint stdin_fd = -1; - gint stdout_fd = -1; - gint stderr_fd = -1; - int i = 0; - - char *username = NULL; - char *dev = NULL; - char *proto = NULL; - char *port = NULL; - char *cipher = NULL; - char *ta = NULL; - char *ta_dir = NULL; - - g_return_val_if_fail (data != NULL, -1); - - data->pid = 0; - - if ( (num_items == 0) || (data_items == NULL) ) { - return -1; - } - - /* Find openvpn */ - openvpn_binary = nm_find_openvpn(); - if (!openvpn_binary) { - nm_info ("Could not find openvpn binary."); - return -1; - } - - // First check in which mode we are operating. Since NM does not - // guarantee any particular order we search this parameter - // explictly once - data->connection_type = NM_OPENVPN_CONTYPE_INVALID; - for (i = 0; i < num_items; ++i) { - if ( strcmp( data_items[i], "connection-type" ) == 0) { - ++i; - if ( strcmp (data_items[i], "x509" ) == 0 ) { - data->connection_type = NM_OPENVPN_CONTYPE_X509; - } else if ( strcmp (data_items[i], "shared-key" ) == 0 ) { - data->connection_type = NM_OPENVPN_CONTYPE_SHAREDKEY; - } else if ( strcmp (data_items[i], "password" ) == 0 ) { - data->connection_type = NM_OPENVPN_CONTYPE_PASSWORD; - } else if ( strcmp (data_items[i], "x509userpass" ) == 0 ) { - data->connection_type = NM_OPENVPN_CONTYPE_X509USERPASS; - } - } else if ( strcmp (data_items[i], "username" ) == 0) { - username = data_items[++i]; - } - } - - if ( data->connection_type != NM_OPENVPN_CONTYPE_INVALID ) { - - openvpn_argv = g_ptr_array_new (); - g_ptr_array_add (openvpn_argv, (gpointer) (openvpn_binary)); - - // Note that it should be guaranteed that num_items % 2 == 0 - // Add global arguments - for (i = 0; i < num_items; ++i) { - if ( strcmp( data_items[i], "remote" ) == 0) { - g_ptr_array_add (openvpn_argv, (gpointer) "--remote"); - g_ptr_array_add (openvpn_argv, (gpointer) data_items[++i]); - } else if ( (strcmp( data_items[i], "comp-lzo" ) == 0) && - (strcmp( data_items[++i], "yes" ) == 0) ) { - g_ptr_array_add (openvpn_argv, (gpointer) "--comp-lzo"); - } else if ( (strcmp( data_items[i], "dev" ) == 0) ) { - dev = data_items[++i]; - } else if ( (strcmp( data_items[i], "proto" ) == 0) ) { - proto = data_items[++i]; - } else if ( (strcmp( data_items[i], "port") == 0) ) { - port = data_items[++i]; - } else if ( (strcmp( data_items[i], "cipher") == 0) ) { - cipher = data_items[++i]; - } else if ( (strcmp( data_items[i], "ta") == 0) ) { - ta = data_items[++i]; - } else if ( (strcmp( data_items[i], "ta-dir") == 0) ) { - ta_dir = data_items[++i]; - } - } - g_ptr_array_add (openvpn_argv, (gpointer) "--nobind"); - - // Device, either tun or tap - g_ptr_array_add (openvpn_argv, (gpointer) "--dev"); - if ( (dev != NULL) ) { - g_ptr_array_add (openvpn_argv, (gpointer) dev); - } else { - // Versions prior to 0.3.0 didn't set this so we default for - // tun for these configs - g_ptr_array_add (openvpn_argv, (gpointer) "tun"); - } - - // Protocol, either tcp or udp - g_ptr_array_add (openvpn_argv, (gpointer) "--proto"); - if ( (proto != NULL) ) { - g_ptr_array_add (openvpn_argv, (gpointer) proto); - } else { - // Versions prior to 0.3.1 didn't set this so we default for - // udp for these configs - g_ptr_array_add (openvpn_argv, (gpointer) "udp"); - } - - // Port - g_ptr_array_add (openvpn_argv, (gpointer) "--port"); - if ( (port != NULL) ) { - g_ptr_array_add (openvpn_argv, (gpointer) port); - } else { - // Versions prior to 0.3.2 didn't set this so we default to - // IANA assigned port 1194 - g_ptr_array_add (openvpn_argv, (gpointer) "1194"); - } - - // Cipher - if (cipher != NULL) { - g_ptr_array_add (openvpn_argv, (gpointer) "--cipher"); - g_ptr_array_add (openvpn_argv, (gpointer) cipher); - } - - // TA - if (ta != NULL) { - g_ptr_array_add (openvpn_argv, (gpointer) "--tls-auth"); - g_ptr_array_add (openvpn_argv, (gpointer) ta); - if (ta_dir != NULL) - g_ptr_array_add (openvpn_argv, (gpointer) ta_dir); - } - - // Syslog - g_ptr_array_add (openvpn_argv, (gpointer) "--syslog"); - g_ptr_array_add (openvpn_argv, (gpointer) "nm-openvpn"); - - // Up script, called when connection has been established or has been restarted - g_ptr_array_add (openvpn_argv, (gpointer) "--up"); - g_ptr_array_add (openvpn_argv, (gpointer) NM_OPENVPN_HELPER_PATH); - g_ptr_array_add (openvpn_argv, (gpointer) "--up-restart"); - - // Keep key and tun if restart is needed - g_ptr_array_add (openvpn_argv, (gpointer) "--persist-key"); - g_ptr_array_add (openvpn_argv, (gpointer) "--persist-tun"); - - // Management socket for localhost access to supply username and password - g_ptr_array_add (openvpn_argv, (gpointer) "--management"); - g_ptr_array_add (openvpn_argv, (gpointer) "127.0.0.1"); - // with have nobind, thus 1194 should be free, it is the IANA assigned port - g_ptr_array_add (openvpn_argv, (gpointer) "1194"); - // Query on the management socket for user/pass - g_ptr_array_add (openvpn_argv, (gpointer) "--management-query-passwords"); - - - // Now append configuration options which are dependent on the configuration type - switch ( data->connection_type ) { - - case NM_OPENVPN_CONTYPE_X509: - - g_ptr_array_add (openvpn_argv, (gpointer) "--client"); - g_ptr_array_add (openvpn_argv, (gpointer) "--ns-cert-type"); - g_ptr_array_add (openvpn_argv, (gpointer) "server"); - - for (i = 0; i < num_items; ++i) { - if ( strcmp( data_items[i], "ca" ) == 0) { - g_ptr_array_add (openvpn_argv, (gpointer) "--ca"); - g_ptr_array_add (openvpn_argv, (gpointer) data_items[++i]); - } else if ( strcmp( data_items[i], "cert" ) == 0) { - g_ptr_array_add (openvpn_argv, (gpointer) "--cert"); - g_ptr_array_add (openvpn_argv, (gpointer) data_items[++i]); - } else if ( strcmp( data_items[i], "key" ) == 0) { - g_ptr_array_add (openvpn_argv, (gpointer) "--key"); - g_ptr_array_add (openvpn_argv, (gpointer) data_items[++i]); - } - } - break; - - case NM_OPENVPN_CONTYPE_SHAREDKEY: - { - char *local_ip = NULL; - char *remote_ip = NULL; - - // Note that it should be guaranteed that num_items % 2 == 0 - for (i = 0; i < num_items; ++i) { - if ( strcmp( data_items[i], "local-ip" ) == 0) { - local_ip = data_items[++i]; - } else if ( strcmp( data_items[i], "remote-ip" ) == 0) { - remote_ip = data_items[++i]; - } else if ( strcmp( data_items[i], "shared-key" ) == 0) { - g_ptr_array_add (openvpn_argv, (gpointer) "--secret"); - g_ptr_array_add (openvpn_argv, (gpointer) data_items[++i]); - } - - } - - if ( (local_ip == NULL) || (remote_ip == NULL) ) { - // Insufficient data - g_ptr_array_free (openvpn_argv, TRUE); - return -1; - } else { - g_ptr_array_add (openvpn_argv, (gpointer) "--ifconfig"); - g_ptr_array_add (openvpn_argv, (gpointer) local_ip); - g_ptr_array_add (openvpn_argv, (gpointer) remote_ip); - } - } - break; - - case NM_OPENVPN_CONTYPE_PASSWORD: - - // Client mode - g_ptr_array_add (openvpn_argv, (gpointer) "--client"); - g_ptr_array_add (openvpn_argv, (gpointer) "--ns-cert-type"); - g_ptr_array_add (openvpn_argv, (gpointer) "server"); - // Use user/path authentication - g_ptr_array_add (openvpn_argv, (gpointer) "--auth-user-pass"); - - for (i = 0; i < num_items; ++i) { - if ( strcmp( data_items[i], "ca" ) == 0) { - g_ptr_array_add (openvpn_argv, (gpointer) "--ca"); - g_ptr_array_add (openvpn_argv, (gpointer) data_items[++i]); - } - } - break; - - - case NM_OPENVPN_CONTYPE_X509USERPASS: - - g_ptr_array_add (openvpn_argv, (gpointer) "--client"); - g_ptr_array_add (openvpn_argv, (gpointer) "--ns-cert-type"); - g_ptr_array_add (openvpn_argv, (gpointer) "server"); - - for (i = 0; i < num_items; ++i) { - if ( strcmp( data_items[i], "ca" ) == 0) { - g_ptr_array_add (openvpn_argv, (gpointer) "--ca"); - g_ptr_array_add (openvpn_argv, (gpointer) data_items[++i]); - } else if ( strcmp( data_items[i], "cert" ) == 0) { - g_ptr_array_add (openvpn_argv, (gpointer) "--cert"); - g_ptr_array_add (openvpn_argv, (gpointer) data_items[++i]); - } else if ( strcmp( data_items[i], "key" ) == 0) { - g_ptr_array_add (openvpn_argv, (gpointer) "--key"); - g_ptr_array_add (openvpn_argv, (gpointer) data_items[++i]); - } - } - // Use user/path authentication - g_ptr_array_add (openvpn_argv, (gpointer) "--auth-user-pass"); - break; - - - } - - g_ptr_array_add (openvpn_argv, NULL); - - if (!g_spawn_async_with_pipes (NULL, (char **) openvpn_argv->pdata, NULL, - G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &stdin_fd, - &stdout_fd, &stderr_fd, &error)) - { - g_ptr_array_free (openvpn_argv, TRUE); - nm_warning ("openvpn failed to start. error: '%s'", error->message); - g_error_free(error); - return -1; - } - g_ptr_array_free (openvpn_argv, TRUE); - - nm_info ("openvpn started with pid %d", pid); - - data->pid = pid; - openvpn_watch = g_child_watch_source_new (pid); - g_source_set_callback (openvpn_watch, (GSourceFunc) openvpn_watch_cb, data, NULL); - g_source_attach (openvpn_watch, NULL); - g_source_unref (openvpn_watch); - - /* Listen to the management socket for a few connection types: - PASSWORD: Will require username and password - X509USERPASS: Will require username and password and maybe certificate password - X509: May require certificate password - */ - if ( (data->connection_type == NM_OPENVPN_CONTYPE_PASSWORD) || - (data->connection_type == NM_OPENVPN_CONTYPE_X509USERPASS) || - (data->connection_type == NM_OPENVPN_CONTYPE_X509) - - ) { - - NmOpenVPN_IOData *io_data; - - io_data = g_new0 (NmOpenVPN_IOData, 1); - io_data->child_stdin_fd = stdin_fd; - io_data->child_stdout_fd = stdout_fd; - io_data->child_stderr_fd = stderr_fd; - io_data->username = g_strdup(username); - io_data->password = g_strdup(passwords[0]); - io_data->certpass = g_strdup(passwords[1]); - - data->io_data = io_data; - - nm_openvpn_schedule_connect_timer (data); - } - - nm_openvpn_schedule_helper_timer (data); - - return stdin_fd; - - } else { - return -1; - } -} - - -typedef enum OptType -{ - OPT_TYPE_UNKNOWN = 0, - OPT_TYPE_ADDRESS, - OPT_TYPE_ASCII, - OPT_TYPE_INTEGER, - OPT_TYPE_NONE -} OptType; - -typedef struct Option -{ - const char *name; - OptType type; -} Option; - -/* - * nm_openvpn_config_options_validate - * - * Make sure the config options are sane - * - */ -static gboolean -nm_openvpn_config_options_validate (char **data_items, int num_items) -{ - Option allowed_opts[] = { - { "remote", OPT_TYPE_ADDRESS }, - { "ca", OPT_TYPE_ASCII }, - { "dev", OPT_TYPE_ASCII }, - { "proto", OPT_TYPE_ASCII }, - { "port", OPT_TYPE_INTEGER }, - { "cert", OPT_TYPE_ASCII }, - { "key", OPT_TYPE_ASCII }, - { "comp-lzo", OPT_TYPE_ASCII }, - { "shared-key", OPT_TYPE_ASCII }, - { "local-ip", OPT_TYPE_ADDRESS }, - { "remote-ip", OPT_TYPE_ADDRESS }, - { "username", OPT_TYPE_ASCII }, - { "connection-type", OPT_TYPE_ASCII }, - { "cipher", OPT_TYPE_ASCII }, - { "ta", OPT_TYPE_ASCII }, - { "ta-dir", OPT_TYPE_ASCII }, - { NULL, OPT_TYPE_UNKNOWN } }; - - unsigned int i; - - g_return_val_if_fail (data_items != NULL, FALSE); - g_return_val_if_fail (num_items >= 2, FALSE); - - /* Must be an even numbers of config options */ - if ((num_items % 2) != 0) - { - nm_warning ("The number of VPN config options was not even."); - return FALSE; - } - - for (i = 0; i < num_items; i += 2) - { - Option *opt = NULL; - unsigned int t, len; - char *opt_value; - - if (!data_items[i] || !data_items[i+1]) - return FALSE; - opt_value = data_items[i+1]; - - /* Find the option in the allowed list */ - for (t = 0; t < sizeof (allowed_opts) / sizeof (Option); t++) - { - opt = &allowed_opts[t]; - if (opt->name && !strcmp (opt->name, data_items[i])) - break; - } - if (!opt->name) /* not found */ - { - nm_warning ("VPN option '%s' is not allowed.", data_items[i]); - return FALSE; - } - - /* Don't allow control characters at all */ - len = strlen (opt_value); - for (t = 0; t < len; t++) - { - if (iscntrl (opt_value[t])) - { - nm_warning ("There were invalid characters in the VPN option '%s' - '%s'.", data_items[i], opt_value); - return FALSE; - } - } - - /* Validate the option's data */ - switch (opt->type) - { - case OPT_TYPE_ASCII: - /* What other characters should we reject?? */ - break; - - case OPT_TYPE_NONE: - /* These have blank data */ - break; - - case OPT_TYPE_ADDRESS: - /* Can be any legal hostname or IP address */ - break; - - case OPT_TYPE_INTEGER: - break; - + /* Reap child if needed. */ + waitpid (priv->pid, NULL, WNOHANG); + priv->pid = 0; + + /* Must be after data->state is set since signals use data->state */ + /* This is still code from vpnc, openvpn does not supply useful exit codes :-/ */ + switch (error) { + case 2: + /* Couldn't log in due to bad user/pass */ + nm_vpn_plugin_failure (plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); + break; + case 1: + /* Other error (couldn't bind to address, etc) */ + nm_vpn_plugin_failure (plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); + break; default: - return FALSE; - break; + break; } - } - return TRUE; + nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED); } +static int +get_connection_type (GHashTable *properties) +{ + int connection_type = NM_OPENVPN_CONTYPE_INVALID; + gpointer tmp; + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_CONNECTION_TYPE); + if (tmp) + connection_type = g_value_get_int ((GValue *) tmp); + + if (connection_type < NM_OPENVPN_CONTYPE_INVALID || connection_type > NM_OPENVPN_CONTYPE_X509USERPASS) + connection_type = NM_OPENVPN_CONTYPE_INVALID; + + return connection_type; +} + +static const char * +nm_find_openvpn (void) +{ + static const char *openvpn_binary_paths[] = { + "/usr/sbin/openvpn", + "/sbin/openvpn", + NULL + }; + const char **openvpn_binary = openvpn_binary_paths; + + while (*openvpn_binary != NULL) { + if (g_file_test (*openvpn_binary, G_FILE_TEST_EXISTS)) + break; + openvpn_binary++; + } + + return *openvpn_binary; +} + +static gint +nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin, GHashTable *properties) +{ + NMOpenvpnPluginPrivate *priv = NM_OPENVPN_PLUGIN_GET_PRIVATE (plugin); + GPid pid; + const char *openvpn_binary; + GPtrArray *openvpn_argv; + GSource *openvpn_watch; + gpointer tmp; + gint stdin_fd; + gint stdout_fd; + gint stderr_fd; + int connection_type; + GError *err = NULL; + + /* Find openvpn */ + openvpn_binary = nm_find_openvpn (); + if (!openvpn_binary) { + nm_info ("Could not find openvpn binary."); + return -1; + } + + connection_type = get_connection_type (properties); + if (connection_type == NM_OPENVPN_CONTYPE_INVALID) + return -1; + + openvpn_argv = g_ptr_array_new (); + g_ptr_array_add (openvpn_argv, (gpointer) (openvpn_binary)); + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_REMOTE); + if (tmp) { + g_ptr_array_add (openvpn_argv, (gpointer) "--remote"); + g_ptr_array_add (openvpn_argv, tmp); + } + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_COMP_LZO); + if (tmp && g_value_get_boolean ((GValue *) tmp)) + g_ptr_array_add (openvpn_argv, (gpointer) "--comp-lzo"); + + g_ptr_array_add (openvpn_argv, (gpointer) "--nobind"); + + /* Device, either tun or tap */ + g_ptr_array_add (openvpn_argv, (gpointer) "--dev"); + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_TAP_DEV); + if (tmp && g_value_get_boolean ((GValue *) tmp)) + g_ptr_array_add (openvpn_argv, (gpointer) "tap"); + else + g_ptr_array_add (openvpn_argv, (gpointer) "tun"); + + /* Protocol, either tcp or udp */ + g_ptr_array_add (openvpn_argv, (gpointer) "--proto"); + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_PROTO_TCP); + if (tmp && g_value_get_boolean ((GValue *) tmp)) + g_ptr_array_add (openvpn_argv, (gpointer) "tcp-client"); + else + g_ptr_array_add (openvpn_argv, (gpointer) "udp"); + + /* Port */ + g_ptr_array_add (openvpn_argv, (gpointer) "--port"); + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_PORT); + if (tmp) + /* The string here is leaked, big deal. */ + g_ptr_array_add (openvpn_argv, g_strdup_printf ("%u", g_value_get_uint ((GValue *) tmp))); + else + /* Default to IANA assigned port 1194 */ + g_ptr_array_add (openvpn_argv, (GValue *) "1194"); + + /* Cipher */ + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_CIPHER); + if (tmp) { + g_ptr_array_add (openvpn_argv, (gpointer) "--cipher"); + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + } + + /* TA */ + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_TA); + if (tmp) { + g_ptr_array_add (openvpn_argv, (gpointer) "--tls-auth"); + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_TA_DIR); + if (tmp) + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + } + + /* Syslog */ + g_ptr_array_add (openvpn_argv, (gpointer) "--syslog"); + g_ptr_array_add (openvpn_argv, (gpointer) "nm-openvpn"); + + /* Up script, called when connection has been established or has been restarted */ + g_ptr_array_add (openvpn_argv, (gpointer) "--up"); + g_ptr_array_add (openvpn_argv, (gpointer) NM_OPENVPN_HELPER_PATH); + g_ptr_array_add (openvpn_argv, (gpointer) "--up-restart"); + + /* Keep key and tun if restart is needed */ + g_ptr_array_add (openvpn_argv, (gpointer) "--persist-key"); + g_ptr_array_add (openvpn_argv, (gpointer) "--persist-tun"); + + /* Management socket for localhost access to supply username and password */ + g_ptr_array_add (openvpn_argv, (gpointer) "--management"); + g_ptr_array_add (openvpn_argv, (gpointer) "127.0.0.1"); + /* with have nobind, thus 1194 should be free, it is the IANA assigned port */ + g_ptr_array_add (openvpn_argv, (gpointer) "1194"); + /* Query on the management socket for user/pass */ + g_ptr_array_add (openvpn_argv, (gpointer) "--management-query-passwords"); + + /* Now append configuration options which are dependent on the configuration type */ + switch (connection_type) { + case NM_OPENVPN_CONTYPE_X509: + g_ptr_array_add (openvpn_argv, (gpointer) "--client"); + g_ptr_array_add (openvpn_argv, (gpointer) "--ns-cert-type"); + g_ptr_array_add (openvpn_argv, (gpointer) "server"); + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_CA); + if (tmp) { + g_ptr_array_add (openvpn_argv, (gpointer) "--ca"); + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + } + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_CERT); + if (tmp) { + g_ptr_array_add (openvpn_argv, (gpointer) "--cert"); + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + } + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_KEY); + if (tmp) { + g_ptr_array_add (openvpn_argv, (gpointer) "--key"); + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + } + break; + + case NM_OPENVPN_CONTYPE_SHAREDKEY: + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_SHARED_KEY); + if (tmp) { + g_ptr_array_add (openvpn_argv, (gpointer) "--secret"); + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + } + + g_ptr_array_add (openvpn_argv, (gpointer) "--ifconfig"); + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_LOCAL_IP); + if (!tmp) { + /* Insufficient data (FIXME: this should really be detected when validating the properties */ + g_ptr_array_free (openvpn_argv, TRUE); + return -1; + } + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_REMOTE_IP); + if (!tmp) { + /* Insufficient data (FIXME: this should really be detected when validating the properties */ + g_ptr_array_free (openvpn_argv, TRUE); + return -1; + } + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + break; + + case NM_OPENVPN_CONTYPE_PASSWORD: + /* Client mode */ + g_ptr_array_add (openvpn_argv, (gpointer) "--client"); + g_ptr_array_add (openvpn_argv, (gpointer) "--ns-cert-type"); + g_ptr_array_add (openvpn_argv, (gpointer) "server"); + /* Use user/path authentication */ + g_ptr_array_add (openvpn_argv, (gpointer) "--auth-user-pass"); + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_CA); + if (tmp) { + g_ptr_array_add (openvpn_argv, (gpointer) "--ca"); + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + } + break; + + case NM_OPENVPN_CONTYPE_X509USERPASS: + g_ptr_array_add (openvpn_argv, (gpointer) "--client"); + g_ptr_array_add (openvpn_argv, (gpointer) "--ns-cert-type"); + g_ptr_array_add (openvpn_argv, (gpointer) "server"); + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_CA); + if (tmp) { + g_ptr_array_add (openvpn_argv, (gpointer) "--ca"); + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + } + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_CERT); + if (tmp) { + g_ptr_array_add (openvpn_argv, (gpointer) "--cert"); + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + } + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_KEY); + if (tmp) { + g_ptr_array_add (openvpn_argv, (gpointer) "--key"); + g_ptr_array_add (openvpn_argv, (gpointer) g_value_get_string ((GValue *) tmp)); + } + + /* Use user/path authentication */ + g_ptr_array_add (openvpn_argv, (gpointer) "--auth-user-pass"); + break; + } + + g_ptr_array_add (openvpn_argv, NULL); + + if (!g_spawn_async_with_pipes (NULL, (char **) openvpn_argv->pdata, NULL, + G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &stdin_fd, + &stdout_fd, &stderr_fd, &err)) { + g_ptr_array_free (openvpn_argv, TRUE); + nm_warning ("openvpn failed to start. error: '%s'", err->message); + g_error_free (err); + return -1; + } + g_ptr_array_free (openvpn_argv, TRUE); + + nm_info ("openvpn started with pid %d", pid); + + priv->pid = pid; + openvpn_watch = g_child_watch_source_new (pid); + g_source_set_callback (openvpn_watch, (GSourceFunc) openvpn_watch_cb, plugin, NULL); + g_source_attach (openvpn_watch, NULL); + g_source_unref (openvpn_watch); + + /* Listen to the management socket for a few connection types: + PASSWORD: Will require username and password + X509USERPASS: Will require username and password and maybe certificate password + X509: May require certificate password + */ + if (connection_type == NM_OPENVPN_CONTYPE_PASSWORD || + connection_type == NM_OPENVPN_CONTYPE_X509USERPASS || + connection_type == NM_OPENVPN_CONTYPE_X509) { + + NMOpenvpnPluginIOData *io_data; + + io_data = g_new0 (NMOpenvpnPluginIOData, 1); + io_data->child_stdin_fd = stdin_fd; + io_data->child_stdout_fd = stdout_fd; + io_data->child_stderr_fd = stderr_fd; + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_USERNAME); + if (tmp) + io_data->username = g_strdup ((char *) g_value_get_string ((GValue *) tmp)); + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_PASSWORD); + if (tmp) + io_data->password = g_strdup ((char *) g_value_get_string ((GValue *) tmp)); + + tmp = g_hash_table_lookup (properties, NM_OPENVPN_KEY_CERTPASS); + if (tmp) + io_data->certpass = g_strdup ((char *) g_value_get_string ((GValue *) tmp)); + + priv->io_data = io_data; + + nm_openvpn_schedule_connect_timer (plugin); + } + + return stdin_fd; +} -/* - * nm_openvpn_dbus_handle_start_vpn - * - * Parse message arguments and start the VPN connection. - * - */ static gboolean -nm_openvpn_dbus_handle_start_vpn (DBusMessage *message, NmOpenVPNData *data) +real_connect (NMVPNPlugin *plugin, + NMConnection *connection, + GError **err) { - char ** data_items = NULL; - int num_items = -1; - char ** password_items = NULL; - int num_passwords = -1; - char ** user_routes = NULL; - int user_routes_count = -1; - const char * name = NULL; - const char * user_name = NULL; - DBusError error; - gboolean success = FALSE; - gint openvpn_fd = -1; + NMSettingVPNProperties *properties; + gint fd; + gboolean success = FALSE; - g_return_val_if_fail (message != NULL, FALSE); - g_return_val_if_fail (data != NULL, FALSE); - - nm_openvpn_set_state (data, NM_VPN_SERVICE_STATE_STARTING); - - dbus_error_init (&error); - if (!dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &user_name, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &password_items, &num_passwords, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &data_items, &num_items, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &user_routes, &user_routes_count, - DBUS_TYPE_INVALID)) - { - nm_warning ("Could not process the request because its arguments were invalid. dbus said: '%s'", error.message); - nm_openvpn_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD); - dbus_error_free (&error); - goto out; - } - - if (!nm_openvpn_config_options_validate (data_items, num_items)) - { - nm_openvpn_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD); - goto out; - } - - /* Now we can finally try to activate the VPN */ - if ((openvpn_fd = nm_openvpn_start_openvpn_binary (data, data_items, num_items, password_items, num_passwords)) >= 0) { - // Everything ok - success = TRUE; - } - - -out: - dbus_free_string_array (data_items); - dbus_free_string_array (password_items); - dbus_free_string_array (user_routes); - if (!success) - nm_openvpn_set_state (data, NM_VPN_SERVICE_STATE_STOPPED); - return success; -} - - -/* - * nm_openvpn_dbus_handle_stop_vpn - * - * Stop the running openvpn dameon. - * - */ -static gboolean nm_openvpn_dbus_handle_stop_vpn (NmOpenVPNData *data) -{ - g_return_val_if_fail (data != NULL, FALSE); - - if (data->pid > 0) - { - nm_openvpn_set_state (data, NM_VPN_SERVICE_STATE_STOPPING); - - kill (data->pid, SIGINT); - nm_info ("Terminated openvpn daemon with PID %d.", data->pid); - data->pid = 0; - - nm_openvpn_set_state (data, NM_VPN_SERVICE_STATE_STOPPED); - nm_openvpn_schedule_quit_timer (data, 10000); - } - - return TRUE; -} - - -/* - * nm_openvpn_dbus_start_vpn - * - * Begin a VPN connection. - * - */ -static DBusMessage * -nm_openvpn_dbus_start_vpn (DBusConnection *con, DBusMessage *message, NmOpenVPNData *data) -{ - DBusMessage *reply = NULL; - - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (con != NULL, NULL); - g_return_val_if_fail (message != NULL, NULL); - - switch (data->state) - { - case NM_VPN_SERVICE_STATE_STARTING: - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_OPENVPN, NM_DBUS_VPN_STARTING_IN_PROGRESS, - "Could not process the request because the VPN connection is already being started."); - break; - - case NM_VPN_SERVICE_STATE_STARTED: - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_OPENVPN, NM_DBUS_VPN_ALREADY_STARTED, - "Could not process the request because a VPN connection was already active."); - break; - - case NM_VPN_SERVICE_STATE_STOPPING: - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_OPENVPN, NM_DBUS_VPN_STOPPING_IN_PROGRESS, - "Could not process the request because the VPN connection is being stopped."); - break; - - case NM_VPN_SERVICE_STATE_STOPPED: - nm_openvpn_cancel_quit_timer (data); - nm_openvpn_dbus_handle_start_vpn (message, data); - reply = dbus_message_new_method_return (message); - break; - - default: - g_assert_not_reached(); - break; - } - - return reply; -} - - -/* - * nm_openvpn_dbus_stop_vpn - * - * Terminate a VPN connection. - * - */ -static DBusMessage * -nm_openvpn_dbus_stop_vpn (DBusConnection *con, DBusMessage *message, NmOpenVPNData *data) -{ - DBusMessage *reply = NULL; - - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (con != NULL, NULL); - g_return_val_if_fail (message != NULL, NULL); - - switch (data->state) - { - case NM_VPN_SERVICE_STATE_STOPPING: - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_OPENVPN, NM_DBUS_VPN_STOPPING_IN_PROGRESS, - "Could not process the request because the VPN connection is already being stopped."); - break; - - case NM_VPN_SERVICE_STATE_STOPPED: - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_OPENVPN, NM_DBUS_VPN_ALREADY_STOPPED, - "Could not process the request because no VPN connection was active."); - break; - - case NM_VPN_SERVICE_STATE_STARTING: - case NM_VPN_SERVICE_STATE_STARTED: - nm_openvpn_dbus_handle_stop_vpn (data); - reply = dbus_message_new_method_return (message); - break; - - default: - g_assert_not_reached(); - break; - } - - return reply; -} - - -/* - * nm_openvpn_dbus_get_state - * - * Return some state information to NetworkManager. - * - */ -static DBusMessage * -nm_openvpn_dbus_get_state (DBusConnection *con, DBusMessage *message, NmOpenVPNData *data) -{ - DBusMessage *reply = NULL; - - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (con != NULL, NULL); - g_return_val_if_fail (message != NULL, NULL); - - if ((reply = dbus_message_new_method_return (message))) - dbus_message_append_args (reply, DBUS_TYPE_UINT32, &(data->state), DBUS_TYPE_INVALID); - - return reply; -} - - -/* - * nm_openvpn_dbus_process_helper_config_error - * - * Signal the bus that the helper could not get all the configuration information - * it needed. - * - */ -static void -nm_openvpn_dbus_process_helper_config_error (DBusConnection *con, DBusMessage *message, NmOpenVPNData *data) -{ - char *error_item; - - g_return_if_fail (data != NULL); - g_return_if_fail (con != NULL); - g_return_if_fail (message != NULL); - - /* Only accept the config info if we're in STARTING state */ - if (data->state != NM_VPN_SERVICE_STATE_STARTING) - return; - - if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &error_item, DBUS_TYPE_INVALID)) - { - nm_warning ("openvpn helper did not receive adequate configuration information from openvpn. It is missing '%s'.", error_item); - nm_openvpn_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD); - } - - nm_openvpn_cancel_helper_timer (data); - nm_openvpn_disconnect_management_socket (data); - nm_openvpn_dbus_handle_stop_vpn (data); -} - - -/* - * nm_openvpn_dbus_process_helper_ip4_config - * - * Signal the bus - * - */ -static void -nm_openvpn_dbus_process_helper_ip4_config (DBusConnection *con, DBusMessage *message, NmOpenVPNData *data) -{ - guint32 ip4_vpn_gateway; - char * tundev; - guint32 ip4_address; - guint32 ip4_ptpaddr; - guint32 ip4_netmask; - guint32 * ip4_dns; - guint32 ip4_dns_len; - guint32 * ip4_nbns; - guint32 ip4_nbns_len; - gboolean success = FALSE; - char * empty = ""; - - g_return_if_fail (data != NULL); - g_return_if_fail (con != NULL); - g_return_if_fail (message != NULL); - - /* Only accept the config info if we're in STARTING state */ - if (data->state != NM_VPN_SERVICE_STATE_STARTING) - return; - - nm_openvpn_cancel_helper_timer (data); - nm_openvpn_disconnect_management_socket (data); - - if (dbus_message_get_args(message, NULL, - DBUS_TYPE_UINT32, &ip4_vpn_gateway, - DBUS_TYPE_STRING, &tundev, - DBUS_TYPE_UINT32, &ip4_address, - DBUS_TYPE_UINT32, &ip4_ptpaddr, - DBUS_TYPE_UINT32, &ip4_netmask, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &ip4_dns, &ip4_dns_len, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &ip4_nbns, &ip4_nbns_len, - DBUS_TYPE_INVALID)) - { - DBusMessage *signal; - DBusMessageIter iter, iter_dict; - - if (!(signal = dbus_message_new_signal (NM_DBUS_PATH_OPENVPN, NM_DBUS_INTERFACE_OPENVPN, NM_DBUS_VPN_SIGNAL_IP4_CONFIG))) - { - nm_warning ("Not enough memory for new dbus message!"); - goto out; - } - - dbus_message_iter_init_append (signal, &iter); - if (!nmu_dbus_dict_open_write (&iter, &iter_dict)) { - nm_warning ("dict open write failed!"); + properties = (NMSettingVPNProperties *) nm_connection_get_setting (connection, NM_SETTING_VPN_PROPERTIES); + if (!properties || !nm_openvpn_properties_validate (properties->data)) { + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "%s", + "Invalid arguments."); goto out; } - if (!nmu_dbus_dict_append_uint32 (&iter_dict, "gateway", ip4_vpn_gateway)) { - nm_warning ("couldn't append gateway to dict"); + if ((fd = nm_openvpn_start_openvpn_binary (NM_OPENVPN_PLUGIN (plugin), properties->data)) < 0) { + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, + "%s", + "Could not start vpnc binary."); goto out; } - if (!nmu_dbus_dict_append_string (&iter_dict, "tundev", tundev)) { - nm_warning ("couldn't append tundev to dict"); - goto out; - } + success = TRUE; - if (!nmu_dbus_dict_append_uint32 (&iter_dict, "local_addr", ip4_address)) { - nm_warning ("couldn't append local_address to dict"); - goto out; - } + out: + /* FIXME: It never did that but I guess it should? */ +/* close (fd); */ - if (!nmu_dbus_dict_append_uint32 (&iter_dict, "ptp_addr", ip4_ptpaddr)) { - nm_warning ("couldn't append ptp_address to dict"); - goto out; - } - - if (!nmu_dbus_dict_append_uint32 (&iter_dict, "netmask", ip4_netmask)) { - nm_warning ("couldn't append local_address to dict"); - goto out; - } - - if (ip4_dns_len > 0) { - if (!nmu_dbus_dict_append_uint32_array (&iter_dict, - "dns_server", - ip4_dns, - ip4_dns_len)) { - nm_warning ("couldn't append dns_servers to dict"); - goto out; - } - } - - if (ip4_nbns_len > 0) { - if (!nmu_dbus_dict_append_uint32_array (&iter_dict, - "nbns_server", - ip4_nbns, - ip4_nbns_len)) { - nm_warning ("couldn't append nbns_servers to dict"); - goto out; - } - } - - if (!nmu_dbus_dict_close_write (&iter, &iter_dict)) { - nm_warning ("dict close write failed!"); - goto out; - } - - if (!dbus_connection_send (data->con, signal, NULL)) - { - nm_warning ("Could not raise the "NM_DBUS_VPN_SIGNAL_IP4_CONFIG" signal!"); - goto out; - } - - dbus_message_unref (signal); - nm_openvpn_set_state (data, NM_VPN_SERVICE_STATE_STARTED); - success = TRUE; - } - -out: - if (!success) - { - nm_warning ("Received invalid IP4 Config information from helper, terminating openvpn."); - nm_openvpn_dbus_handle_stop_vpn (data); - } + return success; } - -/* - * nm_openvpn_dbus_message_handler - * - * Handle requests for our services. - * - */ -static DBusHandlerResult -nm_openvpn_dbus_message_handler (DBusConnection *con, DBusMessage *message, void *user_data) +static gboolean +real_need_secrets (NMVPNPlugin *plugin, + NMConnection *connection, + char **setting_name, + GError **error) { - NmOpenVPNData *data = (NmOpenVPNData *)user_data; - const char *method; - const char *path; - DBusMessage *reply = NULL; - gboolean handled = TRUE; + NMSettingVPNProperties *s_vpn_props; + int connection_type; + gboolean need_secrets = FALSE; - g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - g_return_val_if_fail (con != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - method = dbus_message_get_member (message); - path = dbus_message_get_path (message); - - /* nm_info ("nm_openvpn_dbus_message_handler() got method '%s' for path '%s'.", method, path); */ - - /* If we aren't ready to accept dbus messages, don't */ - if ((data->state == NM_VPN_SERVICE_STATE_INIT) || (data->state == NM_VPN_SERVICE_STATE_SHUTDOWN)) - { - nm_warning ("Received dbus messages but couldn't handle them due to INIT or SHUTDOWN states."); - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_OPENVPN, NM_DBUS_VPN_WRONG_STATE, - "Could not process the request due to current state of STATE_INIT or STATE_SHUTDOWN."); - goto reply; - } - - if (strcmp ("startConnection", method) == 0) - reply = nm_openvpn_dbus_start_vpn (con, message, data); - else if (strcmp ("stopConnection", method) == 0) - reply = nm_openvpn_dbus_stop_vpn (con, message, data); - else if (strcmp ("getState", method) == 0) - reply = nm_openvpn_dbus_get_state (con, message, data); - else if (strcmp ("signalConfigError", method) == 0) - nm_openvpn_dbus_process_helper_config_error (con, message, data); - else if (strcmp ("signalIP4Config", method) == 0) - nm_openvpn_dbus_process_helper_ip4_config (con, message, data); - else - handled = FALSE; - - reply: - if (reply) - { - dbus_connection_send (con, reply, NULL); - dbus_message_unref (reply); - } - - return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); -} - - -/* - * nm_openvpn_dbus_filter - * - * Handle signals from the bus, like NetworkManager network state - * signals. - * - */ -static DBusHandlerResult -nm_openvpn_dbus_filter (DBusConnection *con, DBusMessage *message, void *user_data) -{ - NmOpenVPNData *data = (NmOpenVPNData *)user_data; - gboolean handled = FALSE; - DBusError error; - - g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - g_return_val_if_fail (con != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - - if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) - { - char *service; - char *old_owner; - char *new_owner; - - dbus_error_init (&error); - if ( dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &service, - DBUS_TYPE_STRING, &old_owner, - DBUS_TYPE_STRING, &new_owner, - DBUS_TYPE_INVALID)) - { - gboolean old_owner_good = (old_owner && (strlen (old_owner) > 0)); - gboolean new_owner_good = (new_owner && (strlen (new_owner) > 0)); - - if ((!old_owner_good && new_owner_good) && (strcmp (service, NM_DBUS_SERVICE) == 0)) /* Equivalent to old ServiceCreated signal */ - { - } - else if ((old_owner_good && !new_owner_good) && (strcmp (service, NM_DBUS_SERVICE) == 0)) /* Equivalent to old ServiceDeleted signal */ - { - /* If NM goes away, we don't stick around */ - nm_openvpn_dbus_handle_stop_vpn (data); - g_main_loop_quit (data->loop); - } + s_vpn_props = (NMSettingVPNProperties *) nm_connection_get_setting (connection, NM_SETTING_VPN_PROPERTIES); + if (!s_vpn_props) { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID, + "%s", + "Could not process the request because the VPN connection settings were invalid."); + return FALSE; } - } - else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNoLongerActive")) - { - /* If the active device goes down our VPN is certainly not going to work. */ - nm_openvpn_dbus_handle_stop_vpn (data); - } - return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + connection_type = get_connection_type (s_vpn_props->data); + switch (connection_type) { + case NM_OPENVPN_CONTYPE_X509USERPASS: + /* Will require username and password and maybe certificate password */ + if (!g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_CERTPASS)) + need_secrets = TRUE; + /* Fall through */ + case NM_OPENVPN_CONTYPE_PASSWORD: + /* Will require username and password */ + if (!g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_USERNAME) || + !g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_PASSWORD)) + need_secrets = TRUE; + break; + case NM_OPENVPN_CONTYPE_X509: + /* May require certificate password */ + if (!g_hash_table_lookup (s_vpn_props->data, NM_OPENVPN_KEY_CERTPASS)) + need_secrets = TRUE; + break; + default: + break; + } + + if (need_secrets) + *setting_name = NM_SETTING_VPN_PROPERTIES; + + return need_secrets; } - -/* - * nm_openvpn_dbus_init - * - * Grab our connection to the system bus, return NULL if anything goes wrong. - * - */ -DBusConnection * -nm_openvpn_dbus_init (NmOpenVPNData *data) +static gboolean +real_disconnect (NMVPNPlugin *plugin, + GError **err) { - DBusConnection *connection = NULL; - DBusError error; - DBusObjectPathVTable vtable = { NULL, &nm_openvpn_dbus_message_handler, NULL, NULL, NULL, NULL }; + NMOpenvpnPluginPrivate *priv = NM_OPENVPN_PLUGIN_GET_PRIVATE (plugin); - g_return_val_if_fail (data != NULL, NULL); - - dbus_error_init (&error); - if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error))) - { - nm_warning ("Error connecting to system bus: '%s'", error.message); - goto out; - } - - dbus_connection_setup_with_g_main (connection, NULL); + if (priv->pid) { + kill (priv->pid, SIGTERM); + nm_info ("Terminated openvpn daemon with PID %d.", priv->pid); + priv->pid = 0; + } - dbus_error_init (&error); - dbus_bus_request_name (connection, NM_DBUS_SERVICE_OPENVPN, 0, &error); - if (dbus_error_is_set (&error)) - { - nm_warning ("Could not acquire the dbus service. dbus_bus_request_name() says: '%s'", error.message); - goto out; - } - - if (!dbus_connection_register_object_path (connection, NM_DBUS_PATH_OPENVPN, &vtable, data)) - { - nm_warning ("Could not register a dbus handler for nm-openvpn-service. Not enough memory?"); - return NULL; - } - - if (!dbus_connection_add_filter (connection, nm_openvpn_dbus_filter, data, NULL)) - return NULL; - - dbus_error_init (&error); - dbus_bus_add_match (connection, - "type='signal'," - "interface='" NM_DBUS_INTERFACE "'," - "sender='" NM_DBUS_SERVICE "'," - "path='" NM_DBUS_PATH "'", - &error); - if (dbus_error_is_set (&error)) - goto out; - - dbus_bus_add_match (connection, - "type='signal'," - "interface='" DBUS_INTERFACE_DBUS "'," - "sender='" DBUS_SERVICE_DBUS "'", - &error); - if (dbus_error_is_set (&error)) - goto out; - -out: - if (dbus_error_is_set (&error)) - { - dbus_error_free (&error); - connection = NULL; - } - return connection; + return TRUE; } -NmOpenVPNData *vpn_data = NULL; - static void -sigterm_handler (int signum) +nm_openvpn_plugin_init (NMOpenvpnPlugin *plugin) { - nm_info ("nm-openvpn-service caught SIGINT/SIGTERM"); - - g_main_loop_quit (vpn_data->loop); } +static void +nm_openvpn_plugin_class_init (NMOpenvpnPluginClass *plugin_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (plugin_class); + NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS (plugin_class); + + g_type_class_add_private (object_class, sizeof (NMOpenvpnPluginPrivate)); + + /* virtual methods */ + parent_class->connect = real_connect; + parent_class->need_secrets = real_need_secrets; + parent_class->disconnect = real_disconnect; +} + +NMOpenvpnPlugin * +nm_openvpn_plugin_new (void) +{ + return (NMOpenvpnPlugin *) g_object_new (NM_TYPE_OPENVPN_PLUGIN, + NM_VPN_PLUGIN_DBUS_SERVICE_NAME, + NM_DBUS_SERVICE_OPENVPN, + NULL); +} + +static void +quit_mainloop (NMVPNPlugin *plugin, gpointer user_data) +{ + g_main_loop_quit ((GMainLoop *) user_data); +} -/* - * main - * - */ int -main( int argc, char *argv[] ) +main (int argc, char *argv[]) { - struct sigaction action; - sigset_t block_mask; + NMOpenvpnPlugin *plugin; + GMainLoop *main_loop; - g_type_init (); - if (!g_thread_supported ()) - g_thread_init (NULL); + g_type_init (); - vpn_data = g_malloc0 (sizeof (NmOpenVPNData)); + if (system ("/sbin/modprobe tun") == -1) + exit (EXIT_FAILURE); - vpn_data->state = NM_VPN_SERVICE_STATE_INIT; + plugin = nm_openvpn_plugin_new (); + if (!plugin) + exit (EXIT_FAILURE); - vpn_data->loop = g_main_loop_new (NULL, FALSE); + main_loop = g_main_loop_new (NULL, FALSE); - if (system ("/sbin/modprobe tun") == -1) - exit (EXIT_FAILURE); + g_signal_connect (plugin, "quit", + G_CALLBACK (quit_mainloop), + main_loop); - if (!(vpn_data->con = nm_openvpn_dbus_init (vpn_data))) - exit (EXIT_FAILURE); + g_main_loop_run (main_loop); - action.sa_handler = sigterm_handler; - sigemptyset (&block_mask); - action.sa_mask = block_mask; - action.sa_flags = 0; - sigaction (SIGINT, &action, NULL); - sigaction (SIGTERM, &action, NULL); + g_main_loop_unref (main_loop); + g_object_unref (plugin); - nm_openvpn_set_state (vpn_data, NM_VPN_SERVICE_STATE_STOPPED); - g_main_loop_run (vpn_data->loop); - - nm_openvpn_dbus_handle_stop_vpn (vpn_data); - - g_main_loop_unref (vpn_data->loop); - g_free (vpn_data); - - exit (EXIT_SUCCESS); + exit (EXIT_SUCCESS); } diff --git a/vpn-daemons/openvpn/src/nm-openvpn-service.h b/vpn-daemons/openvpn/src/nm-openvpn-service.h index 51e08b73db..6bb79abb8c 100644 --- a/vpn-daemons/openvpn/src/nm-openvpn-service.h +++ b/vpn-daemons/openvpn/src/nm-openvpn-service.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ /* nm-openvpn-service - openvpn integration with NetworkManager * * Tim Niemueller @@ -22,9 +23,20 @@ #ifndef NM_OPENVPN_SERVICE_H #define NM_OPENVPN_SERVICE_H -#define NM_DBUS_SERVICE_OPENVPN "org.freedesktop.NetworkManager.openvpn" -#define NM_DBUS_INTERFACE_OPENVPN "org.freedesktop.NetworkManager.openvpn" -#define NM_DBUS_PATH_OPENVPN "/org/freedesktop/NetworkManager/openvpn" +#include +#include +#include + +#define NM_TYPE_OPENVPN_PLUGIN (nm_openvpn_plugin_get_type ()) +#define NM_OPENVPN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_OPENVPN_PLUGIN, NMOpenvpnPlugin)) +#define NM_OPENVPN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_OPENVPN_PLUGIN, NMOpenvpnPluginClass)) +#define NM_IS_OPENVPN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_OPENVPN_PLUGIN)) +#define NM_IS_OPENVPN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_OPENVPN_PLUGIN)) +#define NM_OPENVPN_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_OPENVPN_PLUGIN, NMOpenvpnPluginClass)) + +#define NM_DBUS_SERVICE_OPENVPN "org.freedesktop.NetworkManager.openvpn" +#define NM_DBUS_INTERFACE_OPENVPN "org.freedesktop.NetworkManager.openvpn" +#define NM_DBUS_PATH_OPENVPN "/org/freedesktop/NetworkManager/openvpn" /* Do not change numbers, only add if needed! See properties/nm-openvpn.c:connection_type_changed() for details @@ -35,5 +47,36 @@ #define NM_OPENVPN_CONTYPE_PASSWORD 2 #define NM_OPENVPN_CONTYPE_X509USERPASS 3 +#define NM_OPENVPN_KEY_CA "ca" +#define NM_OPENVPN_KEY_CERT "cert" +#define NM_OPENVPN_KEY_CIPHER "cipher" +#define NM_OPENVPN_KEY_COMP_LZO "comp-lzo" +#define NM_OPENVPN_KEY_CONNECTION_TYPE "connection-type" +#define NM_OPENVPN_KEY_TAP_DEV "dev" +#define NM_OPENVPN_KEY_KEY "key" +#define NM_OPENVPN_KEY_LOCAL_IP "local-ip" +#define NM_OPENVPN_KEY_PROTO_TCP "proto" +#define NM_OPENVPN_KEY_PORT "port" +#define NM_OPENVPN_KEY_REMOTE "remote" +#define NM_OPENVPN_KEY_REMOTE_IP "remote-ip" +#define NM_OPENVPN_KEY_SHARED_KEY "shared-key" +#define NM_OPENVPN_KEY_TA "ta" +#define NM_OPENVPN_KEY_TA_DIR "ta-dir" +#define NM_OPENVPN_KEY_USERNAME "username" -#endif +#define NM_OPENVPN_KEY_PASSWORD "password" +#define NM_OPENVPN_KEY_CERTPASS "cert-pass" + +typedef struct { + NMVPNPlugin parent; +} NMOpenvpnPlugin; + +typedef struct { + NMVPNPluginClass parent; +} NMOpenvpnPluginClass; + +GType nm_openvpn_plugin_get_type (void); + +NMOpenvpnPlugin *nm_openvpn_plugin_new (void); + +#endif /* NM_OPENVPN_SERVICE_H */