edaaf030242c09cca886f11eeaeb3e0868d78f1f
[strongswan.git] / src / charon / plugins / nm / gnome / properties / nm-strongswan.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 * Copyright (C) 2005 David Zeuthen
5 * Copyright (C) 2005-2008 Dan Williams
6 *
7 * Based on NetworkManager's vpnc plugin
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * for more details.
18 *
19 * $Id$
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <glib/gi18n-lib.h>
29 #include <string.h>
30 #include <gtk/gtk.h>
31 #include <glade/glade.h>
32
33 #define NM_VPN_API_SUBJECT_TO_CHANGE
34
35 #include <nm-vpn-plugin-ui-interface.h>
36 #include <nm-setting-vpn.h>
37 #include <nm-setting-connection.h>
38 #include <nm-setting-ip4-config.h>
39
40 #include "nm-strongswan.h"
41
42 #define STRONGSWAN_PLUGIN_NAME _("IPsec/IKEv2 (strongswan)")
43 #define STRONGSWAN_PLUGIN_DESC _("IPsec with the IKEv2 key exchange protocol.")
44 #define STRONGSWAN_PLUGIN_SERVICE "org.freedesktop.NetworkManager.strongswan"
45 #define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
46
47 /************** plugin class **************/
48
49 static void strongswan_plugin_ui_interface_init (NMVpnPluginUiInterface *iface_class);
50
51 G_DEFINE_TYPE_EXTENDED (StrongswanPluginUi, strongswan_plugin_ui, G_TYPE_OBJECT, 0,
52 G_IMPLEMENT_INTERFACE (NM_TYPE_VPN_PLUGIN_UI_INTERFACE,
53 strongswan_plugin_ui_interface_init))
54
55 /************** UI widget class **************/
56
57 static void strongswan_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface *iface_class);
58
59 G_DEFINE_TYPE_EXTENDED (StrongswanPluginUiWidget, strongswan_plugin_ui_widget, G_TYPE_OBJECT, 0,
60 G_IMPLEMENT_INTERFACE (NM_TYPE_VPN_PLUGIN_UI_WIDGET_INTERFACE,
61 strongswan_plugin_ui_widget_interface_init))
62
63 #define STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), STRONGSWAN_TYPE_PLUGIN_UI_WIDGET, StrongswanPluginUiWidgetPrivate))
64
65 typedef struct {
66 GladeXML *xml;
67 GtkWidget *widget;
68 } StrongswanPluginUiWidgetPrivate;
69
70
71 #define STRONGSWAN_PLUGIN_UI_ERROR strongswan_plugin_ui_error_quark ()
72
73 static GQuark
74 strongswan_plugin_ui_error_quark (void)
75 {
76 static GQuark error_quark = 0;
77
78 if (G_UNLIKELY (error_quark == 0))
79 error_quark = g_quark_from_static_string ("strongswan-plugin-ui-error-quark");
80
81 return error_quark;
82 }
83
84 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
85
86 GType
87 strongswan_plugin_ui_error_get_type (void)
88 {
89 static GType etype = 0;
90
91 if (etype == 0) {
92 static const GEnumValue values[] = {
93 /* Unknown error. */
94 ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_UNKNOWN, "UnknownError"),
95 /* The specified property was invalid. */
96 ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_INVALID_PROPERTY, "InvalidProperty"),
97 /* The specified property was missing and is required. */
98 ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_MISSING_PROPERTY, "MissingProperty"),
99 { 0, 0, 0 }
100 };
101 etype = g_enum_register_static ("StrongswanPluginUiError", values);
102 }
103 return etype;
104 }
105
106 static gboolean
107 check_validity (StrongswanPluginUiWidget *self, GError **error)
108 {
109 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
110 GtkWidget *widget;
111 char *str;
112
113 widget = glade_xml_get_widget (priv->xml, "address-entry");
114 str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
115 if (!str || !strlen (str)) {
116 g_set_error (error,
117 STRONGSWAN_PLUGIN_UI_ERROR,
118 STRONGSWAN_PLUGIN_UI_ERROR_INVALID_PROPERTY,
119 "address");
120 return FALSE;
121 }
122
123 widget = glade_xml_get_widget (priv->xml, "user-entry");
124 str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
125 if (!str || !strlen (str)) {
126 g_set_error (error,
127 STRONGSWAN_PLUGIN_UI_ERROR,
128 STRONGSWAN_PLUGIN_UI_ERROR_INVALID_PROPERTY,
129 "user");
130 return FALSE;
131 }
132
133 return TRUE;
134 }
135
136 static void
137 stuff_changed_cb (GtkWidget *widget, gpointer user_data)
138 {
139 g_signal_emit_by_name (STRONGSWAN_PLUGIN_UI_WIDGET (user_data), "changed");
140 }
141
142 static gboolean
143 init_plugin_ui (StrongswanPluginUiWidget *self, NMConnection *connection, GError **error)
144 {
145 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
146 NMSettingVPN *settings;
147 GtkWidget *widget;
148 char *value;
149 gboolean active;
150
151 settings = NM_SETTING_VPN(nm_connection_get_setting(connection, NM_TYPE_SETTING_VPN));
152 if (!settings)
153 return FALSE;
154 widget = glade_xml_get_widget (priv->xml, "address-entry");
155 if (!widget)
156 return FALSE;
157 value = g_hash_table_lookup (settings->data, "address");
158 if (value)
159 gtk_entry_set_text (GTK_ENTRY (widget), value);
160 g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
161
162 widget = glade_xml_get_widget (priv->xml, "certificate-button");
163 if (!widget)
164 return FALSE;
165 value = g_hash_table_lookup (settings->data, "certificate");
166 if (value)
167 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
168 g_signal_connect (G_OBJECT (widget), "selection-changed", G_CALLBACK (stuff_changed_cb), self);
169
170 widget = glade_xml_get_widget (priv->xml, "user-entry");
171 if (!widget)
172 return FALSE;
173 value = g_hash_table_lookup (settings->data, "user");
174 if (value)
175 gtk_entry_set_text (GTK_ENTRY (widget), value);
176 g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
177
178 widget = glade_xml_get_widget (priv->xml, "method-combo");
179 if (!widget)
180 return FALSE;
181 gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("EAP"));
182 gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("PSK (insecure)"));
183 value = g_hash_table_lookup (settings->data, "method");
184 if (value) {
185 if (g_strcasecmp (value, "eap") == 0) {
186 gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
187 }
188 if (g_strcasecmp (value, "psk") == 0) {
189 gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
190 }
191 }
192 g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
193 if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == -1)
194 { /* default to EAP */
195 gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
196 }
197
198 widget = glade_xml_get_widget (priv->xml, "virtual-check");
199 if (!widget)
200 return FALSE;
201 value = g_hash_table_lookup (settings->data, "virtual");
202 if (value && strcmp(value, "yes") == 0)
203 {
204 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
205 }
206 g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
207
208 widget = glade_xml_get_widget (priv->xml, "encap-check");
209 if (!widget)
210 return FALSE;
211 value = g_hash_table_lookup (settings->data, "encap");
212 if (value && strcmp(value, "yes") == 0)
213 {
214 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
215 }
216 g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
217
218 widget = glade_xml_get_widget (priv->xml, "ipcomp-check");
219 if (!widget)
220 return FALSE;
221 value = g_hash_table_lookup (settings->data, "ipcomp");
222 if (value && strcmp(value, "yes") == 0)
223 {
224 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
225 }
226 g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
227
228 return TRUE;
229 }
230
231 static GObject *
232 get_widget (NMVpnPluginUiWidgetInterface *iface)
233 {
234 StrongswanPluginUiWidget *self = STRONGSWAN_PLUGIN_UI_WIDGET (iface);
235 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
236
237 return G_OBJECT (priv->widget);
238 }
239
240 static gboolean
241 update_connection (NMVpnPluginUiWidgetInterface *iface,
242 NMConnection *connection,
243 GError **error)
244 {
245 StrongswanPluginUiWidget *self = STRONGSWAN_PLUGIN_UI_WIDGET (iface);
246 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
247 NMSettingVPN *settings;
248 GtkWidget *widget;
249 GValue *value;
250 gboolean active;
251 char *str;
252 GtkTreeModel *model;
253 GtkTreeIter iter;
254
255 if (!check_validity (self, error))
256 return FALSE;
257 settings = NM_SETTING_VPN (nm_setting_vpn_new ());
258 settings->service_type = g_strdup (NM_DBUS_SERVICE_STRONGSWAN);
259
260 widget = glade_xml_get_widget (priv->xml, "address-entry");
261 str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
262 if (str && strlen (str)) {
263 g_hash_table_insert (settings->data, g_strdup ("address"), g_strdup(str));
264 }
265
266 widget = glade_xml_get_widget (priv->xml, "certificate-button");
267 str = (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
268 if (str) {
269 g_hash_table_insert (settings->data, g_strdup ("certificate"), g_strdup(str));
270 }
271
272 widget = glade_xml_get_widget (priv->xml, "user-entry");
273 str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
274 if (str && strlen (str)) {
275 g_hash_table_insert (settings->data, g_strdup ("user"), g_strdup(str));
276 }
277
278 widget = glade_xml_get_widget (priv->xml, "method-combo");
279 switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)))
280 {
281 default:
282 str = "eap";
283 break;
284 case 1:
285 str = "psk";
286 break;
287 case 2:
288 str = "pubkey";
289 break;
290 }
291 g_hash_table_insert (settings->data, g_strdup ("method"), g_strdup(str));
292
293 widget = glade_xml_get_widget (priv->xml, "virtual-check");
294 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
295 g_hash_table_insert (settings->data, g_strdup ("virtual"),
296 g_strdup(active ? "yes" : "no"));
297
298 widget = glade_xml_get_widget (priv->xml, "encap-check");
299 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
300 g_hash_table_insert (settings->data, g_strdup ("encap"),
301 g_strdup(active ? "yes" : "no"));
302
303 widget = glade_xml_get_widget (priv->xml, "ipcomp-check");
304 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
305 g_hash_table_insert (settings->data, g_strdup ("ipcomp"),
306 g_strdup(active ? "yes" : "no"));
307
308 nm_connection_add_setting (connection, NM_SETTING (settings));
309 return TRUE;
310 }
311
312 static NMVpnPluginUiWidgetInterface *
313 nm_vpn_plugin_ui_widget_interface_new (NMConnection *connection, GError **error)
314 {
315 NMVpnPluginUiWidgetInterface *object;
316 StrongswanPluginUiWidgetPrivate *priv;
317 char *glade_file;
318
319 if (error)
320 g_return_val_if_fail (*error == NULL, NULL);
321
322 object = NM_VPN_PLUGIN_UI_WIDGET_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI_WIDGET, NULL));
323 if (!object) {
324 g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0, "could not create strongswan object");
325 return NULL;
326 }
327
328 priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (object);
329
330 glade_file = g_strdup_printf ("%s/%s", GLADEDIR, "nm-strongswan-dialog.glade");
331 priv->xml = glade_xml_new (glade_file, "strongswan-vbox", GETTEXT_PACKAGE);
332 if (priv->xml == NULL) {
333 g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0,
334 "could not load required resources at %s", glade_file);
335 g_free (glade_file);
336 g_object_unref (object);
337 return NULL;
338 }
339 g_free (glade_file);
340
341 priv->widget = glade_xml_get_widget (priv->xml, "strongswan-vbox");
342 if (!priv->widget) {
343 g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0, "could not load UI widget");
344 g_object_unref (object);
345 return NULL;
346 }
347 g_object_ref_sink (priv->widget);
348
349 if (!init_plugin_ui (STRONGSWAN_PLUGIN_UI_WIDGET (object), connection, error)) {
350 g_object_unref (object);
351 return NULL;
352 }
353
354 return object;
355 }
356
357 static void
358 dispose (GObject *object)
359 {
360 StrongswanPluginUiWidget *plugin = STRONGSWAN_PLUGIN_UI_WIDGET (object);
361 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (plugin);
362
363 if (priv->widget)
364 g_object_unref (priv->widget);
365
366 if (priv->xml)
367 g_object_unref (priv->xml);
368
369 G_OBJECT_CLASS (strongswan_plugin_ui_widget_parent_class)->dispose (object);
370 }
371
372 static void
373 strongswan_plugin_ui_widget_class_init (StrongswanPluginUiWidgetClass *req_class)
374 {
375 GObjectClass *object_class = G_OBJECT_CLASS (req_class);
376
377 g_type_class_add_private (req_class, sizeof (StrongswanPluginUiWidgetPrivate));
378
379 object_class->dispose = dispose;
380 }
381
382 static void
383 strongswan_plugin_ui_widget_init (StrongswanPluginUiWidget *plugin)
384 {
385 }
386
387 static void
388 strongswan_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface *iface_class)
389 {
390 /* interface implementation */
391 iface_class->get_widget = get_widget;
392 iface_class->update_connection = update_connection;
393 }
394
395 static guint32
396 get_capabilities (NMVpnPluginUiInterface *iface)
397 {
398 return 0;
399 }
400
401 static NMVpnPluginUiWidgetInterface *
402 ui_factory (NMVpnPluginUiInterface *iface, NMConnection *connection, GError **error)
403 {
404 return nm_vpn_plugin_ui_widget_interface_new (connection, error);
405 }
406
407 static void
408 get_property (GObject *object, guint prop_id,
409 GValue *value, GParamSpec *pspec)
410 {
411 switch (prop_id) {
412 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME:
413 g_value_set_string (value, STRONGSWAN_PLUGIN_NAME);
414 break;
415 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC:
416 g_value_set_string (value, STRONGSWAN_PLUGIN_DESC);
417 break;
418 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE:
419 g_value_set_string (value, STRONGSWAN_PLUGIN_SERVICE);
420 break;
421 default:
422 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
423 break;
424 }
425 }
426
427 static void
428 strongswan_plugin_ui_class_init (StrongswanPluginUiClass *req_class)
429 {
430 GObjectClass *object_class = G_OBJECT_CLASS (req_class);
431
432 object_class->get_property = get_property;
433
434 g_object_class_override_property (object_class,
435 NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME,
436 NM_VPN_PLUGIN_UI_INTERFACE_NAME);
437
438 g_object_class_override_property (object_class,
439 NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC,
440 NM_VPN_PLUGIN_UI_INTERFACE_DESC);
441
442 g_object_class_override_property (object_class,
443 NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE,
444 NM_VPN_PLUGIN_UI_INTERFACE_SERVICE);
445 }
446
447 static void
448 strongswan_plugin_ui_init (StrongswanPluginUi *plugin)
449 {
450 }
451
452 static void
453 strongswan_plugin_ui_interface_init (NMVpnPluginUiInterface *iface_class)
454 {
455 /* interface implementation */
456 iface_class->ui_factory = ui_factory;
457 iface_class->get_capabilities = get_capabilities;
458 }
459
460
461 G_MODULE_EXPORT NMVpnPluginUiInterface *
462 nm_vpn_plugin_ui_factory (GError **error)
463 {
464 if (error)
465 g_return_val_if_fail (*error == NULL, NULL);
466
467 return NM_VPN_PLUGIN_UI_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI, NULL));
468 }
469