import-export.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071
  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
  2. /***************************************************************************
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. *
  18. * Copyright (C) 2008 - 2013 Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
  19. *
  20. **************************************************************************/
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include <string.h>
  25. #include <sys/types.h>
  26. #include <stdlib.h>
  27. #include <sys/stat.h>
  28. #include <fcntl.h>
  29. #include <unistd.h>
  30. #include <errno.h>
  31. #include <ctype.h>
  32. #include <stdio.h>
  33. #include <glib/gi18n-lib.h>
  34. #include <nm-setting-vpn.h>
  35. #include <nm-setting-connection.h>
  36. #include <nm-setting-ip4-config.h>
  37. #include "import-export.h"
  38. #include "nm-openvpn.h"
  39. #include "../src/nm-openvpn-service.h"
  40. #include "../common/utils.h"
  41. #define AUTH_TAG "auth "
  42. #define AUTH_USER_PASS_TAG "auth-user-pass"
  43. #define CA_TAG "ca "
  44. #define CERT_TAG "cert "
  45. #define CIPHER_TAG "cipher "
  46. #define KEYSIZE_TAG "keysize "
  47. #define CLIENT_TAG "client"
  48. #define COMP_TAG "comp-lzo"
  49. #define DEV_TAG "dev "
  50. #define DEV_TYPE_TAG "dev-type "
  51. #define FRAGMENT_TAG "fragment "
  52. #define IFCONFIG_TAG "ifconfig "
  53. #define KEY_TAG "key "
  54. #define MSSFIX_TAG "mssfix"
  55. #define PKCS12_TAG "pkcs12 "
  56. #define PORT_TAG "port "
  57. #define PROTO_TAG "proto "
  58. #define HTTP_PROXY_TAG "http-proxy "
  59. #define HTTP_PROXY_RETRY_TAG "http-proxy-retry"
  60. #define SOCKS_PROXY_TAG "socks-proxy "
  61. #define SOCKS_PROXY_RETRY_TAG "socks-proxy-retry"
  62. #define REMOTE_TAG "remote "
  63. #define RENEG_SEC_TAG "reneg-sec "
  64. #define RPORT_TAG "rport "
  65. #define SECRET_TAG "secret "
  66. #define TLS_AUTH_TAG "tls-auth "
  67. #define TLS_CLIENT_TAG "tls-client"
  68. #define TLS_REMOTE_TAG "tls-remote "
  69. #define REMOTE_CERT_TLS_TAG "remote-cert-tls "
  70. #define TUNMTU_TAG "tun-mtu "
  71. static char *
  72. unquote (const char *line, char **leftover)
  73. {
  74. char *tmp, *item, *unquoted = NULL, *p;
  75. gboolean quoted = FALSE;
  76. if (leftover)
  77. g_return_val_if_fail (*leftover == NULL, FALSE);
  78. tmp = g_strdup (line);
  79. item = g_strstrip (tmp);
  80. if (!strlen (item)) {
  81. g_free (tmp);
  82. return NULL;
  83. }
  84. /* Simple unquote */
  85. if ((item[0] == '"') || (item[0] == '\'')) {
  86. quoted = TRUE;
  87. item++;
  88. }
  89. /* Unquote stuff using openvpn unquoting rules */
  90. unquoted = g_malloc0 (strlen (item) + 1);
  91. for (p = unquoted; *item; item++, p++) {
  92. if (quoted && ((*item == '"') || (*item == '\'')))
  93. break;
  94. else if (!quoted && isspace (*item))
  95. break;
  96. if (*item == '\\' && *(item+1) == '\\')
  97. *p = *(++item);
  98. else if (*item == '\\' && *(item+1) == '"')
  99. *p = *(++item);
  100. else if (*item == '\\' && *(item+1) == ' ')
  101. *p = *(++item);
  102. else
  103. *p = *item;
  104. }
  105. if (leftover && *item)
  106. *leftover = g_strdup (item + 1);
  107. g_free (tmp);
  108. return unquoted;
  109. }
  110. static gboolean
  111. handle_path_item (const char *line,
  112. const char *tag,
  113. const char *key,
  114. NMSettingVPN *s_vpn,
  115. const char *path,
  116. char **leftover)
  117. {
  118. char *file, *full_path = NULL;
  119. if (strncmp (line, tag, strlen (tag)))
  120. return FALSE;
  121. file = unquote (line + strlen (tag), leftover);
  122. if (!file) {
  123. if (leftover) {
  124. g_free (*leftover);
  125. leftover = NULL;
  126. }
  127. return FALSE;
  128. }
  129. /* If file isn't an absolute file name, add the default path */
  130. if (!g_path_is_absolute (file))
  131. full_path = g_build_filename (path, file, NULL);
  132. nm_setting_vpn_add_data_item (s_vpn, key, full_path ? full_path : file);
  133. g_free (file);
  134. g_free (full_path);
  135. return TRUE;
  136. }
  137. static char **
  138. get_args (const char *line, int *nitems)
  139. {
  140. char **split, **sanitized, **tmp, **tmp2;
  141. split = g_strsplit_set (line, " \t", 0);
  142. sanitized = g_malloc0 (sizeof (char *) * (g_strv_length (split) + 1));
  143. for (tmp = split, tmp2 = sanitized; *tmp; tmp++) {
  144. if (strlen (*tmp))
  145. *tmp2++ = g_strdup (*tmp);
  146. }
  147. g_strfreev (split);
  148. *nitems = g_strv_length (sanitized);
  149. return sanitized;
  150. }
  151. static void
  152. handle_direction (const char *tag, const char *key, char *leftover, NMSettingVPN *s_vpn)
  153. {
  154. glong direction;
  155. if (!leftover)
  156. return;
  157. leftover = g_strstrip (leftover);
  158. if (!strlen (leftover))
  159. return;
  160. errno = 0;
  161. direction = strtol (leftover, NULL, 10);
  162. if (errno == 0) {
  163. if (direction == 0)
  164. nm_setting_vpn_add_data_item (s_vpn, key, "0");
  165. else if (direction == 1)
  166. nm_setting_vpn_add_data_item (s_vpn, key, "1");
  167. } else
  168. g_warning ("%s: unknown %s direction '%s'", __func__, tag, leftover);
  169. }
  170. static char *
  171. parse_port (const char *str, const char *line)
  172. {
  173. glong port;
  174. errno = 0;
  175. port = strtol (str, NULL, 10);
  176. if ((errno == 0) && (port > 0) && (port < 65536))
  177. return g_strdup_printf ("%d", (gint) port);
  178. g_warning ("%s: invalid remote port in option '%s'", __func__, line);
  179. return NULL;
  180. }
  181. static gboolean
  182. parse_http_proxy_auth (const char *path,
  183. const char *file,
  184. char **out_user,
  185. char **out_pass)
  186. {
  187. char *contents = NULL, *abspath = NULL, *tmp;
  188. GError *error = NULL;
  189. char **lines, **iter;
  190. g_return_val_if_fail (out_user != NULL, FALSE);
  191. g_return_val_if_fail (out_pass != NULL, FALSE);
  192. if (!file || !strcmp (file, "stdin") || !strcmp (file, "auto") || !strcmp (file, "'auto'"))
  193. return TRUE;
  194. if (!g_path_is_absolute (file)) {
  195. tmp = g_path_get_dirname (path);
  196. abspath = g_build_path ("/", tmp, file, NULL);
  197. g_free (tmp);
  198. } else
  199. abspath = g_strdup (file);
  200. /* Grab user/pass from authfile */
  201. if (!g_file_get_contents (abspath, &contents, NULL, &error)) {
  202. g_warning ("%s: unable to read HTTP proxy authfile '%s': (%d) %s",
  203. __func__, abspath, error ? error->code : -1,
  204. error && error->message ? error->message : "(unknown)");
  205. g_clear_error (&error);
  206. g_free (abspath);
  207. return FALSE;
  208. }
  209. lines = g_strsplit_set (contents, "\n\r", 0);
  210. for (iter = lines; iter && *iter; iter++) {
  211. if (!strlen (*iter))
  212. continue;
  213. if (!*out_user)
  214. *out_user = g_strdup (g_strstrip (*iter));
  215. else if (!*out_pass) {
  216. *out_pass = g_strdup (g_strstrip (*iter));
  217. break;
  218. }
  219. }
  220. if (lines)
  221. g_strfreev (lines);
  222. g_free (contents);
  223. g_free (abspath);
  224. return *out_user && *out_pass;
  225. }
  226. NMConnection *
  227. do_import (const char *path, char **lines, GError **error)
  228. {
  229. NMConnection *connection = NULL;
  230. NMSettingConnection *s_con;
  231. NMSettingVPN *s_vpn;
  232. char *last_dot;
  233. char **line;
  234. gboolean have_client = FALSE, have_remote = FALSE;
  235. gboolean have_pass = FALSE, have_sk = FALSE;
  236. const char *ctype = NULL;
  237. char *basename;
  238. char *default_path, *tmp, *tmp2;
  239. gboolean http_proxy = FALSE, socks_proxy = FALSE, proxy_set = FALSE;
  240. int nitems;
  241. connection = nm_connection_new ();
  242. s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
  243. nm_connection_add_setting (connection, NM_SETTING (s_con));
  244. s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ());
  245. g_object_set (s_vpn, NM_SETTING_VPN_SERVICE_TYPE, NM_DBUS_SERVICE_OPENVPN, NULL);
  246. /* Get the default path for ca, cert, key file, these files maybe
  247. * in same path with the configuration file */
  248. if (g_path_is_absolute (path))
  249. default_path = g_path_get_dirname (path);
  250. else {
  251. tmp = g_get_current_dir ();
  252. tmp2 = g_path_get_dirname (path);
  253. default_path = g_build_filename (tmp, tmp2, NULL);
  254. g_free (tmp);
  255. g_free (tmp2);
  256. }
  257. basename = g_path_get_basename (path);
  258. last_dot = strrchr (basename, '.');
  259. if (last_dot)
  260. *last_dot = '\0';
  261. g_object_set (s_con, NM_SETTING_CONNECTION_ID, basename, NULL);
  262. g_free (basename);
  263. for (line = lines; *line; line++) {
  264. char *comment, **items = NULL, *leftover = NULL;
  265. if ((comment = strchr (*line, '#')))
  266. *comment = '\0';
  267. if ((comment = strchr (*line, ';')))
  268. *comment = '\0';
  269. if (!strlen (*line))
  270. continue;
  271. if ( !strncmp (*line, CLIENT_TAG, strlen (CLIENT_TAG))
  272. || !strncmp (*line, TLS_CLIENT_TAG, strlen (TLS_CLIENT_TAG))) {
  273. have_client = TRUE;
  274. continue;
  275. }
  276. if (!strncmp (*line, DEV_TAG, strlen (DEV_TAG))) {
  277. items = get_args (*line + strlen (DEV_TAG), &nitems);
  278. if (nitems == 1) {
  279. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_DEV, items[0]);
  280. } else
  281. g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
  282. g_strfreev (items);
  283. continue;
  284. }
  285. if (!strncmp (*line, DEV_TYPE_TAG, strlen (DEV_TYPE_TAG))) {
  286. items = get_args (*line + strlen (DEV_TYPE_TAG), &nitems);
  287. if (nitems == 1) {
  288. if (!strcmp (items[0], "tun") || !strcmp (items[0], "tap"))
  289. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_DEV_TYPE, items[0]);
  290. else
  291. g_warning ("%s: unknown %s option '%s'", __func__, DEV_TYPE_TAG, *line);
  292. } else
  293. g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
  294. g_strfreev (items);
  295. continue;
  296. }
  297. if (!strncmp (*line, PROTO_TAG, strlen (PROTO_TAG))) {
  298. items = get_args (*line + strlen (PROTO_TAG), &nitems);
  299. if (nitems == 1) {
  300. /* Valid parameters are "udp", "tcp-client" and "tcp-server".
  301. * 'tcp' isn't technically valid, but it used to be accepted so
  302. * we'll handle it here anyway.
  303. */
  304. if (!strcmp (items[0], "udp")) {
  305. /* ignore; udp is default */
  306. } else if ( !strcmp (items[0], "tcp-client")
  307. || !strcmp (items[0], "tcp-server")
  308. || !strcmp (items[0], "tcp")) {
  309. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_PROTO_TCP, "yes");
  310. } else
  311. g_warning ("%s: unknown %s option '%s'", __func__, PROTO_TAG, *line);
  312. } else
  313. g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
  314. g_strfreev (items);
  315. continue;
  316. }
  317. if (!strncmp (*line, MSSFIX_TAG, strlen (MSSFIX_TAG))) {
  318. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_MSSFIX, "yes");
  319. continue;
  320. }
  321. if (!strncmp (*line, TUNMTU_TAG, strlen (TUNMTU_TAG))) {
  322. items = get_args (*line + strlen (TUNMTU_TAG), &nitems);
  323. if (nitems == 1) {
  324. glong secs;
  325. errno = 0;
  326. secs = strtol (items[0], NULL, 10);
  327. if ((errno == 0) && (secs >= 0) && (secs < 0xffff)) {
  328. tmp = g_strdup_printf ("%d", (guint32) secs);
  329. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_TUNNEL_MTU, tmp);
  330. g_free (tmp);
  331. } else
  332. g_warning ("%s: invalid size in option '%s'", __func__, *line);
  333. } else
  334. g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
  335. g_strfreev (items);
  336. continue;
  337. }
  338. if (!strncmp (*line, FRAGMENT_TAG, strlen (FRAGMENT_TAG))) {
  339. items = get_args (*line + strlen (FRAGMENT_TAG), &nitems);
  340. if (nitems == 1) {
  341. glong secs;
  342. errno = 0;
  343. secs = strtol (items[0], NULL, 10);
  344. if ((errno == 0) && (secs >= 0) && (secs < 0xffff)) {
  345. tmp = g_strdup_printf ("%d", (guint32) secs);
  346. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_FRAGMENT_SIZE, tmp);
  347. g_free (tmp);
  348. } else
  349. g_warning ("%s: invalid size in option '%s'", __func__, *line);
  350. } else
  351. g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
  352. g_strfreev (items);
  353. continue;
  354. }
  355. if (!strncmp (*line, COMP_TAG, strlen (COMP_TAG))) {
  356. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_COMP_LZO, "yes");
  357. continue;
  358. }
  359. if (!strncmp (*line, RENEG_SEC_TAG, strlen (RENEG_SEC_TAG))) {
  360. items = get_args (*line + strlen (RENEG_SEC_TAG), &nitems);
  361. if (nitems == 1) {
  362. glong secs;
  363. errno = 0;
  364. secs = strtol (items[0], NULL, 10);
  365. if ((errno == 0) && (secs >= 0) && (secs <= 604800)) {
  366. tmp = g_strdup_printf ("%d", (guint32) secs);
  367. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_RENEG_SECONDS, tmp);
  368. g_free (tmp);
  369. } else
  370. g_warning ("%s: invalid time length in option '%s'", __func__, *line);
  371. }
  372. g_strfreev (items);
  373. continue;
  374. }
  375. if ( !strncmp (*line, HTTP_PROXY_RETRY_TAG, strlen (HTTP_PROXY_RETRY_TAG))
  376. || !strncmp (*line, SOCKS_PROXY_RETRY_TAG, strlen (SOCKS_PROXY_RETRY_TAG))) {
  377. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_PROXY_RETRY, "yes");
  378. continue;
  379. }
  380. http_proxy = g_str_has_prefix (*line, HTTP_PROXY_TAG);
  381. socks_proxy = g_str_has_prefix (*line, SOCKS_PROXY_TAG);
  382. if ((http_proxy || socks_proxy) && !proxy_set) {
  383. gboolean success = FALSE;
  384. const char *proxy_type = NULL;
  385. if (http_proxy) {
  386. items = get_args (*line + strlen (HTTP_PROXY_TAG), &nitems);
  387. proxy_type = "http";
  388. } else if (socks_proxy) {
  389. items = get_args (*line + strlen (SOCKS_PROXY_TAG), &nitems);
  390. proxy_type = "socks";
  391. }
  392. if (nitems >= 2) {
  393. glong port;
  394. char *s_port = NULL;
  395. char *user = NULL, *pass = NULL;
  396. success = TRUE;
  397. if (http_proxy && nitems >= 3)
  398. success = parse_http_proxy_auth (path, items[2], &user, &pass);
  399. if (success) {
  400. success = FALSE;
  401. errno = 0;
  402. port = strtol (items[1], NULL, 10);
  403. if ((errno == 0) && (port > 0) && (port < 65536)) {
  404. s_port = g_strdup_printf ("%d", (guint32) port);
  405. success = TRUE;
  406. }
  407. }
  408. if (success && proxy_type) {
  409. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_PROXY_TYPE, proxy_type);
  410. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_PROXY_SERVER, items[0]);
  411. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_PROXY_PORT, s_port);
  412. if (user)
  413. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_HTTP_PROXY_USERNAME, user);
  414. if (pass) {
  415. nm_setting_vpn_add_secret (s_vpn, NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD, pass);
  416. nm_setting_set_secret_flags (NM_SETTING (s_vpn),
  417. NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD,
  418. NM_SETTING_SECRET_FLAG_AGENT_OWNED,
  419. NULL);
  420. }
  421. proxy_set = TRUE;
  422. }
  423. g_free (s_port);
  424. g_free (user);
  425. g_free (pass);
  426. }
  427. if (!success)
  428. g_warning ("%s: invalid proxy option '%s'", __func__, *line);
  429. g_strfreev (items);
  430. continue;
  431. }
  432. if (!strncmp (*line, REMOTE_TAG, strlen (REMOTE_TAG))) {
  433. items = get_args (*line + strlen (REMOTE_TAG), &nitems);
  434. if (nitems >= 1 && nitems <= 3) {
  435. const char *prev = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE);
  436. char *new_remote = g_strdup_printf ("%s%s%s", prev ? prev : "", prev ? ", " : "", items[0]);
  437. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE, new_remote);
  438. g_free (new_remote);
  439. have_remote = TRUE;
  440. if (nitems >= 2) {
  441. tmp = parse_port (items[1], *line);
  442. if (tmp) {
  443. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_PORT, tmp);
  444. g_free (tmp);
  445. if (nitems == 3) {
  446. /* TODO */
  447. }
  448. }
  449. }
  450. } else
  451. g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
  452. g_strfreev (items);
  453. continue;
  454. }
  455. if ( !strncmp (*line, PORT_TAG, strlen (PORT_TAG))
  456. || !strncmp (*line, RPORT_TAG, strlen (RPORT_TAG))) {
  457. /* Port specified in 'remote' always takes precedence */
  458. if (nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PORT))
  459. continue;
  460. if (!strncmp (*line, PORT_TAG, strlen (PORT_TAG)))
  461. items = get_args (*line + strlen (PORT_TAG), &nitems);
  462. else if (!strncmp (*line, RPORT_TAG, strlen (RPORT_TAG)))
  463. items = get_args (*line + strlen (RPORT_TAG), &nitems);
  464. else
  465. g_assert_not_reached ();
  466. if (nitems == 1) {
  467. tmp = parse_port (items[0], *line);
  468. if (tmp) {
  469. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_PORT, tmp);
  470. g_free (tmp);
  471. }
  472. } else
  473. g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
  474. g_strfreev (items);
  475. continue;
  476. }
  477. if ( handle_path_item (*line, PKCS12_TAG, NM_OPENVPN_KEY_CA, s_vpn, default_path, NULL) &&
  478. handle_path_item (*line, PKCS12_TAG, NM_OPENVPN_KEY_CERT, s_vpn, default_path, NULL) &&
  479. handle_path_item (*line, PKCS12_TAG, NM_OPENVPN_KEY_KEY, s_vpn, default_path, NULL))
  480. continue;
  481. if (handle_path_item (*line, CA_TAG, NM_OPENVPN_KEY_CA, s_vpn, default_path, NULL))
  482. continue;
  483. if (handle_path_item (*line, CERT_TAG, NM_OPENVPN_KEY_CERT, s_vpn, default_path, NULL))
  484. continue;
  485. if (handle_path_item (*line, KEY_TAG, NM_OPENVPN_KEY_KEY, s_vpn, default_path, NULL))
  486. continue;
  487. if (handle_path_item (*line, SECRET_TAG, NM_OPENVPN_KEY_STATIC_KEY,
  488. s_vpn, default_path, &leftover)) {
  489. handle_direction ("secret",
  490. NM_OPENVPN_KEY_STATIC_KEY_DIRECTION,
  491. leftover,
  492. s_vpn);
  493. g_free (leftover);
  494. have_sk = TRUE;
  495. continue;
  496. }
  497. if (handle_path_item (*line, TLS_AUTH_TAG, NM_OPENVPN_KEY_TA,
  498. s_vpn, default_path, &leftover)) {
  499. handle_direction ("tls-auth",
  500. NM_OPENVPN_KEY_TA_DIR,
  501. leftover,
  502. s_vpn);
  503. g_free (leftover);
  504. continue;
  505. }
  506. if (!strncmp (*line, CIPHER_TAG, strlen (CIPHER_TAG))) {
  507. items = get_args (*line + strlen (CIPHER_TAG), &nitems);
  508. if (nitems == 1)
  509. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_CIPHER, items[0]);
  510. else
  511. g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
  512. g_strfreev (items);
  513. continue;
  514. }
  515. if (!strncmp (*line, KEYSIZE_TAG, strlen (KEYSIZE_TAG))) {
  516. items = get_args (*line + strlen (KEYSIZE_TAG), &nitems);
  517. if (nitems == 1) {
  518. glong key_size;
  519. errno = 0;
  520. key_size = strtol (items[0], NULL, 10);
  521. if ((errno == 0) && (key_size > 0) && (key_size <= 65535)) {
  522. tmp = g_strdup_printf ("%d", (guint32) key_size);
  523. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_KEYSIZE, tmp);
  524. g_free (tmp);
  525. } else
  526. g_warning ("%s: invalid key size in option '%s'", __func__, *line);
  527. } else
  528. g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
  529. g_strfreev (items);
  530. continue;
  531. }
  532. if (!strncmp (*line, TLS_REMOTE_TAG, strlen (TLS_REMOTE_TAG))) {
  533. char *unquoted = unquote (*line + strlen (TLS_REMOTE_TAG), NULL);
  534. if (unquoted) {
  535. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_TLS_REMOTE, unquoted);
  536. g_free (unquoted);
  537. } else
  538. g_warning ("%s: unknown %s option '%s'", __func__, TLS_REMOTE_TAG, *line);
  539. continue;
  540. }
  541. if (!strncmp (*line, REMOTE_CERT_TLS_TAG, strlen (REMOTE_CERT_TLS_TAG))) {
  542. items = get_args (*line + strlen (REMOTE_CERT_TLS_TAG), &nitems);
  543. if (nitems == 1) {
  544. if ( !strcmp (items[0], NM_OPENVPN_REM_CERT_TLS_CLIENT)
  545. || !strcmp (items[0], NM_OPENVPN_REM_CERT_TLS_SERVER)) {
  546. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE_CERT_TLS, items[0]);
  547. } else
  548. g_warning ("%s: unknown %s option '%s'", __func__, REMOTE_CERT_TLS_TAG, *line);
  549. }
  550. g_strfreev (items);
  551. continue;
  552. }
  553. if (!strncmp (*line, IFCONFIG_TAG, strlen (IFCONFIG_TAG))) {
  554. items = get_args (*line + strlen (IFCONFIG_TAG), &nitems);
  555. if (nitems == 2) {
  556. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_LOCAL_IP, items[0]);
  557. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE_IP, items[1]);
  558. } else
  559. g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
  560. g_strfreev (items);
  561. continue;
  562. }
  563. if (!strncmp (*line, AUTH_USER_PASS_TAG, strlen (AUTH_USER_PASS_TAG))) {
  564. have_pass = TRUE;
  565. continue;
  566. }
  567. if (!strncmp (*line, AUTH_TAG, strlen (AUTH_TAG))) {
  568. items = get_args (*line + strlen (AUTH_TAG), &nitems);
  569. if (nitems == 1)
  570. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_AUTH, items[0]);
  571. else
  572. g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
  573. g_strfreev (items);
  574. continue;
  575. }
  576. }
  577. if (!have_client && !have_sk) {
  578. g_set_error_literal (error,
  579. OPENVPN_PLUGIN_UI_ERROR,
  580. OPENVPN_PLUGIN_UI_ERROR_FILE_NOT_OPENVPN,
  581. _("The file to import wasn't a valid OpenVPN client configuration."));
  582. g_object_unref (connection);
  583. connection = NULL;
  584. } else if (!have_remote) {
  585. g_set_error_literal (error,
  586. OPENVPN_PLUGIN_UI_ERROR,
  587. OPENVPN_PLUGIN_UI_ERROR_FILE_NOT_OPENVPN,
  588. _("The file to import wasn't a valid OpenVPN configure (no remote)."));
  589. g_object_unref (connection);
  590. connection = NULL;
  591. } else {
  592. gboolean have_certs = FALSE, have_ca = FALSE;
  593. if (nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CA))
  594. have_ca = TRUE;
  595. if ( have_ca
  596. && nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CERT)
  597. && nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEY))
  598. have_certs = TRUE;
  599. /* Determine connection type */
  600. if (have_pass) {
  601. if (have_certs)
  602. ctype = NM_OPENVPN_CONTYPE_PASSWORD_TLS;
  603. else if (have_ca)
  604. ctype = NM_OPENVPN_CONTYPE_PASSWORD;
  605. } else if (have_certs) {
  606. ctype = NM_OPENVPN_CONTYPE_TLS;
  607. } else if (have_sk)
  608. ctype = NM_OPENVPN_CONTYPE_STATIC_KEY;
  609. if (!ctype)
  610. ctype = NM_OPENVPN_CONTYPE_TLS;
  611. nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, ctype);
  612. /* Default secret flags to be agent-owned */
  613. if (have_pass) {
  614. nm_setting_set_secret_flags (NM_SETTING (s_vpn),
  615. NM_OPENVPN_KEY_PASSWORD,
  616. NM_SETTING_SECRET_FLAG_AGENT_OWNED,
  617. NULL);
  618. }
  619. if (have_certs) {
  620. const char *key_path;
  621. key_path = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEY);
  622. if (key_path && is_encrypted (key_path)) {
  623. /* If there should be a private key password, default it to
  624. * being agent-owned.
  625. */
  626. nm_setting_set_secret_flags (NM_SETTING (s_vpn),
  627. NM_OPENVPN_KEY_CERTPASS,
  628. NM_SETTING_SECRET_FLAG_AGENT_OWNED,
  629. NULL);
  630. }
  631. }
  632. }
  633. g_free (default_path);
  634. if (connection)
  635. nm_connection_add_setting (connection, NM_SETTING (s_vpn));
  636. else if (s_vpn)
  637. g_object_unref (s_vpn);
  638. return connection;
  639. }
  640. gboolean
  641. do_export (const char *path, NMConnection *connection, GError **error)
  642. {
  643. NMSettingConnection *s_con;
  644. NMSettingVPN *s_vpn;
  645. FILE *f;
  646. const char *value;
  647. const char *gateways = NULL;
  648. char **gw_list, **gw_iter;
  649. const char *cipher = NULL;
  650. const char *cacert = NULL;
  651. const char *connection_type = NULL;
  652. const char *user_cert = NULL;
  653. const char *private_key = NULL;
  654. const char *static_key = NULL;
  655. const char *static_key_direction = NULL;
  656. const char *port = NULL;
  657. const char *local_ip = NULL;
  658. const char *remote_ip = NULL;
  659. const char *tls_remote = NULL;
  660. const char *remote_cert_tls = NULL;
  661. const char *tls_auth = NULL;
  662. const char *tls_auth_dir = NULL;
  663. const char *device = NULL;
  664. const char *device_type = NULL;
  665. const char *device_default = "tun";
  666. gboolean success = FALSE;
  667. gboolean proto_udp = TRUE;
  668. gboolean use_lzo = FALSE;
  669. gboolean reneg_exists = FALSE;
  670. guint32 reneg = 0;
  671. gboolean keysize_exists = FALSE;
  672. guint32 keysize = 0;
  673. const char *proxy_type = NULL;
  674. const char *proxy_server = NULL;
  675. const char *proxy_port = NULL;
  676. const char *proxy_retry = NULL;
  677. const char *proxy_username = NULL;
  678. const char *proxy_password = NULL;
  679. s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
  680. g_assert (s_con);
  681. s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
  682. f = fopen (path, "w");
  683. if (!f) {
  684. g_set_error_literal (error, 0, 0, _("could not open file for writing"));
  685. return FALSE;
  686. }
  687. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE);
  688. if (value && strlen (value))
  689. gateways = value;
  690. else {
  691. g_set_error_literal (error, 0, 0, _("connection was incomplete (missing gateway)"));
  692. goto done;
  693. }
  694. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE);
  695. if (value && strlen (value))
  696. connection_type = value;
  697. if ( !strcmp (connection_type, NM_OPENVPN_CONTYPE_TLS)
  698. || !strcmp (connection_type, NM_OPENVPN_CONTYPE_PASSWORD)
  699. || !strcmp (connection_type, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
  700. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CA);
  701. if (value && strlen (value))
  702. cacert = value;
  703. }
  704. if ( !strcmp (connection_type, NM_OPENVPN_CONTYPE_TLS)
  705. || !strcmp (connection_type, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
  706. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CERT);
  707. if (value && strlen (value))
  708. user_cert = value;
  709. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEY);
  710. if (value && strlen (value))
  711. private_key = value;
  712. }
  713. if (!strcmp (connection_type, NM_OPENVPN_CONTYPE_STATIC_KEY)) {
  714. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY);
  715. if (value && strlen (value))
  716. static_key = value;
  717. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY_DIRECTION);
  718. if (value && strlen (value))
  719. static_key_direction = value;
  720. }
  721. /* Export tls-remote value now*/
  722. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TLS_REMOTE);
  723. if (value && strlen (value))
  724. tls_remote = value;
  725. /* Advanced values start */
  726. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PORT);
  727. if (value && strlen (value))
  728. port = value;
  729. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_RENEG_SECONDS);
  730. if (value && strlen (value)) {
  731. reneg_exists = TRUE;
  732. reneg = strtol (value, NULL, 10);
  733. }
  734. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PROTO_TCP);
  735. if (value && !strcmp (value, "yes"))
  736. proto_udp = FALSE;
  737. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_DEV);
  738. if (value && strlen (value))
  739. device = value;
  740. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_DEV_TYPE);
  741. if (value && strlen (value))
  742. device_type = value;
  743. /* Read legacy 'tap-dev' property for backwards compatibility. */
  744. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TAP_DEV);
  745. if (value && !strcmp (value, "yes"))
  746. device_default = "tap";
  747. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_COMP_LZO);
  748. if (value && !strcmp (value, "yes"))
  749. use_lzo = TRUE;
  750. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CIPHER);
  751. if (value && strlen (value))
  752. cipher = value;
  753. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEYSIZE);
  754. if (value && strlen (value)) {
  755. keysize_exists = TRUE;
  756. keysize = strtol (value, NULL, 10);
  757. }
  758. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_LOCAL_IP);
  759. if (value && strlen (value))
  760. local_ip = value;
  761. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE_IP);
  762. if (value && strlen (value))
  763. remote_ip = value;
  764. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TA);
  765. if (value && strlen (value))
  766. tls_auth = value;
  767. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TA_DIR);
  768. if (value && strlen (value))
  769. tls_auth_dir = value;
  770. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE_CERT_TLS);
  771. if (value && strlen (value))
  772. remote_cert_tls = value;
  773. /* Advanced values end */
  774. fprintf (f, "client\n");
  775. gw_list = g_strsplit_set (gateways, " ,", 0);
  776. for (gw_iter = gw_list; gw_iter && *gw_iter; gw_iter++) {
  777. if (**gw_iter == '\0')
  778. continue;
  779. fprintf (f, "remote %s%s%s\n",
  780. *gw_iter,
  781. port ? " " : "",
  782. port ? port : "");
  783. }
  784. g_strfreev (gw_list);
  785. /* Handle PKCS#12 (all certs are the same file) */
  786. if ( cacert && user_cert && private_key
  787. && !strcmp (cacert, user_cert) && !strcmp (cacert, private_key))
  788. fprintf (f, "pkcs12 %s\n", cacert);
  789. else {
  790. if (cacert)
  791. fprintf (f, "ca %s\n", cacert);
  792. if (user_cert)
  793. fprintf (f, "cert %s\n", user_cert);
  794. if (private_key)
  795. fprintf(f, "key %s\n", private_key);
  796. }
  797. if ( !strcmp(connection_type, NM_OPENVPN_CONTYPE_PASSWORD)
  798. || !strcmp(connection_type, NM_OPENVPN_CONTYPE_PASSWORD_TLS))
  799. fprintf (f, "auth-user-pass\n");
  800. if (!strcmp (connection_type, NM_OPENVPN_CONTYPE_STATIC_KEY)) {
  801. if (static_key) {
  802. fprintf (f, "secret %s%s%s\n",
  803. static_key,
  804. static_key_direction ? " " : "",
  805. static_key_direction ? static_key_direction : "");
  806. } else
  807. g_warning ("%s: invalid openvpn static key configuration (missing static key)", __func__);
  808. }
  809. if (reneg_exists)
  810. fprintf (f, "reneg-sec %d\n", reneg);
  811. if (cipher)
  812. fprintf (f, "cipher %s\n", cipher);
  813. if (keysize_exists)
  814. fprintf (f, "keysize %d\n", keysize);
  815. if (use_lzo)
  816. fprintf (f, "comp-lzo yes\n");
  817. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_MSSFIX);
  818. if (value && strlen (value)) {
  819. if (!strcmp (value, "yes"))
  820. fprintf (f, MSSFIX_TAG "\n");
  821. }
  822. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TUNNEL_MTU);
  823. if (value && strlen (value))
  824. fprintf (f, TUNMTU_TAG " %d\n", (int) strtol (value, NULL, 10));
  825. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_FRAGMENT_SIZE);
  826. if (value && strlen (value))
  827. fprintf (f, FRAGMENT_TAG " %d\n", (int) strtol (value, NULL, 10));
  828. fprintf (f, "dev %s\n", device ? device : (device_type ? device_type : device_default));
  829. if (device_type)
  830. fprintf (f, "dev-type %s\n", device_type);
  831. fprintf (f, "proto %s\n", proto_udp ? "udp" : "tcp");
  832. if (local_ip && remote_ip)
  833. fprintf (f, "ifconfig %s %s\n", local_ip, remote_ip);
  834. if ( !strcmp(connection_type, NM_OPENVPN_CONTYPE_TLS)
  835. || !strcmp(connection_type, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
  836. if (tls_remote)
  837. fprintf (f,"tls-remote \"%s\"\n", tls_remote);
  838. if (remote_cert_tls)
  839. fprintf (f,"remote-cert-tls %s\n", remote_cert_tls);
  840. if (tls_auth) {
  841. fprintf (f, "tls-auth %s%s%s\n",
  842. tls_auth,
  843. tls_auth_dir ? " " : "",
  844. tls_auth_dir ? tls_auth_dir : "");
  845. }
  846. }
  847. /* Proxy stuff */
  848. proxy_type = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PROXY_TYPE);
  849. if (proxy_type && strlen (proxy_type)) {
  850. proxy_server = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PROXY_SERVER);
  851. proxy_port = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PROXY_PORT);
  852. proxy_retry = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PROXY_RETRY);
  853. proxy_username = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_HTTP_PROXY_USERNAME);
  854. proxy_password = nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD);
  855. if (!strcmp (proxy_type, "http") && proxy_server && proxy_port) {
  856. char *authfile, *authcontents, *base, *dirname;
  857. if (!proxy_port)
  858. proxy_port = "8080";
  859. /* If there's a username, need to write an authfile */
  860. base = g_path_get_basename (path);
  861. dirname = g_path_get_dirname (path);
  862. authfile = g_strdup_printf ("%s/%s-httpauthfile", dirname, base);
  863. g_free (base);
  864. g_free (dirname);
  865. fprintf (f, "http-proxy %s %s%s%s\n",
  866. proxy_server,
  867. proxy_port,
  868. proxy_username ? " " : "",
  869. proxy_username ? authfile : "");
  870. if (proxy_retry && !strcmp (proxy_retry, "yes"))
  871. fprintf (f, "http-proxy-retry\n");
  872. /* Write out the authfile */
  873. if (proxy_username) {
  874. authcontents = g_strdup_printf ("%s\n%s\n",
  875. proxy_username,
  876. proxy_password ? proxy_password : "");
  877. g_file_set_contents (authfile, authcontents, -1, NULL);
  878. g_free (authcontents);
  879. }
  880. g_free (authfile);
  881. } else if (!strcmp (proxy_type, "socks") && proxy_server && proxy_port) {
  882. if (!proxy_port)
  883. proxy_port = "1080";
  884. fprintf (f, "socks-proxy %s %s\n", proxy_server, proxy_port);
  885. if (proxy_retry && !strcmp (proxy_retry, "yes"))
  886. fprintf (f, "socks-proxy-retry\n");
  887. }
  888. }
  889. /* Add hard-coded stuff */
  890. fprintf (f,
  891. "nobind\n"
  892. "auth-nocache\n"
  893. "script-security 2\n"
  894. "persist-key\n"
  895. "persist-tun\n"
  896. "user openvpn\n"
  897. "group openvpn\n");
  898. success = TRUE;
  899. done:
  900. fclose (f);
  901. return success;
  902. }