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