PageRenderTime 56ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/settings/plugins/ifnet/connection_parser.c

https://bitbucket.org/advaitraut/networkmanager
C | 3065 lines | 2568 code | 311 blank | 186 comment | 438 complexity | 54d6293ebe5a56028711311388915d1f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0
  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
  2. /*
  3. * Mu Qiao <qiaomuf@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. * Copyright (C) 1999-2010 Gentoo Foundation, Inc.
  20. */
  21. #include "config.h"
  22. #include <string.h>
  23. #include <arpa/inet.h>
  24. #include <stdlib.h>
  25. #include <netinet/ether.h>
  26. #include <errno.h>
  27. #include <glib/gi18n.h>
  28. #include <nm-setting-connection.h>
  29. #include <nm-setting-ip4-config.h>
  30. #include <nm-setting-ip6-config.h>
  31. #include <nm-setting-ppp.h>
  32. #include <nm-setting-pppoe.h>
  33. #include <nm-setting-wired.h>
  34. #include <nm-setting-wireless.h>
  35. #include <nm-setting-8021x.h>
  36. #include <nm-system-config-interface.h>
  37. #include <nm-utils.h>
  38. #include "net_utils.h"
  39. #include "wpa_parser.h"
  40. #include "connection_parser.h"
  41. #include "nm-ifnet-connection.h"
  42. static void
  43. update_connection_id (NMConnection *connection, const char *conn_name)
  44. {
  45. gchar *idstr = NULL;
  46. gchar *uuid_base = NULL;
  47. gchar *uuid = NULL;
  48. int name_len;
  49. NMSettingConnection *setting;
  50. name_len = strlen (conn_name);
  51. if ((name_len > 2) && (g_str_has_prefix (conn_name, "0x"))) {
  52. idstr = utils_hexstr2bin (conn_name + 2, name_len - 2);
  53. } else
  54. idstr = g_strdup_printf ("%s", conn_name);
  55. uuid_base = idstr;
  56. uuid = nm_utils_uuid_generate_from_string (uuid_base);
  57. setting = nm_connection_get_setting_connection (connection);
  58. g_object_set (setting, NM_SETTING_CONNECTION_ID, idstr,
  59. NM_SETTING_CONNECTION_UUID, uuid, NULL);
  60. PLUGIN_PRINT (IFNET_PLUGIN_NAME,
  61. "update_connection_setting_from_config_block: name:%s, id:%s, uuid: %s",
  62. conn_name, idstr, uuid);
  63. g_free (uuid);
  64. g_free (idstr);
  65. }
  66. static gboolean eap_simple_reader (const char *eap_method,
  67. const char *ssid,
  68. NMSetting8021x *s_8021x,
  69. gboolean phase2,
  70. const char *basepath,
  71. GError **error);
  72. static gboolean eap_tls_reader (const char *eap_method,
  73. const char *ssid,
  74. NMSetting8021x *s_8021x,
  75. gboolean phase2,
  76. const char *basepath,
  77. GError **error);
  78. static gboolean eap_peap_reader (const char *eap_method,
  79. const char *ssid,
  80. NMSetting8021x *s_8021x,
  81. gboolean phase2,
  82. const char *basepath,
  83. GError **error);
  84. static gboolean eap_ttls_reader (const char *eap_method,
  85. const char *ssid,
  86. NMSetting8021x *s_8021x,
  87. gboolean phase2,
  88. const char *basepath,
  89. GError **error);
  90. typedef struct {
  91. const char *method;
  92. gboolean (*reader) (const char *eap_method,
  93. const char *ssid,
  94. NMSetting8021x *s_8021x,
  95. gboolean phase2,
  96. const char *basepath,
  97. GError **error);
  98. gboolean wifi_phase2_only;
  99. } EAPReader;
  100. static EAPReader eap_readers[] = {
  101. {"md5", eap_simple_reader, TRUE},
  102. {"pap", eap_simple_reader, TRUE},
  103. {"chap", eap_simple_reader, TRUE},
  104. {"mschap", eap_simple_reader, TRUE},
  105. {"mschapv2", eap_simple_reader, TRUE},
  106. {"leap", eap_simple_reader, TRUE},
  107. {"tls", eap_tls_reader, FALSE},
  108. {"peap", eap_peap_reader, FALSE},
  109. {"ttls", eap_ttls_reader, FALSE},
  110. {NULL, NULL}
  111. };
  112. /* reading identity and password */
  113. static gboolean
  114. eap_simple_reader (const char *eap_method,
  115. const char *ssid,
  116. NMSetting8021x *s_8021x,
  117. gboolean phase2,
  118. const char *basepath,
  119. GError **error)
  120. {
  121. const char *value;
  122. /* identity */
  123. value = wpa_get_value (ssid, "identity");
  124. if (!value) {
  125. g_set_error (error, ifnet_plugin_error_quark (), 0,
  126. "Missing IEEE_8021X_IDENTITY for EAP method '%s'.",
  127. eap_method);
  128. return FALSE;
  129. }
  130. g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL);
  131. /* password */
  132. value = wpa_get_value (ssid, "password");
  133. if (!value) {
  134. g_set_error (error, ifnet_plugin_error_quark (), 0,
  135. "Missing IEEE_8021X_PASSWORD for EAP method '%s'.",
  136. eap_method);
  137. return FALSE;
  138. }
  139. g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, value, NULL);
  140. return TRUE;
  141. }
  142. static char *
  143. get_cert (const char *ssid, const char *key, const char *basepath)
  144. {
  145. const char *orig;
  146. /* If it's a relative path, convert to absolute using 'basepath' */
  147. orig = wpa_get_value (ssid, key);
  148. if (g_path_is_absolute (orig))
  149. return g_strdup (orig);
  150. return g_strdup_printf ("%s/%s", basepath, orig);
  151. }
  152. static gboolean
  153. eap_tls_reader (const char *eap_method,
  154. const char *ssid,
  155. NMSetting8021x *s_8021x,
  156. gboolean phase2,
  157. const char *basepath,
  158. GError **error)
  159. {
  160. const char *value;
  161. char *ca_cert = NULL;
  162. char *client_cert = NULL;
  163. char *privkey = NULL;
  164. const char *privkey_password = NULL;
  165. gboolean success = FALSE;
  166. NMSetting8021xCKFormat privkey_format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
  167. /* identity */
  168. value = wpa_get_value (ssid, "identity");
  169. if (!value) {
  170. g_set_error (error, ifnet_plugin_error_quark (), 0,
  171. "Missing IEEE_8021X_IDENTITY for EAP method '%s'.",
  172. eap_method);
  173. return FALSE;
  174. }
  175. g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL);
  176. /* ca cert */
  177. ca_cert = get_cert (ssid, phase2 ? "ca_cert2" : "ca_cert", basepath);
  178. if (ca_cert) {
  179. if (phase2) {
  180. if (!nm_setting_802_1x_set_phase2_ca_cert (s_8021x,
  181. ca_cert,
  182. NM_SETTING_802_1X_CK_SCHEME_PATH,
  183. NULL, error))
  184. goto done;
  185. } else {
  186. if (!nm_setting_802_1x_set_ca_cert (s_8021x,
  187. ca_cert,
  188. NM_SETTING_802_1X_CK_SCHEME_PATH,
  189. NULL, error))
  190. goto done;
  191. }
  192. } else {
  193. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  194. " warning: missing %s for EAP"
  195. " method '%s'; this is insecure!",
  196. phase2 ? "IEEE_8021X_INNER_CA_CERT" :
  197. "IEEE_8021X_CA_CERT", eap_method);
  198. }
  199. /* Private key password */
  200. privkey_password = wpa_get_value (ssid,
  201. phase2 ? "private_key_passwd2" :
  202. "private_key_passwd");
  203. if (!privkey_password) {
  204. g_set_error (error, ifnet_plugin_error_quark (), 0,
  205. "Missing %s for EAP method '%s'.",
  206. phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD" :
  207. "IEEE_8021X_PRIVATE_KEY_PASSWORD", eap_method);
  208. goto done;
  209. }
  210. /* The private key itself */
  211. privkey = get_cert (ssid, phase2 ? "private_key2" : "private_key", basepath);
  212. if (!privkey) {
  213. g_set_error (error, ifnet_plugin_error_quark (), 0,
  214. "Missing %s for EAP method '%s'.",
  215. phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" :
  216. "IEEE_8021X_PRIVATE_KEY", eap_method);
  217. goto done;
  218. }
  219. if (phase2) {
  220. if (!nm_setting_802_1x_set_phase2_private_key (s_8021x,
  221. privkey,
  222. privkey_password,
  223. NM_SETTING_802_1X_CK_SCHEME_PATH,
  224. &privkey_format,
  225. error))
  226. goto done;
  227. } else {
  228. if (!nm_setting_802_1x_set_private_key (s_8021x,
  229. privkey,
  230. privkey_password,
  231. NM_SETTING_802_1X_CK_SCHEME_PATH,
  232. &privkey_format, error))
  233. goto done;
  234. }
  235. /* Only set the client certificate if the private key is not PKCS#12 format,
  236. * as NM (due to supplicant restrictions) requires. If the key was PKCS#12,
  237. * then nm_setting_802_1x_set_private_key() already set the client certificate
  238. * to the same value as the private key.
  239. */
  240. if (privkey_format == NM_SETTING_802_1X_CK_FORMAT_RAW_KEY
  241. || privkey_format == NM_SETTING_802_1X_CK_FORMAT_X509) {
  242. client_cert = get_cert (ssid, phase2 ? "client_cert2" : "client_cert", basepath);
  243. if (!client_cert) {
  244. g_set_error (error, ifnet_plugin_error_quark (), 0,
  245. "Missing %s for EAP method '%s'.",
  246. phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" :
  247. "IEEE_8021X_CLIENT_CERT", eap_method);
  248. goto done;
  249. }
  250. if (phase2) {
  251. if (!nm_setting_802_1x_set_phase2_client_cert (s_8021x,
  252. client_cert,
  253. NM_SETTING_802_1X_CK_SCHEME_PATH,
  254. NULL,
  255. error))
  256. goto done;
  257. } else {
  258. if (!nm_setting_802_1x_set_client_cert (s_8021x,
  259. client_cert,
  260. NM_SETTING_802_1X_CK_SCHEME_PATH,
  261. NULL, error))
  262. goto done;
  263. }
  264. }
  265. success = TRUE;
  266. done:
  267. g_free (ca_cert);
  268. g_free (client_cert);
  269. g_free (privkey);
  270. return success;
  271. }
  272. static gboolean
  273. eap_peap_reader (const char *eap_method,
  274. const char *ssid,
  275. NMSetting8021x *s_8021x,
  276. gboolean phase2,
  277. const char *basepath,
  278. GError **error)
  279. {
  280. char *ca_cert = NULL;
  281. const char *inner_auth = NULL;
  282. const char *peapver = NULL;
  283. char **list = NULL, **iter, *lower;
  284. gboolean success = FALSE;
  285. ca_cert = get_cert (ssid, "ca_cert", basepath);
  286. if (ca_cert) {
  287. if (!nm_setting_802_1x_set_ca_cert (s_8021x,
  288. ca_cert,
  289. NM_SETTING_802_1X_CK_SCHEME_PATH,
  290. NULL, error))
  291. goto done;
  292. } else {
  293. PLUGIN_WARN (IFNET_PLUGIN_NAME, " warning: missing "
  294. "IEEE_8021X_CA_CERT for EAP method '%s'; this is"
  295. " insecure!", eap_method);
  296. }
  297. peapver = wpa_get_value (ssid, "phase1");
  298. /* peap version, default is automatic */
  299. if (peapver && strstr (peapver, "peapver")) {
  300. if (strstr (peapver, "peapver=0"))
  301. g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPVER,
  302. "0", NULL);
  303. else if (strstr (peapver, "peapver=1"))
  304. g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPVER,
  305. "1", NULL);
  306. else {
  307. g_set_error (error, ifnet_plugin_error_quark (), 0,
  308. "Unknown IEEE_8021X_PEAP_VERSION value '%s'",
  309. peapver);
  310. goto done;
  311. }
  312. }
  313. /* peaplabel */
  314. if (peapver && strstr (peapver, "peaplabel=1"))
  315. g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPLABEL, "1",
  316. NULL);
  317. inner_auth = wpa_get_value (ssid, "phase2");
  318. if (!inner_auth) {
  319. g_set_error (error, ifnet_plugin_error_quark (), 0,
  320. "Missing IEEE_8021X_INNER_AUTH_METHODS.");
  321. goto done;
  322. }
  323. /* Handle options for the inner auth method */
  324. list = g_strsplit (inner_auth, " ", 0);
  325. for (iter = list; iter && *iter; iter++) {
  326. gchar *pos = NULL;
  327. if (!strlen (*iter))
  328. continue;
  329. if (!(pos = strstr (*iter, "MSCHAPV2"))
  330. || !(pos = strstr (*iter, "MD5"))
  331. || !(pos = strstr (*iter, "GTC"))) {
  332. if (!eap_simple_reader (pos, ssid, s_8021x, TRUE, basepath, error))
  333. goto done;
  334. } else if (!(pos = strstr (*iter, "TLS"))) {
  335. if (!eap_tls_reader (pos, ssid, s_8021x, TRUE, basepath, error))
  336. goto done;
  337. } else {
  338. g_set_error (error, ifnet_plugin_error_quark (), 0,
  339. "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.",
  340. *iter);
  341. goto done;
  342. }
  343. pos = strchr (*iter, '=');
  344. pos++;
  345. lower = g_ascii_strdown (pos, -1);
  346. g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, lower,
  347. NULL);
  348. g_free (lower);
  349. break;
  350. }
  351. if (!nm_setting_802_1x_get_phase2_auth (s_8021x)) {
  352. g_set_error (error, ifnet_plugin_error_quark (), 0,
  353. "No valid IEEE_8021X_INNER_AUTH_METHODS found.");
  354. goto done;
  355. }
  356. success = TRUE;
  357. done:
  358. g_free (ca_cert);
  359. if (list)
  360. g_strfreev (list);
  361. return success;
  362. }
  363. static gboolean
  364. eap_ttls_reader (const char *eap_method,
  365. const char *ssid,
  366. NMSetting8021x *s_8021x,
  367. gboolean phase2,
  368. const char *basepath,
  369. GError **error)
  370. {
  371. gboolean success = FALSE;
  372. const char *anon_ident = NULL;
  373. char *ca_cert = NULL;
  374. const char *tmp;
  375. char **list = NULL, **iter, *inner_auth = NULL;
  376. /* ca cert */
  377. ca_cert = get_cert (ssid, "ca_cert", basepath);
  378. if (ca_cert) {
  379. if (!nm_setting_802_1x_set_ca_cert (s_8021x,
  380. ca_cert,
  381. NM_SETTING_802_1X_CK_SCHEME_PATH,
  382. NULL, error))
  383. goto done;
  384. } else {
  385. PLUGIN_WARN (IFNET_PLUGIN_NAME, " warning: missing "
  386. "IEEE_8021X_CA_CERT for EAP method '%s'; this is"
  387. " insecure!", eap_method);
  388. }
  389. /* anonymous indentity for tls */
  390. anon_ident = wpa_get_value (ssid, "anonymous_identity");
  391. if (anon_ident && strlen (anon_ident))
  392. g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY,
  393. anon_ident, NULL);
  394. tmp = wpa_get_value (ssid, "phase2");
  395. if (!tmp) {
  396. g_set_error (error, ifnet_plugin_error_quark (), 0,
  397. "Missing IEEE_8021X_INNER_AUTH_METHODS.");
  398. goto done;
  399. }
  400. /* Handle options for the inner auth method */
  401. inner_auth = g_ascii_strdown (tmp, -1);
  402. list = g_strsplit (inner_auth, " ", 0);
  403. for (iter = list; iter && *iter; iter++) {
  404. gchar *pos = NULL;
  405. if (!strlen (*iter))
  406. continue;
  407. if ((pos = strstr (*iter, "mschapv2")) != NULL
  408. || (pos = strstr (*iter, "mschap")) != NULL
  409. || (pos = strstr (*iter, "pap")) != NULL
  410. || (pos = strstr (*iter, "chap")) != NULL) {
  411. if (!eap_simple_reader (pos, ssid, s_8021x, TRUE, basepath, error))
  412. goto done;
  413. g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH,
  414. pos, NULL);
  415. } else if ((pos = strstr (*iter, "tls")) != NULL) {
  416. if (!eap_tls_reader (pos, ssid, s_8021x, TRUE, basepath, error))
  417. goto done;
  418. g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP,
  419. "tls", NULL);
  420. } else if ((pos = strstr (*iter, "mschapv2")) != NULL
  421. || (pos = strstr (*iter, "md5")) != NULL) {
  422. if (!eap_simple_reader (pos, ssid, s_8021x, TRUE, basepath, error)) {
  423. PLUGIN_WARN (IFNET_PLUGIN_NAME, "SIMPLE ERROR");
  424. goto done;
  425. }
  426. g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP,
  427. pos, NULL);
  428. } else {
  429. g_set_error (error, ifnet_plugin_error_quark (), 0,
  430. "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.",
  431. *iter);
  432. goto done;
  433. }
  434. break;
  435. }
  436. success = TRUE;
  437. done:
  438. g_free (ca_cert);
  439. if (list)
  440. g_strfreev (list);
  441. g_free (inner_auth);
  442. return success;
  443. }
  444. /* type is already decided by net_parser, this function is just used to
  445. * doing tansformation*/
  446. static const gchar *
  447. guess_connection_type (const char *conn_name)
  448. {
  449. const gchar *type = ifnet_get_data (conn_name, "type");
  450. const gchar *ret_type = NULL;
  451. if (!g_strcmp0 (type, "ppp"))
  452. ret_type = NM_SETTING_PPPOE_SETTING_NAME;
  453. if (!g_strcmp0 (type, "wireless"))
  454. ret_type = NM_SETTING_WIRELESS_SETTING_NAME;
  455. if (!ret_type)
  456. ret_type = NM_SETTING_WIRED_SETTING_NAME;
  457. PLUGIN_PRINT (IFNET_PLUGIN_NAME,
  458. "guessed connection type (%s) = %s", conn_name, ret_type);
  459. return ret_type;
  460. }
  461. /* Reading mac address for setting connection option.
  462. * Unmanaged device mac address is required by NetworkManager*/
  463. static gboolean
  464. read_mac_address (const char *conn_name, GByteArray **array, GError **error)
  465. {
  466. const char *value = ifnet_get_data (conn_name, "mac");
  467. if (!value || !strlen (value))
  468. return TRUE;
  469. *array = nm_utils_hwaddr_atoba (value, ARPHRD_ETHER);
  470. if (!*array) {
  471. g_set_error (error, ifnet_plugin_error_quark (), 0,
  472. "The MAC address '%s' was invalid.", value);
  473. return FALSE;
  474. }
  475. return TRUE;
  476. }
  477. static void
  478. make_wired_connection_setting (NMConnection *connection,
  479. const char *conn_name,
  480. GError **error)
  481. {
  482. GByteArray *mac = NULL;
  483. NMSettingWired *s_wired = NULL;
  484. const char *value = NULL;
  485. s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
  486. /* mtu_xxx */
  487. value = ifnet_get_data (conn_name, "mtu");
  488. if (value) {
  489. long int mtu;
  490. errno = 0;
  491. mtu = strtol (value, NULL, 10);
  492. if (errno || mtu < 0 || mtu > 65535) {
  493. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  494. " warning: invalid MTU '%s' for %s",
  495. value, conn_name);
  496. } else
  497. g_object_set (s_wired, NM_SETTING_WIRED_MTU,
  498. (guint32) mtu, NULL);
  499. }
  500. if (read_mac_address (conn_name, &mac, error)) {
  501. if (mac) {
  502. g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS,
  503. mac, NULL);
  504. g_byte_array_free (mac, TRUE);
  505. }
  506. } else {
  507. g_object_unref (s_wired);
  508. s_wired = NULL;
  509. }
  510. if (s_wired)
  511. nm_connection_add_setting (connection, NM_SETTING (s_wired));
  512. }
  513. /* add NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME,
  514. * NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID in future*/
  515. static void
  516. make_ip4_setting (NMConnection *connection,
  517. const char *conn_name,
  518. GError **error)
  519. {
  520. NMSettingIP4Config *ip4_setting =
  521. NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
  522. const char *value, *method;
  523. gboolean is_static_block = is_static_ip4 (conn_name);
  524. ip_block *iblock = NULL;
  525. /* set dhcp options (dhcp_xxx) */
  526. value = ifnet_get_data (conn_name, "dhcp");
  527. g_object_set (ip4_setting, NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, value
  528. && strstr (value, "nodns") ? TRUE : FALSE,
  529. NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, value
  530. && strstr (value, "nogateway") ? TRUE : FALSE, NULL);
  531. if (!is_static_block) {
  532. method = ifnet_get_data (conn_name, "config");
  533. if (!method){
  534. g_set_error (error, ifnet_plugin_error_quark (), 0,
  535. "Unknown config for %s", conn_name);
  536. g_object_unref (ip4_setting);
  537. return;
  538. }
  539. if (strstr (method, "dhcp"))
  540. g_object_set (ip4_setting,
  541. NM_SETTING_IP4_CONFIG_METHOD,
  542. NM_SETTING_IP4_CONFIG_METHOD_AUTO,
  543. NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
  544. else if (strstr (method, "autoip")) {
  545. g_object_set (ip4_setting,
  546. NM_SETTING_IP4_CONFIG_METHOD,
  547. NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
  548. NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
  549. nm_connection_add_setting (connection, NM_SETTING (ip4_setting));
  550. return;
  551. } else if (strstr (method, "shared")) {
  552. g_object_set (ip4_setting,
  553. NM_SETTING_IP4_CONFIG_METHOD,
  554. NM_SETTING_IP4_CONFIG_METHOD_SHARED,
  555. NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
  556. nm_connection_add_setting (connection, NM_SETTING (ip4_setting));
  557. return;
  558. } else {
  559. g_set_error (error, ifnet_plugin_error_quark (), 0,
  560. "Unknown config for %s", conn_name);
  561. g_object_unref (ip4_setting);
  562. return;
  563. }
  564. PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Using %s method for %s",
  565. method, conn_name);
  566. }else {
  567. iblock = convert_ip4_config_block (conn_name);
  568. if (!iblock) {
  569. g_set_error (error, ifnet_plugin_error_quark (), 0,
  570. "Ifnet plugin: can't aquire ip configuration for %s",
  571. conn_name);
  572. g_object_unref (ip4_setting);
  573. return;
  574. }
  575. /************** add all ip settings to the connection**********/
  576. while (iblock) {
  577. ip_block *current_iblock;
  578. NMIP4Address *ip4_addr = nm_ip4_address_new ();
  579. nm_ip4_address_set_address (ip4_addr, iblock->ip);
  580. nm_ip4_address_set_prefix (ip4_addr,
  581. nm_utils_ip4_netmask_to_prefix
  582. (iblock->netmask));
  583. /* currently all the IPs has the same gateway */
  584. nm_ip4_address_set_gateway (ip4_addr, iblock->gateway);
  585. if (iblock->gateway)
  586. g_object_set (ip4_setting,
  587. NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES,
  588. TRUE, NULL);
  589. if (!nm_setting_ip4_config_add_address (ip4_setting, ip4_addr))
  590. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  591. "ignoring duplicate IP4 address");
  592. nm_ip4_address_unref (ip4_addr);
  593. current_iblock = iblock;
  594. iblock = iblock->next;
  595. destroy_ip_block (current_iblock);
  596. }
  597. g_object_set (ip4_setting,
  598. NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
  599. NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, !has_default_ip4_route (conn_name),
  600. NULL);
  601. }
  602. /* add dhcp hostname and client id */
  603. if (!is_static_block && strstr (method, "dhcp")) {
  604. gchar *dhcp_hostname, *client_id;
  605. get_dhcp_hostname_and_client_id (&dhcp_hostname, &client_id);
  606. if (dhcp_hostname) {
  607. g_object_set (ip4_setting,
  608. NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME,
  609. dhcp_hostname, NULL);
  610. PLUGIN_PRINT (IFNET_PLUGIN_NAME, "DHCP hostname: %s",
  611. dhcp_hostname);
  612. g_free (dhcp_hostname);
  613. }
  614. if (client_id) {
  615. g_object_set (ip4_setting,
  616. NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID,
  617. client_id, NULL);
  618. PLUGIN_PRINT (IFNET_PLUGIN_NAME, "DHCP client id: %s",
  619. client_id);
  620. g_free (client_id);
  621. }
  622. }
  623. /* add all IPv4 dns servers, IPv6 servers will be ignored */
  624. set_ip4_dns_servers (ip4_setting, conn_name);
  625. /* DNS searches */
  626. value = ifnet_get_data (conn_name, "dns_search");
  627. if (value) {
  628. char *stripped = g_strdup (value);
  629. char **searches = NULL;
  630. strip_string (stripped, '"');
  631. searches = g_strsplit (stripped, " ", 0);
  632. if (searches) {
  633. char **item;
  634. for (item = searches; *item; item++) {
  635. if (strlen (*item)) {
  636. if (!nm_setting_ip4_config_add_dns_search (ip4_setting, *item))
  637. PLUGIN_WARN
  638. (IFNET_PLUGIN_NAME,
  639. " warning: duplicate DNS domain '%s'",
  640. *item);
  641. }
  642. }
  643. g_strfreev (searches);
  644. }
  645. }
  646. /* static routes */
  647. iblock = convert_ip4_routes_block (conn_name);
  648. while (iblock) {
  649. ip_block *current_iblock = iblock;
  650. const char *metric_str;
  651. char *stripped;
  652. long int metric;
  653. NMIP4Route *route = nm_ip4_route_new ();
  654. nm_ip4_route_set_dest (route, iblock->ip);
  655. nm_ip4_route_set_next_hop (route, iblock->gateway);
  656. nm_ip4_route_set_prefix (route,
  657. nm_utils_ip4_netmask_to_prefix
  658. (iblock->netmask));
  659. if ((metric_str = ifnet_get_data (conn_name, "metric")) != NULL) {
  660. metric = strtol (metric_str, NULL, 10);
  661. nm_ip4_route_set_metric (route, (guint32) metric);
  662. } else {
  663. metric_str = ifnet_get_global_data ("metric");
  664. if (metric_str) {
  665. stripped = g_strdup (metric_str);
  666. strip_string (stripped, '"');
  667. metric = strtol (metric_str, NULL, 10);
  668. nm_ip4_route_set_metric (route,
  669. (guint32) metric);
  670. g_free (stripped);
  671. }
  672. }
  673. if (!nm_setting_ip4_config_add_route (ip4_setting, route))
  674. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  675. "warning: duplicate IP4 route");
  676. PLUGIN_PRINT (IFNET_PLUGIN_NAME,
  677. "new IP4 route:%d\n", iblock->ip);
  678. nm_ip4_route_unref (route);
  679. current_iblock = iblock;
  680. iblock = iblock->next;
  681. destroy_ip_block (current_iblock);
  682. }
  683. /* Finally add setting to connection */
  684. nm_connection_add_setting (connection, NM_SETTING (ip4_setting));
  685. }
  686. static void
  687. make_ip6_setting (NMConnection *connection,
  688. const char *conn_name,
  689. GError **error)
  690. {
  691. NMSettingIP6Config *s_ip6 = NULL;
  692. gboolean is_static_block = is_static_ip6 (conn_name);
  693. // used to disable IPv6
  694. gboolean ipv6_enabled = FALSE;
  695. gchar *method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
  696. const char *value;
  697. ip6_block *iblock;
  698. gboolean never_default = !has_default_ip6_route (conn_name);
  699. s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
  700. if (!s_ip6) {
  701. g_set_error (error, ifnet_plugin_error_quark (), 0,
  702. "Could not allocate IP6 setting");
  703. return;
  704. }
  705. value = ifnet_get_data (conn_name, "enable_ipv6");
  706. if (value && is_true (value))
  707. ipv6_enabled = TRUE;
  708. //FIXME Handle other methods that NM supports in future
  709. // Currently only Manual and DHCP are supported
  710. if (!ipv6_enabled) {
  711. g_object_set (s_ip6,
  712. NM_SETTING_IP6_CONFIG_METHOD,
  713. NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
  714. goto done;
  715. } else if (!is_static_block) {
  716. // config_eth* contains "dhcp6"
  717. method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
  718. never_default = FALSE;
  719. }
  720. // else if (!has_ip6_address(conn_name))
  721. // doesn't have "dhcp6" && doesn't have any ipv6 address
  722. // method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
  723. else
  724. // doesn't have "dhcp6" && has at least one ipv6 address
  725. method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
  726. PLUGIN_PRINT (IFNET_PLUGIN_NAME, "IPv6 for %s enabled, using %s",
  727. conn_name, method);
  728. g_object_set (s_ip6,
  729. NM_SETTING_IP6_CONFIG_METHOD, method,
  730. NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS, FALSE,
  731. NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES, FALSE,
  732. NM_SETTING_IP6_CONFIG_NEVER_DEFAULT, never_default, NULL);
  733. /* Make manual settings */
  734. if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
  735. ip6_block *current_iblock;
  736. iblock = convert_ip6_config_block (conn_name);
  737. if (!iblock) {
  738. g_set_error (error, ifnet_plugin_error_quark (), 0,
  739. "Ifnet plugin: can't aquire ip6 configuration for %s",
  740. conn_name);
  741. goto error;
  742. }
  743. /* add all IPv6 addresses */
  744. while (iblock) {
  745. NMIP6Address *ip6_addr = nm_ip6_address_new ();
  746. nm_ip6_address_set_address (ip6_addr, iblock->ip);
  747. nm_ip6_address_set_prefix (ip6_addr, iblock->prefix);
  748. if (nm_setting_ip6_config_add_address (s_ip6, ip6_addr)) {
  749. PLUGIN_PRINT (IFNET_PLUGIN_NAME,
  750. "ipv6 addresses count: %d",
  751. nm_setting_ip6_config_get_num_addresses
  752. (s_ip6));
  753. } else {
  754. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  755. "ignoring duplicate IP4 address");
  756. }
  757. nm_ip6_address_unref (ip6_addr);
  758. current_iblock = iblock;
  759. iblock = iblock->next;
  760. destroy_ip6_block (current_iblock);
  761. }
  762. } else if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
  763. /* - autoconf or DHCPv6 stuff goes here */
  764. }
  765. // DNS Servers, set NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS TRUE here
  766. set_ip6_dns_servers (s_ip6, conn_name);
  767. /* DNS searches ('DOMAIN' key) are read by make_ip4_setting() and included in NMSettingIP4Config */
  768. // Add routes
  769. iblock = convert_ip6_routes_block (conn_name);
  770. if (iblock)
  771. g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES,
  772. TRUE, NULL);
  773. /* Add all IPv6 routes */
  774. while (iblock) {
  775. ip6_block *current_iblock = iblock;
  776. const char *metric_str;
  777. char *stripped;
  778. long int metric = 1;
  779. NMIP6Route *route = nm_ip6_route_new ();
  780. nm_ip6_route_set_dest (route, iblock->ip);
  781. nm_ip6_route_set_next_hop (route, iblock->next_hop);
  782. nm_ip6_route_set_prefix (route, iblock->prefix);
  783. /* metric is not per routes configuration right now
  784. * global metric is also supported (metric="x") */
  785. if ((metric_str = ifnet_get_data (conn_name, "metric")) != NULL) {
  786. metric = strtol (metric_str, NULL, 10);
  787. nm_ip6_route_set_metric (route, (guint32) metric);
  788. } else {
  789. metric_str = ifnet_get_global_data ("metric");
  790. if (metric_str) {
  791. stripped = g_strdup (metric_str);
  792. strip_string (stripped, '"');
  793. metric = strtol (metric_str, NULL, 10);
  794. nm_ip6_route_set_metric (route,
  795. (guint32) metric);
  796. g_free (stripped);
  797. } else
  798. nm_ip6_route_set_metric (route, (guint32) 1);
  799. }
  800. if (!nm_setting_ip6_config_add_route (s_ip6, route))
  801. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  802. " warning: duplicate IP6 route");
  803. PLUGIN_PRINT (IFNET_PLUGIN_NAME, " info: new IP6 route");
  804. nm_ip6_route_unref (route);
  805. current_iblock = iblock;
  806. iblock = iblock->next;
  807. destroy_ip6_block (current_iblock);
  808. }
  809. done:
  810. nm_connection_add_setting (connection, NM_SETTING (s_ip6));
  811. return;
  812. error:
  813. g_object_unref (s_ip6);
  814. PLUGIN_WARN (IFNET_PLUGIN_NAME, " warning: Ignore IPv6 for %s",
  815. conn_name);
  816. return;
  817. }
  818. static NMSetting *
  819. make_wireless_connection_setting (const char *conn_name,
  820. NMSetting8021x **s_8021x,
  821. GError **error)
  822. {
  823. GByteArray *array, *mac = NULL;
  824. NMSettingWireless *wireless_setting = NULL;
  825. gboolean adhoc = FALSE;
  826. const char *value;
  827. const char *type;
  828. /* PPP over WIFI is not supported yet */
  829. g_return_val_if_fail (conn_name != NULL
  830. && strcmp (ifnet_get_data (conn_name, "type"),
  831. "ppp") != 0, NULL);
  832. type = ifnet_get_data (conn_name, "type");
  833. if (strcmp (type, "ppp") == 0) {
  834. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  835. "PPP over WIFI is not supported yet");
  836. return NULL;
  837. }
  838. wireless_setting = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
  839. if (read_mac_address (conn_name, &mac, error)) {
  840. if (mac) {
  841. g_object_set (wireless_setting,
  842. NM_SETTING_WIRELESS_MAC_ADDRESS, mac,
  843. NULL);
  844. g_byte_array_free (mac, TRUE);
  845. }
  846. } else {
  847. g_object_unref (wireless_setting);
  848. return NULL;
  849. }
  850. /* handle ssid (hex and ascii) */
  851. if (conn_name) {
  852. gsize ssid_len = 0, value_len = strlen (conn_name);
  853. const char *p;
  854. char *tmp, *converted = NULL;
  855. ssid_len = value_len;
  856. if ((value_len > 2) && (g_str_has_prefix (conn_name, "0x"))) {
  857. /* Hex representation */
  858. if (value_len % 2) {
  859. g_set_error (error, ifnet_plugin_error_quark (),
  860. 0,
  861. "Invalid SSID '%s' size (looks like hex but length not multiple of 2)",
  862. conn_name);
  863. goto error;
  864. }
  865. // ignore "0x"
  866. p = conn_name + 2;
  867. if (!is_hex (p)) {
  868. g_set_error (error,
  869. ifnet_plugin_error_quark (),
  870. 0,
  871. "Invalid SSID '%s' character (looks like hex SSID but '%c' isn't a hex digit)",
  872. conn_name, *p);
  873. goto error;
  874. }
  875. tmp = utils_hexstr2bin (p, value_len - 2);
  876. ssid_len = (value_len - 2) / 2;
  877. converted = g_malloc0 (ssid_len + 1);
  878. memcpy (converted, tmp, ssid_len);
  879. g_free (tmp);
  880. }
  881. if (ssid_len > 32 || ssid_len == 0) {
  882. g_set_error (error, ifnet_plugin_error_quark (), 0,
  883. "Invalid SSID '%s' (size %zu not between 1 and 32 inclusive)",
  884. conn_name, ssid_len);
  885. goto error;
  886. }
  887. array = g_byte_array_sized_new (ssid_len);
  888. g_byte_array_append (array, (const guint8 *) (converted ? converted : conn_name), ssid_len);
  889. g_object_set (wireless_setting, NM_SETTING_WIRELESS_SSID, array, NULL);
  890. g_byte_array_free (array, TRUE);
  891. g_free (converted);
  892. } else {
  893. g_set_error (error, ifnet_plugin_error_quark (), 0,
  894. "Missing SSID");
  895. goto error;
  896. }
  897. /* mode=0: infrastructure
  898. * mode=1: adhoc */
  899. value = wpa_get_value (conn_name, "mode");
  900. if (value)
  901. adhoc = strcmp (value, "1") == 0 ? TRUE : FALSE;
  902. if (exist_ssid (conn_name)) {
  903. const char *mode = adhoc ? "adhoc" : "infrastructure";
  904. g_object_set (wireless_setting, NM_SETTING_WIRELESS_MODE, mode,
  905. NULL);
  906. PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Using mode: %s", mode);
  907. }
  908. /* BSSID setting */
  909. value = wpa_get_value (conn_name, "bssid");
  910. if (value) {
  911. GByteArray *bssid;
  912. bssid = nm_utils_hwaddr_atoba (value, ARPHRD_ETHER);
  913. if (!bssid) {
  914. g_set_error (error, ifnet_plugin_error_quark (), 0,
  915. "Invalid BSSID '%s'", value);
  916. goto error;
  917. }
  918. g_object_set (wireless_setting, NM_SETTING_WIRELESS_BSSID,
  919. bssid, NULL);
  920. g_byte_array_free (bssid, TRUE);
  921. }
  922. /* mtu_ssid="xx" */
  923. value = ifnet_get_data (conn_name, "mtu");
  924. if (value) {
  925. long int mtu;
  926. errno = 0;
  927. mtu = strtol (value, NULL, 10);
  928. if (errno || mtu < 0 || mtu > 50000) {
  929. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  930. " warning: invalid MTU '%s' for %s",
  931. value, conn_name);
  932. } else
  933. g_object_set (wireless_setting, NM_SETTING_WIRELESS_MTU,
  934. (guint32) mtu, NULL);
  935. }
  936. PLUGIN_PRINT (IFNET_PLUGIN_NAME, "wireless_setting added for %s",
  937. conn_name);
  938. return NM_SETTING (wireless_setting);
  939. error:
  940. if (wireless_setting)
  941. g_object_unref (wireless_setting);
  942. return NULL;
  943. }
  944. static NMSettingWirelessSecurity *
  945. make_leap_setting (const char *ssid, GError **error)
  946. {
  947. NMSettingWirelessSecurity *wsec;
  948. const char *value;
  949. wsec =
  950. NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
  951. value = wpa_get_value (ssid, "key_mgmt");
  952. if (!value || strcmp (value, "IEEE8021X"))
  953. goto error; /* Not LEAP */
  954. value = wpa_get_value (ssid, "eap");
  955. if (!value || strcasecmp (value, "LEAP"))
  956. goto error; /* Not LEAP */
  957. value = wpa_get_value (ssid, "password");
  958. if (value && strlen (value))
  959. g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
  960. value, NULL);
  961. value = wpa_get_value (ssid, "identity");
  962. if (!value || !strlen (value)) {
  963. g_set_error (error, ifnet_plugin_error_quark (), 0,
  964. "Missing LEAP identity");
  965. goto error;
  966. }
  967. g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, value,
  968. NULL);
  969. g_object_set (wsec,
  970. NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x",
  971. NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", NULL);
  972. return wsec;
  973. error:
  974. if (wsec)
  975. g_object_unref (wsec);
  976. return NULL;
  977. }
  978. static gboolean
  979. add_one_wep_key (const char *ssid,
  980. const char *key,
  981. int key_idx,
  982. NMSettingWirelessSecurity *s_wsec,
  983. GError **error)
  984. {
  985. const char *value;
  986. char *converted = NULL;
  987. gboolean success = FALSE;
  988. g_return_val_if_fail (ssid != NULL, FALSE);
  989. g_return_val_if_fail (key != NULL, FALSE);
  990. g_return_val_if_fail (key_idx >= 0 && key_idx <= 3, FALSE);
  991. g_return_val_if_fail (s_wsec != NULL, FALSE);
  992. value = wpa_get_value (ssid, key);
  993. if (!value)
  994. return TRUE;
  995. /* Validate keys */
  996. if (strlen (value) == 10 || strlen (value) == 26) {
  997. /* Hexadecimal WEP key */
  998. if (!is_hex (value)) {
  999. g_set_error (error, ifnet_plugin_error_quark (),
  1000. 0, "Invalid hexadecimal WEP key.");
  1001. goto out;
  1002. }
  1003. converted = g_strdup (value);
  1004. } else if (value[0] == '"'
  1005. && (strlen (value) == 7 || strlen (value) == 15)) {
  1006. /* ASCII passphrase */
  1007. char *tmp = g_strdup (value);
  1008. char *p = strip_string (tmp, '"');
  1009. if (!is_ascii (p)) {
  1010. g_set_error (error, ifnet_plugin_error_quark (),
  1011. 0, "Invalid ASCII WEP passphrase.");
  1012. g_free (tmp);
  1013. goto out;
  1014. }
  1015. converted = utils_bin2hexstr (tmp, strlen (tmp), strlen (tmp) * 2);
  1016. g_free (tmp);
  1017. } else {
  1018. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1019. "Invalid WEP key length. Key: %s", value);
  1020. goto out;
  1021. }
  1022. if (converted) {
  1023. nm_setting_wireless_security_set_wep_key (s_wsec, key_idx, converted);
  1024. g_free (converted);
  1025. success = TRUE;
  1026. }
  1027. out:
  1028. return success;
  1029. }
  1030. static gboolean
  1031. add_wep_keys (const char *ssid,
  1032. NMSettingWirelessSecurity *s_wsec,
  1033. GError **error)
  1034. {
  1035. if (!add_one_wep_key (ssid, "wep_key0", 0, s_wsec, error))
  1036. return FALSE;
  1037. if (!add_one_wep_key (ssid, "wep_key1", 1, s_wsec, error))
  1038. return FALSE;
  1039. if (!add_one_wep_key (ssid, "wep_key2", 2, s_wsec, error))
  1040. return FALSE;
  1041. if (!add_one_wep_key (ssid, "wep_key3", 3, s_wsec, error))
  1042. return FALSE;
  1043. return TRUE;
  1044. }
  1045. static NMSettingWirelessSecurity *
  1046. make_wep_setting (const char *ssid, GError **error)
  1047. {
  1048. const char *auth_alg, *value;
  1049. int default_key_idx = 0;
  1050. NMSettingWirelessSecurity *s_wireless_sec;
  1051. s_wireless_sec =
  1052. NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
  1053. g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
  1054. "none", NULL);
  1055. /* default key index */
  1056. value = wpa_get_value (ssid, "wep_tx_keyidx");
  1057. if (value) {
  1058. default_key_idx = atoi (value);
  1059. if (default_key_idx >= 0 && default_key_idx <= 3) {
  1060. g_object_set (s_wireless_sec,
  1061. NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX,
  1062. default_key_idx, NULL);
  1063. PLUGIN_PRINT (IFNET_PLUGIN_NAME,
  1064. "Default key index: %d", default_key_idx);
  1065. } else {
  1066. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1067. "Invalid default WEP key '%s'", value);
  1068. goto error;
  1069. }
  1070. }
  1071. if (!add_wep_keys (ssid, s_wireless_sec, error))
  1072. goto error;
  1073. /* If there's a default key, ensure that key exists */
  1074. if ((default_key_idx == 1)
  1075. && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 1)) {
  1076. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1077. "Default WEP key index was 2, but no valid KEY2 exists.");
  1078. goto error;
  1079. } else if ((default_key_idx == 2)
  1080. && !nm_setting_wireless_security_get_wep_key (s_wireless_sec,
  1081. 2)) {
  1082. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1083. "Default WEP key index was 3, but no valid KEY3 exists.");
  1084. goto error;
  1085. } else if ((default_key_idx == 3)
  1086. && !nm_setting_wireless_security_get_wep_key (s_wireless_sec,
  1087. 3)) {
  1088. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1089. "Default WEP key index was 4, but no valid KEY4 exists.");
  1090. goto error;
  1091. }
  1092. /* authentication algorithms */
  1093. auth_alg = wpa_get_value (ssid, "auth_alg");
  1094. if (auth_alg) {
  1095. if (strcmp (auth_alg, "OPEN") == 0) {
  1096. g_object_set (s_wireless_sec,
  1097. NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
  1098. "open", NULL);
  1099. PLUGIN_PRINT (IFNET_PLUGIN_NAME,
  1100. "WEP: Use open system authentication");
  1101. } else if (strcmp (auth_alg, "SHARED") == 0) {
  1102. g_object_set (s_wireless_sec,
  1103. NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
  1104. "shared", NULL);
  1105. PLUGIN_PRINT (IFNET_PLUGIN_NAME,
  1106. "WEP: Use shared system authentication");
  1107. } else {
  1108. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1109. "Invalid WEP authentication algorithm '%s'",
  1110. auth_alg);
  1111. goto error;
  1112. }
  1113. }
  1114. if (!nm_setting_wireless_security_get_wep_key (s_wireless_sec, 0)
  1115. && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 1)
  1116. && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 2)
  1117. && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 3)
  1118. && !nm_setting_wireless_security_get_wep_tx_keyidx (s_wireless_sec)) {
  1119. if (auth_alg && !strcmp (auth_alg, "shared")) {
  1120. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1121. "WEP Shared Key authentication is invalid for "
  1122. "unencrypted connections.");
  1123. goto error;
  1124. }
  1125. /* Unencrypted */
  1126. g_object_unref (s_wireless_sec);
  1127. s_wireless_sec = NULL;
  1128. }
  1129. return s_wireless_sec;
  1130. error:
  1131. if (s_wireless_sec)
  1132. g_object_unref (s_wireless_sec);
  1133. return NULL;
  1134. }
  1135. static char *
  1136. parse_wpa_psk (const char *psk, GError **error)
  1137. {
  1138. char *hashed = NULL;
  1139. gboolean quoted = FALSE;
  1140. if (!psk) {
  1141. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1142. "Missing WPA_PSK for WPA-PSK key management");
  1143. return NULL;
  1144. }
  1145. /* Passphrase must be between 10 and 66 characters in length becuase WPA
  1146. * hex keys are exactly 64 characters (no quoting), and WPA passphrases
  1147. * are between 8 and 63 characters (inclusive), plus optional quoting if
  1148. * the passphrase contains spaces.
  1149. */
  1150. if (psk[0] == '"' && psk[strlen (psk) - 1] == '"')
  1151. quoted = TRUE;
  1152. if (!quoted && (strlen (psk) == 64)) {
  1153. /* Verify the hex PSK; 64 digits */
  1154. if (!is_hex (psk)) {
  1155. g_set_error (error, ifnet_plugin_error_quark (),
  1156. 0,
  1157. "Invalid WPA_PSK (contains non-hexadecimal characters)");
  1158. goto out;
  1159. }
  1160. hashed = g_strdup (psk);
  1161. } else {
  1162. char *stripped = g_strdup (psk);
  1163. strip_string (stripped, '"');
  1164. /* Length check */
  1165. if (strlen (stripped) < 8 || strlen (stripped) > 63) {
  1166. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1167. "Invalid WPA_PSK (passphrases must be between "
  1168. "8 and 63 characters long (inclusive))");
  1169. g_free (stripped);
  1170. goto out;
  1171. }
  1172. hashed = g_strdup (stripped);
  1173. g_free (stripped);
  1174. }
  1175. if (!hashed) {
  1176. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1177. "Invalid WPA_PSK (doesn't look like a passphrase or hex key)");
  1178. goto out;
  1179. }
  1180. out:
  1181. return hashed;
  1182. }
  1183. static gboolean
  1184. fill_wpa_ciphers (const char *ssid,
  1185. NMSettingWirelessSecurity *wsec,
  1186. gboolean group,
  1187. gboolean adhoc)
  1188. {
  1189. const char *value;
  1190. char **list = NULL, **iter;
  1191. int i = 0;
  1192. value = wpa_get_value (ssid, group ? "group" : "pairwise");
  1193. if (!value)
  1194. return TRUE;
  1195. list = g_strsplit_set (value, " ", 0);
  1196. for (iter = list; iter && *iter; iter++, i++) {
  1197. /* Ad-Hoc configurations cannot have pairwise ciphers, and can only
  1198. * have one group cipher. Ignore any additional group ciphers and
  1199. * any pairwise ciphers specified.
  1200. */
  1201. if (adhoc) {
  1202. if (group && (i > 0)) {
  1203. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  1204. " warning: ignoring group cipher '%s' (only one group cipher allowed in Ad-Hoc mode)",
  1205. *iter);
  1206. continue;
  1207. } else if (!group) {
  1208. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  1209. " warning: ignoring pairwise cipher '%s' (pairwise not used in Ad-Hoc mode)",
  1210. *iter);
  1211. continue;
  1212. }
  1213. }
  1214. if (!strcmp (*iter, "CCMP")) {
  1215. if (group)
  1216. nm_setting_wireless_security_add_group (wsec,
  1217. "ccmp");
  1218. else
  1219. nm_setting_wireless_security_add_pairwise (wsec,
  1220. "ccmp");
  1221. } else if (!strcmp (*iter, "TKIP")) {
  1222. if (group)
  1223. nm_setting_wireless_security_add_group (wsec,
  1224. "tkip");
  1225. else
  1226. nm_setting_wireless_security_add_pairwise (wsec,
  1227. "tkip");
  1228. } else if (group && !strcmp (*iter, "WEP104"))
  1229. nm_setting_wireless_security_add_group (wsec, "wep104");
  1230. else if (group && !strcmp (*iter, "WEP40"))
  1231. nm_setting_wireless_security_add_group (wsec, "wep40");
  1232. else {
  1233. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  1234. " warning: ignoring invalid %s cipher '%s'",
  1235. group ? "CIPHER_GROUP" : "CIPHER_PAIRWISE",
  1236. *iter);
  1237. }
  1238. }
  1239. if (list)
  1240. g_strfreev (list);
  1241. return TRUE;
  1242. }
  1243. static NMSetting8021x *
  1244. fill_8021x (const char *ssid,
  1245. const char *key_mgmt,
  1246. gboolean wifi,
  1247. const char *basepath,
  1248. GError **error)
  1249. {
  1250. NMSetting8021x *s_8021x;
  1251. const char *value;
  1252. char **list, **iter;
  1253. value = wpa_get_value (ssid, "eap");
  1254. if (!value) {
  1255. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1256. "Missing IEEE_8021X_EAP_METHODS for key management '%s'",
  1257. key_mgmt);
  1258. return NULL;
  1259. }
  1260. list = g_strsplit (value, " ", 0);
  1261. s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
  1262. /* Validate and handle each EAP method */
  1263. for (iter = list; iter && *iter; iter++) {
  1264. EAPReader *eap = &eap_readers[0];
  1265. gboolean found = FALSE;
  1266. char *lower = NULL;
  1267. lower = g_ascii_strdown (*iter, -1);
  1268. while (eap->method && !found) {
  1269. if (strcmp (eap->method, lower))
  1270. goto next;
  1271. /* Some EAP methods don't provide keying material, thus they
  1272. * cannot be used with WiFi unless they are an inner method
  1273. * used with TTLS or PEAP or whatever.
  1274. */
  1275. if (wifi && eap->wifi_phase2_only) {
  1276. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  1277. " warning: ignored invalid "
  1278. "IEEE_8021X_EAP_METHOD '%s'; not allowed for wifi.",
  1279. lower);
  1280. goto next;
  1281. }
  1282. /* Parse EAP method specific options */
  1283. if (!(*eap->reader) (lower, ssid, s_8021x, FALSE, basepath, error)) {
  1284. g_free (lower);
  1285. goto error;
  1286. }
  1287. nm_setting_802_1x_add_eap_method (s_8021x, lower);
  1288. found = TRUE;
  1289. next:
  1290. eap++;
  1291. }
  1292. if (!found) {
  1293. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  1294. " warning: ignored unknown"
  1295. "IEEE_8021X_EAP_METHOD '%s'.", lower);
  1296. }
  1297. g_free (lower);
  1298. }
  1299. g_strfreev (list);
  1300. if (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 0) {
  1301. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1302. "No valid EAP methods found in IEEE_8021X_EAP_METHODS.");
  1303. goto error;
  1304. }
  1305. return s_8021x;
  1306. error:
  1307. g_object_unref (s_8021x);
  1308. return NULL;
  1309. }
  1310. static NMSettingWirelessSecurity *
  1311. make_wpa_setting (const char *ssid,
  1312. const char *basepath,
  1313. NMSetting8021x **s_8021x,
  1314. GError **error)
  1315. {
  1316. NMSettingWirelessSecurity *wsec;
  1317. const char *value;
  1318. char *lower;
  1319. gboolean adhoc = FALSE;
  1320. if (!exist_ssid (ssid)) {
  1321. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1322. "No security info found for ssid: %s", ssid);
  1323. return NULL;
  1324. }
  1325. wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
  1326. /* mode=1: adhoc
  1327. * mode=0: infrastructure */
  1328. value = wpa_get_value (ssid, "mode");
  1329. if (value)
  1330. adhoc = strcmp (value, "1") == 0 ? TRUE : FALSE;
  1331. value = wpa_get_value (ssid, "key_mgmt");
  1332. /* Not WPA or Dynamic WEP */
  1333. if (!value)
  1334. goto error;
  1335. if (strcmp (value, "WPA-PSK") && strcmp (value, "WPA-EAP"))
  1336. goto error;
  1337. /* Pairwise and Group ciphers */
  1338. fill_wpa_ciphers (ssid, wsec, FALSE, adhoc);
  1339. fill_wpa_ciphers (ssid, wsec, TRUE, adhoc);
  1340. /* WPA and/or RSN */
  1341. if (adhoc) {
  1342. /* Ad-Hoc mode only supports WPA proto for now */
  1343. nm_setting_wireless_security_add_proto (wsec, "wpa");
  1344. } else {
  1345. nm_setting_wireless_security_add_proto (wsec, "wpa");
  1346. nm_setting_wireless_security_add_proto (wsec, "rsn");
  1347. }
  1348. if (!strcmp (value, "WPA-PSK")) {
  1349. char *psk = parse_wpa_psk (wpa_get_value (ssid, "psk"), error);
  1350. if (!psk)
  1351. goto error;
  1352. g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_PSK, psk,
  1353. NULL);
  1354. g_free (psk);
  1355. if (adhoc)
  1356. g_object_set (wsec,
  1357. NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
  1358. "wpa-none", NULL);
  1359. else
  1360. g_object_set (wsec,
  1361. NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
  1362. "wpa-psk", NULL);
  1363. } else if (!strcmp (value, "WPA-EAP") || !strcmp (value, "IEEE8021X")) {
  1364. if (adhoc) {
  1365. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1366. "Ad-Hoc mode cannot be used with KEY_MGMT type '%s'",
  1367. value);
  1368. goto error;
  1369. }
  1370. *s_8021x = fill_8021x (ssid, value, TRUE, basepath, error);
  1371. if (!*s_8021x)
  1372. goto error;
  1373. lower = g_ascii_strdown (value, -1);
  1374. g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
  1375. lower, NULL);
  1376. g_free (lower);
  1377. } else {
  1378. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1379. "Unknown wireless KEY_MGMT type '%s'", value);
  1380. goto error;
  1381. }
  1382. return wsec;
  1383. error:
  1384. if (wsec)
  1385. g_object_unref (wsec);
  1386. return NULL;
  1387. }
  1388. static NMSettingWirelessSecurity *
  1389. make_wireless_security_setting (const char *conn_name,
  1390. const char *basepath,
  1391. NMSetting8021x **s_8021x,
  1392. GError ** error)
  1393. {
  1394. NMSettingWirelessSecurity *wsec = NULL;
  1395. const char *ssid;
  1396. gboolean adhoc = FALSE;
  1397. const char *value;
  1398. g_return_val_if_fail (conn_name != NULL
  1399. && strcmp (ifnet_get_data (conn_name, "type"),
  1400. "ppp") != 0, NULL);
  1401. if (!wpa_get_value (conn_name, "ssid"))
  1402. return NULL;
  1403. PLUGIN_PRINT (IFNET_PLUGIN_NAME,
  1404. "updating wireless security settings (%s).", conn_name);
  1405. ssid = conn_name;
  1406. value = wpa_get_value (ssid, "mode");
  1407. if (value)
  1408. adhoc = strcmp (value, "1") == 0 ? TRUE : FALSE;
  1409. if (!adhoc) {
  1410. wsec = make_leap_setting (ssid, error);
  1411. if (error && *error)
  1412. goto error;
  1413. }
  1414. if (!wsec) {
  1415. wsec = make_wpa_setting (ssid, basepath, s_8021x, error);
  1416. if (error && *error)
  1417. goto error;
  1418. }
  1419. if (!wsec) {
  1420. wsec = make_wep_setting (ssid, error);
  1421. if (error && *error)
  1422. goto error;
  1423. }
  1424. if (!wsec) {
  1425. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1426. "Can't handle security information for ssid: %s",
  1427. conn_name);
  1428. }
  1429. return wsec;
  1430. error:
  1431. return NULL;
  1432. }
  1433. /* Currently only support username and password */
  1434. static void
  1435. make_pppoe_connection_setting (NMConnection *connection,
  1436. const char *conn_name,
  1437. GError **error)
  1438. {
  1439. NMSettingPPPOE *s_pppoe;
  1440. NMSettingPPP *s_ppp;
  1441. const char *value;
  1442. s_pppoe = NM_SETTING_PPPOE (nm_setting_pppoe_new ());
  1443. /* username */
  1444. value = ifnet_get_data (conn_name, "username");
  1445. if (!value) {
  1446. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1447. "ppp requires at lease a username");
  1448. return;
  1449. }
  1450. g_object_set (s_pppoe, NM_SETTING_PPPOE_USERNAME, value, NULL);
  1451. /* password */
  1452. value = ifnet_get_data (conn_name, "password");
  1453. if (!value) {
  1454. value = "";
  1455. }
  1456. g_object_set (s_pppoe, NM_SETTING_PPPOE_PASSWORD, value, NULL);
  1457. nm_connection_add_setting (connection, NM_SETTING (s_pppoe));
  1458. /* PPP setting */
  1459. s_ppp = (NMSettingPPP *) nm_setting_ppp_new ();
  1460. nm_connection_add_setting (connection, NM_SETTING (s_ppp));
  1461. }
  1462. NMConnection *
  1463. ifnet_update_connection_from_config_block (const char *conn_name,
  1464. const char *basepath,
  1465. GError **error)
  1466. {
  1467. const gchar *type = NULL;
  1468. NMConnection *connection = NULL;
  1469. NMSettingConnection *setting = NULL;
  1470. NMSetting8021x *s_8021x = NULL;
  1471. NMSettingWirelessSecurity *wsec = NULL;
  1472. gboolean auto_conn = TRUE;
  1473. const char *value = NULL;
  1474. gboolean success = FALSE;
  1475. connection = nm_connection_new ();
  1476. if (!connection)
  1477. return NULL;
  1478. setting = nm_connection_get_setting_connection (connection);
  1479. if (!setting) {
  1480. setting = NM_SETTING_CONNECTION (nm_setting_connection_new ());
  1481. g_assert (setting);
  1482. nm_connection_add_setting (connection, NM_SETTING (setting));
  1483. }
  1484. type = guess_connection_type (conn_name);
  1485. value = ifnet_get_data (conn_name, "auto");
  1486. if (value && !strcmp (value, "false"))
  1487. auto_conn = FALSE;
  1488. update_connection_id (connection, conn_name);
  1489. g_object_set (setting, NM_SETTING_CONNECTION_TYPE, type,
  1490. NM_SETTING_CONNECTION_READ_ONLY, FALSE,
  1491. NM_SETTING_CONNECTION_AUTOCONNECT, auto_conn, NULL);
  1492. if (!strcmp (NM_SETTING_WIRED_SETTING_NAME, type)
  1493. || !strcmp (NM_SETTING_PPPOE_SETTING_NAME, type)) {
  1494. /* wired setting */
  1495. make_wired_connection_setting (connection, conn_name, error);
  1496. if (error && *error) {
  1497. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  1498. "Found error: %s", (*error)->message);
  1499. goto error;
  1500. }
  1501. /* pppoe setting */
  1502. if (!strcmp (NM_SETTING_PPPOE_SETTING_NAME, type))
  1503. make_pppoe_connection_setting (connection, conn_name,
  1504. error);
  1505. if (error && *error) {
  1506. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  1507. "Found error: %s", (*error)->message);
  1508. goto error;
  1509. }
  1510. } else if (!strcmp (NM_SETTING_WIRELESS_SETTING_NAME, type)) {
  1511. /* wireless setting */
  1512. NMSetting *wireless_setting;
  1513. wireless_setting = make_wireless_connection_setting (conn_name, &s_8021x, error);
  1514. if (!wireless_setting)
  1515. goto error;
  1516. nm_connection_add_setting (connection, wireless_setting);
  1517. if (error && *error) {
  1518. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  1519. "Found error: %s", (*error)->message);
  1520. goto error;
  1521. }
  1522. /* wireless security setting */
  1523. wsec = make_wireless_security_setting (conn_name, basepath, &s_8021x, error);
  1524. if (wsec) {
  1525. nm_connection_add_setting (connection,
  1526. NM_SETTING (wsec));
  1527. if (s_8021x)
  1528. nm_connection_add_setting (connection,
  1529. NM_SETTING
  1530. (s_8021x));
  1531. g_object_set (wireless_setting, NM_SETTING_WIRELESS_SEC,
  1532. NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
  1533. NULL);
  1534. }
  1535. if (error && *error) {
  1536. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  1537. "Found error: %s", (*error)->message);
  1538. goto error;
  1539. }
  1540. } else
  1541. goto error;
  1542. /* IPv4 setting */
  1543. make_ip4_setting (connection, conn_name, error);
  1544. if (error && *error) {
  1545. PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s", (*error)->message);
  1546. goto error;
  1547. }
  1548. /* IPv6 setting */
  1549. make_ip6_setting (connection, conn_name, error);
  1550. if (error && *error) {
  1551. PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s", (*error)->message);
  1552. goto error;
  1553. }
  1554. success = nm_connection_verify (connection, error);
  1555. if (error && *error)
  1556. PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s", (*error)->message);
  1557. PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Connection verified %s:%d", conn_name, success);
  1558. if (!success)
  1559. goto error;
  1560. return connection;
  1561. error:
  1562. g_object_unref (connection);
  1563. return NULL;
  1564. }
  1565. typedef NMSetting8021xCKScheme (*SchemeFunc) (NMSetting8021x * setting);
  1566. typedef const char *(*PathFunc) (NMSetting8021x * setting);
  1567. typedef const GByteArray *(*BlobFunc) (NMSetting8021x * setting);
  1568. typedef struct ObjectType {
  1569. const char *setting_key;
  1570. SchemeFunc scheme_func;
  1571. PathFunc path_func;
  1572. BlobFunc blob_func;
  1573. const char *conn_name_key;
  1574. const char *suffix;
  1575. } ObjectType;
  1576. static const ObjectType ca_type = {
  1577. NM_SETTING_802_1X_CA_CERT,
  1578. nm_setting_802_1x_get_ca_cert_scheme,
  1579. nm_setting_802_1x_get_ca_cert_path,
  1580. nm_setting_802_1x_get_ca_cert_blob,
  1581. "ca_cert",
  1582. "ca-cert.der"
  1583. };
  1584. static const ObjectType phase2_ca_type = {
  1585. NM_SETTING_802_1X_PHASE2_CA_CERT,
  1586. nm_setting_802_1x_get_phase2_ca_cert_scheme,
  1587. nm_setting_802_1x_get_phase2_ca_cert_path,
  1588. nm_setting_802_1x_get_phase2_ca_cert_blob,
  1589. "ca_cert2",
  1590. "inner-ca-cert.der"
  1591. };
  1592. static const ObjectType client_type = {
  1593. NM_SETTING_802_1X_CLIENT_CERT,
  1594. nm_setting_802_1x_get_client_cert_scheme,
  1595. nm_setting_802_1x_get_client_cert_path,
  1596. nm_setting_802_1x_get_client_cert_blob,
  1597. "client_cert",
  1598. "client-cert.der"
  1599. };
  1600. static const ObjectType phase2_client_type = {
  1601. NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
  1602. nm_setting_802_1x_get_phase2_client_cert_scheme,
  1603. nm_setting_802_1x_get_phase2_client_cert_path,
  1604. nm_setting_802_1x_get_phase2_client_cert_blob,
  1605. "client_cert2",
  1606. "inner-client-cert.der"
  1607. };
  1608. static const ObjectType pk_type = {
  1609. NM_SETTING_802_1X_PRIVATE_KEY,
  1610. nm_setting_802_1x_get_private_key_scheme,
  1611. nm_setting_802_1x_get_private_key_path,
  1612. nm_setting_802_1x_get_private_key_blob,
  1613. "private_key",
  1614. "private-key.pem"
  1615. };
  1616. static const ObjectType phase2_pk_type = {
  1617. NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
  1618. nm_setting_802_1x_get_phase2_private_key_scheme,
  1619. nm_setting_802_1x_get_phase2_private_key_path,
  1620. nm_setting_802_1x_get_phase2_private_key_blob,
  1621. "private_key2",
  1622. "inner-private-key.pem"
  1623. };
  1624. static const ObjectType p12_type = {
  1625. NM_SETTING_802_1X_PRIVATE_KEY,
  1626. nm_setting_802_1x_get_private_key_scheme,
  1627. nm_setting_802_1x_get_private_key_path,
  1628. nm_setting_802_1x_get_private_key_blob,
  1629. "private_key",
  1630. "private-key.p12"
  1631. };
  1632. static const ObjectType phase2_p12_type = {
  1633. NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
  1634. nm_setting_802_1x_get_phase2_private_key_scheme,
  1635. nm_setting_802_1x_get_phase2_private_key_path,
  1636. nm_setting_802_1x_get_phase2_private_key_blob,
  1637. "private_key2",
  1638. "inner-private-key.p12"
  1639. };
  1640. static gboolean
  1641. write_object (NMSetting8021x *s_8021x,
  1642. const char *conn_name,
  1643. const GByteArray *override_data,
  1644. const ObjectType *objtype,
  1645. GError **error)
  1646. {
  1647. NMSetting8021xCKScheme scheme;
  1648. const char *path = NULL;
  1649. const GByteArray *blob = NULL;
  1650. g_return_val_if_fail (conn_name != NULL, FALSE);
  1651. g_return_val_if_fail (objtype != NULL, FALSE);
  1652. if (override_data)
  1653. /* if given explicit data to save, always use that instead of asking
  1654. * the setting what to do.
  1655. */
  1656. blob = override_data;
  1657. else {
  1658. scheme = (*(objtype->scheme_func)) (s_8021x);
  1659. switch (scheme) {
  1660. case NM_SETTING_802_1X_CK_SCHEME_BLOB:
  1661. blob = (*(objtype->blob_func)) (s_8021x);
  1662. break;
  1663. case NM_SETTING_802_1X_CK_SCHEME_PATH:
  1664. path = (*(objtype->path_func)) (s_8021x);
  1665. break;
  1666. default:
  1667. break;
  1668. }
  1669. }
  1670. /* If the object path was specified, prefer that over any raw cert data that
  1671. * may have been sent.
  1672. */
  1673. if (path) {
  1674. wpa_set_data (conn_name, (gchar *) objtype->conn_name_key,
  1675. (gchar *) path);
  1676. return TRUE;
  1677. }
  1678. /* does not support writing encryption data now */
  1679. if (blob) {
  1680. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  1681. " warning: Currently we do not support certs writing.");
  1682. }
  1683. return TRUE;
  1684. }
  1685. static gboolean
  1686. write_8021x_certs (NMSetting8021x *s_8021x,
  1687. gboolean phase2,
  1688. const char *conn_name,
  1689. GError **error)
  1690. {
  1691. char *password = NULL;
  1692. const ObjectType *otype = NULL;
  1693. gboolean is_pkcs12 = FALSE, success = FALSE;
  1694. const GByteArray *blob = NULL;
  1695. GByteArray *enc_key = NULL;
  1696. gchar *generated_pw = NULL;
  1697. /* CA certificate */
  1698. if (phase2)
  1699. otype = &phase2_ca_type;
  1700. else
  1701. otype = &ca_type;
  1702. if (!write_object (s_8021x, conn_name, NULL, otype, error))
  1703. return FALSE;
  1704. /* Private key */
  1705. if (phase2) {
  1706. if (nm_setting_802_1x_get_phase2_private_key_scheme (s_8021x) !=
  1707. NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
  1708. if (nm_setting_802_1x_get_phase2_private_key_format
  1709. (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
  1710. is_pkcs12 = TRUE;
  1711. }
  1712. password = (char *)
  1713. nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
  1714. } else {
  1715. if (nm_setting_802_1x_get_private_key_scheme (s_8021x) !=
  1716. NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
  1717. if (nm_setting_802_1x_get_private_key_format (s_8021x)
  1718. == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
  1719. is_pkcs12 = TRUE;
  1720. }
  1721. password = (char *)
  1722. nm_setting_802_1x_get_private_key_password (s_8021x);
  1723. }
  1724. if (is_pkcs12)
  1725. otype = phase2 ? &phase2_p12_type : &p12_type;
  1726. else
  1727. otype = phase2 ? &phase2_pk_type : &pk_type;
  1728. if ((*(otype->scheme_func)) (s_8021x) ==
  1729. NM_SETTING_802_1X_CK_SCHEME_BLOB)
  1730. blob = (*(otype->blob_func)) (s_8021x);
  1731. /* Only do the private key re-encrypt dance if we got the raw key data, which
  1732. * by definition will be unencrypted. If we're given a direct path to the
  1733. * private key file, it'll be encrypted, so we don't need to re-encrypt.
  1734. */
  1735. if (blob && !is_pkcs12) {
  1736. /* Encrypt the unencrypted private key with the fake password */
  1737. enc_key =
  1738. nm_utils_rsa_key_encrypt (blob, password, &generated_pw,
  1739. error);
  1740. if (!enc_key)
  1741. goto out;
  1742. if (generated_pw)
  1743. password = generated_pw;
  1744. }
  1745. /* Save the private key */
  1746. if (!write_object
  1747. (s_8021x, conn_name, enc_key ? enc_key : blob, otype, error))
  1748. goto out;
  1749. if (phase2)
  1750. wpa_set_data (conn_name, "private_key_passwd2", password);
  1751. else
  1752. wpa_set_data (conn_name, "private_key_passwd", password);
  1753. /* Client certificate */
  1754. if (is_pkcs12) {
  1755. wpa_set_data (conn_name,
  1756. phase2 ? "client_cert2" : "client_cert", NULL);
  1757. } else {
  1758. if (phase2)
  1759. otype = &phase2_client_type;
  1760. else
  1761. otype = &client_type;
  1762. /* Save the client certificate */
  1763. if (!write_object (s_8021x, conn_name, NULL, otype, error))
  1764. goto out;
  1765. }
  1766. success = TRUE;
  1767. out:
  1768. if (generated_pw) {
  1769. memset (generated_pw, 0, strlen (generated_pw));
  1770. g_free (generated_pw);
  1771. }
  1772. if (enc_key) {
  1773. memset (enc_key->data, 0, enc_key->len);
  1774. g_byte_array_free (enc_key, TRUE);
  1775. }
  1776. return success;
  1777. }
  1778. static gboolean
  1779. write_8021x_setting (NMConnection *connection,
  1780. const char *conn_name,
  1781. gboolean wired,
  1782. GError **error)
  1783. {
  1784. NMSetting8021x *s_8021x;
  1785. const char *value;
  1786. char *tmp = NULL;
  1787. gboolean success = FALSE;
  1788. GString *phase2_auth;
  1789. GString *phase1;
  1790. s_8021x = nm_connection_get_setting_802_1x (connection);
  1791. if (!s_8021x) {
  1792. return TRUE;
  1793. }
  1794. PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding 8021x setting for %s",
  1795. conn_name);
  1796. /* If wired, write KEY_MGMT */
  1797. if (wired)
  1798. wpa_set_data (conn_name, "key_mgmt", "IEEE8021X");
  1799. /* EAP method */
  1800. if (nm_setting_802_1x_get_num_eap_methods (s_8021x)) {
  1801. value = nm_setting_802_1x_get_eap_method (s_8021x, 0);
  1802. if (value)
  1803. tmp = g_ascii_strup (value, -1);
  1804. }
  1805. wpa_set_data (conn_name, "eap", tmp ? tmp : NULL);
  1806. g_free (tmp);
  1807. wpa_set_data (conn_name, "identity",
  1808. (gchar *) nm_setting_802_1x_get_identity (s_8021x));
  1809. wpa_set_data (conn_name, "anonymous_identity", (gchar *)
  1810. nm_setting_802_1x_get_anonymous_identity (s_8021x));
  1811. wpa_set_data (conn_name, "password",
  1812. (gchar *) nm_setting_802_1x_get_password (s_8021x));
  1813. phase1 = g_string_new (NULL);
  1814. /* PEAP version */
  1815. wpa_set_data (conn_name, "phase1", NULL);
  1816. value = nm_setting_802_1x_get_phase1_peapver (s_8021x);
  1817. if (value && (!strcmp (value, "0") || !strcmp (value, "1")))
  1818. g_string_append_printf (phase1, "peapver=%s ", value);
  1819. /* PEAP label */
  1820. value = nm_setting_802_1x_get_phase1_peaplabel (s_8021x);
  1821. if (value && !strcmp (value, "1"))
  1822. g_string_append_printf (phase1, "peaplabel=%s ", value);
  1823. if (phase1->len) {
  1824. tmp = g_strstrip (g_strdup (phase1->str));
  1825. wpa_set_data (conn_name, "phase1", tmp);
  1826. g_free (tmp);
  1827. }
  1828. /* Phase2 auth methods */
  1829. wpa_set_data (conn_name, "phase2", NULL);
  1830. phase2_auth = g_string_new (NULL);
  1831. value = nm_setting_802_1x_get_phase2_auth (s_8021x);
  1832. if (value) {
  1833. tmp = g_ascii_strup (value, -1);
  1834. g_string_append_printf (phase2_auth, "auth=%s ", tmp);
  1835. g_free (tmp);
  1836. }
  1837. /* Phase2 auth heap */
  1838. value = nm_setting_802_1x_get_phase2_autheap (s_8021x);
  1839. if (value) {
  1840. tmp = g_ascii_strup (value, -1);
  1841. g_string_append_printf (phase2_auth, "autheap=%s ", tmp);
  1842. g_free (tmp);
  1843. }
  1844. tmp = g_strstrip (g_strdup (phase2_auth->str));
  1845. wpa_set_data (conn_name, "phase2", phase2_auth->len ? tmp : NULL);
  1846. g_free (tmp);
  1847. g_string_free (phase2_auth, TRUE);
  1848. g_string_free (phase1, TRUE);
  1849. success = write_8021x_certs (s_8021x, FALSE, conn_name, error);
  1850. if (success) {
  1851. /* phase2/inner certs */
  1852. success = write_8021x_certs (s_8021x, TRUE, conn_name, error);
  1853. }
  1854. return success;
  1855. }
  1856. static gboolean
  1857. write_wireless_security_setting (NMConnection * connection,
  1858. gchar * conn_name,
  1859. gboolean adhoc,
  1860. gboolean * no_8021x, GError ** error)
  1861. {
  1862. NMSettingWirelessSecurity *s_wsec;
  1863. const char *key_mgmt, *auth_alg, *key, *cipher, *psk;
  1864. gboolean wep = FALSE, wpa = FALSE;
  1865. char *tmp;
  1866. guint32 i, num;
  1867. GString *str;
  1868. s_wsec = nm_connection_get_setting_wireless_security (connection);
  1869. if (!s_wsec) {
  1870. g_set_error (error, ifnet_plugin_error_quark (), 0,
  1871. "Missing '%s' setting",
  1872. NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
  1873. return FALSE;
  1874. }
  1875. key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
  1876. g_assert (key_mgmt);
  1877. auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
  1878. if (!strcmp (key_mgmt, "none")) {
  1879. wpa_set_data (conn_name, "key_mgmt", "NONE");
  1880. wep = TRUE;
  1881. *no_8021x = TRUE;
  1882. } else if (!strcmp (key_mgmt, "wpa-none")
  1883. || !strcmp (key_mgmt, "wpa-psk")) {
  1884. wpa_set_data (conn_name, "key_mgmt", "WPA-PSK");
  1885. wpa = TRUE;
  1886. *no_8021x = TRUE;
  1887. } else if (!strcmp (key_mgmt, "ieee8021x")) {
  1888. wpa_set_data (conn_name, "key_mgmt", "IEEE8021X");
  1889. } else if (!strcmp (key_mgmt, "wpa-eap")) {
  1890. wpa_set_data (conn_name, "key_mgmt", "WPA-EAP");
  1891. wpa = TRUE;
  1892. } else
  1893. PLUGIN_WARN (IFNET_PLUGIN_NAME, "Unknown key_mgmt: %s", key_mgmt);
  1894. if (auth_alg) {
  1895. if (!strcmp (auth_alg, "shared"))
  1896. wpa_set_data (conn_name, "auth_alg", "SHARED");
  1897. else if (!strcmp (auth_alg, "open"))
  1898. wpa_set_data (conn_name, "auth_alg", "OPEN");
  1899. else if (!strcmp (auth_alg, "leap")) {
  1900. wpa_set_data (conn_name, "auth_alg", "LEAP");
  1901. wpa_set_data (conn_name, "eap", "LEAP");
  1902. wpa_set_data (conn_name, "identity", (gchar *)
  1903. nm_setting_wireless_security_get_leap_username
  1904. (s_wsec));
  1905. wpa_set_data (conn_name, "password", (gchar *)
  1906. nm_setting_wireless_security_get_leap_password
  1907. (s_wsec));
  1908. *no_8021x = TRUE;
  1909. }
  1910. } else
  1911. wpa_set_data (conn_name, "auth_alg", NULL);
  1912. /* Default WEP TX key index */
  1913. if (wep) {
  1914. tmp =
  1915. g_strdup_printf ("%d",
  1916. nm_setting_wireless_security_get_wep_tx_keyidx
  1917. (s_wsec));
  1918. wpa_set_data (conn_name, "wep_tx_keyidx", tmp);
  1919. g_free (tmp);
  1920. } else
  1921. wpa_set_data (conn_name, "wep_tx_keyidx", NULL);
  1922. /* WEP keys */
  1923. for (i = 0; i < 4; i++) {
  1924. int length;
  1925. key = nm_setting_wireless_security_get_wep_key (s_wsec, i);
  1926. if (!key)
  1927. continue;
  1928. tmp = g_strdup_printf ("wep_key%d", i);
  1929. length = strlen (key);
  1930. if (length == 10 || length == 26 || length == 58)
  1931. wpa_set_data (conn_name, tmp, (gchar *) key);
  1932. else {
  1933. gchar *tmp_key = g_strdup_printf ("\"%s\"", key);
  1934. wpa_set_data (conn_name, tmp, tmp_key);
  1935. g_free (tmp_key);
  1936. }
  1937. g_free (tmp);
  1938. }
  1939. /* WPA Pairwise ciphers */
  1940. wpa_set_data (conn_name, "pairwise", NULL);
  1941. str = g_string_new (NULL);
  1942. num = nm_setting_wireless_security_get_num_pairwise (s_wsec);
  1943. for (i = 0; i < num; i++) {
  1944. if (i > 0)
  1945. g_string_append_c (str, ' ');
  1946. cipher = nm_setting_wireless_security_get_pairwise (s_wsec, i);
  1947. tmp = g_ascii_strup (cipher, -1);
  1948. g_string_append (str, tmp);
  1949. g_free (tmp);
  1950. }
  1951. if (strlen (str->str))
  1952. wpa_set_data (conn_name, "pairwise", str->str);
  1953. g_string_free (str, TRUE);
  1954. /* WPA Group ciphers */
  1955. wpa_set_data (conn_name, "group", NULL);
  1956. str = g_string_new (NULL);
  1957. num = nm_setting_wireless_security_get_num_groups (s_wsec);
  1958. for (i = 0; i < num; i++) {
  1959. if (i > 0)
  1960. g_string_append_c (str, ' ');
  1961. cipher = nm_setting_wireless_security_get_group (s_wsec, i);
  1962. tmp = g_ascii_strup (cipher, -1);
  1963. g_string_append (str, tmp);
  1964. g_free (tmp);
  1965. }
  1966. if (strlen (str->str))
  1967. wpa_set_data (conn_name, "group", str->str);
  1968. g_string_free (str, TRUE);
  1969. /* WPA Passphrase */
  1970. if (wpa) {
  1971. GString *quoted = NULL;
  1972. psk = nm_setting_wireless_security_get_psk (s_wsec);
  1973. if (psk && (strlen (psk) != 64)) {
  1974. quoted = g_string_sized_new (strlen (psk) + 2);
  1975. g_string_append_c (quoted, '"');
  1976. g_string_append (quoted, psk);
  1977. g_string_append_c (quoted, '"');
  1978. }
  1979. /* psk will be lost here if we don't check it for NULL */
  1980. if (psk)
  1981. wpa_set_data (conn_name, "psk",
  1982. quoted ? quoted->str : (gchar *) psk);
  1983. if (quoted)
  1984. g_string_free (quoted, TRUE);
  1985. } else
  1986. wpa_set_data (conn_name, "psk", NULL);
  1987. return TRUE;
  1988. }
  1989. /* remove old ssid and add new one*/
  1990. static void
  1991. update_wireless_ssid (NMConnection *connection,
  1992. const char *conn_name,
  1993. const char *ssid,
  1994. gboolean hex)
  1995. {
  1996. if(strcmp (conn_name, ssid)){
  1997. ifnet_delete_network (conn_name);
  1998. wpa_delete_security (conn_name);
  1999. }
  2000. ifnet_add_network (ssid, "wireless");
  2001. wpa_add_security (ssid);
  2002. }
  2003. static gboolean
  2004. write_wireless_setting (NMConnection *connection,
  2005. const char *conn_name,
  2006. gboolean *no_8021x,
  2007. const char **out_new_name,
  2008. GError **error)
  2009. {
  2010. NMSettingWireless *s_wireless;
  2011. const GByteArray *ssid, *mac, *bssid;
  2012. const char *mode;
  2013. char buf[33];
  2014. guint32 mtu, i;
  2015. gboolean adhoc = FALSE, hex_ssid = FALSE;
  2016. gchar *ssid_str, *tmp;
  2017. s_wireless = nm_connection_get_setting_wireless (connection);
  2018. if (!s_wireless) {
  2019. g_set_error (error, ifnet_plugin_error_quark (), 0,
  2020. "Missing '%s' setting",
  2021. NM_SETTING_WIRELESS_SETTING_NAME);
  2022. return FALSE;
  2023. }
  2024. ssid = nm_setting_wireless_get_ssid (s_wireless);
  2025. if (!ssid) {
  2026. g_set_error (error, ifnet_plugin_error_quark (), 0,
  2027. "Missing SSID in '%s' setting",
  2028. NM_SETTING_WIRELESS_SETTING_NAME);
  2029. return FALSE;
  2030. }
  2031. if (!ssid->len || ssid->len > 32) {
  2032. g_set_error (error, ifnet_plugin_error_quark (), 0,
  2033. "Invalid SSID in '%s' setting",
  2034. NM_SETTING_WIRELESS_SETTING_NAME);
  2035. return FALSE;
  2036. }
  2037. /* If the SSID contains any non-alnum characters, we need to use
  2038. * the hex notation of the SSID instead. (Because openrc doesn't
  2039. * support these characters, see bug #356337)
  2040. */
  2041. for (i = 0; i < ssid->len; i++) {
  2042. if (!g_ascii_isalnum (ssid->data[i])) {
  2043. hex_ssid = TRUE;
  2044. break;
  2045. }
  2046. }
  2047. if (hex_ssid) {
  2048. GString *str;
  2049. /* Hex SSIDs don't get quoted */
  2050. str = g_string_sized_new (ssid->len * 2 + 3);
  2051. g_string_append (str, "0x");
  2052. for (i = 0; i < ssid->len; i++)
  2053. g_string_append_printf (str, "%02X", ssid->data[i]);
  2054. update_wireless_ssid (connection, conn_name, str->str, hex_ssid);
  2055. ssid_str = g_string_free (str, FALSE);
  2056. } else {
  2057. /* Printable SSIDs get quoted */
  2058. memset (buf, 0, sizeof (buf));
  2059. memcpy (buf, ssid->data, ssid->len);
  2060. g_strstrip (buf);
  2061. update_wireless_ssid (connection, conn_name, buf, hex_ssid);
  2062. ssid_str = g_strdup (buf);
  2063. }
  2064. ifnet_set_data (ssid_str, "mac", NULL);
  2065. mac = nm_setting_wireless_get_mac_address (s_wireless);
  2066. if (mac) {
  2067. tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
  2068. mac->data[0], mac->data[1], mac->data[2],
  2069. mac->data[3], mac->data[4],
  2070. mac->data[5]);
  2071. ifnet_set_data (ssid_str, "mac", tmp);
  2072. g_free (tmp);
  2073. }
  2074. ifnet_set_data (ssid_str, "mtu", NULL);
  2075. mtu = nm_setting_wireless_get_mtu (s_wireless);
  2076. if (mtu) {
  2077. tmp = g_strdup_printf ("%u", mtu);
  2078. ifnet_set_data (ssid_str, "mtu", tmp);
  2079. g_free (tmp);
  2080. }
  2081. ifnet_set_data (ssid_str, "mode", NULL);
  2082. mode = nm_setting_wireless_get_mode (s_wireless);
  2083. if (!mode || !strcmp (mode, "infrastructure")) {
  2084. wpa_set_data (ssid_str, "mode", "0");
  2085. } else if (!strcmp (mode, "adhoc")) {
  2086. wpa_set_data (ssid_str, "mode", "1");
  2087. adhoc = TRUE;
  2088. } else {
  2089. PLUGIN_WARN (IFNET_PLUGIN_NAME,
  2090. "Invalid mode '%s' in '%s' setting",
  2091. mode, NM_SETTING_WIRELESS_SETTING_NAME);
  2092. return FALSE;
  2093. }
  2094. wpa_set_data (ssid_str, "bssid", NULL);
  2095. bssid = nm_setting_wireless_get_bssid (s_wireless);
  2096. if (bssid) {
  2097. tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
  2098. bssid->data[0], bssid->data[1],
  2099. bssid->data[2], bssid->data[3],
  2100. bssid->data[4], bssid->data[5]);
  2101. wpa_set_data (ssid_str, "bssid", tmp);
  2102. g_free (tmp);
  2103. }
  2104. if (nm_setting_wireless_get_security (s_wireless)) {
  2105. if (!write_wireless_security_setting
  2106. (connection, ssid_str, adhoc, no_8021x, error))
  2107. return FALSE;
  2108. } else
  2109. wpa_delete_security (ssid_str);
  2110. if (out_new_name)
  2111. *out_new_name = ifnet_get_data (ssid_str, "name");
  2112. g_free (ssid_str);
  2113. return TRUE;
  2114. }
  2115. static gboolean
  2116. write_wired_setting (NMConnection *connection,
  2117. const char *conn_name,
  2118. GError **error)
  2119. {
  2120. NMSettingWired *s_wired;
  2121. const GByteArray *mac;
  2122. char *tmp;
  2123. guint32 mtu;
  2124. s_wired = nm_connection_get_setting_wired (connection);
  2125. if (!s_wired) {
  2126. g_set_error (error, ifnet_plugin_error_quark (), 0,
  2127. "Missing '%s' setting",
  2128. NM_SETTING_WIRED_SETTING_NAME);
  2129. return FALSE;
  2130. }
  2131. ifnet_set_data (conn_name, "mac", NULL);
  2132. mac = nm_setting_wired_get_mac_address (s_wired);
  2133. if (mac) {
  2134. tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
  2135. mac->data[0], mac->data[1], mac->data[2],
  2136. mac->data[3], mac->data[4],
  2137. mac->data[5]);
  2138. ifnet_set_data (conn_name, "mac", tmp);
  2139. g_free (tmp);
  2140. }
  2141. ifnet_set_data (conn_name, "mtu", NULL);
  2142. mtu = nm_setting_wired_get_mtu (s_wired);
  2143. if (mtu) {
  2144. tmp = g_strdup_printf ("%u", mtu);
  2145. ifnet_set_data (conn_name, "mtu", tmp);
  2146. g_free (tmp);
  2147. }
  2148. //FIXME may add connection type in future
  2149. //ifnet_set_data (conn_name, "TYPE", TYPE_ETHERNET);
  2150. return TRUE;
  2151. }
  2152. static void
  2153. write_connection_setting (NMSettingConnection *s_con, const char *conn_name)
  2154. {
  2155. ifnet_set_data (conn_name, "auto",
  2156. nm_setting_connection_get_autoconnect (s_con) ? "true" :
  2157. "false");
  2158. }
  2159. static gboolean
  2160. write_ip4_setting (NMConnection *connection, const char *conn_name, GError **error)
  2161. {
  2162. NMSettingIP4Config *s_ip4;
  2163. const char *value;
  2164. char *tmp;
  2165. guint32 i, num;
  2166. GString *searches;
  2167. GString *ips;
  2168. GString *routes;
  2169. GString *dns;
  2170. gboolean has_def_route = FALSE;
  2171. gboolean success = FALSE;
  2172. s_ip4 = nm_connection_get_setting_ip4_config (connection);
  2173. if (!s_ip4) {
  2174. g_set_error (error, ifnet_plugin_error_quark (), 0,
  2175. "Missing '%s' setting",
  2176. NM_SETTING_IP4_CONFIG_SETTING_NAME);
  2177. return FALSE;
  2178. }
  2179. routes = g_string_new (NULL);
  2180. value = nm_setting_ip4_config_get_method (s_ip4);
  2181. g_assert (value);
  2182. if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
  2183. num = nm_setting_ip4_config_get_num_addresses (s_ip4);
  2184. ips = g_string_new (NULL);
  2185. /* IPv4 addresses */
  2186. for (i = 0; i < num; i++) {
  2187. char buf[INET_ADDRSTRLEN + 1];
  2188. NMIP4Address *addr;
  2189. guint32 ip;
  2190. addr = nm_setting_ip4_config_get_address (s_ip4, i);
  2191. memset (buf, 0, sizeof (buf));
  2192. ip = nm_ip4_address_get_address (addr);
  2193. inet_ntop (AF_INET, (const void *) &ip, &buf[0],
  2194. sizeof (buf));
  2195. g_string_append_printf (ips, "\"%s", &buf[0]);
  2196. tmp =
  2197. g_strdup_printf ("%u",
  2198. nm_ip4_address_get_prefix (addr));
  2199. g_string_append_printf (ips, "/%s\" ", tmp);
  2200. g_free (tmp);
  2201. /* only the first gateway will be written */
  2202. if (!has_def_route && nm_ip4_address_get_gateway (addr)) {
  2203. memset (buf, 0, sizeof (buf));
  2204. ip = nm_ip4_address_get_gateway (addr);
  2205. inet_ntop (AF_INET, (const void *) &ip, &buf[0],
  2206. sizeof (buf));
  2207. g_string_append_printf (routes,
  2208. "\"default via %s\" ",
  2209. &buf[0]);
  2210. has_def_route = TRUE;
  2211. }
  2212. }
  2213. ifnet_set_data (conn_name, "config", ips->str);
  2214. g_string_free (ips, TRUE);
  2215. } else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
  2216. ifnet_set_data (conn_name, "config", "shared");
  2217. else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL))
  2218. ifnet_set_data (conn_name, "config", "autoip");
  2219. else
  2220. ifnet_set_data (conn_name, "config", "dhcp");
  2221. /* DNS Servers */
  2222. num = nm_setting_ip4_config_get_num_dns (s_ip4);
  2223. if (num > 0) {
  2224. dns = g_string_new (NULL);
  2225. for (i = 0; i < num; i++) {
  2226. char buf[INET_ADDRSTRLEN + 1];
  2227. guint32 ip;
  2228. ip = nm_setting_ip4_config_get_dns (s_ip4, i);
  2229. memset (buf, 0, sizeof (buf));
  2230. inet_ntop (AF_INET, (const void *) &ip, &buf[0],
  2231. sizeof (buf));
  2232. g_string_append_printf (dns, " %s", buf);
  2233. }
  2234. ifnet_set_data (conn_name, "dns_servers", dns->str);
  2235. g_string_free (dns, TRUE);
  2236. } else
  2237. ifnet_set_data (conn_name, "dns_servers", NULL);
  2238. /* DNS Searches */
  2239. num = nm_setting_ip4_config_get_num_dns_searches (s_ip4);
  2240. if (num > 0) {
  2241. searches = g_string_new (NULL);
  2242. for (i = 0; i < num; i++) {
  2243. if (i > 0)
  2244. g_string_append_c (searches, ' ');
  2245. g_string_append (searches,
  2246. nm_setting_ip4_config_get_dns_search
  2247. (s_ip4, i));
  2248. }
  2249. ifnet_set_data (conn_name, "dns_search", searches->str);
  2250. g_string_free (searches, TRUE);
  2251. } else
  2252. ifnet_set_data (conn_name, "dns_search", NULL);
  2253. /* FIXME Will be implemented when configuration supports it
  2254. if (!strcmp(value, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
  2255. value = nm_setting_ip4_config_get_dhcp_hostname(s_ip4);
  2256. if (value)
  2257. ifnet_set_data(conn_name, "DHCP_HOSTNAME", value,
  2258. FALSE);
  2259. value = nm_setting_ip4_config_get_dhcp_client_id(s_ip4);
  2260. if (value)
  2261. ifnet_set_data(conn_name, "DHCP_CLIENT_ID", value,
  2262. FALSE);
  2263. }
  2264. */
  2265. /* Static routes */
  2266. num = nm_setting_ip4_config_get_num_routes (s_ip4);
  2267. if (num > 0) {
  2268. for (i = 0; i < num; i++) {
  2269. char buf[INET_ADDRSTRLEN + 1];
  2270. NMIP4Route *route;
  2271. guint32 ip;
  2272. route = nm_setting_ip4_config_get_route (s_ip4, i);
  2273. memset (buf, 0, sizeof (buf));
  2274. ip = nm_ip4_route_get_dest (route);
  2275. inet_ntop (AF_INET, (const void *) &ip, &buf[0],
  2276. sizeof (buf));
  2277. g_string_append_printf (routes, "\"%s", buf);
  2278. tmp =
  2279. g_strdup_printf ("%u",
  2280. nm_ip4_route_get_prefix (route));
  2281. g_string_append_printf (routes, "/%s via ", tmp);
  2282. g_free (tmp);
  2283. memset (buf, 0, sizeof (buf));
  2284. ip = nm_ip4_route_get_next_hop (route);
  2285. inet_ntop (AF_INET, (const void *) &ip, &buf[0],
  2286. sizeof (buf));
  2287. g_string_append_printf (routes, "%s\" ", buf);
  2288. }
  2289. }
  2290. if (routes->len > 0)
  2291. ifnet_set_data (conn_name, "routes", routes->str);
  2292. else
  2293. ifnet_set_data (conn_name, "routes", NULL);
  2294. g_string_free (routes, TRUE);
  2295. success = TRUE;
  2296. return success;
  2297. }
  2298. static gboolean
  2299. write_route6_file (NMSettingIP6Config *s_ip6, const char *conn_name, GError **error)
  2300. {
  2301. char dest[INET6_ADDRSTRLEN + 1];
  2302. char next_hop[INET6_ADDRSTRLEN + 1];
  2303. NMIP6Route *route;
  2304. const struct in6_addr *ip;
  2305. guint32 prefix;
  2306. guint32 i, num;
  2307. GString *routes_string;
  2308. const char *old_routes;
  2309. g_return_val_if_fail (s_ip6 != NULL, FALSE);
  2310. num = nm_setting_ip6_config_get_num_routes (s_ip6);
  2311. if (num == 0) {
  2312. return TRUE;
  2313. }
  2314. old_routes = ifnet_get_data (conn_name, "routes");
  2315. routes_string = g_string_new (old_routes);
  2316. if (old_routes)
  2317. g_string_append (routes_string, "\" ");
  2318. for (i = 0; i < num; i++) {
  2319. route = nm_setting_ip6_config_get_route (s_ip6, i);
  2320. memset (dest, 0, sizeof (dest));
  2321. ip = nm_ip6_route_get_dest (route);
  2322. inet_ntop (AF_INET6, (const void *) ip, &dest[0],
  2323. sizeof (dest));
  2324. prefix = nm_ip6_route_get_prefix (route);
  2325. memset (next_hop, 0, sizeof (next_hop));
  2326. ip = nm_ip6_route_get_next_hop (route);
  2327. inet_ntop (AF_INET6, (const void *) ip, &next_hop[0],
  2328. sizeof (next_hop));
  2329. g_string_append_printf (routes_string, "\"%s/%u via %s\" ",
  2330. dest, prefix, next_hop);
  2331. }
  2332. if (num > 0)
  2333. ifnet_set_data (conn_name, "routes", routes_string->str);
  2334. g_string_free (routes_string, TRUE);
  2335. return TRUE;
  2336. }
  2337. static gboolean
  2338. write_ip6_setting (NMConnection *connection, const char *conn_name, GError **error)
  2339. {
  2340. NMSettingIP6Config *s_ip6;
  2341. const char *value;
  2342. char *prefix;
  2343. guint32 i, num;
  2344. GString *searches;
  2345. char buf[INET6_ADDRSTRLEN + 1];
  2346. NMIP6Address *addr;
  2347. const struct in6_addr *ip;
  2348. s_ip6 = nm_connection_get_setting_ip6_config (connection);
  2349. if (!s_ip6) {
  2350. g_set_error (error, ifnet_plugin_error_quark (), 0,
  2351. "Missing '%s' setting",
  2352. NM_SETTING_IP6_CONFIG_SETTING_NAME);
  2353. return FALSE;
  2354. }
  2355. value = nm_setting_ip6_config_get_method (s_ip6);
  2356. g_assert (value);
  2357. if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
  2358. ifnet_set_data (conn_name, "enable_ipv6", "false");
  2359. return TRUE;
  2360. } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
  2361. /* nothing to do now */
  2362. } else {
  2363. // if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
  2364. const char *config = ifnet_get_data (conn_name, "config");
  2365. gchar *tmp;
  2366. if (!config)
  2367. tmp = g_strdup_printf ("dhcp6");
  2368. else
  2369. tmp = g_strdup_printf ("%s\" \"dhcp6\"", config);
  2370. ifnet_set_data (conn_name, "config", tmp);
  2371. g_free (tmp);
  2372. }
  2373. /* else if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
  2374. } else if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
  2375. } else if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
  2376. } */
  2377. /* Remember to set IPv6 enabled */
  2378. ifnet_set_data (conn_name, "enable_ipv6", "true");
  2379. if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
  2380. const char *config = ifnet_get_data (conn_name, "config");
  2381. gchar *tmp;
  2382. GString *ip_str;
  2383. if (!config)
  2384. config = "";
  2385. num = nm_setting_ip6_config_get_num_addresses (s_ip6);
  2386. /* IPv6 addresses */
  2387. ip_str = g_string_new (NULL);
  2388. for (i = 0; i < num; i++) {
  2389. addr = nm_setting_ip6_config_get_address (s_ip6, i);
  2390. ip = nm_ip6_address_get_address (addr);
  2391. prefix =
  2392. g_strdup_printf ("%u",
  2393. nm_ip6_address_get_prefix (addr));
  2394. memset (buf, 0, sizeof (buf));
  2395. inet_ntop (AF_INET6, (const void *) ip, buf,
  2396. sizeof (buf));
  2397. g_string_append_printf (ip_str, "\"%s/", buf);
  2398. g_string_append_printf (ip_str, "%s\" ", prefix);
  2399. g_free (prefix);
  2400. }
  2401. tmp = g_strdup_printf ("%s\" %s", config, ip_str->str);
  2402. ifnet_set_data (conn_name, "config", tmp);
  2403. g_free (tmp);
  2404. g_string_free (ip_str, TRUE);
  2405. }
  2406. /* DNS Servers */
  2407. num = nm_setting_ip6_config_get_num_dns (s_ip6);
  2408. if (num > 0) {
  2409. const char *dns_servers = ifnet_get_data (conn_name, "dns_servers");
  2410. gchar *tmp;
  2411. GString *dns_string = g_string_new (NULL);
  2412. if (!dns_servers)
  2413. dns_servers = "";
  2414. for (i = 0; i < num; i++) {
  2415. ip = nm_setting_ip6_config_get_dns (s_ip6, i);
  2416. memset (buf, 0, sizeof (buf));
  2417. inet_ntop (AF_INET6, (const void *) ip, buf,
  2418. sizeof (buf));
  2419. if (!strstr (dns_servers, buf))
  2420. g_string_append_printf (dns_string, "%s ", buf);
  2421. }
  2422. tmp = g_strdup_printf ("%s %s", dns_servers, dns_string->str);
  2423. ifnet_set_data (conn_name, "dns_servers", tmp);
  2424. g_free (tmp);
  2425. g_string_free (dns_string, TRUE);
  2426. } else
  2427. /* DNS Searches */
  2428. num = nm_setting_ip6_config_get_num_dns_searches (s_ip6);
  2429. if (num > 0) {
  2430. const char *ip4_domains;
  2431. ip4_domains = ifnet_get_data (conn_name, "dns_search");
  2432. if (!ip4_domains)
  2433. ip4_domains = "";
  2434. searches = g_string_new (ip4_domains);
  2435. for (i = 0; i < num; i++) {
  2436. const gchar *search = NULL;
  2437. search =
  2438. nm_setting_ip6_config_get_dns_search (s_ip6, i);
  2439. if (search && !strstr (searches->str, search)) {
  2440. if (searches->len > 0)
  2441. g_string_append_c (searches, ' ');
  2442. g_string_append (searches, search);
  2443. }
  2444. }
  2445. ifnet_set_data (conn_name, "dns_search", searches->str);
  2446. g_string_free (searches, TRUE);
  2447. }
  2448. write_route6_file (s_ip6, conn_name, error);
  2449. if (error && *error)
  2450. return FALSE;
  2451. return TRUE;
  2452. }
  2453. static gboolean
  2454. write_pppoe_setting (const char *conn_name, NMSettingPPPOE * s_pppoe)
  2455. {
  2456. const gchar *value;
  2457. value = nm_setting_pppoe_get_username (s_pppoe);
  2458. if (!value) {
  2459. return FALSE;
  2460. }
  2461. ifnet_set_data (conn_name, "username", (gchar *) value);
  2462. value = nm_setting_pppoe_get_password (s_pppoe);
  2463. /* password could be NULL here */
  2464. if (value) {
  2465. ifnet_set_data (conn_name, "password", (gchar *) value);
  2466. }
  2467. return TRUE;
  2468. }
  2469. gboolean
  2470. ifnet_update_parsers_by_connection (NMConnection *connection,
  2471. const char *conn_name,
  2472. const char *config_file,
  2473. const char *wpa_file,
  2474. gchar **out_new_name,
  2475. gchar **out_backup,
  2476. GError **error)
  2477. {
  2478. NMSettingConnection *s_con;
  2479. NMSettingIP6Config *s_ip6;
  2480. gboolean success = FALSE;
  2481. const char *type;
  2482. gboolean no_8021x = FALSE;
  2483. gboolean wired = FALSE, pppoe = TRUE;
  2484. const char *new_name = NULL;
  2485. s_con =
  2486. NM_SETTING_CONNECTION (nm_connection_get_setting
  2487. (connection, NM_TYPE_SETTING_CONNECTION));
  2488. if (!s_con) {
  2489. g_set_error (error, ifnet_plugin_error_quark (), 0,
  2490. "Missing '%s' setting",
  2491. NM_SETTING_CONNECTION_SETTING_NAME);
  2492. return FALSE;
  2493. }
  2494. type = nm_setting_connection_get_connection_type (s_con);
  2495. if (!type) {
  2496. g_set_error (error, ifnet_plugin_error_quark (), 0,
  2497. "Missing connection type!");
  2498. goto out;
  2499. }
  2500. if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) {
  2501. /* Writing wired setting */
  2502. if (!write_wired_setting (connection, conn_name, error))
  2503. goto out;
  2504. wired = TRUE;
  2505. no_8021x = TRUE;
  2506. } else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) {
  2507. /* Writing wireless setting */
  2508. if (!write_wireless_setting (connection, conn_name, &no_8021x, &new_name, error))
  2509. goto out;
  2510. } else if (!strcmp (type, NM_SETTING_PPPOE_SETTING_NAME)) {
  2511. NMSettingPPPOE *s_pppoe;
  2512. /* Writing pppoe setting */
  2513. s_pppoe = nm_connection_get_setting_pppoe (connection);
  2514. if (!write_pppoe_setting (conn_name, s_pppoe))
  2515. goto out;
  2516. pppoe = TRUE;
  2517. wired = TRUE;
  2518. no_8021x = TRUE;
  2519. } else {
  2520. g_set_error (error, ifnet_plugin_error_quark (), 0,
  2521. "Can't write connection type '%s'", type);
  2522. goto out;
  2523. }
  2524. /* connection name may have been updated; use it when writing out
  2525. * the rest of the settings.
  2526. */
  2527. if (new_name)
  2528. conn_name = new_name;
  2529. //FIXME wired connection doesn't support 8021x now
  2530. if (!no_8021x) {
  2531. if (!write_8021x_setting (connection, conn_name, wired, error))
  2532. goto out;
  2533. }
  2534. /* IPv4 Setting */
  2535. if (!write_ip4_setting (connection, conn_name, error))
  2536. goto out;
  2537. s_ip6 = nm_connection_get_setting_ip6_config (connection);
  2538. if (s_ip6) {
  2539. /* IPv6 Setting */
  2540. if (!write_ip6_setting (connection, conn_name, error))
  2541. goto out;
  2542. }
  2543. /* Connection Setting */
  2544. write_connection_setting (s_con, conn_name);
  2545. /* connection id will be displayed in nm-applet */
  2546. update_connection_id (connection, conn_name);
  2547. success = ifnet_flush_to_file (config_file, out_backup);
  2548. if (success)
  2549. wpa_flush_to_file (wpa_file);
  2550. if (out_new_name)
  2551. *out_new_name = g_strdup (conn_name);
  2552. out:
  2553. return success;
  2554. }
  2555. gboolean
  2556. ifnet_delete_connection_in_parsers (const char *conn_name,
  2557. const char *config_file,
  2558. const char *wpa_file,
  2559. gchar **out_backup)
  2560. {
  2561. gboolean result = FALSE;
  2562. ifnet_delete_network (conn_name);
  2563. result = ifnet_flush_to_file (config_file, out_backup);
  2564. if (result) {
  2565. /* connection may not have security information
  2566. * so simply ignore the return value*/
  2567. wpa_delete_security (conn_name);
  2568. wpa_flush_to_file (wpa_file);
  2569. }
  2570. return result;
  2571. }
  2572. /* get the available wired name(eth*). */
  2573. static gchar *
  2574. get_wired_name ()
  2575. {
  2576. int i = 0;
  2577. for (; i < 256; i++) {
  2578. gchar *conn_name = g_strdup_printf ("eth%d", i);
  2579. if (!ifnet_has_network (conn_name)) {
  2580. return conn_name;
  2581. } else
  2582. g_free (conn_name);
  2583. }
  2584. return NULL;
  2585. }
  2586. /* get the available pppoe name(ppp*). */
  2587. static gchar *
  2588. get_ppp_name ()
  2589. {
  2590. int i = 0;
  2591. for (; i < 256; i++) {
  2592. gchar *conn_name = g_strdup_printf ("ppp%d", i);
  2593. if (!ifnet_has_network (conn_name)) {
  2594. return conn_name;
  2595. } else
  2596. g_free (conn_name);
  2597. }
  2598. return NULL;
  2599. }
  2600. /* get wireless ssid */
  2601. static gchar *
  2602. get_wireless_name (NMConnection * connection)
  2603. {
  2604. NMSettingWireless *s_wireless;
  2605. const GByteArray *ssid;
  2606. gboolean hex_ssid = FALSE;
  2607. gchar *result = NULL;
  2608. char buf[33];
  2609. int i = 0;
  2610. s_wireless = nm_connection_get_setting_wireless (connection);
  2611. if (!s_wireless)
  2612. return NULL;
  2613. ssid = nm_setting_wireless_get_ssid (s_wireless);
  2614. if (!ssid->len || ssid->len > 32) {
  2615. return NULL;
  2616. }
  2617. for (i = 0; i < ssid->len; i++) {
  2618. if (!g_ascii_isprint (ssid->data[i])) {
  2619. hex_ssid = TRUE;
  2620. break;
  2621. }
  2622. }
  2623. if (hex_ssid) {
  2624. GString *str;
  2625. str = g_string_sized_new (ssid->len * 2 + 3);
  2626. g_string_append (str, "0x");
  2627. for (i = 0; i < ssid->len; i++)
  2628. g_string_append_printf (str, "%02X", ssid->data[i]);
  2629. result = g_strdup (str->str);
  2630. g_string_free (str, TRUE);
  2631. } else {
  2632. memset (buf, 0, sizeof (buf));
  2633. memcpy (buf, ssid->data, ssid->len);
  2634. result = g_strdup_printf ("%s", buf);
  2635. g_strstrip (result);
  2636. }
  2637. return result;
  2638. }
  2639. char *
  2640. ifnet_add_new_connection (NMConnection *connection,
  2641. const char *config_file,
  2642. const char *wpa_file,
  2643. gchar **out_backup,
  2644. GError **error)
  2645. {
  2646. NMSettingConnection *s_con;
  2647. gboolean success = FALSE;
  2648. const char *type;
  2649. gchar *new_type, *new_name = NULL;
  2650. s_con = nm_connection_get_setting_connection (connection);
  2651. g_assert (s_con);
  2652. type = nm_setting_connection_get_connection_type (s_con);
  2653. g_assert (type);
  2654. PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding %s connection", type);
  2655. /* get name and type
  2656. * Wireless type: wireless
  2657. * Wired type: wired
  2658. * PPPoE type: ppp*/
  2659. if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) {
  2660. new_name = get_wired_name ();
  2661. if (!new_name)
  2662. goto out;
  2663. new_type = "wired";
  2664. } else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) {
  2665. new_name = get_wireless_name (connection);
  2666. new_type = "wireless";
  2667. } else if (!strcmp (type, NM_SETTING_PPPOE_SETTING_NAME)) {
  2668. new_name = get_ppp_name ();
  2669. if (!new_name)
  2670. goto out;
  2671. new_type = "ppp";
  2672. } else {
  2673. g_set_error (error, ifnet_plugin_error_quark (), 0,
  2674. "Can't write connection type '%s'", type);
  2675. goto out;
  2676. }
  2677. if (ifnet_add_network (new_name, new_type)) {
  2678. success = ifnet_update_parsers_by_connection (connection,
  2679. new_name,
  2680. config_file,
  2681. wpa_file,
  2682. NULL,
  2683. out_backup,
  2684. error);
  2685. }
  2686. PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Added new connection: %s, result: %s",
  2687. new_name, success ? "success" : "fail");
  2688. out:
  2689. if (!success)
  2690. g_free (new_name);
  2691. return success ? new_name : NULL;
  2692. }