272f79a3c8dd37ae7ea8392ba6e5e2900f6dee7e
[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-vpn-properties.h>
38 #include <nm-setting-connection.h>
39 #include <nm-setting-ip4-config.h>
40
41 #include "nm-strongswan.h"
42
43 #define STRONGSWAN_PLUGIN_NAME _("IPsec/IKEv2 (strongswan)")
44 #define STRONGSWAN_PLUGIN_DESC _("IPsec with the IKEv2 key exchange protocol.")
45 #define STRONGSWAN_PLUGIN_SERVICE "org.freedesktop.NetworkManager.strongswan"
46 #define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
47
48 /************** plugin class **************/
49
50 static void strongswan_plugin_ui_interface_init (NMVpnPluginUiInterface *iface_class);
51
52 G_DEFINE_TYPE_EXTENDED (StrongswanPluginUi, strongswan_plugin_ui, G_TYPE_OBJECT, 0,
53 G_IMPLEMENT_INTERFACE (NM_TYPE_VPN_PLUGIN_UI_INTERFACE,
54 strongswan_plugin_ui_interface_init))
55
56 #define STRONGSWAN_PLUGIN_UI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), STRONGSWAN_TYPE_PLUGIN_UI, StrongswanPluginUiPrivate))
57
58 typedef struct {
59 } StrongswanPluginUiPrivate;
60
61
62 /************** UI widget class **************/
63
64 static void strongswan_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface *iface_class);
65
66 G_DEFINE_TYPE_EXTENDED (StrongswanPluginUiWidget, strongswan_plugin_ui_widget, G_TYPE_OBJECT, 0,
67 G_IMPLEMENT_INTERFACE (NM_TYPE_VPN_PLUGIN_UI_WIDGET_INTERFACE,
68 strongswan_plugin_ui_widget_interface_init))
69
70 #define STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), STRONGSWAN_TYPE_PLUGIN_UI_WIDGET, StrongswanPluginUiWidgetPrivate))
71
72 typedef struct {
73 GladeXML *xml;
74 GtkWidget *widget;
75 } StrongswanPluginUiWidgetPrivate;
76
77
78 #define STRONGSWAN_PLUGIN_UI_ERROR strongswan_plugin_ui_error_quark ()
79
80 static GQuark
81 strongswan_plugin_ui_error_quark (void)
82 {
83 static GQuark error_quark = 0;
84
85 if (G_UNLIKELY (error_quark == 0))
86 error_quark = g_quark_from_static_string ("strongswan-plugin-ui-error-quark");
87
88 return error_quark;
89 }
90
91 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
92
93 GType
94 strongswan_plugin_ui_error_get_type (void)
95 {
96 static GType etype = 0;
97
98 if (etype == 0) {
99 static const GEnumValue values[] = {
100 /* Unknown error. */
101 ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_UNKNOWN, "UnknownError"),
102 /* The specified property was invalid. */
103 ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_INVALID_PROPERTY, "InvalidProperty"),
104 /* The specified property was missing and is required. */
105 ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_MISSING_PROPERTY, "MissingProperty"),
106 { 0, 0, 0 }
107 };
108 etype = g_enum_register_static ("StrongswanPluginUiError", values);
109 }
110 return etype;
111 }
112
113 static gboolean
114 check_validity (StrongswanPluginUiWidget *self, GError **error)
115 {
116 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
117 GtkWidget *widget;
118 char *str;
119
120 widget = glade_xml_get_widget (priv->xml, "address-entry");
121 str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
122 if (!str || !strlen (str)) {
123 g_set_error (error,
124 STRONGSWAN_PLUGIN_UI_ERROR,
125 STRONGSWAN_PLUGIN_UI_ERROR_INVALID_PROPERTY,
126 "address");
127 return FALSE;
128 }
129
130 widget = glade_xml_get_widget (priv->xml, "user-entry");
131 str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
132 if (!str || !strlen (str)) {
133 g_set_error (error,
134 STRONGSWAN_PLUGIN_UI_ERROR,
135 STRONGSWAN_PLUGIN_UI_ERROR_INVALID_PROPERTY,
136 "user");
137 return FALSE;
138 }
139
140 return TRUE;
141 }
142
143 static void
144 stuff_changed_cb (GtkWidget *widget, gpointer user_data)
145 {
146 g_signal_emit_by_name (STRONGSWAN_PLUGIN_UI_WIDGET (user_data), "changed");
147 }
148
149 static gboolean
150 init_plugin_ui (StrongswanPluginUiWidget *self, NMConnection *connection, GError **error)
151 {
152 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
153 NMSettingVPNProperties *s_vpn_props;
154 GtkWidget *widget;
155 GValue *value;
156 gboolean active;
157
158 s_vpn_props = (NMSettingVPNProperties *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN_PROPERTIES);
159
160
161 widget = glade_xml_get_widget (priv->xml, "address-entry");
162 if (!widget)
163 return FALSE;
164 if (s_vpn_props) {
165 value = g_hash_table_lookup (s_vpn_props->data, "address");
166 if (value && G_VALUE_HOLDS_STRING (value))
167 gtk_entry_set_text (GTK_ENTRY (widget), g_value_get_string (value));
168 }
169 g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
170
171 widget = glade_xml_get_widget (priv->xml, "user-entry");
172 if (!widget)
173 return FALSE;
174 if (s_vpn_props) {
175 value = g_hash_table_lookup (s_vpn_props->data, "user");
176 if (value && G_VALUE_HOLDS_STRING (value))
177 gtk_entry_set_text (GTK_ENTRY (widget), g_value_get_string (value));
178 }
179 g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
180
181 widget = glade_xml_get_widget (priv->xml, "virtual-check");
182 if (!widget)
183 return FALSE;
184 active = TRUE;
185 if (s_vpn_props) {
186 value = g_hash_table_lookup (s_vpn_props->data, "virtual");
187 if (value && G_VALUE_HOLDS_BOOLEAN (value))
188 active = g_value_get_boolean (value);
189 }
190 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), active);
191 g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
192
193 widget = glade_xml_get_widget (priv->xml, "encap-check");
194 if (!widget)
195 return FALSE;
196 active = TRUE;
197 if (s_vpn_props) {
198 value = g_hash_table_lookup (s_vpn_props->data, "encap");
199 if (value && G_VALUE_HOLDS_BOOLEAN (value))
200 active = g_value_get_boolean (value);
201 }
202 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), active);
203 g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
204
205 widget = glade_xml_get_widget (priv->xml, "ipcomp-check");
206 if (!widget)
207 return FALSE;
208 active = FALSE;
209 if (s_vpn_props) {
210 value = g_hash_table_lookup (s_vpn_props->data, "ipcomp");
211 if (value && G_VALUE_HOLDS_BOOLEAN (value))
212 active = g_value_get_boolean (value);
213 }
214 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), active);
215 g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
216
217 return TRUE;
218 }
219
220 static GObject *
221 get_widget (NMVpnPluginUiWidgetInterface *iface)
222 {
223 StrongswanPluginUiWidget *self = STRONGSWAN_PLUGIN_UI_WIDGET (iface);
224 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
225
226 return G_OBJECT (priv->widget);
227 }
228
229 static GValue *
230 str_to_gvalue (const char *str)
231 {
232 GValue *value;
233
234 value = g_slice_new0 (GValue);
235 g_value_init (value, G_TYPE_STRING);
236 g_value_set_string (value, str);
237
238 return value;
239 }
240
241 static GValue *
242 bool_to_gvalue (gboolean b)
243 {
244 GValue *value;
245
246 value = g_slice_new0 (GValue);
247 g_value_init (value, G_TYPE_BOOLEAN);
248 g_value_set_boolean (value, b);
249
250 return value;
251 }
252
253 static GValue *
254 int_to_gvalue (gint i)
255 {
256 GValue *value;
257
258 value = g_slice_new0 (GValue);
259 g_value_init (value, G_TYPE_INT);
260 g_value_set_int (value, i);
261
262 return value;
263 }
264
265 static gboolean
266 update_connection (NMVpnPluginUiWidgetInterface *iface,
267 NMConnection *connection,
268 GError **error)
269 {
270 StrongswanPluginUiWidget *self = STRONGSWAN_PLUGIN_UI_WIDGET (iface);
271 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
272 NMSettingVPN *s_vpn;
273 NMSettingVPNProperties *s_vpn_props;
274 GtkWidget *widget;
275 GValue *value;
276 gboolean active;
277 char *str;
278 GtkTreeModel *model;
279 GtkTreeIter iter;
280
281 if (!check_validity (self, error))
282 return FALSE;
283
284 s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ());
285 s_vpn->service_type = g_strdup (NM_DBUS_SERVICE_STRONGSWAN);
286 nm_connection_add_setting (connection, NM_SETTING (s_vpn));
287
288 s_vpn_props = NM_SETTING_VPN_PROPERTIES (nm_setting_vpn_properties_new ());
289
290 widget = glade_xml_get_widget (priv->xml, "address-entry");
291 str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
292 if (str && strlen (str)) {
293 g_hash_table_insert (s_vpn_props->data,
294 g_strdup ("address"),
295 str_to_gvalue (str));
296 }
297
298 widget = glade_xml_get_widget (priv->xml, "user-entry");
299 str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
300 if (str && strlen (str)) {
301 g_hash_table_insert (s_vpn_props->data,
302 g_strdup ("user"),
303 str_to_gvalue (str));
304 }
305
306 widget = glade_xml_get_widget (priv->xml, "virtual-check");
307 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
308 g_hash_table_insert (s_vpn_props->data, g_strdup ("virtual"),
309 bool_to_gvalue(active));
310
311 widget = glade_xml_get_widget (priv->xml, "encap-check");
312 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
313 g_hash_table_insert (s_vpn_props->data, g_strdup ("encap"),
314 bool_to_gvalue(active));
315
316 widget = glade_xml_get_widget (priv->xml, "ipcomp-check");
317 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
318 g_hash_table_insert (s_vpn_props->data, g_strdup ("ipcomp"),
319 bool_to_gvalue(active));
320
321 nm_connection_add_setting (connection, NM_SETTING (s_vpn_props));
322 return TRUE;
323 }
324
325 static NMVpnPluginUiWidgetInterface *
326 nm_vpn_plugin_ui_widget_interface_new (NMConnection *connection, GError **error)
327 {
328 NMVpnPluginUiWidgetInterface *object;
329 StrongswanPluginUiWidgetPrivate *priv;
330 char *glade_file;
331
332 if (error)
333 g_return_val_if_fail (*error == NULL, NULL);
334
335 object = NM_VPN_PLUGIN_UI_WIDGET_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI_WIDGET, NULL));
336 if (!object) {
337 g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0, "could not create strongswan object");
338 return NULL;
339 }
340
341 priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (object);
342
343 glade_file = g_strdup_printf ("%s/%s", GLADEDIR, "nm-strongswan-dialog.glade");
344 priv->xml = glade_xml_new (glade_file, "strongswan-vbox", GETTEXT_PACKAGE);
345 if (priv->xml == NULL) {
346 g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0,
347 "could not load required resources at %s", glade_file);
348 g_free (glade_file);
349 g_object_unref (object);
350 return NULL;
351 }
352 g_free (glade_file);
353
354 priv->widget = glade_xml_get_widget (priv->xml, "strongswan-vbox");
355 if (!priv->widget) {
356 g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0, "could not load UI widget");
357 g_object_unref (object);
358 return NULL;
359 }
360 g_object_ref_sink (priv->widget);
361
362 if (!init_plugin_ui (STRONGSWAN_PLUGIN_UI_WIDGET (object), connection, error)) {
363 g_object_unref (object);
364 return NULL;
365 }
366
367 return object;
368 }
369
370 static void
371 dispose (GObject *object)
372 {
373 StrongswanPluginUiWidget *plugin = STRONGSWAN_PLUGIN_UI_WIDGET (object);
374 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (plugin);
375
376 if (priv->widget)
377 g_object_unref (priv->widget);
378
379 if (priv->xml)
380 g_object_unref (priv->xml);
381
382 G_OBJECT_CLASS (strongswan_plugin_ui_widget_parent_class)->dispose (object);
383 }
384
385 static void
386 strongswan_plugin_ui_widget_class_init (StrongswanPluginUiWidgetClass *req_class)
387 {
388 GObjectClass *object_class = G_OBJECT_CLASS (req_class);
389
390 g_type_class_add_private (req_class, sizeof (StrongswanPluginUiWidgetPrivate));
391
392 object_class->dispose = dispose;
393 }
394
395 static void
396 strongswan_plugin_ui_widget_init (StrongswanPluginUiWidget *plugin)
397 {
398 }
399
400 static void
401 strongswan_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface *iface_class)
402 {
403 /* interface implementation */
404 iface_class->get_widget = get_widget;
405 iface_class->update_connection = update_connection;
406 }
407
408 static guint32
409 get_capabilities (NMVpnPluginUiInterface *iface)
410 {
411 return 0;
412 }
413
414 static NMVpnPluginUiWidgetInterface *
415 ui_factory (NMVpnPluginUiInterface *iface, NMConnection *connection, GError **error)
416 {
417 return nm_vpn_plugin_ui_widget_interface_new (connection, error);
418 }
419
420 static void
421 get_property (GObject *object, guint prop_id,
422 GValue *value, GParamSpec *pspec)
423 {
424 switch (prop_id) {
425 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME:
426 g_value_set_string (value, STRONGSWAN_PLUGIN_NAME);
427 break;
428 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC:
429 g_value_set_string (value, STRONGSWAN_PLUGIN_DESC);
430 break;
431 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE:
432 g_value_set_string (value, STRONGSWAN_PLUGIN_SERVICE);
433 break;
434 default:
435 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
436 break;
437 }
438 }
439
440 static void
441 strongswan_plugin_ui_class_init (StrongswanPluginUiClass *req_class)
442 {
443 GObjectClass *object_class = G_OBJECT_CLASS (req_class);
444
445 g_type_class_add_private (req_class, sizeof (StrongswanPluginUiPrivate));
446
447 object_class->get_property = get_property;
448
449 g_object_class_override_property (object_class,
450 NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME,
451 NM_VPN_PLUGIN_UI_INTERFACE_NAME);
452
453 g_object_class_override_property (object_class,
454 NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC,
455 NM_VPN_PLUGIN_UI_INTERFACE_DESC);
456
457 g_object_class_override_property (object_class,
458 NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE,
459 NM_VPN_PLUGIN_UI_INTERFACE_SERVICE);
460 }
461
462 static void
463 strongswan_plugin_ui_init (StrongswanPluginUi *plugin)
464 {
465 }
466
467 static void
468 strongswan_plugin_ui_interface_init (NMVpnPluginUiInterface *iface_class)
469 {
470 /* interface implementation */
471 iface_class->ui_factory = ui_factory;
472 iface_class->get_capabilities = get_capabilities;
473 }
474
475
476 G_MODULE_EXPORT NMVpnPluginUiInterface *
477 nm_vpn_plugin_ui_factory (GError **error)
478 {
479 if (error)
480 g_return_val_if_fail (*error == NULL, NULL);
481
482 return NM_VPN_PLUGIN_UI_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI, NULL));
483 }
484