285a7f7b4450f559c930b71283dd59d28d7e84d0
[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 value = g_hash_table_lookup (settings->data, "method");
183 if (value) {
184 if (g_strcasecmp (value, "EAP") == 0) {
185 gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
186 }
187 }
188 g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
189 if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == -1)
190 { /* default to EAP */
191 gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
192 }
193
194 widget = glade_xml_get_widget (priv->xml, "virtual-check");
195 if (!widget)
196 return FALSE;
197 value = g_hash_table_lookup (settings->data, "virtual");
198 if (value && strcmp(value, "yes") == 0)
199 {
200 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
201 }
202 g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
203
204 widget = glade_xml_get_widget (priv->xml, "encap-check");
205 if (!widget)
206 return FALSE;
207 value = g_hash_table_lookup (settings->data, "encap");
208 if (value && strcmp(value, "yes") == 0)
209 {
210 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
211 }
212 g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
213
214 widget = glade_xml_get_widget (priv->xml, "ipcomp-check");
215 if (!widget)
216 return FALSE;
217 value = g_hash_table_lookup (settings->data, "ipcomp");
218 if (value && strcmp(value, "yes") == 0)
219 {
220 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
221 }
222 g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
223
224 return TRUE;
225 }
226
227 static GObject *
228 get_widget (NMVpnPluginUiWidgetInterface *iface)
229 {
230 StrongswanPluginUiWidget *self = STRONGSWAN_PLUGIN_UI_WIDGET (iface);
231 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
232
233 return G_OBJECT (priv->widget);
234 }
235
236 static gboolean
237 update_connection (NMVpnPluginUiWidgetInterface *iface,
238 NMConnection *connection,
239 GError **error)
240 {
241 StrongswanPluginUiWidget *self = STRONGSWAN_PLUGIN_UI_WIDGET (iface);
242 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
243 NMSettingVPN *settings;
244 GtkWidget *widget;
245 GValue *value;
246 gboolean active;
247 char *str;
248 GtkTreeModel *model;
249 GtkTreeIter iter;
250
251 if (!check_validity (self, error))
252 return FALSE;
253 settings = NM_SETTING_VPN (nm_setting_vpn_new ());
254 settings->service_type = g_strdup (NM_DBUS_SERVICE_STRONGSWAN);
255
256 widget = glade_xml_get_widget (priv->xml, "address-entry");
257 str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
258 if (str && strlen (str)) {
259 g_hash_table_insert (settings->data, g_strdup ("address"), g_strdup(str));
260 }
261
262 widget = glade_xml_get_widget (priv->xml, "certificate-button");
263 str = (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
264 if (str) {
265 g_hash_table_insert (settings->data, g_strdup ("certificate"), g_strdup(str));
266 }
267
268 widget = glade_xml_get_widget (priv->xml, "user-entry");
269 str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
270 if (str && strlen (str)) {
271 g_hash_table_insert (settings->data, g_strdup ("user"), g_strdup(str));
272 }
273
274 widget = glade_xml_get_widget (priv->xml, "method-combo");
275 str = (char *) gtk_combo_box_get_active_text (GTK_COMBO_BOX (widget));
276 if (str) {
277 g_hash_table_insert (settings->data, g_strdup ("method"), g_strdup(str));
278 }
279
280 widget = glade_xml_get_widget (priv->xml, "virtual-check");
281 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
282 g_hash_table_insert (settings->data, g_strdup ("virtual"),
283 g_strdup(active ? "yes" : "no"));
284
285 widget = glade_xml_get_widget (priv->xml, "encap-check");
286 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
287 g_hash_table_insert (settings->data, g_strdup ("encap"),
288 g_strdup(active ? "yes" : "no"));
289
290 widget = glade_xml_get_widget (priv->xml, "ipcomp-check");
291 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
292 g_hash_table_insert (settings->data, g_strdup ("ipcomp"),
293 g_strdup(active ? "yes" : "no"));
294
295 nm_connection_add_setting (connection, NM_SETTING (settings));
296 return TRUE;
297 }
298
299 static NMVpnPluginUiWidgetInterface *
300 nm_vpn_plugin_ui_widget_interface_new (NMConnection *connection, GError **error)
301 {
302 NMVpnPluginUiWidgetInterface *object;
303 StrongswanPluginUiWidgetPrivate *priv;
304 char *glade_file;
305
306 if (error)
307 g_return_val_if_fail (*error == NULL, NULL);
308
309 object = NM_VPN_PLUGIN_UI_WIDGET_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI_WIDGET, NULL));
310 if (!object) {
311 g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0, "could not create strongswan object");
312 return NULL;
313 }
314
315 priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (object);
316
317 glade_file = g_strdup_printf ("%s/%s", GLADEDIR, "nm-strongswan-dialog.glade");
318 priv->xml = glade_xml_new (glade_file, "strongswan-vbox", GETTEXT_PACKAGE);
319 if (priv->xml == NULL) {
320 g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0,
321 "could not load required resources at %s", glade_file);
322 g_free (glade_file);
323 g_object_unref (object);
324 return NULL;
325 }
326 g_free (glade_file);
327
328 priv->widget = glade_xml_get_widget (priv->xml, "strongswan-vbox");
329 if (!priv->widget) {
330 g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0, "could not load UI widget");
331 g_object_unref (object);
332 return NULL;
333 }
334 g_object_ref_sink (priv->widget);
335
336 if (!init_plugin_ui (STRONGSWAN_PLUGIN_UI_WIDGET (object), connection, error)) {
337 g_object_unref (object);
338 return NULL;
339 }
340
341 return object;
342 }
343
344 static void
345 dispose (GObject *object)
346 {
347 StrongswanPluginUiWidget *plugin = STRONGSWAN_PLUGIN_UI_WIDGET (object);
348 StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (plugin);
349
350 if (priv->widget)
351 g_object_unref (priv->widget);
352
353 if (priv->xml)
354 g_object_unref (priv->xml);
355
356 G_OBJECT_CLASS (strongswan_plugin_ui_widget_parent_class)->dispose (object);
357 }
358
359 static void
360 strongswan_plugin_ui_widget_class_init (StrongswanPluginUiWidgetClass *req_class)
361 {
362 GObjectClass *object_class = G_OBJECT_CLASS (req_class);
363
364 g_type_class_add_private (req_class, sizeof (StrongswanPluginUiWidgetPrivate));
365
366 object_class->dispose = dispose;
367 }
368
369 static void
370 strongswan_plugin_ui_widget_init (StrongswanPluginUiWidget *plugin)
371 {
372 }
373
374 static void
375 strongswan_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface *iface_class)
376 {
377 /* interface implementation */
378 iface_class->get_widget = get_widget;
379 iface_class->update_connection = update_connection;
380 }
381
382 static guint32
383 get_capabilities (NMVpnPluginUiInterface *iface)
384 {
385 return 0;
386 }
387
388 static NMVpnPluginUiWidgetInterface *
389 ui_factory (NMVpnPluginUiInterface *iface, NMConnection *connection, GError **error)
390 {
391 return nm_vpn_plugin_ui_widget_interface_new (connection, error);
392 }
393
394 static void
395 get_property (GObject *object, guint prop_id,
396 GValue *value, GParamSpec *pspec)
397 {
398 switch (prop_id) {
399 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME:
400 g_value_set_string (value, STRONGSWAN_PLUGIN_NAME);
401 break;
402 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC:
403 g_value_set_string (value, STRONGSWAN_PLUGIN_DESC);
404 break;
405 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE:
406 g_value_set_string (value, STRONGSWAN_PLUGIN_SERVICE);
407 break;
408 default:
409 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
410 break;
411 }
412 }
413
414 static void
415 strongswan_plugin_ui_class_init (StrongswanPluginUiClass *req_class)
416 {
417 GObjectClass *object_class = G_OBJECT_CLASS (req_class);
418
419 object_class->get_property = get_property;
420
421 g_object_class_override_property (object_class,
422 NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME,
423 NM_VPN_PLUGIN_UI_INTERFACE_NAME);
424
425 g_object_class_override_property (object_class,
426 NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC,
427 NM_VPN_PLUGIN_UI_INTERFACE_DESC);
428
429 g_object_class_override_property (object_class,
430 NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE,
431 NM_VPN_PLUGIN_UI_INTERFACE_SERVICE);
432 }
433
434 static void
435 strongswan_plugin_ui_init (StrongswanPluginUi *plugin)
436 {
437 }
438
439 static void
440 strongswan_plugin_ui_interface_init (NMVpnPluginUiInterface *iface_class)
441 {
442 /* interface implementation */
443 iface_class->ui_factory = ui_factory;
444 iface_class->get_capabilities = get_capabilities;
445 }
446
447
448 G_MODULE_EXPORT NMVpnPluginUiInterface *
449 nm_vpn_plugin_ui_factory (GError **error)
450 {
451 if (error)
452 g_return_val_if_fail (*error == NULL, NULL);
453
454 return NM_VPN_PLUGIN_UI_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI, NULL));
455 }
456