nm_service.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  1. /*
  2. * Copyright (C) 2017 Lubomir Rintel
  3. *
  4. * Copyright (C) 2013-2019 Tobias Brunner
  5. * Copyright (C) 2008-2009 Martin Willi
  6. * HSR Hochschule fuer Technik Rapperswil
  7. *
  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>.
  12. *
  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
  16. * for more details.
  17. */
  18. #include "nm_service.h"
  19. #include <daemon.h>
  20. #include <networking/host.h>
  21. #include <utils/identification.h>
  22. #include <config/peer_cfg.h>
  23. #include <credentials/certificates/x509.h>
  24. #include <stdio.h>
  25. G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_SERVICE_PLUGIN)
  26. /**
  27. * Private data of NMStrongswanPlugin
  28. */
  29. typedef struct {
  30. /* implements bus listener interface */
  31. listener_t listener;
  32. /* IKE_SA we are listening on */
  33. ike_sa_t *ike_sa;
  34. /* backref to public plugin */
  35. NMVpnServicePlugin *plugin;
  36. /* credentials to use for authentication */
  37. nm_creds_t *creds;
  38. /* attribute handler for DNS/NBNS server information */
  39. nm_handler_t *handler;
  40. /* name of the connection */
  41. char *name;
  42. } NMStrongswanPluginPrivate;
  43. #define NM_STRONGSWAN_PLUGIN_GET_PRIVATE(o) \
  44. (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
  45. NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate))
  46. /**
  47. * Convert an address chunk to a GValue
  48. */
  49. static GVariant *addr_to_variant(chunk_t addr)
  50. {
  51. GVariantBuilder builder;
  52. int i;
  53. switch (addr.len)
  54. {
  55. case 4:
  56. return g_variant_new_uint32 (*(uint32_t*)addr.ptr);
  57. case 16:
  58. g_variant_builder_init (&builder, G_VARIANT_TYPE ("ay"));
  59. for (i = 0; i < addr.len; i++)
  60. {
  61. g_variant_builder_add (&builder, "y", addr.ptr[i]);
  62. }
  63. return g_variant_builder_end (&builder);
  64. default:
  65. return NULL;
  66. }
  67. }
  68. /**
  69. * Convert a host to a GValue
  70. */
  71. static GVariant *host_to_variant(host_t *host)
  72. {
  73. return addr_to_variant(host->get_address(host));
  74. }
  75. /**
  76. * Convert enumerated handler chunks to a GValue
  77. */
  78. static GVariant* handler_to_variant(nm_handler_t *handler, char *variant_type,
  79. configuration_attribute_type_t type)
  80. {
  81. GVariantBuilder builder;
  82. enumerator_t *enumerator;
  83. chunk_t *chunk;
  84. g_variant_builder_init (&builder, G_VARIANT_TYPE (variant_type));
  85. enumerator = handler->create_enumerator(handler, type);
  86. while (enumerator->enumerate(enumerator, &chunk))
  87. {
  88. g_variant_builder_add_value (&builder, addr_to_variant(*chunk));
  89. }
  90. enumerator->destroy(enumerator);
  91. return g_variant_builder_end (&builder);
  92. }
  93. /**
  94. * Signal IP config to NM, set connection as established
  95. */
  96. static void signal_ip_config(NMVpnServicePlugin *plugin,
  97. ike_sa_t *ike_sa, child_sa_t *child_sa)
  98. {
  99. NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
  100. GVariantBuilder builder, ip4builder, ip6builder;
  101. GVariant *ip4config, *ip6config;
  102. enumerator_t *enumerator;
  103. host_t *me, *other, *vip4 = NULL, *vip6 = NULL;
  104. nm_handler_t *handler;
  105. g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
  106. g_variant_builder_init (&ip4builder, G_VARIANT_TYPE_VARDICT);
  107. g_variant_builder_init (&ip6builder, G_VARIANT_TYPE_VARDICT);
  108. handler = priv->handler;
  109. /* NM apparently requires to know the gateway */
  110. other = ike_sa->get_other_host(ike_sa);
  111. g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY,
  112. host_to_variant(other));
  113. /* pass the first virtual IPs we got or use the physical IP */
  114. enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
  115. while (enumerator->enumerate(enumerator, &me))
  116. {
  117. switch (me->get_family(me))
  118. {
  119. case AF_INET:
  120. if (!vip4)
  121. {
  122. vip4 = me;
  123. }
  124. break;
  125. case AF_INET6:
  126. if (!vip6)
  127. {
  128. vip6 = me;
  129. }
  130. break;
  131. }
  132. }
  133. enumerator->destroy(enumerator);
  134. if (!vip4 && !vip6)
  135. {
  136. me = ike_sa->get_my_host(ike_sa);
  137. switch (me->get_family(me))
  138. {
  139. case AF_INET:
  140. vip4 = me;
  141. break;
  142. case AF_INET6:
  143. vip6 = me;
  144. break;
  145. }
  146. }
  147. if (vip4)
  148. {
  149. g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS,
  150. host_to_variant(vip4));
  151. g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX,
  152. g_variant_new_uint32 (vip4->get_address(vip4).len * 8));
  153. /* prevent NM from changing the default route. we set our own route in our
  154. * own routing table
  155. */
  156. g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT,
  157. g_variant_new_boolean (TRUE));
  158. g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DNS,
  159. handler_to_variant(handler, "au", INTERNAL_IP4_DNS));
  160. g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NBNS,
  161. handler_to_variant(handler, "au", INTERNAL_IP4_NBNS));
  162. }
  163. if (vip6)
  164. {
  165. g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_ADDRESS,
  166. host_to_variant(vip6));
  167. g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_PREFIX,
  168. g_variant_new_uint32 (vip6->get_address(vip6).len * 8));
  169. g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_NEVER_DEFAULT,
  170. g_variant_new_boolean (TRUE));
  171. g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_DNS,
  172. handler_to_variant(handler, "aay", INTERNAL_IP6_DNS));
  173. /* NM_VPN_PLUGIN_IP6_CONFIG_NBNS is not defined */
  174. }
  175. ip4config = g_variant_builder_end (&ip4builder);
  176. if (g_variant_n_children (ip4config))
  177. {
  178. g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP4,
  179. g_variant_new_boolean (TRUE));
  180. }
  181. else
  182. {
  183. g_variant_unref (ip4config);
  184. ip4config = NULL;
  185. }
  186. ip6config = g_variant_builder_end (&ip6builder);
  187. if (g_variant_n_children (ip6config))
  188. {
  189. g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP6,
  190. g_variant_new_boolean (TRUE));
  191. }
  192. else
  193. {
  194. g_variant_unref (ip6config);
  195. ip6config = NULL;
  196. }
  197. handler->reset(handler);
  198. nm_vpn_service_plugin_set_config (plugin, g_variant_builder_end (&builder));
  199. if (ip4config)
  200. {
  201. nm_vpn_service_plugin_set_ip4_config (plugin, ip4config);
  202. }
  203. if (ip6config)
  204. {
  205. nm_vpn_service_plugin_set_ip6_config (plugin, ip6config);
  206. }
  207. }
  208. /**
  209. * signal failure to NM, connecting failed
  210. */
  211. static void signal_failure(NMVpnServicePlugin *plugin, NMVpnPluginFailure failure)
  212. {
  213. nm_handler_t *handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler;
  214. handler->reset(handler);
  215. nm_vpn_service_plugin_failure(plugin, failure);
  216. }
  217. /**
  218. * Implementation of listener_t.ike_state_change
  219. */
  220. static bool ike_state_change(listener_t *listener, ike_sa_t *ike_sa,
  221. ike_sa_state_t state)
  222. {
  223. NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
  224. if (private->ike_sa == ike_sa && state == IKE_DESTROYING)
  225. {
  226. signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED);
  227. return FALSE;
  228. }
  229. return TRUE;
  230. }
  231. /**
  232. * Implementation of listener_t.child_state_change
  233. */
  234. static bool child_state_change(listener_t *listener, ike_sa_t *ike_sa,
  235. child_sa_t *child_sa, child_sa_state_t state)
  236. {
  237. NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
  238. if (private->ike_sa == ike_sa && state == CHILD_DESTROYING)
  239. {
  240. signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
  241. return FALSE;
  242. }
  243. return TRUE;
  244. }
  245. /**
  246. * Implementation of listener_t.child_updown
  247. */
  248. static bool child_updown(listener_t *listener, ike_sa_t *ike_sa,
  249. child_sa_t *child_sa, bool up)
  250. {
  251. NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
  252. if (private->ike_sa == ike_sa)
  253. {
  254. if (up)
  255. { /* disable initiate-failure-detection hooks */
  256. private->listener.ike_state_change = NULL;
  257. private->listener.child_state_change = NULL;
  258. signal_ip_config(private->plugin, ike_sa, child_sa);
  259. }
  260. else
  261. {
  262. signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
  263. return FALSE;
  264. }
  265. }
  266. return TRUE;
  267. }
  268. /**
  269. * Implementation of listener_t.ike_rekey
  270. */
  271. static bool ike_rekey(listener_t *listener, ike_sa_t *old, ike_sa_t *new)
  272. {
  273. NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
  274. if (private->ike_sa == old)
  275. { /* follow a rekeyed IKE_SA */
  276. private->ike_sa = new;
  277. }
  278. return TRUE;
  279. }
  280. /**
  281. * Find a certificate for which we have a private key on a smartcard
  282. */
  283. static identification_t *find_smartcard_key(NMStrongswanPluginPrivate *priv,
  284. char *pin)
  285. {
  286. enumerator_t *enumerator, *sans;
  287. identification_t *id = NULL;
  288. certificate_t *cert;
  289. x509_t *x509;
  290. private_key_t *key;
  291. chunk_t keyid;
  292. enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
  293. CERT_X509, KEY_ANY, NULL, FALSE);
  294. while (enumerator->enumerate(enumerator, &cert))
  295. {
  296. x509 = (x509_t*)cert;
  297. /* there might be a lot of certificates, filter them by usage */
  298. if ((x509->get_flags(x509) & X509_CLIENT_AUTH) &&
  299. !(x509->get_flags(x509) & X509_CA))
  300. {
  301. keyid = x509->get_subjectKeyIdentifier(x509);
  302. if (keyid.ptr)
  303. {
  304. /* try to find a private key by the certificate keyid */
  305. priv->creds->set_pin(priv->creds, keyid, pin);
  306. key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
  307. KEY_ANY, BUILD_PKCS11_KEYID, keyid, BUILD_END);
  308. if (key)
  309. {
  310. /* prefer a more convenient subjectAltName */
  311. sans = x509->create_subjectAltName_enumerator(x509);
  312. if (!sans->enumerate(sans, &id))
  313. {
  314. id = cert->get_subject(cert);
  315. }
  316. id = id->clone(id);
  317. sans->destroy(sans);
  318. DBG1(DBG_CFG, "using smartcard certificate '%Y'", id);
  319. priv->creds->set_cert_and_key(priv->creds,
  320. cert->get_ref(cert), key);
  321. break;
  322. }
  323. }
  324. }
  325. }
  326. enumerator->destroy(enumerator);
  327. return id;
  328. }
  329. /**
  330. * Connect function called from NM via DBUS
  331. */
  332. static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
  333. GError **err)
  334. {
  335. NMStrongswanPluginPrivate *priv;
  336. NMSettingConnection *conn;
  337. NMSettingVpn *vpn;
  338. enumerator_t *enumerator;
  339. identification_t *user = NULL, *gateway = NULL;
  340. const char *str;
  341. bool virtual, proposal;
  342. proposal_t *prop;
  343. ike_cfg_t *ike_cfg;
  344. peer_cfg_t *peer_cfg;
  345. child_cfg_t *child_cfg;
  346. traffic_selector_t *ts;
  347. ike_sa_t *ike_sa;
  348. auth_cfg_t *auth;
  349. auth_class_t auth_class = AUTH_CLASS_EAP;
  350. certificate_t *cert = NULL;
  351. x509_t *x509;
  352. bool agent = FALSE, smartcard = FALSE, loose_gateway_id = FALSE;
  353. ike_cfg_create_t ike = {
  354. .version = IKEV2,
  355. .local = "%any",
  356. .local_port = charon->socket->get_port(charon->socket, FALSE),
  357. .remote_port = IKEV2_UDP_PORT,
  358. .fragmentation = FRAGMENTATION_YES,
  359. };
  360. peer_cfg_create_t peer = {
  361. .cert_policy = CERT_SEND_IF_ASKED,
  362. .unique = UNIQUE_REPLACE,
  363. .keyingtries = 1,
  364. .rekey_time = 36000, /* 10h */
  365. .jitter_time = 600, /* 10min */
  366. .over_time = 600, /* 10min */
  367. };
  368. child_cfg_create_t child = {
  369. .lifetime = {
  370. .time = {
  371. .life = 10800 /* 3h */,
  372. .rekey = 10200 /* 2h50min */,
  373. .jitter = 300 /* 5min */
  374. },
  375. },
  376. .mode = MODE_TUNNEL,
  377. };
  378. /**
  379. * Read parameters
  380. */
  381. priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
  382. conn = NM_SETTING_CONNECTION(nm_connection_get_setting(connection,
  383. NM_TYPE_SETTING_CONNECTION));
  384. vpn = NM_SETTING_VPN(nm_connection_get_setting(connection,
  385. NM_TYPE_SETTING_VPN));
  386. if (priv->name)
  387. {
  388. free(priv->name);
  389. }
  390. priv->name = strdup(nm_setting_connection_get_id(conn));
  391. DBG1(DBG_CFG, "received initiate for NetworkManager connection %s",
  392. priv->name);
  393. DBG4(DBG_CFG, "%s",
  394. nm_setting_to_string(NM_SETTING(vpn)));
  395. ike.remote = (char*)nm_setting_vpn_get_data_item(vpn, "address");
  396. if (!ike.remote || !*ike.remote)
  397. {
  398. g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
  399. "Gateway address missing.");
  400. return FALSE;
  401. }
  402. str = nm_setting_vpn_get_data_item(vpn, "virtual");
  403. virtual = streq(str, "yes");
  404. str = nm_setting_vpn_get_data_item(vpn, "encap");
  405. ike.force_encap = streq(str, "yes");
  406. str = nm_setting_vpn_get_data_item(vpn, "ipcomp");
  407. child.options |= streq(str, "yes") ? OPT_IPCOMP : 0;
  408. str = nm_setting_vpn_get_data_item(vpn, "method");
  409. if (streq(str, "psk"))
  410. {
  411. auth_class = AUTH_CLASS_PSK;
  412. }
  413. else if (streq(str, "agent"))
  414. {
  415. auth_class = AUTH_CLASS_PUBKEY;
  416. agent = TRUE;
  417. }
  418. else if (streq(str, "key"))
  419. {
  420. auth_class = AUTH_CLASS_PUBKEY;
  421. }
  422. else if (streq(str, "smartcard"))
  423. {
  424. auth_class = AUTH_CLASS_PUBKEY;
  425. smartcard = TRUE;
  426. }
  427. /**
  428. * Register credentials
  429. */
  430. priv->creds->clear(priv->creds);
  431. /* gateway/CA cert */
  432. str = nm_setting_vpn_get_data_item(vpn, "certificate");
  433. if (str)
  434. {
  435. cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
  436. BUILD_FROM_FILE, str, BUILD_END);
  437. if (!cert)
  438. {
  439. g_set_error(err, NM_VPN_PLUGIN_ERROR,
  440. NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
  441. "Loading gateway certificate failed.");
  442. return FALSE;
  443. }
  444. priv->creds->add_certificate(priv->creds, cert);
  445. x509 = (x509_t*)cert;
  446. if (!(x509->get_flags(x509) & X509_CA))
  447. { /* For a gateway certificate, we use the cert subject as identity. */
  448. gateway = cert->get_subject(cert);
  449. gateway = gateway->clone(gateway);
  450. DBG1(DBG_CFG, "using gateway certificate, identity '%Y'", gateway);
  451. }
  452. }
  453. else
  454. {
  455. /* no certificate defined, fall back to system-wide CA certificates */
  456. priv->creds->load_ca_dir(priv->creds, lib->settings->get_str(
  457. lib->settings, "charon-nm.ca_dir", NM_CA_DIR));
  458. }
  459. if (!gateway)
  460. {
  461. /* If the user configured a CA certificate, we use the IP/DNS
  462. * of the gateway as its identity. This identity will be used for
  463. * certificate lookup and requires the configured IP/DNS to be
  464. * included in the gateway certificate. */
  465. gateway = identification_create_from_string(ike.remote);
  466. DBG1(DBG_CFG, "using CA certificate, gateway identity '%Y'", gateway);
  467. loose_gateway_id = TRUE;
  468. }
  469. if (auth_class == AUTH_CLASS_EAP ||
  470. auth_class == AUTH_CLASS_PSK)
  471. {
  472. /* username/password or PSK authentication ... */
  473. str = nm_setting_vpn_get_data_item(vpn, "user");
  474. if (str)
  475. {
  476. user = identification_create_from_string((char*)str);
  477. str = nm_setting_vpn_get_secret(vpn, "password");
  478. if (auth_class == AUTH_CLASS_PSK &&
  479. strlen(str) < 20)
  480. {
  481. g_set_error(err, NM_VPN_PLUGIN_ERROR,
  482. NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
  483. "pre-shared key is too short.");
  484. gateway->destroy(gateway);
  485. user->destroy(user);
  486. return FALSE;
  487. }
  488. priv->creds->set_username_password(priv->creds, user, (char*)str);
  489. }
  490. }
  491. if (auth_class == AUTH_CLASS_PUBKEY)
  492. {
  493. if (smartcard)
  494. {
  495. char *pin;
  496. pin = (char*)nm_setting_vpn_get_secret(vpn, "password");
  497. if (pin)
  498. {
  499. user = find_smartcard_key(priv, pin);
  500. }
  501. if (!user)
  502. {
  503. g_set_error(err, NM_VPN_PLUGIN_ERROR,
  504. NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
  505. "no usable smartcard certificate found.");
  506. gateway->destroy(gateway);
  507. return FALSE;
  508. }
  509. }
  510. /* ... or certificate/private key authenitcation */
  511. else if ((str = nm_setting_vpn_get_data_item(vpn, "usercert")))
  512. {
  513. public_key_t *public;
  514. private_key_t *private = NULL;
  515. cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
  516. BUILD_FROM_FILE, str, BUILD_END);
  517. if (!cert)
  518. {
  519. g_set_error(err, NM_VPN_PLUGIN_ERROR,
  520. NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
  521. "Loading peer certificate failed.");
  522. gateway->destroy(gateway);
  523. return FALSE;
  524. }
  525. /* try agent */
  526. str = nm_setting_vpn_get_secret(vpn, "agent");
  527. if (agent && str)
  528. {
  529. public = cert->get_public_key(cert);
  530. if (public)
  531. {
  532. private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
  533. public->get_type(public),
  534. BUILD_AGENT_SOCKET, str,
  535. BUILD_PUBLIC_KEY, public,
  536. BUILD_END);
  537. public->destroy(public);
  538. }
  539. if (!private)
  540. {
  541. g_set_error(err, NM_VPN_PLUGIN_ERROR,
  542. NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
  543. "Connecting to SSH agent failed.");
  544. }
  545. }
  546. /* ... or key file */
  547. str = nm_setting_vpn_get_data_item(vpn, "userkey");
  548. if (!agent && str)
  549. {
  550. char *secret;
  551. secret = (char*)nm_setting_vpn_get_secret(vpn, "password");
  552. if (secret)
  553. {
  554. priv->creds->set_key_password(priv->creds, secret);
  555. }
  556. private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
  557. KEY_ANY, BUILD_FROM_FILE, str, BUILD_END);
  558. if (!private)
  559. {
  560. g_set_error(err, NM_VPN_PLUGIN_ERROR,
  561. NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
  562. "Loading private key failed.");
  563. }
  564. }
  565. if (private)
  566. {
  567. user = cert->get_subject(cert);
  568. user = user->clone(user);
  569. priv->creds->set_cert_and_key(priv->creds, cert, private);
  570. }
  571. else
  572. {
  573. DESTROY_IF(cert);
  574. gateway->destroy(gateway);
  575. return FALSE;
  576. }
  577. }
  578. }
  579. if (!user)
  580. {
  581. g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
  582. "Configuration parameters missing.");
  583. gateway->destroy(gateway);
  584. return FALSE;
  585. }
  586. /**
  587. * Set up configurations
  588. */
  589. ike_cfg = ike_cfg_create(&ike);
  590. str = nm_setting_vpn_get_data_item(vpn, "proposal");
  591. proposal = streq(str, "yes");
  592. str = nm_setting_vpn_get_data_item(vpn, "ike");
  593. if (proposal && str && strlen(str))
  594. {
  595. enumerator = enumerator_create_token(str, ";", "");
  596. while (enumerator->enumerate(enumerator, &str))
  597. {
  598. prop = proposal_create_from_string(PROTO_IKE, str);
  599. if (!prop)
  600. {
  601. g_set_error(err, NM_VPN_PLUGIN_ERROR,
  602. NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
  603. "Invalid IKE proposal.");
  604. enumerator->destroy(enumerator);
  605. ike_cfg->destroy(ike_cfg);
  606. gateway->destroy(gateway);
  607. user->destroy(user);
  608. return FALSE;
  609. }
  610. ike_cfg->add_proposal(ike_cfg, prop);
  611. }
  612. enumerator->destroy(enumerator);
  613. }
  614. else
  615. {
  616. ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
  617. ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
  618. }
  619. peer_cfg = peer_cfg_create(priv->name, ike_cfg, &peer);
  620. if (virtual)
  621. {
  622. peer_cfg->add_virtual_ip(peer_cfg, host_create_any(AF_INET));
  623. peer_cfg->add_virtual_ip(peer_cfg, host_create_any(AF_INET6));
  624. }
  625. auth = auth_cfg_create();
  626. auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class);
  627. auth->add(auth, AUTH_RULE_IDENTITY, user);
  628. peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
  629. auth = auth_cfg_create();
  630. if (auth_class == AUTH_CLASS_PSK)
  631. {
  632. auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
  633. }
  634. else
  635. {
  636. auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
  637. }
  638. auth->add(auth, AUTH_RULE_IDENTITY, gateway);
  639. auth->add(auth, AUTH_RULE_IDENTITY_LOOSE, loose_gateway_id);
  640. peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
  641. child_cfg = child_cfg_create(priv->name, &child);
  642. str = nm_setting_vpn_get_data_item(vpn, "esp");
  643. if (proposal && str && strlen(str))
  644. {
  645. enumerator = enumerator_create_token(str, ";", "");
  646. while (enumerator->enumerate(enumerator, &str))
  647. {
  648. prop = proposal_create_from_string(PROTO_ESP, str);
  649. if (!prop)
  650. {
  651. g_set_error(err, NM_VPN_PLUGIN_ERROR,
  652. NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
  653. "Invalid ESP proposal.");
  654. enumerator->destroy(enumerator);
  655. child_cfg->destroy(child_cfg);
  656. peer_cfg->destroy(peer_cfg);
  657. return FALSE;
  658. }
  659. child_cfg->add_proposal(child_cfg, prop);
  660. }
  661. enumerator->destroy(enumerator);
  662. }
  663. else
  664. {
  665. child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
  666. child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
  667. }
  668. ts = traffic_selector_create_dynamic(0, 0, 65535);
  669. child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
  670. ts = traffic_selector_create_from_cidr("0.0.0.0/0", 0, 0, 65535);
  671. child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
  672. ts = traffic_selector_create_from_cidr("::/0", 0, 0, 65535);
  673. child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
  674. peer_cfg->add_child_cfg(peer_cfg, child_cfg);
  675. /**
  676. * Prepare IKE_SA
  677. */
  678. ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
  679. peer_cfg);
  680. if (!ike_sa)
  681. {
  682. peer_cfg->destroy(peer_cfg);
  683. g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
  684. "IKE version not supported.");
  685. return FALSE;
  686. }
  687. if (!ike_sa->get_peer_cfg(ike_sa))
  688. {
  689. ike_sa->set_peer_cfg(ike_sa, peer_cfg);
  690. }
  691. peer_cfg->destroy(peer_cfg);
  692. /**
  693. * Register listener, enable initiate-failure-detection hooks
  694. */
  695. priv->ike_sa = ike_sa;
  696. priv->listener.ike_state_change = ike_state_change;
  697. priv->listener.child_state_change = child_state_change;
  698. charon->bus->add_listener(charon->bus, &priv->listener);
  699. /**
  700. * Initiate
  701. */
  702. child_cfg->get_ref(child_cfg);
  703. if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
  704. {
  705. charon->bus->remove_listener(charon->bus, &priv->listener);
  706. charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
  707. g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
  708. "Initiating failed.");
  709. return FALSE;
  710. }
  711. charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
  712. return TRUE;
  713. }
  714. /**
  715. * NeedSecrets called from NM via DBUS
  716. */
  717. static gboolean need_secrets(NMVpnServicePlugin *plugin, NMConnection *connection,
  718. const char **setting_name, GError **error)
  719. {
  720. NMSettingVpn *settings;
  721. const char *method, *path;
  722. settings = NM_SETTING_VPN(nm_connection_get_setting(connection,
  723. NM_TYPE_SETTING_VPN));
  724. method = nm_setting_vpn_get_data_item(settings, "method");
  725. if (method)
  726. {
  727. if (streq(method, "eap") || streq(method, "psk"))
  728. {
  729. if (nm_setting_vpn_get_secret(settings, "password"))
  730. {
  731. return FALSE;
  732. }
  733. }
  734. else if (streq(method, "agent"))
  735. {
  736. if (nm_setting_vpn_get_secret(settings, "agent"))
  737. {
  738. return FALSE;
  739. }
  740. }
  741. else if (streq(method, "key"))
  742. {
  743. path = nm_setting_vpn_get_data_item(settings, "userkey");
  744. if (path)
  745. {
  746. private_key_t *key;
  747. /* try to load/decrypt the private key */
  748. key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
  749. KEY_ANY, BUILD_FROM_FILE, path, BUILD_END);
  750. if (key)
  751. {
  752. key->destroy(key);
  753. return FALSE;
  754. }
  755. else if (nm_setting_vpn_get_secret(settings, "password"))
  756. {
  757. return FALSE;
  758. }
  759. }
  760. }
  761. else if (streq(method, "smartcard"))
  762. {
  763. if (nm_setting_vpn_get_secret(settings, "password"))
  764. {
  765. return FALSE;
  766. }
  767. }
  768. }
  769. *setting_name = NM_SETTING_VPN_SETTING_NAME;
  770. return TRUE;
  771. }
  772. /**
  773. * The actual disconnection
  774. */
  775. static gboolean do_disconnect(gpointer plugin)
  776. {
  777. NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
  778. enumerator_t *enumerator;
  779. ike_sa_t *ike_sa;
  780. u_int id;
  781. /* our ike_sa pointer might be invalid, lookup sa */
  782. enumerator = charon->controller->create_ike_sa_enumerator(
  783. charon->controller, TRUE);
  784. while (enumerator->enumerate(enumerator, &ike_sa))
  785. {
  786. if (priv->ike_sa == ike_sa)
  787. {
  788. id = ike_sa->get_unique_id(ike_sa);
  789. enumerator->destroy(enumerator);
  790. charon->controller->terminate_ike(charon->controller, id, FALSE,
  791. controller_cb_empty, NULL, 0);
  792. return FALSE;
  793. }
  794. }
  795. enumerator->destroy(enumerator);
  796. g_debug("Connection not found.");
  797. return FALSE;
  798. }
  799. /**
  800. * Disconnect called from NM via DBUS
  801. */
  802. static gboolean disconnect(NMVpnServicePlugin *plugin, GError **err)
  803. {
  804. /* enqueue the actual disconnection, because we may be called in
  805. * response to a listener_t callback and the SA enumeration would
  806. * possibly deadlock. */
  807. g_idle_add(do_disconnect, plugin);
  808. return TRUE;
  809. }
  810. /**
  811. * Initializer
  812. */
  813. static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
  814. {
  815. NMStrongswanPluginPrivate *priv;
  816. priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
  817. priv->plugin = NM_VPN_SERVICE_PLUGIN(plugin);
  818. memset(&priv->listener, 0, sizeof(listener_t));
  819. priv->listener.child_updown = child_updown;
  820. priv->listener.ike_rekey = ike_rekey;
  821. priv->name = NULL;
  822. }
  823. /**
  824. * Class constructor
  825. */
  826. static void nm_strongswan_plugin_class_init(
  827. NMStrongswanPluginClass *strongswan_class)
  828. {
  829. NMVpnServicePluginClass *parent_class = NM_VPN_SERVICE_PLUGIN_CLASS(strongswan_class);
  830. g_type_class_add_private(G_OBJECT_CLASS(strongswan_class),
  831. sizeof(NMStrongswanPluginPrivate));
  832. parent_class->connect = connect_;
  833. parent_class->need_secrets = need_secrets;
  834. parent_class->disconnect = disconnect;
  835. }
  836. /**
  837. * Object constructor
  838. */
  839. NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
  840. nm_handler_t *handler)
  841. {
  842. GError *error = NULL;
  843. NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_initable_new (
  844. NM_TYPE_STRONGSWAN_PLUGIN,
  845. NULL,
  846. &error,
  847. NM_VPN_SERVICE_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN,
  848. NULL);
  849. if (plugin)
  850. {
  851. NMStrongswanPluginPrivate *priv;
  852. /* the rest of the initialization happened in _init above */
  853. priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
  854. priv->creds = creds;
  855. priv->handler = handler;
  856. }
  857. else
  858. {
  859. g_warning ("Failed to initialize a plugin instance: %s", error->message);
  860. g_error_free (error);
  861. }
  862. return plugin;
  863. }