2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 * Copyright (C) 2005 David Zeuthen
5 * Copyright (C) 2005-2008 Dan Williams
7 * Based on NetworkManager's vpnc plugin
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>.
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
25 #include <glib/gi18n-lib.h>
27 #include <glade/glade.h>
29 #define NM_VPN_API_SUBJECT_TO_CHANGE
31 #include <nm-vpn-plugin-ui-interface.h>
32 #include <nm-setting-vpn.h>
33 #include <nm-setting-connection.h>
34 #include <nm-setting-ip4-config.h>
36 #include "nm-strongswan.h"
38 #define STRONGSWAN_PLUGIN_NAME _("IPsec/IKEv2 (strongswan)")
39 #define STRONGSWAN_PLUGIN_DESC _("IPsec with the IKEv2 key exchange protocol.")
40 #define STRONGSWAN_PLUGIN_SERVICE "org.freedesktop.NetworkManager.strongswan"
41 #define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
43 /************** plugin class **************/
45 static void strongswan_plugin_ui_interface_init (NMVpnPluginUiInterface
*iface_class
);
47 G_DEFINE_TYPE_EXTENDED (StrongswanPluginUi
, strongswan_plugin_ui
, G_TYPE_OBJECT
, 0,
48 G_IMPLEMENT_INTERFACE (NM_TYPE_VPN_PLUGIN_UI_INTERFACE
,
49 strongswan_plugin_ui_interface_init
))
51 /************** UI widget class **************/
53 static void strongswan_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface
*iface_class
);
55 G_DEFINE_TYPE_EXTENDED (StrongswanPluginUiWidget
, strongswan_plugin_ui_widget
, G_TYPE_OBJECT
, 0,
56 G_IMPLEMENT_INTERFACE (NM_TYPE_VPN_PLUGIN_UI_WIDGET_INTERFACE
,
57 strongswan_plugin_ui_widget_interface_init
))
59 #define STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), STRONGSWAN_TYPE_PLUGIN_UI_WIDGET, StrongswanPluginUiWidgetPrivate))
64 } StrongswanPluginUiWidgetPrivate
;
67 #define STRONGSWAN_PLUGIN_UI_ERROR strongswan_plugin_ui_error_quark ()
70 strongswan_plugin_ui_error_quark (void)
72 static GQuark error_quark
= 0;
74 if (G_UNLIKELY (error_quark
== 0))
75 error_quark
= g_quark_from_static_string ("strongswan-plugin-ui-error-quark");
80 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
83 strongswan_plugin_ui_error_get_type (void)
85 static GType etype
= 0;
88 static const GEnumValue values
[] = {
90 ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_UNKNOWN
, "UnknownError"),
91 /* The specified property was invalid. */
92 ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_INVALID_PROPERTY
, "InvalidProperty"),
93 /* The specified property was missing and is required. */
94 ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_MISSING_PROPERTY
, "MissingProperty"),
97 etype
= g_enum_register_static ("StrongswanPluginUiError", values
);
103 check_validity (StrongswanPluginUiWidget
*self
, GError
**error
)
105 StrongswanPluginUiWidgetPrivate
*priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self
);
109 widget
= glade_xml_get_widget (priv
->xml
, "address-entry");
110 str
= (char *) gtk_entry_get_text (GTK_ENTRY (widget
));
111 if (!str
|| !strlen (str
)) {
113 STRONGSWAN_PLUGIN_UI_ERROR
,
114 STRONGSWAN_PLUGIN_UI_ERROR_INVALID_PROPERTY
,
121 static void update_layout (GtkWidget
*widget
, StrongswanPluginUiWidgetPrivate
*priv
)
123 switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget
)))
126 gtk_combo_box_set_active (GTK_COMBO_BOX (widget
), 0);
129 gtk_widget_show (glade_xml_get_widget (priv
->xml
, "usercert-label"));
130 gtk_widget_show (glade_xml_get_widget (priv
->xml
, "usercert-button"));
131 gtk_widget_show (glade_xml_get_widget (priv
->xml
, "userkey-label"));
132 gtk_widget_show (glade_xml_get_widget (priv
->xml
, "userkey-button"));
133 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "user-label"));
134 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "user-entry"));
137 gtk_widget_show (glade_xml_get_widget (priv
->xml
, "usercert-label"));
138 gtk_widget_show (glade_xml_get_widget (priv
->xml
, "usercert-button"));
139 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "user-label"));
140 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "user-entry"));
141 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "userkey-label"));
142 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "userkey-button"));
145 gtk_widget_show (glade_xml_get_widget (priv
->xml
, "user-label"));
146 gtk_widget_show (glade_xml_get_widget (priv
->xml
, "user-entry"));
147 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "usercert-label"));
148 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "usercert-button"));
149 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "userkey-label"));
150 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "userkey-button"));
157 settings_changed_cb (GtkWidget
*widget
, gpointer user_data
)
159 StrongswanPluginUiWidget
*self
= STRONGSWAN_PLUGIN_UI_WIDGET (user_data
);
160 StrongswanPluginUiWidgetPrivate
*priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self
);
162 if (widget
== glade_xml_get_widget (priv
->xml
, "method-combo"))
164 update_layout(glade_xml_get_widget (priv
->xml
, "method-combo"), priv
);
166 g_signal_emit_by_name (STRONGSWAN_PLUGIN_UI_WIDGET (user_data
), "changed");
170 init_plugin_ui (StrongswanPluginUiWidget
*self
, NMConnection
*connection
, GError
**error
)
172 StrongswanPluginUiWidgetPrivate
*priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self
);
173 NMSettingVPN
*settings
;
177 settings
= NM_SETTING_VPN(nm_connection_get_setting(connection
, NM_TYPE_SETTING_VPN
));
178 widget
= glade_xml_get_widget (priv
->xml
, "address-entry");
179 value
= nm_setting_vpn_get_data_item (settings
, "address");
181 gtk_entry_set_text (GTK_ENTRY (widget
), value
);
182 g_signal_connect (G_OBJECT (widget
), "changed", G_CALLBACK (settings_changed_cb
), self
);
184 widget
= glade_xml_get_widget (priv
->xml
, "certificate-button");
185 value
= nm_setting_vpn_get_data_item (settings
, "certificate");
187 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget
), value
);
188 g_signal_connect (G_OBJECT (widget
), "selection-changed", G_CALLBACK (settings_changed_cb
), self
);
190 widget
= glade_xml_get_widget (priv
->xml
, "user-label");
191 gtk_widget_set_no_show_all (widget
, TRUE
);
192 widget
= glade_xml_get_widget (priv
->xml
, "user-entry");
193 gtk_widget_set_no_show_all (widget
, TRUE
);
194 value
= nm_setting_vpn_get_data_item (settings
, "user");
196 gtk_entry_set_text (GTK_ENTRY (widget
), value
);
197 g_signal_connect (G_OBJECT (widget
), "changed", G_CALLBACK (settings_changed_cb
), self
);
199 widget
= glade_xml_get_widget (priv
->xml
, "method-combo");
200 gtk_combo_box_append_text (GTK_COMBO_BOX (widget
), _("Certificate/private key"));
201 gtk_combo_box_append_text (GTK_COMBO_BOX (widget
), _("Certificate/ssh-agent"));
202 gtk_combo_box_append_text (GTK_COMBO_BOX (widget
), _("EAP"));
203 value
= nm_setting_vpn_get_data_item (settings
, "method");
205 if (g_strcmp0 (value
, "key") == 0) {
206 gtk_combo_box_set_active (GTK_COMBO_BOX (widget
), 0);
208 if (g_strcmp0 (value
, "agent") == 0) {
209 gtk_combo_box_set_active (GTK_COMBO_BOX (widget
), 1);
211 if (g_strcmp0 (value
, "eap") == 0) {
212 gtk_combo_box_set_active (GTK_COMBO_BOX (widget
), 2);
215 if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget
)) == -1)
217 gtk_combo_box_set_active (GTK_COMBO_BOX (widget
), 0);
219 update_layout (widget
, priv
);
220 g_signal_connect (G_OBJECT (widget
), "changed", G_CALLBACK (settings_changed_cb
), self
);
222 widget
= glade_xml_get_widget (priv
->xml
, "usercert-label");
223 gtk_widget_set_no_show_all (widget
, TRUE
);
224 widget
= glade_xml_get_widget (priv
->xml
, "usercert-button");
225 gtk_widget_set_no_show_all (widget
, TRUE
);
226 value
= nm_setting_vpn_get_data_item (settings
, "usercert");
228 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget
), value
);
229 g_signal_connect (G_OBJECT (widget
), "selection-changed", G_CALLBACK (settings_changed_cb
), self
);
231 widget
= glade_xml_get_widget (priv
->xml
, "userkey-label");
232 gtk_widget_set_no_show_all (widget
, TRUE
);
233 widget
= glade_xml_get_widget (priv
->xml
, "userkey-button");
234 gtk_widget_set_no_show_all (widget
, TRUE
);
235 value
= nm_setting_vpn_get_data_item (settings
, "userkey");
237 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget
), value
);
238 g_signal_connect (G_OBJECT (widget
), "selection-changed", G_CALLBACK (settings_changed_cb
), self
);
240 widget
= glade_xml_get_widget (priv
->xml
, "virtual-check");
241 value
= nm_setting_vpn_get_data_item (settings
, "virtual");
242 if (value
&& strcmp(value
, "yes") == 0)
244 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
), TRUE
);
246 g_signal_connect (G_OBJECT (widget
), "toggled", G_CALLBACK (settings_changed_cb
), self
);
248 widget
= glade_xml_get_widget (priv
->xml
, "encap-check");
249 value
= nm_setting_vpn_get_data_item (settings
, "encap");
250 if (value
&& strcmp(value
, "yes") == 0)
252 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
), TRUE
);
254 g_signal_connect (G_OBJECT (widget
), "toggled", G_CALLBACK (settings_changed_cb
), self
);
256 widget
= glade_xml_get_widget (priv
->xml
, "ipcomp-check");
257 value
= nm_setting_vpn_get_data_item (settings
, "ipcomp");
258 if (value
&& strcmp(value
, "yes") == 0)
260 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
), TRUE
);
262 g_signal_connect (G_OBJECT (widget
), "toggled", G_CALLBACK (settings_changed_cb
), self
);
268 get_widget (NMVpnPluginUiWidgetInterface
*iface
)
270 StrongswanPluginUiWidget
*self
= STRONGSWAN_PLUGIN_UI_WIDGET (iface
);
271 StrongswanPluginUiWidgetPrivate
*priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self
);
273 return G_OBJECT (priv
->widget
);
277 update_connection (NMVpnPluginUiWidgetInterface
*iface
,
278 NMConnection
*connection
,
281 StrongswanPluginUiWidget
*self
= STRONGSWAN_PLUGIN_UI_WIDGET (iface
);
282 StrongswanPluginUiWidgetPrivate
*priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self
);
283 NMSettingVPN
*settings
;
288 if (!check_validity (self
, error
))
290 settings
= NM_SETTING_VPN (nm_setting_vpn_new ());
292 g_object_set (settings
, NM_SETTING_VPN_SERVICE_TYPE
,
293 NM_DBUS_SERVICE_STRONGSWAN
, NULL
);
295 widget
= glade_xml_get_widget (priv
->xml
, "address-entry");
296 str
= (char *) gtk_entry_get_text (GTK_ENTRY (widget
));
297 if (str
&& strlen (str
)) {
298 nm_setting_vpn_add_data_item (settings
, "address", str
);
301 widget
= glade_xml_get_widget (priv
->xml
, "certificate-button");
302 str
= (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget
));
304 nm_setting_vpn_add_data_item (settings
, "certificate", str
);
307 widget
= glade_xml_get_widget (priv
->xml
, "method-combo");
308 switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget
)))
312 widget
= glade_xml_get_widget (priv
->xml
, "userkey-button");
313 str
= (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget
));
315 nm_setting_vpn_add_data_item (settings
, "userkey", str
);
317 widget
= glade_xml_get_widget (priv
->xml
, "usercert-button");
318 str
= (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget
));
320 nm_setting_vpn_add_data_item (settings
, "usercert", str
);
325 widget
= glade_xml_get_widget (priv
->xml
, "usercert-button");
326 str
= (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget
));
328 nm_setting_vpn_add_data_item (settings
, "usercert", str
);
333 widget
= glade_xml_get_widget (priv
->xml
, "user-entry");
334 str
= (char *) gtk_entry_get_text (GTK_ENTRY (widget
));
335 if (str
&& strlen (str
)) {
336 nm_setting_vpn_add_data_item (settings
, "user", str
);
341 nm_setting_vpn_add_data_item (settings
, "method", str
);
343 widget
= glade_xml_get_widget (priv
->xml
, "virtual-check");
344 active
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
));
345 nm_setting_vpn_add_data_item (settings
, "virtual", active ?
"yes" : "no");
347 widget
= glade_xml_get_widget (priv
->xml
, "encap-check");
348 active
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
));
349 nm_setting_vpn_add_data_item (settings
, "encap", active ?
"yes" : "no");
351 widget
= glade_xml_get_widget (priv
->xml
, "ipcomp-check");
352 active
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
));
353 nm_setting_vpn_add_data_item (settings
, "ipcomp", active ?
"yes" : "no");
355 nm_connection_add_setting (connection
, NM_SETTING (settings
));
360 save_secrets (NMVpnPluginUiWidgetInterface
*iface
,
361 NMConnection
*connection
, GError
**error
)
363 /* no secrets to save */
367 static NMVpnPluginUiWidgetInterface
*
368 nm_vpn_plugin_ui_widget_interface_new (NMConnection
*connection
, GError
**error
)
370 NMVpnPluginUiWidgetInterface
*object
;
371 StrongswanPluginUiWidgetPrivate
*priv
;
375 g_return_val_if_fail (*error
== NULL
, NULL
);
377 object
= NM_VPN_PLUGIN_UI_WIDGET_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI_WIDGET
, NULL
));
379 g_set_error (error
, STRONGSWAN_PLUGIN_UI_ERROR
, 0, "could not create strongswan object");
383 priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (object
);
385 glade_file
= g_strdup_printf ("%s/%s", GLADEDIR
, "nm-strongswan-dialog.glade");
386 priv
->xml
= glade_xml_new (glade_file
, "strongswan-vbox", GETTEXT_PACKAGE
);
387 if (priv
->xml
== NULL
) {
388 g_set_error (error
, STRONGSWAN_PLUGIN_UI_ERROR
, 0,
389 "could not load required resources at %s", glade_file
);
391 g_object_unref (object
);
396 priv
->widget
= glade_xml_get_widget (priv
->xml
, "strongswan-vbox");
398 g_set_error (error
, STRONGSWAN_PLUGIN_UI_ERROR
, 0, "could not load UI widget");
399 g_object_unref (object
);
402 g_object_ref_sink (priv
->widget
);
404 if (!init_plugin_ui (STRONGSWAN_PLUGIN_UI_WIDGET (object
), connection
, error
)) {
405 g_object_unref (object
);
413 dispose (GObject
*object
)
415 StrongswanPluginUiWidget
*plugin
= STRONGSWAN_PLUGIN_UI_WIDGET (object
);
416 StrongswanPluginUiWidgetPrivate
*priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (plugin
);
419 g_object_unref (priv
->widget
);
422 g_object_unref (priv
->xml
);
424 G_OBJECT_CLASS (strongswan_plugin_ui_widget_parent_class
)->dispose (object
);
428 strongswan_plugin_ui_widget_class_init (StrongswanPluginUiWidgetClass
*req_class
)
430 GObjectClass
*object_class
= G_OBJECT_CLASS (req_class
);
432 g_type_class_add_private (req_class
, sizeof (StrongswanPluginUiWidgetPrivate
));
434 object_class
->dispose
= dispose
;
438 strongswan_plugin_ui_widget_init (StrongswanPluginUiWidget
*plugin
)
443 strongswan_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface
*iface_class
)
445 /* interface implementation */
446 iface_class
->get_widget
= get_widget
;
447 iface_class
->update_connection
= update_connection
;
448 iface_class
->save_secrets
= save_secrets
;
452 get_capabilities (NMVpnPluginUiInterface
*iface
)
457 static NMVpnPluginUiWidgetInterface
*
458 ui_factory (NMVpnPluginUiInterface
*iface
, NMConnection
*connection
, GError
**error
)
460 return nm_vpn_plugin_ui_widget_interface_new (connection
, error
);
464 get_property (GObject
*object
, guint prop_id
,
465 GValue
*value
, GParamSpec
*pspec
)
468 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME
:
469 g_value_set_string (value
, STRONGSWAN_PLUGIN_NAME
);
471 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC
:
472 g_value_set_string (value
, STRONGSWAN_PLUGIN_DESC
);
474 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE
:
475 g_value_set_string (value
, STRONGSWAN_PLUGIN_SERVICE
);
478 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
484 strongswan_plugin_ui_class_init (StrongswanPluginUiClass
*req_class
)
486 GObjectClass
*object_class
= G_OBJECT_CLASS (req_class
);
488 object_class
->get_property
= get_property
;
490 g_object_class_override_property (object_class
,
491 NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME
,
492 NM_VPN_PLUGIN_UI_INTERFACE_NAME
);
494 g_object_class_override_property (object_class
,
495 NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC
,
496 NM_VPN_PLUGIN_UI_INTERFACE_DESC
);
498 g_object_class_override_property (object_class
,
499 NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE
,
500 NM_VPN_PLUGIN_UI_INTERFACE_SERVICE
);
504 strongswan_plugin_ui_init (StrongswanPluginUi
*plugin
)
509 strongswan_plugin_ui_interface_init (NMVpnPluginUiInterface
*iface_class
)
511 /* interface implementation */
512 iface_class
->ui_factory
= ui_factory
;
513 iface_class
->get_capabilities
= get_capabilities
;
514 /* TODO: implement delete_connection to purge associated secrets */
518 G_MODULE_EXPORT NMVpnPluginUiInterface
*
519 nm_vpn_plugin_ui_factory (GError
**error
)
522 g_return_val_if_fail (*error
== NULL
, NULL
);
524 return NM_VPN_PLUGIN_UI_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI
, NULL
));