wg-user.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
  4. *
  5. * Based on wireguard-tools:
  6. * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
  7. */
  8. #include <stdbool.h>
  9. #include <stddef.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <dirent.h>
  14. #include <errno.h>
  15. #include <sys/types.h>
  16. #include <sys/socket.h>
  17. #include <sys/stat.h>
  18. #include <sys/un.h>
  19. #include <arpa/inet.h>
  20. #include <time.h>
  21. #include <netdb.h>
  22. #include "unetd.h"
  23. #define SOCK_PATH RUNSTATEDIR "/wireguard/"
  24. #define SOCK_SUFFIX ".sock"
  25. struct wg_req {
  26. FILE *f;
  27. char *buf;
  28. size_t buf_len;
  29. char *key, *value;
  30. int ret;
  31. };
  32. static void
  33. key_to_hex(char hex[static WG_KEY_LEN_HEX], const uint8_t key[static WG_KEY_LEN])
  34. {
  35. unsigned int i;
  36. for (i = 0; i < WG_KEY_LEN; ++i) {
  37. hex[i * 2] = 87U + (key[i] >> 4) + ((((key[i] >> 4) - 10U) >> 8) & ~38U);
  38. hex[i * 2 + 1] = 87U + (key[i] & 0xf) + ((((key[i] & 0xf) - 10U) >> 8) & ~38U);
  39. }
  40. hex[i * 2] = '\0';
  41. }
  42. static bool
  43. key_from_hex(uint8_t key[static WG_KEY_LEN], const char *hex)
  44. {
  45. uint8_t c, c_acc, c_alpha0, c_alpha, c_num0, c_num, c_val;
  46. volatile uint8_t ret = 0;
  47. if (strlen(hex) != WG_KEY_LEN_HEX - 1)
  48. return false;
  49. for (unsigned int i = 0; i < WG_KEY_LEN_HEX - 1; i += 2) {
  50. c = (uint8_t)hex[i];
  51. c_num = c ^ 48U;
  52. c_num0 = (c_num - 10U) >> 8;
  53. c_alpha = (c & ~32U) - 55U;
  54. c_alpha0 = ((c_alpha - 10U) ^ (c_alpha - 16U)) >> 8;
  55. ret |= ((c_num0 | c_alpha0) - 1) >> 8;
  56. c_val = (c_num0 & c_num) | (c_alpha0 & c_alpha);
  57. c_acc = c_val * 16U;
  58. c = (uint8_t)hex[i + 1];
  59. c_num = c ^ 48U;
  60. c_num0 = (c_num - 10U) >> 8;
  61. c_alpha = (c & ~32U) - 55U;
  62. c_alpha0 = ((c_alpha - 10U) ^ (c_alpha - 16U)) >> 8;
  63. ret |= ((c_num0 | c_alpha0) - 1) >> 8;
  64. c_val = (c_num0 & c_num) | (c_alpha0 & c_alpha);
  65. key[i / 2] = c_acc | c_val;
  66. }
  67. return 1 & ((ret - 1) >> 8);
  68. }
  69. static bool wg_user_check(struct network *net)
  70. {
  71. struct sockaddr_un addr = { .sun_family = AF_UNIX };
  72. struct stat sbuf;
  73. int fd, ret;
  74. if (snprintf(addr.sun_path, sizeof(addr.sun_path), SOCK_PATH "%s" SOCK_SUFFIX, network_name(net)) < 0)
  75. return false;
  76. if (stat(addr.sun_path, &sbuf) < 0)
  77. return false;
  78. if (!S_ISSOCK(sbuf.st_mode))
  79. return false;
  80. ret = fd = socket(AF_UNIX, SOCK_STREAM, 0);
  81. if (ret < 0)
  82. return false;
  83. ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
  84. if (ret < 0 && errno == ECONNREFUSED) { /* If the process is gone, we try to clean up the socket. */
  85. close(fd);
  86. unlink(addr.sun_path);
  87. return false;
  88. }
  89. close(fd);
  90. return true;
  91. }
  92. static FILE *wg_user_file(struct network *net)
  93. {
  94. struct stat sbuf;
  95. struct sockaddr_un addr = { .sun_family = AF_UNIX };
  96. int fd = -1, ret;
  97. FILE *f = NULL;
  98. errno = EINVAL;
  99. ret = snprintf(addr.sun_path, sizeof(addr.sun_path), SOCK_PATH "%s" SOCK_SUFFIX, network_name(net));
  100. if (ret < 0)
  101. goto out;
  102. ret = stat(addr.sun_path, &sbuf);
  103. if (ret < 0)
  104. goto out;
  105. errno = EBADF;
  106. if (!S_ISSOCK(sbuf.st_mode))
  107. goto out;
  108. ret = fd = socket(AF_UNIX, SOCK_STREAM, 0);
  109. if (ret < 0)
  110. goto out;
  111. ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
  112. if (ret < 0) {
  113. if (errno == ECONNREFUSED) /* If the process is gone, we try to clean up the socket. */
  114. unlink(addr.sun_path);
  115. goto out;
  116. }
  117. f = fdopen(fd, "r+");
  118. if (f)
  119. errno = 0;
  120. out:
  121. ret = -errno;
  122. if (ret) {
  123. if (fd >= 0)
  124. close(fd);
  125. errno = -ret;
  126. return NULL;
  127. }
  128. return f;
  129. }
  130. static void wg_req_set(struct wg_req *req, const char *key, const char *value)
  131. {
  132. fprintf(req->f, "%s=%s\n", key, value);
  133. }
  134. static void wg_req_set_int(struct wg_req *req, const char *key, int value)
  135. {
  136. fprintf(req->f, "%s=%d\n", key, value);
  137. }
  138. #define wg_req_printf(req, name, format, ...) fprintf((req)->f, "%s=" format "\n", name, ##__VA_ARGS__)
  139. static int wg_req_init(struct wg_req *req, struct network *net, bool set)
  140. {
  141. memset(req, 0, sizeof(*req));
  142. req->ret = -1;
  143. req->f = wg_user_file(net);
  144. if (!req->f)
  145. return -1;
  146. wg_req_set(req, set ? "set" : "get", "1");
  147. return 0;
  148. }
  149. static bool wg_req_fetch(struct wg_req *req)
  150. {
  151. int len;
  152. if (!req->buf) {
  153. fprintf(req->f, "\n");
  154. fflush(req->f);
  155. }
  156. if (getline(&req->buf, &req->buf_len, req->f) <= 0)
  157. return false;
  158. req->key = req->buf;
  159. len = strlen(req->key);
  160. if (len == 1 && req->key[0] == '\n')
  161. return false;
  162. req->value = strchr(req->key, '=');
  163. if (!req->value || !len || req->key[len - 1] != '\n')
  164. return false;
  165. *(req->value++) = req->key[--len] = 0;
  166. if (!strcmp(req->key, "errno"))
  167. req->ret = atoi(req->value);
  168. return true;
  169. }
  170. static void wg_req_complete(struct wg_req *req)
  171. {
  172. while (wg_req_fetch(req));
  173. }
  174. static int wg_req_done(struct wg_req *req)
  175. {
  176. if (!req->buf)
  177. wg_req_complete(req);
  178. if (req->f)
  179. fclose(req->f);
  180. free(req->buf);
  181. return -req->ret;
  182. }
  183. static int
  184. wg_user_test(struct network *net)
  185. {
  186. struct wg_req req;
  187. if (wg_req_init(&req, net, false))
  188. return -1;
  189. return wg_req_done(&req);
  190. }
  191. static int
  192. wg_network_reset(struct network *net, uint8_t *key)
  193. {
  194. struct wg_req req;
  195. char key_str[WG_KEY_LEN_HEX];
  196. if (wg_req_init(&req, net, true))
  197. return -1;
  198. wg_req_set(&req, "replace_peers", "true");
  199. key_to_hex(key_str, key);
  200. wg_req_set(&req, "private_key", key_str);
  201. return wg_req_done(&req);
  202. }
  203. static int
  204. wg_user_init(struct network *net)
  205. {
  206. int err;
  207. err = wg_user_test(net);
  208. if (err)
  209. return err;
  210. return wg_network_reset(net, net->config.key);
  211. }
  212. static void
  213. wg_user_cleanup(struct network *net)
  214. {
  215. uint8_t key[WG_KEY_LEN] = {};
  216. wg_network_reset(net, key);
  217. }
  218. static int
  219. wg_user_init_local(struct network *net, struct network_peer *peer)
  220. {
  221. struct wg_req req;
  222. if (wg_req_init(&req, net, true))
  223. return -1;
  224. wg_req_set_int(&req, "listen_port", peer ? peer->port : 0);
  225. return wg_req_done(&req);
  226. }
  227. static void
  228. wg_user_peer_req_add_allowed_ip(struct wg_req *req, struct network_peer *peer)
  229. {
  230. char addr[INET6_ADDRSTRLEN];
  231. struct blob_attr *cur;
  232. int rem;
  233. inet_ntop(AF_INET6, &peer->local_addr.in6, addr, sizeof(addr));
  234. wg_req_printf(req, "allowed_ip", "%s/128", addr);
  235. blobmsg_for_each_attr(cur, peer->ipaddr, rem) {
  236. const char *str = blobmsg_get_string(cur);
  237. struct in6_addr in6;
  238. int af, mask;
  239. if (strchr(str, ':')) {
  240. af = AF_INET6;
  241. mask = 128;
  242. } else {
  243. af = AF_INET;
  244. mask = 32;
  245. }
  246. if (inet_pton(af, str, &in6) != 1)
  247. continue;
  248. wg_req_printf(req, "allowed_ip", "%s/%d", str, mask);
  249. }
  250. blobmsg_for_each_attr(cur, peer->subnet, rem) {
  251. const char *str = blobmsg_get_string(cur);
  252. char buf[INET6_ADDRSTRLEN];
  253. union network_addr addr;
  254. int mask;
  255. int af;
  256. af = strchr(str, ':') ? AF_INET6 : AF_INET;
  257. if (network_get_subnet(af, &addr, &mask, str))
  258. continue;
  259. inet_ntop(af, &addr, buf, sizeof(buf));
  260. wg_req_printf(req, "allowed_ip", "%s/%d", buf, mask);
  261. }
  262. }
  263. static int
  264. wg_user_peer_update(struct network *net, struct network_peer *peer, enum wg_update_cmd cmd)
  265. {
  266. struct network_host *host;
  267. struct wg_req req;
  268. char key[WG_KEY_LEN_HEX];
  269. if (wg_req_init(&req, net, true))
  270. return -1;
  271. key_to_hex(key, peer->key);
  272. wg_req_set(&req, "public_key", key);
  273. if (cmd == WG_PEER_DELETE) {
  274. wg_req_set(&req, "remove", "true");
  275. goto out;
  276. }
  277. wg_req_set(&req, "replace_allowed_ips", "true");
  278. wg_user_peer_req_add_allowed_ip(&req, peer);
  279. for_each_routed_host(host, net, peer)
  280. wg_user_peer_req_add_allowed_ip(&req, &host->peer);
  281. out:
  282. return wg_req_done(&req);
  283. }
  284. static int
  285. wg_user_peer_refresh(struct network *net)
  286. {
  287. struct network_peer *peer = NULL;
  288. struct wg_req req;
  289. uint8_t key[WG_KEY_LEN];
  290. time_t now = time(NULL);
  291. if (wg_req_init(&req, net, false))
  292. return -1;
  293. while (wg_req_fetch(&req)) {
  294. if (!strcmp(req.key, "public_key")) {
  295. if (peer)
  296. wg_peer_update_done(net, peer);
  297. if (key_from_hex(key, req.value))
  298. peer = wg_peer_update_start(net, key);
  299. else
  300. peer = NULL;
  301. continue;
  302. }
  303. if (!peer)
  304. continue;
  305. if (!strcmp(req.key, "last_handshake_time_sec")) {
  306. uint64_t sec = strtoull(req.value, NULL, 0);
  307. wg_peer_set_last_handshake(net, peer, now, sec);
  308. continue;
  309. }
  310. if (!strcmp(req.key, "rx_bytes")) {
  311. uint64_t bytes = strtoull(req.value, NULL, 0);
  312. wg_peer_set_rx_bytes(net, peer, bytes);
  313. continue;
  314. }
  315. if (!strcmp(req.key, "endpoint")) {
  316. struct addrinfo *resolved;
  317. struct addrinfo hints = {
  318. .ai_family = AF_UNSPEC,
  319. .ai_socktype = SOCK_DGRAM,
  320. .ai_protocol = IPPROTO_UDP,
  321. };
  322. char *port;
  323. if (!strlen(req.value))
  324. continue;
  325. if (req.value[0] == '[') {
  326. req.value++;
  327. port = strchr(req.value, ']');
  328. if (!port)
  329. continue;
  330. *port++ = 0;
  331. if (*port++ != ':')
  332. continue;
  333. } else {
  334. port = strchr(req.value, ':');
  335. if (!port)
  336. continue;
  337. *port++ = 0;
  338. }
  339. if (!*port)
  340. continue;
  341. if (getaddrinfo(req.value, port, &hints, &resolved) != 0)
  342. continue;
  343. if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(struct sockaddr_in)) ||
  344. (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(struct sockaddr_in6)))
  345. wg_peer_set_endpoint(net, peer, resolved->ai_addr, resolved->ai_addrlen);
  346. freeaddrinfo(resolved);
  347. continue;
  348. }
  349. }
  350. if (peer)
  351. wg_peer_update_done(net, peer);
  352. return wg_req_done(&req);
  353. }
  354. static int
  355. wg_user_peer_connect(struct network *net, struct network_peer *peer,
  356. union network_endpoint *ep)
  357. {
  358. struct wg_req req;
  359. char addr[INET6_ADDRSTRLEN];
  360. char key[WG_KEY_LEN_HEX];
  361. const void *ip;
  362. int port;
  363. if (wg_req_init(&req, net, true))
  364. return -1;
  365. key_to_hex(key, peer->key);
  366. wg_req_set(&req, "public_key", key);
  367. if (ep->in.sin_family == AF_INET6)
  368. ip = &ep->in6.sin6_addr;
  369. else
  370. ip = &ep->in.sin_addr;
  371. inet_ntop(ep->in.sin_family, ip, addr, sizeof(addr));
  372. port = ntohs(ep->in.sin_port);
  373. if (ep->in.sin_family == AF_INET6)
  374. wg_req_printf(&req, "endpoint", "[%s]:%d", addr, port);
  375. else
  376. wg_req_printf(&req, "endpoint", "%s:%d", addr, port);
  377. if (net->net_config.keepalive) {
  378. wg_req_set_int(&req, "persistent_keepalive_interval", 0);
  379. wg_req_set_int(&req, "persistent_keepalive_interval",
  380. net->net_config.keepalive);
  381. }
  382. return wg_req_done(&req);
  383. }
  384. const struct wg_ops wg_user_ops = {
  385. .name = "user",
  386. .check = wg_user_check,
  387. .init = wg_user_init,
  388. .cleanup = wg_user_cleanup,
  389. .init_local = wg_user_init_local,
  390. .peer_update = wg_user_peer_update,
  391. .peer_refresh = wg_user_peer_refresh,
  392. .peer_connect = wg_user_peer_connect,
  393. };