2 * Copyright (C) 2017 Lubomir Rintel
4 * Copyright (C) 2013 Tobias Brunner
5 * Copyright (C) 2008-2009 Martin Willi
6 * Hochschule fuer Technik Rapperswil
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include "nm_service.h"
22 #include <networking/host.h>
23 #include <utils/identification.h>
24 #include <config/peer_cfg.h>
25 #include <credentials/certificates/x509.h>
29 G_DEFINE_TYPE(NMStrongswanPlugin
, nm_strongswan_plugin
, NM_TYPE_VPN_SERVICE_PLUGIN
)
32 * Private data of NMStrongswanPlugin
35 /* implements bus listener interface */
37 /* IKE_SA we are listening on */
39 /* backref to public plugin */
40 NMVpnServicePlugin
*plugin
;
41 /* credentials to use for authentication */
43 /* attribute handler for DNS/NBNS server information */
44 nm_handler_t
*handler
;
45 /* name of the connection */
47 } NMStrongswanPluginPrivate
;
49 #define NM_STRONGSWAN_PLUGIN_GET_PRIVATE(o) \
50 (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
51 NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate))
54 * convert enumerated handler chunks to a UINT_ARRAY GValue
56 static GVariant
* handler_to_variant(nm_handler_t
*handler
,
57 configuration_attribute_type_t type
)
59 GVariantBuilder builder
;
60 enumerator_t
*enumerator
;
63 g_variant_builder_init (&builder
, G_VARIANT_TYPE ("au"));
65 enumerator
= handler
->create_enumerator(handler
, type
);
66 while (enumerator
->enumerate(enumerator
, &chunk
))
68 g_variant_builder_add (&builder
, "u",
69 g_variant_new_uint32 (*(uint32_t*)chunk
.ptr
));
71 enumerator
->destroy(enumerator
);
73 return g_variant_builder_end (&builder
);
77 * signal IPv4 config to NM, set connection as established
79 static void signal_ipv4_config(NMVpnServicePlugin
*plugin
,
80 ike_sa_t
*ike_sa
, child_sa_t
*child_sa
)
82 NMStrongswanPluginPrivate
*priv
= NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin
);
83 GVariantBuilder builder
;
84 enumerator_t
*enumerator
;
86 nm_handler_t
*handler
;
88 g_variant_builder_init (&builder
, G_VARIANT_TYPE_VARDICT
);
90 handler
= priv
->handler
;
92 /* NM apparently requires to know the gateway */
93 other
= ike_sa
->get_other_host(ike_sa
);
94 g_variant_builder_add (&builder
, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY
,
95 g_variant_new_uint32 (*(uint32_t*)other
->get_address(other
).ptr
));
97 /* NM installs this IP address on the interface above, so we use the VIP if
100 enumerator
= ike_sa
->create_virtual_ip_enumerator(ike_sa
, TRUE
);
101 if (!enumerator
->enumerate(enumerator
, &me
))
103 me
= ike_sa
->get_my_host(ike_sa
);
105 enumerator
->destroy(enumerator
);
106 g_variant_builder_add (&builder
, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS
,
107 g_variant_new_uint32 (*(uint32_t*)other
->get_address(me
).ptr
));
109 g_variant_builder_add (&builder
, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX
,
110 g_variant_new_uint32 (me
->get_address(me
).len
* 8));
112 /* prevent NM from changing the default route. we set our own route in our
115 g_variant_builder_add (&builder
, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT
,
116 g_variant_new_boolean (TRUE
));
119 g_variant_builder_add (&builder
, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DNS
,
120 handler_to_variant(handler
, INTERNAL_IP4_DNS
));
122 g_variant_builder_add (&builder
, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NBNS
,
123 handler_to_variant(handler
, INTERNAL_IP4_NBNS
));
125 handler
->reset(handler
);
127 nm_vpn_service_plugin_set_ip4_config(plugin
, g_variant_builder_end (&builder
));
131 * signal failure to NM, connecting failed
133 static void signal_failure(NMVpnServicePlugin
*plugin
, NMVpnPluginFailure failure
)
135 nm_handler_t
*handler
= NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin
)->handler
;
137 handler
->reset(handler
);
139 nm_vpn_service_plugin_failure(plugin
, failure
);
143 * Implementation of listener_t.ike_state_change
145 static bool ike_state_change(listener_t
*listener
, ike_sa_t
*ike_sa
,
146 ike_sa_state_t state
)
148 NMStrongswanPluginPrivate
*private = (NMStrongswanPluginPrivate
*)listener
;
150 if (private->ike_sa
== ike_sa
&& state
== IKE_DESTROYING
)
152 signal_failure(private->plugin
, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED
);
159 * Implementation of listener_t.child_state_change
161 static bool child_state_change(listener_t
*listener
, ike_sa_t
*ike_sa
,
162 child_sa_t
*child_sa
, child_sa_state_t state
)
164 NMStrongswanPluginPrivate
*private = (NMStrongswanPluginPrivate
*)listener
;
166 if (private->ike_sa
== ike_sa
&& state
== CHILD_DESTROYING
)
168 signal_failure(private->plugin
, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED
);
175 * Implementation of listener_t.child_updown
177 static bool child_updown(listener_t
*listener
, ike_sa_t
*ike_sa
,
178 child_sa_t
*child_sa
, bool up
)
180 NMStrongswanPluginPrivate
*private = (NMStrongswanPluginPrivate
*)listener
;
182 if (private->ike_sa
== ike_sa
)
185 { /* disable initiate-failure-detection hooks */
186 private->listener
.ike_state_change
= NULL
;
187 private->listener
.child_state_change
= NULL
;
188 signal_ipv4_config(private->plugin
, ike_sa
, child_sa
);
192 signal_failure(private->plugin
, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED
);
200 * Implementation of listener_t.ike_rekey
202 static bool ike_rekey(listener_t
*listener
, ike_sa_t
*old
, ike_sa_t
*new)
204 NMStrongswanPluginPrivate
*private = (NMStrongswanPluginPrivate
*)listener
;
206 if (private->ike_sa
== old
)
207 { /* follow a rekeyed IKE_SA */
208 private->ike_sa
= new;
214 * Find a certificate for which we have a private key on a smartcard
216 static identification_t
*find_smartcard_key(NMStrongswanPluginPrivate
*priv
,
219 enumerator_t
*enumerator
, *sans
;
220 identification_t
*id
= NULL
;
226 enumerator
= lib
->credmgr
->create_cert_enumerator(lib
->credmgr
,
227 CERT_X509
, KEY_ANY
, NULL
, FALSE
);
228 while (enumerator
->enumerate(enumerator
, &cert
))
230 x509
= (x509_t
*)cert
;
232 /* there might be a lot of certificates, filter them by usage */
233 if ((x509
->get_flags(x509
) & X509_CLIENT_AUTH
) &&
234 !(x509
->get_flags(x509
) & X509_CA
))
236 keyid
= x509
->get_subjectKeyIdentifier(x509
);
239 /* try to find a private key by the certificate keyid */
240 priv
->creds
->set_pin(priv
->creds
, keyid
, pin
);
241 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
,
242 KEY_ANY
, BUILD_PKCS11_KEYID
, keyid
, BUILD_END
);
245 /* prefer a more convenient subjectAltName */
246 sans
= x509
->create_subjectAltName_enumerator(x509
);
247 if (!sans
->enumerate(sans
, &id
))
249 id
= cert
->get_subject(cert
);
254 DBG1(DBG_CFG
, "using smartcard certificate '%Y'", id
);
255 priv
->creds
->set_cert_and_key(priv
->creds
,
256 cert
->get_ref(cert
), key
);
262 enumerator
->destroy(enumerator
);
267 * Connect function called from NM via DBUS
269 static gboolean
connect_(NMVpnServicePlugin
*plugin
, NMConnection
*connection
,
272 NMStrongswanPluginPrivate
*priv
;
273 NMSettingConnection
*conn
;
275 enumerator_t
*enumerator
;
276 identification_t
*user
= NULL
, *gateway
= NULL
;
277 const char *address
, *str
;
278 bool virtual, encap
, proposal
;
281 peer_cfg_t
*peer_cfg
;
282 child_cfg_t
*child_cfg
;
283 traffic_selector_t
*ts
;
286 auth_class_t auth_class
= AUTH_CLASS_EAP
;
287 certificate_t
*cert
= NULL
;
289 bool agent
= FALSE
, smartcard
= FALSE
, loose_gateway_id
= FALSE
;
290 peer_cfg_create_t peer
= {
291 .cert_policy
= CERT_SEND_IF_ASKED
,
292 .unique
= UNIQUE_REPLACE
,
294 .rekey_time
= 36000, /* 10h */
295 .jitter_time
= 600, /* 10min */
296 .over_time
= 600, /* 10min */
298 child_cfg_create_t child
= {
301 .life
= 10800 /* 3h */,
302 .rekey
= 10200 /* 2h50min */,
303 .jitter
= 300 /* 5min */
312 priv
= NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin
);
313 conn
= NM_SETTING_CONNECTION(nm_connection_get_setting(connection
,
314 NM_TYPE_SETTING_CONNECTION
));
315 vpn
= NM_SETTING_VPN(nm_connection_get_setting(connection
,
316 NM_TYPE_SETTING_VPN
));
321 priv
->name
= strdup(nm_setting_connection_get_id(conn
));
322 DBG1(DBG_CFG
, "received initiate for NetworkManager connection %s",
325 nm_setting_to_string(NM_SETTING(vpn
)));
326 address
= nm_setting_vpn_get_data_item(vpn
, "address");
327 if (!address
|| !*address
)
329 g_set_error(err
, NM_VPN_PLUGIN_ERROR
, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS
,
330 "Gateway address missing.");
333 str
= nm_setting_vpn_get_data_item(vpn
, "virtual");
334 virtual = streq(str
, "yes");
335 str
= nm_setting_vpn_get_data_item(vpn
, "encap");
336 encap
= streq(str
, "yes");
337 str
= nm_setting_vpn_get_data_item(vpn
, "ipcomp");
338 child
.options
|= streq(str
, "yes") ? OPT_IPCOMP
: 0;
339 str
= nm_setting_vpn_get_data_item(vpn
, "method");
340 if (streq(str
, "psk"))
342 auth_class
= AUTH_CLASS_PSK
;
344 else if (streq(str
, "agent"))
346 auth_class
= AUTH_CLASS_PUBKEY
;
349 else if (streq(str
, "key"))
351 auth_class
= AUTH_CLASS_PUBKEY
;
353 else if (streq(str
, "smartcard"))
355 auth_class
= AUTH_CLASS_PUBKEY
;
360 * Register credentials
362 priv
->creds
->clear(priv
->creds
);
364 /* gateway/CA cert */
365 str
= nm_setting_vpn_get_data_item(vpn
, "certificate");
368 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
369 BUILD_FROM_FILE
, str
, BUILD_END
);
372 g_set_error(err
, NM_VPN_PLUGIN_ERROR
,
373 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS
,
374 "Loading gateway certificate failed.");
377 priv
->creds
->add_certificate(priv
->creds
, cert
);
379 x509
= (x509_t
*)cert
;
380 if (!(x509
->get_flags(x509
) & X509_CA
))
381 { /* For a gateway certificate, we use the cert subject as identity. */
382 gateway
= cert
->get_subject(cert
);
383 gateway
= gateway
->clone(gateway
);
384 DBG1(DBG_CFG
, "using gateway certificate, identity '%Y'", gateway
);
389 /* no certificate defined, fall back to system-wide CA certificates */
390 priv
->creds
->load_ca_dir(priv
->creds
, lib
->settings
->get_str(
391 lib
->settings
, "charon-nm.ca_dir", NM_CA_DIR
));
395 /* If the user configured a CA certificate, we use the IP/DNS
396 * of the gateway as its identity. This identity will be used for
397 * certificate lookup and requires the configured IP/DNS to be
398 * included in the gateway certificate. */
399 gateway
= identification_create_from_string((char*)address
);
400 DBG1(DBG_CFG
, "using CA certificate, gateway identity '%Y'", gateway
);
401 loose_gateway_id
= TRUE
;
404 if (auth_class
== AUTH_CLASS_EAP
||
405 auth_class
== AUTH_CLASS_PSK
)
407 /* username/password or PSK authentication ... */
408 str
= nm_setting_vpn_get_data_item(vpn
, "user");
411 user
= identification_create_from_string((char*)str
);
412 str
= nm_setting_vpn_get_secret(vpn
, "password");
413 if (auth_class
== AUTH_CLASS_PSK
&&
416 g_set_error(err
, NM_VPN_PLUGIN_ERROR
,
417 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS
,
418 "pre-shared key is too short.");
419 gateway
->destroy(gateway
);
423 priv
->creds
->set_username_password(priv
->creds
, user
, (char*)str
);
427 if (auth_class
== AUTH_CLASS_PUBKEY
)
433 pin
= (char*)nm_setting_vpn_get_secret(vpn
, "password");
436 user
= find_smartcard_key(priv
, pin
);
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
);
447 /* ... or certificate/private key authenitcation */
448 else if ((str
= nm_setting_vpn_get_data_item(vpn
, "usercert")))
450 public_key_t
*public;
451 private_key_t
*private = NULL
;
453 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
454 BUILD_FROM_FILE
, str
, BUILD_END
);
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
);
464 str
= nm_setting_vpn_get_secret(vpn
, "agent");
467 public = cert
->get_public_key(cert
);
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,
475 public->destroy(public);
479 g_set_error(err
, NM_VPN_PLUGIN_ERROR
,
480 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS
,
481 "Connecting to SSH agent failed.");
484 /* ... or key file */
485 str
= nm_setting_vpn_get_data_item(vpn
, "userkey");
490 secret
= (char*)nm_setting_vpn_get_secret(vpn
, "password");
493 priv
->creds
->set_key_password(priv
->creds
, secret
);
495 private = lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
,
496 KEY_RSA
, BUILD_FROM_FILE
, str
, BUILD_END
);
499 g_set_error(err
, NM_VPN_PLUGIN_ERROR
,
500 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS
,
501 "Loading private key failed.");
506 user
= cert
->get_subject(cert
);
507 user
= user
->clone(user
);
508 priv
->creds
->set_cert_and_key(priv
->creds
, cert
, private);
513 gateway
->destroy(gateway
);
521 g_set_error(err
, NM_VPN_PLUGIN_ERROR
, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS
,
522 "Configuration parameters missing.");
523 gateway
->destroy(gateway
);
528 * Set up configurations
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_YES
, 0);
535 str
= nm_setting_vpn_get_data_item(vpn
, "proposal");
536 proposal
= streq(str
, "yes");
537 str
= nm_setting_vpn_get_data_item(vpn
, "ike");
538 if (proposal
&& str
&& strlen(str
))
540 enumerator
= enumerator_create_token(str
, ";", "");
541 while (enumerator
->enumerate(enumerator
, &str
))
543 prop
= proposal_create_from_string(PROTO_IKE
, str
);
546 g_set_error(err
, NM_VPN_PLUGIN_ERROR
,
547 NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED
,
548 "Invalid IKE proposal.");
549 enumerator
->destroy(enumerator
);
550 ike_cfg
->destroy(ike_cfg
);
551 gateway
->destroy(gateway
);
555 ike_cfg
->add_proposal(ike_cfg
, prop
);
557 enumerator
->destroy(enumerator
);
561 ike_cfg
->add_proposal(ike_cfg
, proposal_create_default(PROTO_IKE
));
562 ike_cfg
->add_proposal(ike_cfg
, proposal_create_default_aead(PROTO_IKE
));
565 peer_cfg
= peer_cfg_create(priv
->name
, ike_cfg
, &peer
);
568 peer_cfg
->add_virtual_ip(peer_cfg
, host_create_from_string("0.0.0.0", 0));
570 auth
= auth_cfg_create();
571 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, auth_class
);
572 auth
->add(auth
, AUTH_RULE_IDENTITY
, user
);
573 peer_cfg
->add_auth_cfg(peer_cfg
, auth
, TRUE
);
574 auth
= auth_cfg_create();
575 if (auth_class
== AUTH_CLASS_PSK
)
577 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PSK
);
581 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
583 auth
->add(auth
, AUTH_RULE_IDENTITY
, gateway
);
584 auth
->add(auth
, AUTH_RULE_IDENTITY_LOOSE
, loose_gateway_id
);
585 peer_cfg
->add_auth_cfg(peer_cfg
, auth
, FALSE
);
587 child_cfg
= child_cfg_create(priv
->name
, &child
);
588 str
= nm_setting_vpn_get_data_item(vpn
, "esp");
589 if (proposal
&& str
&& strlen(str
))
591 enumerator
= enumerator_create_token(str
, ";", "");
592 while (enumerator
->enumerate(enumerator
, &str
))
594 prop
= proposal_create_from_string(PROTO_ESP
, str
);
597 g_set_error(err
, NM_VPN_PLUGIN_ERROR
,
598 NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED
,
599 "Invalid ESP proposal.");
600 enumerator
->destroy(enumerator
);
601 child_cfg
->destroy(child_cfg
);
602 peer_cfg
->destroy(peer_cfg
);
605 child_cfg
->add_proposal(child_cfg
, prop
);
607 enumerator
->destroy(enumerator
);
611 child_cfg
->add_proposal(child_cfg
, proposal_create_default(PROTO_ESP
));
612 child_cfg
->add_proposal(child_cfg
, proposal_create_default_aead(PROTO_ESP
));
614 ts
= traffic_selector_create_dynamic(0, 0, 65535);
615 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, ts
);
616 ts
= traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE
,
618 "255.255.255.255", 65535);
619 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, ts
);
620 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
625 ike_sa
= charon
->ike_sa_manager
->checkout_by_config(charon
->ike_sa_manager
,
629 peer_cfg
->destroy(peer_cfg
);
630 g_set_error(err
, NM_VPN_PLUGIN_ERROR
, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED
,
631 "IKE version not supported.");
634 if (!ike_sa
->get_peer_cfg(ike_sa
))
636 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
638 peer_cfg
->destroy(peer_cfg
);
641 * Register listener, enable initiate-failure-detection hooks
643 priv
->ike_sa
= ike_sa
;
644 priv
->listener
.ike_state_change
= ike_state_change
;
645 priv
->listener
.child_state_change
= child_state_change
;
646 charon
->bus
->add_listener(charon
->bus
, &priv
->listener
);
651 child_cfg
->get_ref(child_cfg
);
652 if (ike_sa
->initiate(ike_sa
, child_cfg
, 0, NULL
, NULL
) != SUCCESS
)
654 charon
->bus
->remove_listener(charon
->bus
, &priv
->listener
);
655 charon
->ike_sa_manager
->checkin_and_destroy(charon
->ike_sa_manager
, ike_sa
);
657 g_set_error(err
, NM_VPN_PLUGIN_ERROR
, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED
,
658 "Initiating failed.");
661 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
666 * NeedSecrets called from NM via DBUS
668 static gboolean
need_secrets(NMVpnServicePlugin
*plugin
, NMConnection
*connection
,
669 const char **setting_name
, GError
**error
)
671 NMSettingVpn
*settings
;
672 const char *method
, *path
;
674 settings
= NM_SETTING_VPN(nm_connection_get_setting(connection
,
675 NM_TYPE_SETTING_VPN
));
676 method
= nm_setting_vpn_get_data_item(settings
, "method");
679 if (streq(method
, "eap") || streq(method
, "psk"))
681 if (nm_setting_vpn_get_secret(settings
, "password"))
686 else if (streq(method
, "agent"))
688 if (nm_setting_vpn_get_secret(settings
, "agent"))
693 else if (streq(method
, "key"))
695 path
= nm_setting_vpn_get_data_item(settings
, "userkey");
700 /* try to load/decrypt the private key */
701 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
,
702 KEY_RSA
, BUILD_FROM_FILE
, path
, BUILD_END
);
708 else if (nm_setting_vpn_get_secret(settings
, "password"))
714 else if (streq(method
, "smartcard"))
716 if (nm_setting_vpn_get_secret(settings
, "password"))
722 *setting_name
= NM_SETTING_VPN_SETTING_NAME
;
727 * The actual disconnection
729 static gboolean
do_disconnect(gpointer plugin
)
731 NMStrongswanPluginPrivate
*priv
= NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin
);
732 enumerator_t
*enumerator
;
736 /* our ike_sa pointer might be invalid, lookup sa */
737 enumerator
= charon
->controller
->create_ike_sa_enumerator(
738 charon
->controller
, TRUE
);
739 while (enumerator
->enumerate(enumerator
, &ike_sa
))
741 if (priv
->ike_sa
== ike_sa
)
743 id
= ike_sa
->get_unique_id(ike_sa
);
744 enumerator
->destroy(enumerator
);
745 charon
->controller
->terminate_ike(charon
->controller
, id
,
746 controller_cb_empty
, NULL
, 0);
750 enumerator
->destroy(enumerator
);
752 g_debug("Connection not found.");
757 * Disconnect called from NM via DBUS
759 static gboolean
disconnect(NMVpnServicePlugin
*plugin
, GError
**err
)
761 /* enqueue the actual disconnection, because we may be called in
762 * response to a listener_t callback and the SA enumeration would
763 * possibly deadlock. */
764 g_idle_add(do_disconnect
, plugin
);
772 static void nm_strongswan_plugin_init(NMStrongswanPlugin
*plugin
)
774 NMStrongswanPluginPrivate
*priv
;
776 priv
= NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin
);
777 priv
->plugin
= NM_VPN_SERVICE_PLUGIN(plugin
);
778 memset(&priv
->listener
, 0, sizeof(listener_t
));
779 priv
->listener
.child_updown
= child_updown
;
780 priv
->listener
.ike_rekey
= ike_rekey
;
787 static void nm_strongswan_plugin_class_init(
788 NMStrongswanPluginClass
*strongswan_class
)
790 NMVpnServicePluginClass
*parent_class
= NM_VPN_SERVICE_PLUGIN_CLASS(strongswan_class
);
792 g_type_class_add_private(G_OBJECT_CLASS(strongswan_class
),
793 sizeof(NMStrongswanPluginPrivate
));
794 parent_class
->connect
= connect_
;
795 parent_class
->need_secrets
= need_secrets
;
796 parent_class
->disconnect
= disconnect
;
802 NMStrongswanPlugin
*nm_strongswan_plugin_new(nm_creds_t
*creds
,
803 nm_handler_t
*handler
)
805 GError
*error
= NULL
;
807 NMStrongswanPlugin
*plugin
= (NMStrongswanPlugin
*)g_initable_new (
808 NM_TYPE_STRONGSWAN_PLUGIN
,
811 NM_VPN_SERVICE_PLUGIN_DBUS_SERVICE_NAME
, NM_DBUS_SERVICE_STRONGSWAN
,
816 NMStrongswanPluginPrivate
*priv
;
818 /* the rest of the initialization happened in _init above */
819 priv
= NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin
);
821 priv
->handler
= handler
;
825 g_warning ("Failed to initialize a plugin instance: %s", error
->message
);
826 g_error_free (error
);