NetworkManager/vpn-daemons/openvpn/properties/nm-openvpn.c
Dan Williams 00b70f06fa 2007-02-26 Dan Williams <dcbw@redhat.com>
Patch from Jon Nettleton

	* properties/nm-openvpn-dialog.glade
	  properties/nm-openvpn.c
		- Reduce size of OpenVPN configuration dialog (Gnome.org #410669)



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2377 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2007-02-26 21:01:11 +00:00

1697 lines
58 KiB
C

/* nm-openvpn.c : GNOME UI dialogs for configuring OpenVPN connections
*
* Copyright (C) 2005 Tim Niemueller <tim@niemueller.de>
* Based on work by David Zeuthen, <davidz@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n-lib.h>
#include <string.h>
#include <glade/glade.h>
#define NM_VPN_API_SUBJECT_TO_CHANGE
#include <nm-vpn-ui-interface.h>
#include "../src/nm-openvpn-service.h"
#include "../src/nm-utils.h"
typedef struct _NetworkManagerVpnUIImpl NetworkManagerVpnUIImpl;
struct _NetworkManagerVpnUIImpl {
NetworkManagerVpnUI parent;
NetworkManagerVpnUIDialogValidityCallback callback;
gpointer callback_user_data;
gchar *last_fc_dir;
GladeXML *xml;
GtkWidget *widget;
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_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;
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);
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_expander_set_expanded (impl->w_opt_info_expander, 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_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");
}
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_expander_set_expanded (impl->w_opt_info_expander, should_expand);
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;
}
static GSList *
get_routes (NetworkManagerVpnUIImpl *impl)
{
GSList *routes;
const char *routes_entry;
gboolean use_routes;
char **substrs;
unsigned int i;
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));
if (!use_routes)
goto out;
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));
}
g_strfreev (substrs);
out:
return routes;
}
static GSList *
impl_get_routes (NetworkManagerVpnUI *self)
{
NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data;
return get_routes (impl);
}
/** Checks if port is an integer and
* less than 65
*/
static gboolean
check_port (const char *port)
{
int d;
if (sscanf (port, "%d", &d) != 1) {
return FALSE;
}
if (d < 1 || d > 65536 ) {
return FALSE;
}
return TRUE;
}
/** Checks if ip is in notation
* a.b.c.d where a,b,c,d in {0..255}
*/
static gboolean
check_ip (const char *ip)
{
int d1, d2, d3, d4;
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 ) {
return FALSE;
}
return TRUE;
}
/** Checks if net cidr is in notation
* a.b.c.d/n where a,b,c,d in {0..255} and
* n in {0..32}
*/
static gboolean
check_net_cidr (const char *net)
{
int d1, d2, d3, d4, mask;
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;
}
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;
}
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));
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;
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;
} 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);
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;
}
} else if ( connection_type == NM_OPENVPN_CONTYPE_PASSWORD ) {
const char *username;
const char *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) ) {
is_valid = TRUE;
}
} else if ( connection_type == NM_OPENVPN_CONTYPE_X509USERPASS ) {
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);
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;
}
} 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);
/* 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;
}
}
/* 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);
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);
}
}
return is_valid;
}
static void
use_editable_toggled (GtkToggleButton *togglebutton, gpointer 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_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;
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;
if (impl->callback != NULL) {
gboolean is_valid;
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)));
}
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_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)
{
NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->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;
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);
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 ) {
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, "\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, _("Key: %s"), key);
break;
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, _("Local IP: %s"), local_ip);
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"));
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;
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, "\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, _("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, _("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, _("Device: %s"), ((use_tap) ? _("TAP") : _("TUN")));
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);
}
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_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");
*retval = g_string_free (buf, FALSE);
}
static gboolean
import_from_file (NetworkManagerVpnUIImpl *impl, const char *path)
{
char *basename;
GKeyFile *keyfile;
gboolean file_is_good;
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;
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 ("");
/* 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
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;
}
} 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_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);
}
gtk_expander_set_expanded (impl->w_opt_info_expander, should_expand);
} 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;
}
static void
import_button_clicked (GtkButton *button, gpointer user_data)
{
char *filename = NULL;
GtkWidget *dialog;
NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) 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);
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);*/
}
gtk_widget_destroy (dialog);
if (filename != NULL) {
import_from_file (impl, filename);
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 );
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;
const char *msg;
GtkEntry *entry;
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;
}
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 (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);
}
static gboolean
impl_can_export (NetworkManagerVpnUI *self)
{
return TRUE;
}
static gboolean
impl_import_file (NetworkManagerVpnUI *self, const char *path)
{
NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data;
return import_from_file (impl, path);
}
static gboolean
export_to_file (NetworkManagerVpnUIImpl *impl, const char *path,
GSList *properties, GSList *routes, const char *connection_name)
{
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;
/*printf ("in export_to_file; path='%s'\n", path);*/
for (i = properties; i != NULL && g_slist_next (i) != NULL; i = g_slist_next (g_slist_next (i))) {
const char *k;
const char *value;
k = i->data;
value = (g_slist_next (i))->data;
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;
}
}
if (routes != NULL) {
GString *str;
str = g_string_new ("");
for (i = routes; i != NULL; i = g_slist_next (i)) {
const char *route;
if (i != routes)
g_string_append_c (str, ' ');
route = (const char *) i->data;
g_string_append (str, route);
}
g_string_append_c (str, '\n');
routes_str = g_string_free (str, FALSE);
}
f = fopen (path, "w");
if (f != NULL) {
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;
}
static gboolean
impl_export (NetworkManagerVpnUI *self, GSList *properties, GSList *routes, const char *connection_name)
{
char *suggested_name;
char *path = NULL;
GtkWidget *dialog;
NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data;
/*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);
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);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
{
path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
/* printf ("User selected '%s'\n", path); */
}
gtk_widget_destroy (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;
}
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);
}
}
out:
g_free (path);
return TRUE;
}
static void
populate_cipher(GtkComboBox *box)
{
const char *openvpn_binary = NULL;
gchar *cmdline, *tmp, *token;
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;
token = strtok(tmp, "\n");
while (token) {
if (strlen(token))
gtk_combo_box_append_text(box, token);
token = strtok(NULL, "\n");
}
end:
g_free(tmp);
}
static NetworkManagerVpnUI*
impl_get_object (void)
{
char *glade_file;
NetworkManagerVpnUIImpl *impl;
impl = g_new0 (NetworkManagerVpnUIImpl, 1);
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) {
impl->widget = glade_xml_get_widget(impl->xml, "nm-openvpn-widget");
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_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_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_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_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_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_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_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;
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_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_import_button),
"clicked", GTK_SIGNAL_FUNC (import_button_clicked), 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);
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;
return &(impl->parent);
} else {
g_free (impl);
return NULL;
}
}
NetworkManagerVpnUI*
nm_vpn_properties_factory (void)
{
return impl_get_object();
}