make IKEv1 DPD timeout configurable in charon
[strongswan.git] / src / charon-nm / nm / nm_service.c
1 /*
2 * Copyright (C) 2008-2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <nm-setting-vpn.h>
17 #include <nm-setting-connection.h>
18 #include "nm_service.h"
19
20 #include <daemon.h>
21 #include <utils/host.h>
22 #include <utils/identification.h>
23 #include <config/peer_cfg.h>
24 #include <credentials/certificates/x509.h>
25
26 #include <stdio.h>
27
28 G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_PLUGIN)
29
30 /**
31 * Private data of NMStrongswanPlugin
32 */
33 typedef struct {
34 /* implements bus listener interface */
35 listener_t listener;
36 /* IKE_SA we are listening on */
37 ike_sa_t *ike_sa;
38 /* backref to public plugin */
39 NMVPNPlugin *plugin;
40 /* credentials to use for authentication */
41 nm_creds_t *creds;
42 /* attribute handler for DNS/NBNS server information */
43 nm_handler_t *handler;
44 /* name of the connection */
45 char *name;
46 } NMStrongswanPluginPrivate;
47
48 #define NM_STRONGSWAN_PLUGIN_GET_PRIVATE(o) \
49 (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
50 NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate))
51
52 /**
53 * convert enumerated handler chunks to a UINT_ARRAY GValue
54 */
55 static GValue* handler_to_val(nm_handler_t *handler,
56 configuration_attribute_type_t type)
57 {
58 GValue *val;
59 GArray *array;
60 enumerator_t *enumerator;
61 chunk_t chunk;
62
63 enumerator = handler->create_enumerator(handler, type);
64 array = g_array_new (FALSE, TRUE, sizeof (guint32));
65 while (enumerator->enumerate(enumerator, &chunk))
66 {
67 g_array_append_val (array, *(u_int32_t*)chunk.ptr);
68 }
69 enumerator->destroy(enumerator);
70 val = g_slice_new0 (GValue);
71 g_value_init (val, DBUS_TYPE_G_UINT_ARRAY);
72 g_value_set_boxed (val, array);
73
74 return val;
75 }
76
77 /**
78 * signal IPv4 config to NM, set connection as established
79 */
80 static void signal_ipv4_config(NMVPNPlugin *plugin,
81 ike_sa_t *ike_sa, child_sa_t *child_sa)
82 {
83 GValue *val;
84 GHashTable *config;
85 host_t *me;
86 nm_handler_t *handler;
87
88 config = g_hash_table_new(g_str_hash, g_str_equal);
89 me = ike_sa->get_my_host(ike_sa);
90 handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler;
91
92 /* NM requires a tundev, but netkey does not use one. Passing an invalid
93 * iface makes NM complain, but it accepts it without fiddling on eth0. */
94 val = g_slice_new0 (GValue);
95 g_value_init (val, G_TYPE_STRING);
96 g_value_set_string (val, "none");
97 g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val);
98
99 val = g_slice_new0(GValue);
100 g_value_init(val, G_TYPE_UINT);
101 g_value_set_uint(val, *(u_int32_t*)me->get_address(me).ptr);
102 g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val);
103
104 val = g_slice_new0(GValue);
105 g_value_init(val, G_TYPE_UINT);
106 g_value_set_uint(val, me->get_address(me).len * 8);
107 g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
108
109 val = handler_to_val(handler, INTERNAL_IP4_DNS);
110 g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_DNS, val);
111
112 val = handler_to_val(handler, INTERNAL_IP4_NBNS);
113 g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, val);
114
115 handler->reset(handler);
116
117 nm_vpn_plugin_set_ip4_config(plugin, config);
118 }
119
120 /**
121 * signal failure to NM, connecting failed
122 */
123 static void signal_failure(NMVPNPlugin *plugin, NMVPNPluginFailure failure)
124 {
125 nm_handler_t *handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler;
126
127 handler->reset(handler);
128
129 /* TODO: NM does not handle this failure!? */
130 nm_vpn_plugin_failure(plugin, failure);
131 nm_vpn_plugin_set_state(plugin, NM_VPN_SERVICE_STATE_STOPPED);
132 }
133
134 /**
135 * Implementation of listener_t.ike_state_change
136 */
137 static bool ike_state_change(listener_t *listener, ike_sa_t *ike_sa,
138 ike_sa_state_t state)
139 {
140 NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
141
142 if (private->ike_sa == ike_sa && state == IKE_DESTROYING)
143 {
144 signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED);
145 return FALSE;
146 }
147 return TRUE;
148 }
149
150 /**
151 * Implementation of listener_t.child_state_change
152 */
153 static bool child_state_change(listener_t *listener, ike_sa_t *ike_sa,
154 child_sa_t *child_sa, child_sa_state_t state)
155 {
156 NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
157
158 if (private->ike_sa == ike_sa && state == CHILD_DESTROYING)
159 {
160 signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
161 return FALSE;
162 }
163 return TRUE;
164 }
165
166 /**
167 * Implementation of listener_t.child_updown
168 */
169 static bool child_updown(listener_t *listener, ike_sa_t *ike_sa,
170 child_sa_t *child_sa, bool up)
171 {
172 NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
173
174 if (private->ike_sa == ike_sa)
175 {
176 if (up)
177 { /* disable initiate-failure-detection hooks */
178 private->listener.ike_state_change = NULL;
179 private->listener.child_state_change = NULL;
180 signal_ipv4_config(private->plugin, ike_sa, child_sa);
181 }
182 else
183 {
184 signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
185 return FALSE;
186 }
187 }
188 return TRUE;
189 }
190
191 /**
192 * Implementation of listener_t.ike_rekey
193 */
194 static bool ike_rekey(listener_t *listener, ike_sa_t *old, ike_sa_t *new)
195 {
196 NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
197
198 if (private->ike_sa == old)
199 { /* follow a rekeyed IKE_SA */
200 private->ike_sa = new;
201 }
202 return TRUE;
203 }
204
205 /**
206 * Find a certificate for which we have a private key on a smartcard
207 */
208 static identification_t *find_smartcard_key(NMStrongswanPluginPrivate *priv,
209 char *pin)
210 {
211 enumerator_t *enumerator, *sans;
212 identification_t *id = NULL;
213 certificate_t *cert;
214 x509_t *x509;
215 private_key_t *key;
216 chunk_t keyid;
217
218 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
219 CERT_X509, KEY_ANY, NULL, FALSE);
220 while (enumerator->enumerate(enumerator, &cert))
221 {
222 x509 = (x509_t*)cert;
223
224 /* there might be a lot of certificates, filter them by usage */
225 if ((x509->get_flags(x509) & X509_CLIENT_AUTH) &&
226 !(x509->get_flags(x509) & X509_CA))
227 {
228 keyid = x509->get_subjectKeyIdentifier(x509);
229 if (keyid.ptr)
230 {
231 /* try to find a private key by the certificate keyid */
232 priv->creds->set_pin(priv->creds, keyid, pin);
233 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
234 KEY_ANY, BUILD_PKCS11_KEYID, keyid, BUILD_END);
235 if (key)
236 {
237 /* prefer a more convenient subjectAltName */
238 sans = x509->create_subjectAltName_enumerator(x509);
239 if (!sans->enumerate(sans, &id))
240 {
241 id = cert->get_subject(cert);
242 }
243 id = id->clone(id);
244 sans->destroy(sans);
245
246 DBG1(DBG_CFG, "using smartcard certificate '%Y'", id);
247 priv->creds->set_cert_and_key(priv->creds,
248 cert->get_ref(cert), key);
249 break;
250 }
251 }
252 }
253 }
254 enumerator->destroy(enumerator);
255 return id;
256 }
257
258 /**
259 * Connect function called from NM via DBUS
260 */
261 static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
262 GError **err)
263 {
264 NMStrongswanPluginPrivate *priv;
265 NMSettingConnection *conn;
266 NMSettingVPN *vpn;
267 identification_t *user = NULL, *gateway = NULL;
268 const char *address, *str;
269 bool virtual, encap, ipcomp;
270 ike_cfg_t *ike_cfg;
271 peer_cfg_t *peer_cfg;
272 child_cfg_t *child_cfg;
273 traffic_selector_t *ts;
274 ike_sa_t *ike_sa;
275 auth_cfg_t *auth;
276 auth_class_t auth_class = AUTH_CLASS_EAP;
277 certificate_t *cert = NULL;
278 x509_t *x509;
279 bool agent = FALSE, smartcard = FALSE;
280 lifetime_cfg_t lifetime = {
281 .time = {
282 .life = 10800 /* 3h */,
283 .rekey = 10200 /* 2h50min */,
284 .jitter = 300 /* 5min */
285 }
286 };
287
288 /**
289 * Read parameters
290 */
291 priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
292 conn = NM_SETTING_CONNECTION(nm_connection_get_setting(connection,
293 NM_TYPE_SETTING_CONNECTION));
294 vpn = NM_SETTING_VPN(nm_connection_get_setting(connection,
295 NM_TYPE_SETTING_VPN));
296 if (priv->name)
297 {
298 free(priv->name);
299 }
300 priv->name = strdup(nm_setting_connection_get_id(conn));
301 DBG1(DBG_CFG, "received initiate for NetworkManager connection %s",
302 priv->name);
303 DBG4(DBG_CFG, "%s",
304 nm_setting_to_string(NM_SETTING(vpn)));
305 address = nm_setting_vpn_get_data_item(vpn, "address");
306 if (!address || !*address)
307 {
308 g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
309 "Gateway address missing.");
310 return FALSE;
311 }
312 str = nm_setting_vpn_get_data_item(vpn, "virtual");
313 virtual = str && streq(str, "yes");
314 str = nm_setting_vpn_get_data_item(vpn, "encap");
315 encap = str && streq(str, "yes");
316 str = nm_setting_vpn_get_data_item(vpn, "ipcomp");
317 ipcomp = str && streq(str, "yes");
318 str = nm_setting_vpn_get_data_item(vpn, "method");
319 if (str)
320 {
321 if (streq(str, "psk"))
322 {
323 auth_class = AUTH_CLASS_PSK;
324 }
325 else if (streq(str, "agent"))
326 {
327 auth_class = AUTH_CLASS_PUBKEY;
328 agent = TRUE;
329 }
330 else if (streq(str, "key"))
331 {
332 auth_class = AUTH_CLASS_PUBKEY;
333 }
334 else if (streq(str, "smartcard"))
335 {
336 auth_class = AUTH_CLASS_PUBKEY;
337 smartcard = TRUE;
338 }
339 }
340
341 /**
342 * Register credentials
343 */
344 priv->creds->clear(priv->creds);
345
346 /* gateway/CA cert */
347 str = nm_setting_vpn_get_data_item(vpn, "certificate");
348 if (str)
349 {
350 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
351 BUILD_FROM_FILE, str, BUILD_END);
352 if (!cert)
353 {
354 g_set_error(err, NM_VPN_PLUGIN_ERROR,
355 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
356 "Loading gateway certificate failed.");
357 return FALSE;
358 }
359 priv->creds->add_certificate(priv->creds, cert);
360
361 x509 = (x509_t*)cert;
362 if (!(x509->get_flags(x509) & X509_CA))
363 { /* For a gateway certificate, we use the cert subject as identity. */
364 gateway = cert->get_subject(cert);
365 gateway = gateway->clone(gateway);
366 DBG1(DBG_CFG, "using gateway certificate, identity '%Y'", gateway);
367 }
368 }
369 else
370 {
371 /* no certificate defined, fall back to system-wide CA certificates */
372 priv->creds->load_ca_dir(priv->creds, NM_CA_DIR);
373 }
374 if (!gateway)
375 {
376 /* If the user configured a CA certificate, we use the IP/DNS
377 * of the gateway as its identity. This identity will be used for
378 * certificate lookup and requires the configured IP/DNS to be
379 * included in the gateway certificate. */
380 gateway = identification_create_from_string((char*)address);
381 DBG1(DBG_CFG, "using CA certificate, gateway identity '%Y'", gateway);
382 }
383
384 if (auth_class == AUTH_CLASS_EAP)
385 {
386 /* username/password authentication ... */
387 str = nm_setting_vpn_get_data_item(vpn, "user");
388 if (str)
389 {
390 user = identification_create_from_string((char*)str);
391 str = nm_setting_vpn_get_secret(vpn, "password");
392 priv->creds->set_username_password(priv->creds, user, (char*)str);
393 }
394 }
395
396 if (auth_class == AUTH_CLASS_PUBKEY)
397 {
398 if (smartcard)
399 {
400 char *pin;
401
402 pin = (char*)nm_setting_vpn_get_secret(vpn, "password");
403 if (pin)
404 {
405 user = find_smartcard_key(priv, pin);
406 }
407 if (!user)
408 {
409 g_set_error(err, NM_VPN_PLUGIN_ERROR,
410 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
411 "no usable smartcard certificate found.");
412 gateway->destroy(gateway);
413 return FALSE;
414 }
415 }
416 /* ... or certificate/private key authenitcation */
417 else if ((str = nm_setting_vpn_get_data_item(vpn, "usercert")))
418 {
419 public_key_t *public;
420 private_key_t *private = NULL;
421
422 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
423 BUILD_FROM_FILE, str, BUILD_END);
424 if (!cert)
425 {
426 g_set_error(err, NM_VPN_PLUGIN_ERROR,
427 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
428 "Loading peer certificate failed.");
429 gateway->destroy(gateway);
430 return FALSE;
431 }
432 /* try agent */
433 str = nm_setting_vpn_get_secret(vpn, "agent");
434 if (agent && str)
435 {
436 public = cert->get_public_key(cert);
437 if (public)
438 {
439 private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
440 public->get_type(public),
441 BUILD_AGENT_SOCKET, str,
442 BUILD_PUBLIC_KEY, public,
443 BUILD_END);
444 public->destroy(public);
445 }
446 if (!private)
447 {
448 g_set_error(err, NM_VPN_PLUGIN_ERROR,
449 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
450 "Connecting to SSH agent failed.");
451 }
452 }
453 /* ... or key file */
454 str = nm_setting_vpn_get_data_item(vpn, "userkey");
455 if (!agent && str)
456 {
457 char *secret;
458
459 secret = (char*)nm_setting_vpn_get_secret(vpn, "password");
460 if (secret)
461 {
462 priv->creds->set_key_password(priv->creds, secret);
463 }
464 private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
465 KEY_RSA, BUILD_FROM_FILE, str, BUILD_END);
466 if (!private)
467 {
468 g_set_error(err, NM_VPN_PLUGIN_ERROR,
469 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
470 "Loading private key failed.");
471 }
472 }
473 if (private)
474 {
475 user = cert->get_subject(cert);
476 user = user->clone(user);
477 priv->creds->set_cert_and_key(priv->creds, cert, private);
478 }
479 else
480 {
481 DESTROY_IF(cert);
482 gateway->destroy(gateway);
483 return FALSE;
484 }
485 }
486 }
487
488 if (!user)
489 {
490 g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
491 "Configuration parameters missing.");
492 gateway->destroy(gateway);
493 return FALSE;
494 }
495
496 /**
497 * Set up configurations
498 */
499 ike_cfg = ike_cfg_create(TRUE, encap,
500 "0.0.0.0", IKEV2_UDP_PORT, (char*)address, IKEV2_UDP_PORT);
501 ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
502 peer_cfg = peer_cfg_create(priv->name, IKEV2, ike_cfg,
503 CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
504 36000, 0, /* rekey 10h, reauth none */
505 600, 600, /* jitter, over 10min */
506 TRUE, FALSE, /* mobike, aggressive */
507 0, 0, /* DPD delay, timeout */
508 virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
509 NULL, FALSE, NULL, NULL); /* pool, mediation */
510 auth = auth_cfg_create();
511 auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class);
512 auth->add(auth, AUTH_RULE_IDENTITY, user);
513 peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
514 auth = auth_cfg_create();
515 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
516 auth->add(auth, AUTH_RULE_IDENTITY, gateway);
517 peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
518
519 child_cfg = child_cfg_create(priv->name, &lifetime,
520 NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
521 ACTION_NONE, ACTION_NONE, ACTION_NONE, ipcomp,
522 0, 0, NULL, NULL, 0);
523 child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
524 ts = traffic_selector_create_dynamic(0, 0, 65535);
525 child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
526 ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
527 "0.0.0.0", 0,
528 "255.255.255.255", 65535);
529 child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
530 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
531
532 /**
533 * Prepare IKE_SA
534 */
535 ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
536 peer_cfg);
537 if (!ike_sa)
538 {
539 peer_cfg->destroy(peer_cfg);
540 g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
541 "IKE version not supported.");
542 return FALSE;
543 }
544 if (!ike_sa->get_peer_cfg(ike_sa))
545 {
546 ike_sa->set_peer_cfg(ike_sa, peer_cfg);
547 }
548 peer_cfg->destroy(peer_cfg);
549
550 /**
551 * Register listener, enable initiate-failure-detection hooks
552 */
553 priv->ike_sa = ike_sa;
554 priv->listener.ike_state_change = ike_state_change;
555 priv->listener.child_state_change = child_state_change;
556 charon->bus->add_listener(charon->bus, &priv->listener);
557
558 /**
559 * Initiate
560 */
561 child_cfg->get_ref(child_cfg);
562 if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
563 {
564 charon->bus->remove_listener(charon->bus, &priv->listener);
565 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
566
567 g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
568 "Initiating failed.");
569 return FALSE;
570 }
571 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
572 return TRUE;
573 }
574
575 /**
576 * NeedSecrets called from NM via DBUS
577 */
578 static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
579 char **setting_name, GError **error)
580 {
581 NMSettingVPN *settings;
582 const char *method, *path;
583
584 settings = NM_SETTING_VPN(nm_connection_get_setting(connection,
585 NM_TYPE_SETTING_VPN));
586 method = nm_setting_vpn_get_data_item(settings, "method");
587 if (method)
588 {
589 if (streq(method, "eap"))
590 {
591 if (nm_setting_vpn_get_secret(settings, "password"))
592 {
593 return FALSE;
594 }
595 }
596 else if (streq(method, "agent"))
597 {
598 if (nm_setting_vpn_get_secret(settings, "agent"))
599 {
600 return FALSE;
601 }
602 }
603 else if (streq(method, "key"))
604 {
605 path = nm_setting_vpn_get_data_item(settings, "userkey");
606 if (path)
607 {
608 private_key_t *key;
609
610 /* try to load/decrypt the private key */
611 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
612 KEY_RSA, BUILD_FROM_FILE, path, BUILD_END);
613 if (key)
614 {
615 key->destroy(key);
616 return FALSE;
617 }
618 }
619 }
620 else if streq(method, "smartcard")
621 {
622 if (nm_setting_vpn_get_secret(settings, "password"))
623 {
624 return FALSE;
625 }
626 }
627 }
628 *setting_name = NM_SETTING_VPN_SETTING_NAME;
629 return TRUE;
630 }
631
632 /**
633 * Disconnect called from NM via DBUS
634 */
635 static gboolean disconnect(NMVPNPlugin *plugin, GError **err)
636 {
637 NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
638 enumerator_t *enumerator;
639 ike_sa_t *ike_sa;
640 u_int id;
641
642 /* our ike_sa pointer might be invalid, lookup sa */
643 enumerator = charon->controller->create_ike_sa_enumerator(
644 charon->controller, TRUE);
645 while (enumerator->enumerate(enumerator, &ike_sa))
646 {
647 if (priv->ike_sa == ike_sa)
648 {
649 id = ike_sa->get_unique_id(ike_sa);
650 enumerator->destroy(enumerator);
651 charon->controller->terminate_ike(charon->controller, id,
652 controller_cb_empty, NULL, 0);
653 return TRUE;
654 }
655 }
656 enumerator->destroy(enumerator);
657
658 g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL,
659 "Connection not found.");
660 return FALSE;
661 }
662
663 /**
664 * Initializer
665 */
666 static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
667 {
668 NMStrongswanPluginPrivate *priv;
669
670 priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
671 priv->plugin = NM_VPN_PLUGIN(plugin);
672 memset(&priv->listener, 0, sizeof(listener_t));
673 priv->listener.child_updown = child_updown;
674 priv->listener.ike_rekey = ike_rekey;
675 }
676
677 /**
678 * Class constructor
679 */
680 static void nm_strongswan_plugin_class_init(
681 NMStrongswanPluginClass *strongswan_class)
682 {
683 NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS(strongswan_class);
684
685 g_type_class_add_private(G_OBJECT_CLASS(strongswan_class),
686 sizeof(NMStrongswanPluginPrivate));
687 parent_class->connect = connect_;
688 parent_class->need_secrets = need_secrets;
689 parent_class->disconnect = disconnect;
690 }
691
692 /**
693 * Object constructor
694 */
695 NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
696 nm_handler_t *handler)
697 {
698 NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_object_new (
699 NM_TYPE_STRONGSWAN_PLUGIN,
700 NM_VPN_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN,
701 NULL);
702 if (plugin)
703 {
704 NMStrongswanPluginPrivate *priv;
705
706 priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
707 priv->creds = creds;
708 priv->handler = handler;
709 priv->name = NULL;
710 }
711 return plugin;
712 }
713