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