]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/charon-nm/nm/nm_service.c
ike: Add an additional but separate AEAD proposal to CHILD config
[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 ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
536 peer_cfg = peer_cfg_create(priv->name, ike_cfg,
537 CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
538 36000, 0, /* rekey 10h, reauth none */
539 600, 600, /* jitter, over 10min */
540 TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
541 0, 0, /* DPD delay, timeout */
542 FALSE, NULL, NULL); /* mediation */
543 if (virtual)
544 {
545 peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
546 }
547 auth = auth_cfg_create();
548 auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class);
549 auth->add(auth, AUTH_RULE_IDENTITY, user);
550 peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
551 auth = auth_cfg_create();
552 if (auth_class == AUTH_CLASS_PSK)
553 {
554 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
555 }
556 else
557 {
558 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
559 }
560 auth->add(auth, AUTH_RULE_IDENTITY, gateway);
561 auth->add(auth, AUTH_RULE_IDENTITY_LOOSE, loose_gateway_id);
562 peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
563
564 child_cfg = child_cfg_create(priv->name, &lifetime,
565 NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
566 ACTION_NONE, ACTION_NONE, ACTION_NONE, ipcomp,
567 0, 0, NULL, NULL, 0);
568 child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
569 child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
570 ts = traffic_selector_create_dynamic(0, 0, 65535);
571 child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
572 ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
573 "0.0.0.0", 0,
574 "255.255.255.255", 65535);
575 child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
576 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
577
578 /**
579 * Prepare IKE_SA
580 */
581 ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
582 peer_cfg);
583 if (!ike_sa)
584 {
585 peer_cfg->destroy(peer_cfg);
586 g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
587 "IKE version not supported.");
588 return FALSE;
589 }
590 if (!ike_sa->get_peer_cfg(ike_sa))
591 {
592 ike_sa->set_peer_cfg(ike_sa, peer_cfg);
593 }
594 peer_cfg->destroy(peer_cfg);
595
596 /**
597 * Register listener, enable initiate-failure-detection hooks
598 */
599 priv->ike_sa = ike_sa;
600 priv->listener.ike_state_change = ike_state_change;
601 priv->listener.child_state_change = child_state_change;
602 charon->bus->add_listener(charon->bus, &priv->listener);
603
604 /**
605 * Initiate
606 */
607 child_cfg->get_ref(child_cfg);
608 if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
609 {
610 charon->bus->remove_listener(charon->bus, &priv->listener);
611 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
612
613 g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
614 "Initiating failed.");
615 return FALSE;
616 }
617 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
618 return TRUE;
619 }
620
621 /**
622 * NeedSecrets called from NM via DBUS
623 */
624 static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
625 char **setting_name, GError **error)
626 {
627 NMSettingVPN *settings;
628 const char *method, *path;
629
630 settings = NM_SETTING_VPN(nm_connection_get_setting(connection,
631 NM_TYPE_SETTING_VPN));
632 method = nm_setting_vpn_get_data_item(settings, "method");
633 if (method)
634 {
635 if (streq(method, "eap") || streq(method, "psk"))
636 {
637 if (nm_setting_vpn_get_secret(settings, "password"))
638 {
639 return FALSE;
640 }
641 }
642 else if (streq(method, "agent"))
643 {
644 if (nm_setting_vpn_get_secret(settings, "agent"))
645 {
646 return FALSE;
647 }
648 }
649 else if (streq(method, "key"))
650 {
651 path = nm_setting_vpn_get_data_item(settings, "userkey");
652 if (path)
653 {
654 private_key_t *key;
655
656 /* try to load/decrypt the private key */
657 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
658 KEY_RSA, BUILD_FROM_FILE, path, BUILD_END);
659 if (key)
660 {
661 key->destroy(key);
662 return FALSE;
663 }
664 else if (nm_setting_vpn_get_secret(settings, "password"))
665 {
666 return FALSE;
667 }
668 }
669 }
670 else if (streq(method, "smartcard"))
671 {
672 if (nm_setting_vpn_get_secret(settings, "password"))
673 {
674 return FALSE;
675 }
676 }
677 }
678 *setting_name = NM_SETTING_VPN_SETTING_NAME;
679 return TRUE;
680 }
681
682 /**
683 * Disconnect called from NM via DBUS
684 */
685 static gboolean disconnect(NMVPNPlugin *plugin, GError **err)
686 {
687 NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
688 enumerator_t *enumerator;
689 ike_sa_t *ike_sa;
690 u_int id;
691
692 /* our ike_sa pointer might be invalid, lookup sa */
693 enumerator = charon->controller->create_ike_sa_enumerator(
694 charon->controller, TRUE);
695 while (enumerator->enumerate(enumerator, &ike_sa))
696 {
697 if (priv->ike_sa == ike_sa)
698 {
699 id = ike_sa->get_unique_id(ike_sa);
700 enumerator->destroy(enumerator);
701 charon->controller->terminate_ike(charon->controller, id,
702 controller_cb_empty, NULL, 0);
703 return TRUE;
704 }
705 }
706 enumerator->destroy(enumerator);
707
708 g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL,
709 "Connection not found.");
710 return FALSE;
711 }
712
713 /**
714 * Initializer
715 */
716 static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
717 {
718 NMStrongswanPluginPrivate *priv;
719
720 priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
721 priv->plugin = NM_VPN_PLUGIN(plugin);
722 memset(&priv->listener, 0, sizeof(listener_t));
723 priv->listener.child_updown = child_updown;
724 priv->listener.ike_rekey = ike_rekey;
725 priv->tun = tun_device_create(NULL);
726 priv->name = NULL;
727 }
728
729 /**
730 * Destructor
731 */
732 static void nm_strongswan_plugin_dispose(GObject *obj)
733 {
734 NMStrongswanPlugin *plugin;
735 NMStrongswanPluginPrivate *priv;
736
737 plugin = NM_STRONGSWAN_PLUGIN(obj);
738 priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
739 if (priv->tun)
740 {
741 priv->tun->destroy(priv->tun);
742 priv->tun = NULL;
743 }
744 }
745
746 /**
747 * Class constructor
748 */
749 static void nm_strongswan_plugin_class_init(
750 NMStrongswanPluginClass *strongswan_class)
751 {
752 NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS(strongswan_class);
753
754 g_type_class_add_private(G_OBJECT_CLASS(strongswan_class),
755 sizeof(NMStrongswanPluginPrivate));
756 parent_class->connect = connect_;
757 parent_class->need_secrets = need_secrets;
758 parent_class->disconnect = disconnect;
759 G_OBJECT_CLASS(strongswan_class)->dispose = nm_strongswan_plugin_dispose;
760 }
761
762 /**
763 * Object constructor
764 */
765 NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
766 nm_handler_t *handler)
767 {
768 NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_object_new (
769 NM_TYPE_STRONGSWAN_PLUGIN,
770 NM_VPN_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN,
771 NULL);
772 if (plugin)
773 {
774 NMStrongswanPluginPrivate *priv;
775
776 /* the rest of the initialization happened in _init above */
777 priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
778 priv->creds = creds;
779 priv->handler = handler;
780 }
781 return plugin;
782 }