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_hide (glade_xml_get_widget (priv
->xml
, "usercert-label"));
146 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "usercert-button"));
147 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "user-label"));
148 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "user-entry"));
149 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "userkey-label"));
150 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "userkey-button"));
153 gtk_widget_show (glade_xml_get_widget (priv
->xml
, "user-label"));
154 gtk_widget_show (glade_xml_get_widget (priv
->xml
, "user-entry"));
155 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "usercert-label"));
156 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "usercert-button"));
157 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "userkey-label"));
158 gtk_widget_hide (glade_xml_get_widget (priv
->xml
, "userkey-button"));
165 settings_changed_cb (GtkWidget
*widget
, gpointer user_data
)
167 StrongswanPluginUiWidget
*self
= STRONGSWAN_PLUGIN_UI_WIDGET (user_data
);
168 StrongswanPluginUiWidgetPrivate
*priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self
);
170 if (widget
== glade_xml_get_widget (priv
->xml
, "method-combo"))
172 update_layout(glade_xml_get_widget (priv
->xml
, "method-combo"), priv
);
174 g_signal_emit_by_name (STRONGSWAN_PLUGIN_UI_WIDGET (user_data
), "changed");
178 init_plugin_ui (StrongswanPluginUiWidget
*self
, NMConnection
*connection
, GError
**error
)
180 StrongswanPluginUiWidgetPrivate
*priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self
);
181 NMSettingVPN
*settings
;
185 settings
= NM_SETTING_VPN(nm_connection_get_setting(connection
, NM_TYPE_SETTING_VPN
));
186 widget
= glade_xml_get_widget (priv
->xml
, "address-entry");
187 value
= nm_setting_vpn_get_data_item (settings
, "address");
189 gtk_entry_set_text (GTK_ENTRY (widget
), value
);
190 g_signal_connect (G_OBJECT (widget
), "changed", G_CALLBACK (settings_changed_cb
), self
);
192 widget
= glade_xml_get_widget (priv
->xml
, "certificate-button");
193 value
= nm_setting_vpn_get_data_item (settings
, "certificate");
195 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget
), value
);
196 g_signal_connect (G_OBJECT (widget
), "selection-changed", G_CALLBACK (settings_changed_cb
), self
);
198 widget
= glade_xml_get_widget (priv
->xml
, "user-label");
199 gtk_widget_set_no_show_all (widget
, TRUE
);
200 widget
= glade_xml_get_widget (priv
->xml
, "user-entry");
201 gtk_widget_set_no_show_all (widget
, TRUE
);
202 value
= nm_setting_vpn_get_data_item (settings
, "user");
204 gtk_entry_set_text (GTK_ENTRY (widget
), value
);
205 g_signal_connect (G_OBJECT (widget
), "changed", G_CALLBACK (settings_changed_cb
), self
);
207 widget
= glade_xml_get_widget (priv
->xml
, "method-combo");
208 gtk_combo_box_append_text (GTK_COMBO_BOX (widget
), _("Certificate/private key"));
209 gtk_combo_box_append_text (GTK_COMBO_BOX (widget
), _("Certificate/ssh-agent"));
210 gtk_combo_box_append_text (GTK_COMBO_BOX (widget
), _("Smartcard"));
211 gtk_combo_box_append_text (GTK_COMBO_BOX (widget
), _("EAP"));
212 value
= nm_setting_vpn_get_data_item (settings
, "method");
214 if (g_strcmp0 (value
, "key") == 0) {
215 gtk_combo_box_set_active (GTK_COMBO_BOX (widget
), 0);
217 if (g_strcmp0 (value
, "agent") == 0) {
218 gtk_combo_box_set_active (GTK_COMBO_BOX (widget
), 1);
220 if (g_strcmp0 (value
, "smartcard") == 0) {
221 gtk_combo_box_set_active (GTK_COMBO_BOX (widget
), 2);
223 if (g_strcmp0 (value
, "eap") == 0) {
224 gtk_combo_box_set_active (GTK_COMBO_BOX (widget
), 3);
227 if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget
)) == -1)
229 gtk_combo_box_set_active (GTK_COMBO_BOX (widget
), 0);
231 update_layout (widget
, priv
);
232 g_signal_connect (G_OBJECT (widget
), "changed", G_CALLBACK (settings_changed_cb
), self
);
234 widget
= glade_xml_get_widget (priv
->xml
, "usercert-label");
235 gtk_widget_set_no_show_all (widget
, TRUE
);
236 widget
= glade_xml_get_widget (priv
->xml
, "usercert-button");
237 gtk_widget_set_no_show_all (widget
, TRUE
);
238 value
= nm_setting_vpn_get_data_item (settings
, "usercert");
240 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget
), value
);
241 g_signal_connect (G_OBJECT (widget
), "selection-changed", G_CALLBACK (settings_changed_cb
), self
);
243 widget
= glade_xml_get_widget (priv
->xml
, "userkey-label");
244 gtk_widget_set_no_show_all (widget
, TRUE
);
245 widget
= glade_xml_get_widget (priv
->xml
, "userkey-button");
246 gtk_widget_set_no_show_all (widget
, TRUE
);
247 value
= nm_setting_vpn_get_data_item (settings
, "userkey");
249 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget
), value
);
250 g_signal_connect (G_OBJECT (widget
), "selection-changed", G_CALLBACK (settings_changed_cb
), self
);
252 widget
= glade_xml_get_widget (priv
->xml
, "virtual-check");
253 value
= nm_setting_vpn_get_data_item (settings
, "virtual");
254 if (value
&& strcmp(value
, "yes") == 0)
256 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
), TRUE
);
258 g_signal_connect (G_OBJECT (widget
), "toggled", G_CALLBACK (settings_changed_cb
), self
);
260 widget
= glade_xml_get_widget (priv
->xml
, "encap-check");
261 value
= nm_setting_vpn_get_data_item (settings
, "encap");
262 if (value
&& strcmp(value
, "yes") == 0)
264 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
), TRUE
);
266 g_signal_connect (G_OBJECT (widget
), "toggled", G_CALLBACK (settings_changed_cb
), self
);
268 widget
= glade_xml_get_widget (priv
->xml
, "ipcomp-check");
269 value
= nm_setting_vpn_get_data_item (settings
, "ipcomp");
270 if (value
&& strcmp(value
, "yes") == 0)
272 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
), TRUE
);
274 g_signal_connect (G_OBJECT (widget
), "toggled", G_CALLBACK (settings_changed_cb
), self
);
280 get_widget (NMVpnPluginUiWidgetInterface
*iface
)
282 StrongswanPluginUiWidget
*self
= STRONGSWAN_PLUGIN_UI_WIDGET (iface
);
283 StrongswanPluginUiWidgetPrivate
*priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self
);
285 return G_OBJECT (priv
->widget
);
289 update_connection (NMVpnPluginUiWidgetInterface
*iface
,
290 NMConnection
*connection
,
293 StrongswanPluginUiWidget
*self
= STRONGSWAN_PLUGIN_UI_WIDGET (iface
);
294 StrongswanPluginUiWidgetPrivate
*priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self
);
295 NMSettingVPN
*settings
;
300 if (!check_validity (self
, error
))
302 settings
= NM_SETTING_VPN (nm_setting_vpn_new ());
304 g_object_set (settings
, NM_SETTING_VPN_SERVICE_TYPE
,
305 NM_DBUS_SERVICE_STRONGSWAN
, NULL
);
307 widget
= glade_xml_get_widget (priv
->xml
, "address-entry");
308 str
= (char *) gtk_entry_get_text (GTK_ENTRY (widget
));
309 if (str
&& strlen (str
)) {
310 nm_setting_vpn_add_data_item (settings
, "address", str
);
313 widget
= glade_xml_get_widget (priv
->xml
, "certificate-button");
314 str
= (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget
));
316 nm_setting_vpn_add_data_item (settings
, "certificate", str
);
319 widget
= glade_xml_get_widget (priv
->xml
, "method-combo");
320 switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget
)))
324 widget
= glade_xml_get_widget (priv
->xml
, "userkey-button");
325 str
= (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget
));
327 nm_setting_vpn_add_data_item (settings
, "userkey", str
);
329 widget
= glade_xml_get_widget (priv
->xml
, "usercert-button");
330 str
= (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget
));
332 nm_setting_vpn_add_data_item (settings
, "usercert", str
);
337 widget
= glade_xml_get_widget (priv
->xml
, "usercert-button");
338 str
= (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget
));
340 nm_setting_vpn_add_data_item (settings
, "usercert", str
);
348 widget
= glade_xml_get_widget (priv
->xml
, "user-entry");
349 str
= (char *) gtk_entry_get_text (GTK_ENTRY (widget
));
350 if (str
&& strlen (str
)) {
351 nm_setting_vpn_add_data_item (settings
, "user", str
);
356 nm_setting_vpn_add_data_item (settings
, "method", str
);
358 widget
= glade_xml_get_widget (priv
->xml
, "virtual-check");
359 active
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
));
360 nm_setting_vpn_add_data_item (settings
, "virtual", active ?
"yes" : "no");
362 widget
= glade_xml_get_widget (priv
->xml
, "encap-check");
363 active
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
));
364 nm_setting_vpn_add_data_item (settings
, "encap", active ?
"yes" : "no");
366 widget
= glade_xml_get_widget (priv
->xml
, "ipcomp-check");
367 active
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
));
368 nm_setting_vpn_add_data_item (settings
, "ipcomp", active ?
"yes" : "no");
370 nm_connection_add_setting (connection
, NM_SETTING (settings
));
375 save_secrets (NMVpnPluginUiWidgetInterface
*iface
,
376 NMConnection
*connection
, GError
**error
)
378 /* no secrets to save */
382 static NMVpnPluginUiWidgetInterface
*
383 nm_vpn_plugin_ui_widget_interface_new (NMConnection
*connection
, GError
**error
)
385 NMVpnPluginUiWidgetInterface
*object
;
386 StrongswanPluginUiWidgetPrivate
*priv
;
390 g_return_val_if_fail (*error
== NULL
, NULL
);
392 object
= NM_VPN_PLUGIN_UI_WIDGET_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI_WIDGET
, NULL
));
394 g_set_error (error
, STRONGSWAN_PLUGIN_UI_ERROR
, 0, "could not create strongswan object");
398 priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (object
);
400 glade_file
= g_strdup_printf ("%s/%s", GLADEDIR
, "nm-strongswan-dialog.glade");
401 priv
->xml
= glade_xml_new (glade_file
, "strongswan-vbox", GETTEXT_PACKAGE
);
402 if (priv
->xml
== NULL
) {
403 g_set_error (error
, STRONGSWAN_PLUGIN_UI_ERROR
, 0,
404 "could not load required resources at %s", glade_file
);
406 g_object_unref (object
);
411 priv
->widget
= glade_xml_get_widget (priv
->xml
, "strongswan-vbox");
413 g_set_error (error
, STRONGSWAN_PLUGIN_UI_ERROR
, 0, "could not load UI widget");
414 g_object_unref (object
);
417 g_object_ref_sink (priv
->widget
);
419 if (!init_plugin_ui (STRONGSWAN_PLUGIN_UI_WIDGET (object
), connection
, error
)) {
420 g_object_unref (object
);
428 dispose (GObject
*object
)
430 StrongswanPluginUiWidget
*plugin
= STRONGSWAN_PLUGIN_UI_WIDGET (object
);
431 StrongswanPluginUiWidgetPrivate
*priv
= STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (plugin
);
434 g_object_unref (priv
->widget
);
437 g_object_unref (priv
->xml
);
439 G_OBJECT_CLASS (strongswan_plugin_ui_widget_parent_class
)->dispose (object
);
443 strongswan_plugin_ui_widget_class_init (StrongswanPluginUiWidgetClass
*req_class
)
445 GObjectClass
*object_class
= G_OBJECT_CLASS (req_class
);
447 g_type_class_add_private (req_class
, sizeof (StrongswanPluginUiWidgetPrivate
));
449 object_class
->dispose
= dispose
;
453 strongswan_plugin_ui_widget_init (StrongswanPluginUiWidget
*plugin
)
458 strongswan_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface
*iface_class
)
460 /* interface implementation */
461 iface_class
->get_widget
= get_widget
;
462 iface_class
->update_connection
= update_connection
;
463 iface_class
->save_secrets
= save_secrets
;
467 get_capabilities (NMVpnPluginUiInterface
*iface
)
472 static NMVpnPluginUiWidgetInterface
*
473 ui_factory (NMVpnPluginUiInterface
*iface
, NMConnection
*connection
, GError
**error
)
475 return nm_vpn_plugin_ui_widget_interface_new (connection
, error
);
479 get_property (GObject
*object
, guint prop_id
,
480 GValue
*value
, GParamSpec
*pspec
)
483 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME
:
484 g_value_set_string (value
, STRONGSWAN_PLUGIN_NAME
);
486 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC
:
487 g_value_set_string (value
, STRONGSWAN_PLUGIN_DESC
);
489 case NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE
:
490 g_value_set_string (value
, STRONGSWAN_PLUGIN_SERVICE
);
493 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
499 strongswan_plugin_ui_class_init (StrongswanPluginUiClass
*req_class
)
501 GObjectClass
*object_class
= G_OBJECT_CLASS (req_class
);
503 object_class
->get_property
= get_property
;
505 g_object_class_override_property (object_class
,
506 NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME
,
507 NM_VPN_PLUGIN_UI_INTERFACE_NAME
);
509 g_object_class_override_property (object_class
,
510 NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC
,
511 NM_VPN_PLUGIN_UI_INTERFACE_DESC
);
513 g_object_class_override_property (object_class
,
514 NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE
,
515 NM_VPN_PLUGIN_UI_INTERFACE_SERVICE
);
519 strongswan_plugin_ui_init (StrongswanPluginUi
*plugin
)
524 strongswan_plugin_ui_interface_init (NMVpnPluginUiInterface
*iface_class
)
526 /* interface implementation */
527 iface_class
->ui_factory
= ui_factory
;
528 iface_class
->get_capabilities
= get_capabilities
;
529 /* TODO: implement delete_connection to purge associated secrets */
533 G_MODULE_EXPORT NMVpnPluginUiInterface
*
534 nm_vpn_plugin_ui_factory (GError
**error
)
537 g_return_val_if_fail (*error
== NULL
, NULL
);
539 return NM_VPN_PLUGIN_UI_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI
, NULL
));