1 /* $OpenBSD: iked.c,v 1.72 2024/12/26 18:24:54 sthen Exp $ */ 2 3 /* 4 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> 5 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/queue.h> 21 #include <sys/socket.h> 22 #include <sys/wait.h> 23 #include <sys/uio.h> 24 25 #include <stdlib.h> 26 #include <stdio.h> 27 #include <unistd.h> 28 #include <string.h> 29 #include <getopt.h> 30 #include <signal.h> 31 #include <syslog.h> 32 #include <errno.h> 33 #include <err.h> 34 #include <pwd.h> 35 #include <event.h> 36 37 #include "iked.h" 38 #include "ikev2.h" 39 #include "version.h" 40 41 __dead void usage(void); 42 43 void parent_shutdown(struct iked *); 44 void parent_sig_handler(int, short, void *); 45 int parent_dispatch_ca(int, struct privsep_proc *, struct imsg *); 46 int parent_dispatch_control(int, struct privsep_proc *, struct imsg *); 47 int parent_dispatch_ikev2(int, struct privsep_proc *, struct imsg *); 48 void parent_connected(struct privsep *); 49 int parent_configure(struct iked *); 50 51 struct iked *iked_env; 52 53 static struct privsep_proc procs[] = { 54 { "ca", PROC_CERT, parent_dispatch_ca, caproc, IKED_CA }, 55 { "control", PROC_CONTROL, parent_dispatch_control, control }, 56 { "ikev2", PROC_IKEV2, parent_dispatch_ikev2, ikev2 } 57 }; 58 59 __dead void 60 usage(void) 61 { 62 extern char *__progname; 63 64 fprintf(stderr, "usage: %s [-dnSTtVv] [-D macro=value] " 65 "[-f file] [-p udpencap_port] [-s socket]\n", __progname); 66 exit(1); 67 } 68 69 int 70 main(int argc, char *argv[]) 71 { 72 int c; 73 int debug = 0, verbose = 0; 74 int opts = 0; 75 enum natt_mode natt_mode = NATT_DEFAULT; 76 in_port_t port = IKED_NATT_PORT; 77 const char *conffile = IKED_CONFIG; 78 const char *sock = IKED_SOCKET; 79 const char *errstr, *title = NULL; 80 struct iked *env = NULL; 81 struct privsep *ps; 82 enum privsep_procid proc_id = PROC_PARENT; 83 int proc_instance = 0; 84 int argc0 = argc; 85 86 log_init(1, LOG_DAEMON); 87 88 while ((c = getopt(argc, argv, "6D:df:I:nP:p:Ss:TtvV")) != -1) { 89 switch (c) { 90 case '6': 91 log_warnx("the -6 option is ignored and will be " 92 "removed in the future."); 93 break; 94 case 'D': 95 if (cmdline_symset(optarg) < 0) 96 log_warnx("could not parse macro definition %s", 97 optarg); 98 break; 99 case 'd': 100 debug++; 101 break; 102 case 'f': 103 conffile = optarg; 104 break; 105 case 'I': 106 proc_instance = strtonum(optarg, 0, 107 PROC_MAX_INSTANCES, &errstr); 108 if (errstr) 109 fatalx("invalid process instance"); 110 break; 111 case 'n': 112 debug = 1; 113 opts |= IKED_OPT_NOACTION; 114 break; 115 case 'P': 116 title = optarg; 117 proc_id = proc_getid(procs, nitems(procs), title); 118 if (proc_id == PROC_MAX) 119 fatalx("invalid process name"); 120 break; 121 case 'p': 122 if (natt_mode == NATT_DISABLE) 123 errx(1, "-T and -p are mutually exclusive"); 124 port = strtonum(optarg, 1, UINT16_MAX, &errstr); 125 if (errstr != NULL) 126 errx(1, "port is %s: %s", errstr, optarg); 127 natt_mode = NATT_FORCE; 128 break; 129 case 'S': 130 opts |= IKED_OPT_PASSIVE; 131 break; 132 case 's': 133 sock = optarg; 134 break; 135 case 'T': 136 if (natt_mode == NATT_FORCE) 137 errx(1, "-T and -t/-p are mutually exclusive"); 138 natt_mode = NATT_DISABLE; 139 break; 140 case 't': 141 if (natt_mode == NATT_DISABLE) 142 errx(1, "-T and -t are mutually exclusive"); 143 natt_mode = NATT_FORCE; 144 break; 145 case 'v': 146 verbose++; 147 opts |= IKED_OPT_VERBOSE; 148 break; 149 case 'V': 150 fprintf(stderr, "OpenIKED %s\n", IKED_VERSION); 151 return 0; 152 default: 153 usage(); 154 } 155 } 156 157 /* log to stderr until daemonized */ 158 log_init(debug ? debug : 1, LOG_DAEMON); 159 160 argc -= optind; 161 if (argc > 0) 162 usage(); 163 164 if ((env = calloc(1, sizeof(*env))) == NULL) 165 fatal("calloc: env"); 166 167 iked_env = env; 168 env->sc_opts = opts; 169 env->sc_nattmode = natt_mode; 170 env->sc_nattport = port; 171 172 ps = &env->sc_ps; 173 ps->ps_env = env; 174 175 if (strlcpy(env->sc_conffile, conffile, PATH_MAX) >= PATH_MAX) 176 errx(1, "config file exceeds PATH_MAX"); 177 178 group_init(); 179 policy_init(env); 180 181 if ((ps->ps_pw = getpwnam(IKED_USER)) == NULL) 182 errx(1, "unknown user %s", IKED_USER); 183 184 /* Configure the control socket */ 185 ps->ps_csock.cs_name = sock; 186 187 log_init(debug, LOG_DAEMON); 188 log_setverbose(verbose); 189 190 if (opts & IKED_OPT_NOACTION) 191 ps->ps_noaction = 1; 192 else { 193 /* check for root privileges */ 194 if (geteuid()) 195 errx(1, "need root privileges"); 196 } 197 198 ps->ps_instance = proc_instance; 199 if (title != NULL) 200 ps->ps_title[proc_id] = title; 201 202 /* only the parent returns */ 203 proc_init(ps, procs, nitems(procs), debug, argc0, argv, proc_id); 204 205 setproctitle("parent"); 206 log_procinit("parent"); 207 208 event_init(); 209 210 signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps); 211 signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps); 212 signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps); 213 signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps); 214 signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps); 215 signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps); 216 217 signal_add(&ps->ps_evsigint, NULL); 218 signal_add(&ps->ps_evsigterm, NULL); 219 signal_add(&ps->ps_evsigchld, NULL); 220 signal_add(&ps->ps_evsighup, NULL); 221 signal_add(&ps->ps_evsigpipe, NULL); 222 signal_add(&ps->ps_evsigusr1, NULL); 223 224 vroute_init(env); 225 226 proc_connect(ps, parent_connected); 227 228 event_dispatch(); 229 230 log_debug("%d parent exiting", getpid()); 231 parent_shutdown(env); 232 233 return (0); 234 } 235 236 void 237 parent_connected(struct privsep *ps) 238 { 239 struct iked *env = ps->ps_env; 240 241 if (parent_configure(env) == -1) 242 fatalx("configuration failed"); 243 } 244 245 int 246 parent_configure(struct iked *env) 247 { 248 struct sockaddr_storage ss; 249 250 if (parse_config(env->sc_conffile, env) == -1) { 251 proc_kill(&env->sc_ps); 252 exit(1); 253 } 254 255 if (env->sc_opts & IKED_OPT_NOACTION) { 256 fprintf(stderr, "configuration OK\n"); 257 proc_kill(&env->sc_ps); 258 exit(0); 259 } 260 261 env->sc_pfkey = -1; 262 config_setpfkey(env); 263 264 /* Send private and public keys to cert after forking the children */ 265 if (config_setkeys(env) == -1) 266 fatalx("%s: failed to send keys", __func__); 267 config_setreset(env, RESET_CA, PROC_CERT); 268 269 /* Now compile the policies and calculate skip steps */ 270 config_setcompile(env, PROC_IKEV2); 271 272 bzero(&ss, sizeof(ss)); 273 ss.ss_family = AF_INET; 274 275 /* see comment on config_setsocket() */ 276 if (env->sc_nattmode != NATT_FORCE) 277 config_setsocket(env, &ss, htons(IKED_IKE_PORT), PROC_IKEV2); 278 if (env->sc_nattmode != NATT_DISABLE) 279 config_setsocket(env, &ss, htons(env->sc_nattport), PROC_IKEV2); 280 281 bzero(&ss, sizeof(ss)); 282 ss.ss_family = AF_INET6; 283 284 if (env->sc_nattmode != NATT_FORCE) 285 config_setsocket(env, &ss, htons(IKED_IKE_PORT), PROC_IKEV2); 286 if (env->sc_nattmode != NATT_DISABLE) 287 config_setsocket(env, &ss, htons(env->sc_nattport), PROC_IKEV2); 288 289 /* 290 * pledge in the parent process: 291 * It has to run fairly late to allow forking the processes and 292 * opening the PFKEY socket and the listening UDP sockets (once) 293 * that need the bypass ioctls that are never allowed by pledge. 294 * 295 * Other flags: 296 * stdio - for malloc and basic I/O including events. 297 * rpath - for reload to open and read the configuration files. 298 * proc - run kill to terminate its children safely. 299 * dns - for reload and ocsp connect. 300 * inet - for ocsp connect. 301 * route - for using interfaces in iked.conf (SIOCGIFGMEMB) 302 * wroute - for adding and removing addresses (SIOCAIFGMEMB) 303 * sendfd - for ocsp sockets. 304 */ 305 if (pledge("stdio rpath proc dns inet route wroute sendfd", NULL) == -1) 306 fatal("pledge"); 307 308 config_setstatic(env); 309 config_setcoupled(env, env->sc_decoupled ? 0 : 1); 310 config_setocsp(env); 311 config_setradauth(env); 312 config_setradacct(env); 313 /* Must be last */ 314 config_setmode(env, env->sc_passive ? 1 : 0); 315 316 return (0); 317 } 318 319 void 320 parent_reload(struct iked *env, int reset, const char *filename) 321 { 322 /* Switch back to the default config file */ 323 if (filename == NULL || *filename == '\0') 324 filename = env->sc_conffile; 325 326 log_debug("%s: level %d config file %s", __func__, reset, filename); 327 328 if (reset == RESET_RELOAD) { 329 config_setreset(env, RESET_POLICY, PROC_IKEV2); 330 config_setreset(env, RESET_RADIUS, PROC_IKEV2); 331 if (config_setkeys(env) == -1) 332 fatalx("%s: failed to send keys", __func__); 333 config_setreset(env, RESET_CA, PROC_CERT); 334 335 if (parse_config(filename, env) == -1) { 336 log_debug("%s: failed to load config file %s", 337 __func__, filename); 338 } 339 340 /* Re-compile policies and skip steps */ 341 config_setcompile(env, PROC_IKEV2); 342 343 config_setstatic(env); 344 config_setcoupled(env, env->sc_decoupled ? 0 : 1); 345 config_setocsp(env); 346 /* Must be last */ 347 config_setmode(env, env->sc_passive ? 1 : 0); 348 } else { 349 config_setreset(env, reset, PROC_IKEV2); 350 config_setreset(env, reset, PROC_CERT); 351 } 352 } 353 354 void 355 parent_sig_handler(int sig, short event, void *arg) 356 { 357 struct privsep *ps = arg; 358 int die = 0, status, fail, id; 359 pid_t pid; 360 char *cause; 361 362 switch (sig) { 363 case SIGHUP: 364 log_info("%s: reload requested with SIGHUP", __func__); 365 366 /* 367 * This is safe because libevent uses async signal handlers 368 * that run in the event loop and not in signal context. 369 */ 370 parent_reload(ps->ps_env, 0, NULL); 371 break; 372 case SIGPIPE: 373 log_info("%s: ignoring SIGPIPE", __func__); 374 break; 375 case SIGUSR1: 376 log_info("%s: ignoring SIGUSR1", __func__); 377 break; 378 case SIGTERM: 379 case SIGINT: 380 die = 1; 381 /* FALLTHROUGH */ 382 case SIGCHLD: 383 do { 384 int len = 0; 385 386 pid = waitpid(-1, &status, WNOHANG); 387 if (pid <= 0) 388 continue; 389 390 fail = 0; 391 if (WIFSIGNALED(status)) { 392 fail = 1; 393 len = asprintf(&cause, "terminated; signal %d", 394 WTERMSIG(status)); 395 } else if (WIFEXITED(status)) { 396 if (WEXITSTATUS(status) != 0) { 397 fail = 1; 398 len = asprintf(&cause, 399 "exited abnormally"); 400 } else 401 len = asprintf(&cause, "exited okay"); 402 } else 403 fatalx("unexpected cause of SIGCHLD"); 404 405 if (len == -1) 406 fatal("asprintf"); 407 408 die = 1; 409 410 for (id = 0; id < PROC_MAX; id++) 411 if (pid == ps->ps_pid[id]) { 412 if (fail) 413 log_warnx("lost child: %s %s", 414 ps->ps_title[id], cause); 415 break; 416 } 417 418 free(cause); 419 } while (pid > 0 || (pid == -1 && errno == EINTR)); 420 421 if (die) 422 parent_shutdown(ps->ps_env); 423 break; 424 default: 425 fatalx("unexpected signal"); 426 } 427 } 428 429 int 430 parent_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg) 431 { 432 struct iked *env = iked_env; 433 434 switch (imsg->hdr.type) { 435 case IMSG_CTL_ACTIVE: 436 case IMSG_CTL_PASSIVE: 437 proc_forward_imsg(&env->sc_ps, imsg, PROC_IKEV2, -1); 438 break; 439 case IMSG_OCSP_FD: 440 ocsp_connect(env, imsg); 441 break; 442 default: 443 return (-1); 444 } 445 446 return (0); 447 } 448 449 int 450 parent_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg) 451 { 452 struct iked *env = iked_env; 453 int v; 454 char *str = NULL; 455 unsigned int type = imsg->hdr.type; 456 457 switch (type) { 458 case IMSG_CTL_RESET: 459 IMSG_SIZE_CHECK(imsg, &v); 460 memcpy(&v, imsg->data, sizeof(v)); 461 parent_reload(env, v, NULL); 462 break; 463 case IMSG_CTL_COUPLE: 464 case IMSG_CTL_DECOUPLE: 465 case IMSG_CTL_ACTIVE: 466 case IMSG_CTL_PASSIVE: 467 proc_compose(&env->sc_ps, PROC_IKEV2, type, NULL, 0); 468 break; 469 case IMSG_CTL_RELOAD: 470 if (IMSG_DATA_SIZE(imsg) > 0) 471 str = get_string(imsg->data, IMSG_DATA_SIZE(imsg)); 472 parent_reload(env, 0, str); 473 free(str); 474 break; 475 case IMSG_CTL_VERBOSE: 476 proc_forward_imsg(&env->sc_ps, imsg, PROC_IKEV2, -1); 477 proc_forward_imsg(&env->sc_ps, imsg, PROC_CERT, -1); 478 479 /* return 1 to let proc.c handle it locally */ 480 return (1); 481 default: 482 return (-1); 483 } 484 485 return (0); 486 } 487 488 int 489 parent_dispatch_ikev2(int fd, struct privsep_proc *p, struct imsg *imsg) 490 { 491 struct iked *env = iked_env; 492 493 switch (imsg->hdr.type) { 494 case IMSG_IF_ADDADDR: 495 case IMSG_IF_DELADDR: 496 return (vroute_getaddr(env, imsg)); 497 case IMSG_VDNS_ADD: 498 case IMSG_VDNS_DEL: 499 return (vroute_getdns(env, imsg)); 500 case IMSG_VROUTE_ADD: 501 case IMSG_VROUTE_DEL: 502 return (vroute_getroute(env, imsg)); 503 case IMSG_VROUTE_CLONE: 504 return (vroute_getcloneroute(env, imsg)); 505 default: 506 return (-1); 507 } 508 509 return (0); 510 } 511 512 void 513 parent_shutdown(struct iked *env) 514 { 515 proc_kill(&env->sc_ps); 516 517 vroute_cleanup(env); 518 free(env->sc_vroute); 519 free(env); 520 521 log_warnx("parent terminating"); 522 exit(0); 523 } 524