PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/src/cfg_client.c

https://gitlab.com/mdimjasevic/IKEv2
C | 411 lines | 245 code | 80 blank | 86 comment | 58 complexity | a1bb961da9a0c5b9d7291bec4c97c54d MD5 | raw file
Possible License(s): GPL-2.0
  1. /***************************************************************************
  2. * *
  3. * This program is free software; you can redistribute it and/or modify *
  4. * it under the terms of the GNU General Public License as published by *
  5. * the Free Software Foundation; either version 2 of the License, or *
  6. * (at your option) any later version. *
  7. * *
  8. ***************************************************************************/
  9. #define __CFG_CLIENT_C
  10. #ifdef CFG_CLIENT
  11. #define LOGGERNAME "cfg_client"
  12. #include <stdio.h>
  13. #ifdef HAVE_STDLIB_H
  14. #include <stdlib.h>
  15. #endif /* HAVE_STDLIB_H */
  16. #ifdef HAVE_STRING_H
  17. #include <string.h>
  18. #endif /* HAVE_STRING_H */
  19. #ifdef HAVE_SYS_SOCKET_H
  20. #include <sys/socket.h>
  21. #endif /* HAVE_SYS_SOCKET_H */
  22. #ifdef HAVE_SYS_TYPES_H
  23. #include <sys/types.h>
  24. #endif /* HAVE_SYS_TYPES_H */
  25. #ifdef HAVE_NETINET_IN_H
  26. #include <netinet/in.h>
  27. #endif /* HAVE_NETINET_IN_H */
  28. #include <linux/ipsec.h>
  29. #ifdef HAVE_ARPA_INET
  30. #include <arpa/inet.h>
  31. #endif /* HAVE_ARPA_INET */
  32. #ifdef HAVE_UNISTD_H
  33. #include <unistd.h>
  34. #endif /* HAVE_UNISTD_H */
  35. #include <sys/wait.h>
  36. #include <glib.h>
  37. #include <gmodule.h>
  38. #include "logging.h"
  39. #include "netlib.h"
  40. #include "auth.h"
  41. #include "cfg.h"
  42. #include "cfg_client.h"
  43. #define MAX_ENVLINE_LEN 256
  44. #define MAX_IPBUF_SIZE 80
  45. /**
  46. * Put variable into environemnt
  47. *
  48. * \return This function does not return
  49. *
  50. * In case of an error, exit() is called since we assume that we run
  51. * from fork()-ed process.
  52. */
  53. void newenv(char *c)
  54. {
  55. LOG_DEBUG("New env item '%s'", c);
  56. if (putenv(g_strdup(c)) < 0) {
  57. LOG_PERROR(LOG_PRIORITY_FATAL);
  58. exit(EXIT_FAILURE);
  59. }
  60. }
  61. /**
  62. * Execute script to update network parameters received from responder
  63. *
  64. * @param argv Script to execute, along with additional parameters
  65. * @param cfg Configuration data
  66. * @param id ID used to represent client to VPN gateway
  67. * @param vpngw IP address of the VIP gateway (either IPv4 or IPv6)
  68. * @param interface Interface through which we established connection
  69. *
  70. * \return 0 if execution was successful, -1 otherwise
  71. */
  72. int cfg_client_exec_script(gchar **argv, struct cfg *cfg, struct id *id,
  73. struct netaddr *vpngw, gchar *interface)
  74. {
  75. GSList *c;
  76. pid_t pid;
  77. char buf[MAX_ENVLINE_LEN];
  78. char ipbuf[MAX_IPBUF_SIZE];
  79. char *p;
  80. pid_t status;
  81. gint retval;
  82. LOG_FUNC_START(1);
  83. retval = -1;
  84. pid = fork();
  85. if (pid < 0) {
  86. LOG_PERROR(LOG_PRIORITY_ERROR);
  87. goto out;
  88. }
  89. if (!pid) {
  90. /*
  91. * Child process should prepare environment and
  92. * execute startup script.
  93. */
  94. strcpy(buf, IKEV2_CLIENT_ENV_ID);
  95. strcat(buf, "=");
  96. p = id_id2str(id);
  97. strcat(buf, p);
  98. g_free(p);
  99. newenv(buf);
  100. if (vpngw) {
  101. if (netaddr_get_family(vpngw) == AF_INET)
  102. strcpy(buf, IKEV2_CLIENT_ENV_VPN_IP4_ADDR);
  103. else
  104. strcpy(buf, IKEV2_CLIENT_ENV_VPN_IP6_ADDR);
  105. strcat(buf, "=");
  106. netaddr_ip2str(vpngw, ipbuf, MAX_IPBUF_SIZE);
  107. strcat(buf, ipbuf);
  108. newenv(buf);
  109. }
  110. strcpy(buf, IKEV2_CLIENT_ENV_IF);
  111. strcat(buf, "=");
  112. strcat(buf, interface);
  113. newenv(buf);
  114. if (cfg->flags & OPTION_F4_ADDR) {
  115. /*
  116. * If there are IPv4 addresses put them into
  117. * environemnt variable
  118. */
  119. strcpy(buf, IKEV2_CLIENT_ENV_ADDR4);
  120. strcat(buf, "=");
  121. for (c = cfg->netaddrs; c; c = c->next) {
  122. if (netaddr_get_family(c->data) == AF_INET) {
  123. netaddr_ip2str(c->data, ipbuf,
  124. MAX_IPBUF_SIZE);
  125. strcat(buf, ipbuf);
  126. strcat(buf, " ");
  127. }
  128. }
  129. if (strlen(buf) > sizeof(IKEV2_CLIENT_ENV_ADDR4) + 1)
  130. newenv(buf);
  131. if (cfg->expiry4) {
  132. snprintf(buf, MAX_ENVLINE_LEN, "%s=%u",
  133. IKEV2_CLIENT_ENV_EXPIRES4,
  134. cfg->expiry4);
  135. newenv(buf);
  136. }
  137. }
  138. if (cfg->flags & OPTION_F4_NETMASK) {
  139. /*
  140. * If there are IPv4 addresses put them into
  141. * environemnt variable
  142. */
  143. strcpy(buf, IKEV2_CLIENT_ENV_NETMASK4);
  144. strcat(buf, "=");
  145. inet_ntop(AF_INET, (struct in_addr *)&cfg->netmask,
  146. buf + strlen(buf), MAX_ENVLINE_LEN - strlen(buf));
  147. if (strlen(buf) > sizeof(IKEV2_CLIENT_ENV_NETMASK4) + 1)
  148. newenv(buf);
  149. }
  150. if (cfg->flags & OPTION_F4_SUBNETS) {
  151. /*
  152. * If there are IPv4 addresses put them into
  153. * environemnt variable
  154. */
  155. strcpy(buf, IKEV2_CLIENT_ENV_SUBNETS4);
  156. strcat(buf, "=");
  157. for (c = cfg->subnets; c; c = c->next) {
  158. if (netaddr_get_family(c->data) == AF_INET) {
  159. netaddr_net2str(c->data, ipbuf,
  160. MAX_IPBUF_SIZE);
  161. strcat(buf, ipbuf);
  162. strcat(buf, " ");
  163. }
  164. }
  165. if (strlen(buf) > sizeof(IKEV2_CLIENT_ENV_SUBNETS4) + 1)
  166. newenv(buf);
  167. }
  168. if (cfg->flags & OPTION_F6_ADDR) {
  169. /*
  170. * If there are IPv4 addresses put them into
  171. * environemnt variable
  172. */
  173. strcpy(buf, IKEV2_CLIENT_ENV_ADDR6);
  174. strcat(buf, "=");
  175. for (c = cfg->netaddrs; c; c = c->next) {
  176. if (netaddr_get_family(c->data) == AF_INET6) {
  177. netaddr_ip2str(c->data, ipbuf,
  178. MAX_IPBUF_SIZE);
  179. strcat(buf, ipbuf);
  180. strcat(buf, " ");
  181. }
  182. }
  183. if (strlen(buf) > sizeof(IKEV2_CLIENT_ENV_ADDR6) + 1)
  184. newenv(buf);
  185. if (cfg->expiry6) {
  186. snprintf(buf, MAX_ENVLINE_LEN, "%s=%u",
  187. IKEV2_CLIENT_ENV_EXPIRES6,
  188. cfg->expiry6);
  189. newenv(buf);
  190. }
  191. }
  192. if (cfg->flags & OPTION_F6_SUBNETS) {
  193. /*
  194. * If there are IPv4 addresses put them into
  195. * environemnt variable
  196. */
  197. strcpy(buf, IKEV2_CLIENT_ENV_SUBNETS6);
  198. strcat(buf, "=");
  199. for (c = cfg->subnets; c; c = c->next) {
  200. if (netaddr_get_family(c->data) == AF_INET6) {
  201. netaddr_ip2str(c->data, ipbuf,
  202. MAX_IPBUF_SIZE);
  203. strcat(buf, ipbuf);
  204. strcat(buf, " ");
  205. }
  206. }
  207. if (strlen(buf) > sizeof(IKEV2_CLIENT_ENV_SUBNETS6) + 1)
  208. newenv(buf);
  209. }
  210. if (cfg->flags & OPTION_F4_DNS) {
  211. /*
  212. * If there are IPv4 addresses put them into
  213. * environemnt variable
  214. */
  215. strcpy(buf, IKEV2_CLIENT_ENV_DNS4);
  216. strcat(buf, "=");
  217. for (c = cfg->dns; c; c = c->next) {
  218. if (netaddr_get_family(c->data) == AF_INET) {
  219. netaddr_ip2str(c->data, ipbuf,
  220. MAX_IPBUF_SIZE);
  221. strcat(buf, ipbuf);
  222. strcat(buf, " ");
  223. }
  224. }
  225. if (strlen(buf) > sizeof(IKEV2_CLIENT_ENV_DNS4) + 1)
  226. newenv(buf);
  227. }
  228. if (cfg->flags & OPTION_F6_DNS) {
  229. /*
  230. * If there are IPv4 addresses put them into
  231. * environemnt variable
  232. */
  233. strcpy(buf, IKEV2_CLIENT_ENV_DNS6);
  234. strcat(buf, "=");
  235. for (c = cfg->dns; c; c = c->next) {
  236. if (netaddr_get_family(c->data) == AF_INET6) {
  237. netaddr_ip2str(c->data, ipbuf,
  238. MAX_IPBUF_SIZE);
  239. strcat(buf, ipbuf);
  240. strcat(buf, " ");
  241. }
  242. }
  243. if (strlen(buf) > sizeof(IKEV2_CLIENT_ENV_DNS6) + 1)
  244. newenv(buf);
  245. }
  246. if (cfg->flags & OPTION_F4_NBNS) {
  247. /*
  248. * If there are IPv4 addresses put them into
  249. * environemnt variable
  250. */
  251. strcpy(buf, IKEV2_CLIENT_ENV_NBNS);
  252. strcat(buf, "=");
  253. for (c = cfg->nbns; c; c = c->next) {
  254. if (netaddr_get_family(c->data) == AF_INET) {
  255. netaddr_ip2str(c->data, ipbuf,
  256. MAX_IPBUF_SIZE);
  257. strcat(buf, ipbuf);
  258. strcat(buf, " ");
  259. }
  260. }
  261. if (strlen(buf) > sizeof(IKEV2_CLIENT_ENV_NBNS) + 1)
  262. newenv(buf);
  263. }
  264. if (cfg->flags & OPTION_F4_DHCP) {
  265. /*
  266. * If there are IPv4 addresses put them into
  267. * environemnt variable
  268. */
  269. strcpy(buf, IKEV2_CLIENT_ENV_DHCP4);
  270. strcat(buf, "=");
  271. for (c = cfg->dhcp; c; c = c->next) {
  272. if (netaddr_get_family(c->data) == AF_INET) {
  273. netaddr_ip2str(c->data, ipbuf,
  274. MAX_IPBUF_SIZE);
  275. strcat(buf, ipbuf);
  276. strcat(buf, " ");
  277. }
  278. }
  279. if (strlen(buf) > sizeof(IKEV2_CLIENT_ENV_DHCP4) + 1)
  280. newenv(buf);
  281. }
  282. if (cfg->flags & OPTION_F6_DHCP) {
  283. /*
  284. * If there are IPv4 addresses put them into
  285. * environemnt variable
  286. */
  287. strcpy(buf, IKEV2_CLIENT_ENV_DHCP6);
  288. strcat(buf, "=");
  289. for (c = cfg->dhcp; c; c = c->next) {
  290. if (netaddr_get_family(c->data) == AF_INET6) {
  291. netaddr_ip2str(c->data, ipbuf,
  292. MAX_IPBUF_SIZE);
  293. strcat(buf, ipbuf);
  294. strcat(buf, " ");
  295. }
  296. }
  297. if (strlen(buf) > sizeof(IKEV2_CLIENT_ENV_DHCP6) + 1)
  298. newenv(buf);
  299. }
  300. execv(argv[0], argv);
  301. /*
  302. * If we reached this part then there was error in the
  303. * previous function.
  304. */
  305. LOG_PERROR(LOG_PRIORITY_ERROR);
  306. exit(1);
  307. }
  308. /*
  309. * Parent process should wait for the child process
  310. * and monitor return value...
  311. *
  312. * There is a potential DoS here. If the script never
  313. * returns then the IKEv2 will block!
  314. */
  315. wait(&status);
  316. /**
  317. * Check that script exited via exit call and that it
  318. * returned zero. This signals successful script run.
  319. */
  320. if (!WIFEXITED(status))
  321. LOG_ERROR("Script %s prematurely ended!", argv[0]);
  322. else if (WEXITSTATUS(status))
  323. LOG_ERROR("Script %s returned exit code %d",
  324. argv[0], WEXITSTATUS(status));
  325. else
  326. retval = 0;
  327. out:
  328. LOG_FUNC_END(1);
  329. return retval;
  330. }
  331. #endif /* CFG_CLIENT */