1 /* $OpenBSD: iked.c,v 1.52 2020/12/17 20:43:07 tobhe 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 40 __dead void usage(void); 41 42 void parent_shutdown(struct iked *); 43 void parent_sig_handler(int, short, void *); 44 int parent_dispatch_ca(int, struct privsep_proc *, struct imsg *); 45 int parent_dispatch_control(int, struct privsep_proc *, struct imsg *); 46 int parent_configure(struct iked *); 47 48 static struct privsep_proc procs[] = { 49 { "ca", PROC_CERT, parent_dispatch_ca, caproc, IKED_CA }, 50 { "control", PROC_CONTROL, parent_dispatch_control, control }, 51 { "ikev2", PROC_IKEV2, NULL, ikev2 } 52 }; 53 54 __dead void 55 usage(void) 56 { 57 extern char *__progname; 58 59 fprintf(stderr, "usage: %s [-dnSTtv] [-D macro=value] " 60 "[-f file] [-p udpencap_port] [-s socket]\n", __progname); 61 exit(1); 62 } 63 64 int 65 main(int argc, char *argv[]) 66 { 67 int c; 68 int debug = 0, verbose = 0; 69 int opts = 0; 70 enum natt_mode natt_mode = NATT_DEFAULT; 71 in_port_t port = IKED_NATT_PORT; 72 const char *conffile = IKED_CONFIG; 73 const char *sock = IKED_SOCKET; 74 const char *errstr; 75 struct iked *env = NULL; 76 struct privsep *ps; 77 78 log_init(1, LOG_DAEMON); 79 80 while ((c = getopt(argc, argv, "6D:df:np:Ss:Ttv")) != -1) { 81 switch (c) { 82 case '6': 83 log_warnx("the -6 option is ignored and will be " 84 "removed in the future."); 85 break; 86 case 'D': 87 if (cmdline_symset(optarg) < 0) 88 log_warnx("could not parse macro definition %s", 89 optarg); 90 break; 91 case 'd': 92 debug++; 93 break; 94 case 'f': 95 conffile = optarg; 96 break; 97 case 'n': 98 debug = 1; 99 opts |= IKED_OPT_NOACTION; 100 break; 101 case 'p': 102 if (natt_mode == NATT_DISABLE) 103 errx(1, "-T and -p are mutually exclusive"); 104 port = strtonum(optarg, 1, UINT16_MAX, &errstr); 105 if (errstr != NULL) 106 errx(1, "port is %s: %s", errstr, optarg); 107 natt_mode = NATT_FORCE; 108 break; 109 case 'S': 110 opts |= IKED_OPT_PASSIVE; 111 break; 112 case 's': 113 sock = optarg; 114 break; 115 case 'T': 116 if (natt_mode == NATT_FORCE) 117 errx(1, "-T and -t/-p are mutually exclusive"); 118 natt_mode = NATT_DISABLE; 119 break; 120 case 't': 121 if (natt_mode == NATT_DISABLE) 122 errx(1, "-T and -t are mutually exclusive"); 123 natt_mode = NATT_FORCE; 124 break; 125 case 'v': 126 verbose++; 127 opts |= IKED_OPT_VERBOSE; 128 break; 129 default: 130 usage(); 131 } 132 } 133 134 argc -= optind; 135 argv += optind; 136 if (argc > 0) 137 usage(); 138 139 if ((env = calloc(1, sizeof(*env))) == NULL) 140 fatal("calloc: env"); 141 142 env->sc_opts = opts; 143 env->sc_nattmode = natt_mode; 144 env->sc_nattport = port; 145 146 ps = &env->sc_ps; 147 ps->ps_env = env; 148 TAILQ_INIT(&ps->ps_rcsocks); 149 150 if (strlcpy(env->sc_conffile, conffile, PATH_MAX) >= PATH_MAX) 151 errx(1, "config file exceeds PATH_MAX"); 152 153 ca_sslinit(); 154 policy_init(env); 155 156 /* check for root privileges */ 157 if (geteuid()) 158 errx(1, "need root privileges"); 159 160 if ((ps->ps_pw = getpwnam(IKED_USER)) == NULL) 161 errx(1, "unknown user %s", IKED_USER); 162 163 /* Configure the control socket */ 164 ps->ps_csock.cs_name = sock; 165 166 log_init(debug, LOG_DAEMON); 167 log_setverbose(verbose); 168 169 if (opts & IKED_OPT_NOACTION) 170 ps->ps_noaction = 1; 171 172 if (!debug && daemon(0, 0) == -1) 173 err(1, "failed to daemonize"); 174 175 group_init(); 176 177 ps->ps_ninstances = 1; 178 proc_init(ps, procs, nitems(procs)); 179 180 setproctitle("parent"); 181 log_procinit("parent"); 182 183 event_init(); 184 185 signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps); 186 signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps); 187 signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps); 188 signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps); 189 signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps); 190 signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps); 191 192 signal_add(&ps->ps_evsigint, NULL); 193 signal_add(&ps->ps_evsigterm, NULL); 194 signal_add(&ps->ps_evsigchld, NULL); 195 signal_add(&ps->ps_evsighup, NULL); 196 signal_add(&ps->ps_evsigpipe, NULL); 197 signal_add(&ps->ps_evsigusr1, NULL); 198 199 proc_listen(ps, procs, nitems(procs)); 200 201 if (parent_configure(env) == -1) 202 fatalx("configuration failed"); 203 204 event_dispatch(); 205 206 log_debug("%d parent exiting", getpid()); 207 208 return (0); 209 } 210 211 int 212 parent_configure(struct iked *env) 213 { 214 struct sockaddr_storage ss; 215 216 if (parse_config(env->sc_conffile, env) == -1) { 217 proc_kill(&env->sc_ps); 218 exit(1); 219 } 220 221 if (env->sc_opts & IKED_OPT_NOACTION) { 222 fprintf(stderr, "configuration OK\n"); 223 proc_kill(&env->sc_ps); 224 exit(0); 225 } 226 227 env->sc_pfkey = -1; 228 config_setpfkey(env, PROC_IKEV2); 229 230 /* Send private and public keys to cert after forking the children */ 231 if (config_setkeys(env) == -1) 232 fatalx("%s: failed to send keys", __func__); 233 config_setreset(env, RESET_CA, PROC_CERT); 234 235 /* Now compile the policies and calculate skip steps */ 236 config_setcompile(env, PROC_IKEV2); 237 238 bzero(&ss, sizeof(ss)); 239 ss.ss_family = AF_INET; 240 241 /* see comment on config_setsocket() */ 242 if (env->sc_nattmode != NATT_FORCE) 243 config_setsocket(env, &ss, htons(IKED_IKE_PORT), PROC_IKEV2); 244 if (env->sc_nattmode != NATT_DISABLE) 245 config_setsocket(env, &ss, htons(env->sc_nattport), PROC_IKEV2); 246 247 bzero(&ss, sizeof(ss)); 248 ss.ss_family = AF_INET6; 249 250 if (env->sc_nattmode != NATT_FORCE) 251 config_setsocket(env, &ss, htons(IKED_IKE_PORT), PROC_IKEV2); 252 if (env->sc_nattmode != NATT_DISABLE) 253 config_setsocket(env, &ss, htons(env->sc_nattport), PROC_IKEV2); 254 255 /* 256 * pledge in the parent process: 257 * It has to run fairly late to allow forking the processes and 258 * opening the PFKEY socket and the listening UDP sockets (once) 259 * that need the bypass ioctls that are never allowed by pledge. 260 * 261 * Other flags: 262 * stdio - for malloc and basic I/O including events. 263 * rpath - for reload to open and read the configuration files. 264 * proc - run kill to terminate its children safely. 265 * dns - for reload and ocsp connect. 266 * inet - for ocsp connect. 267 * route - for using interfaces in iked.conf (SIOCGIFGMEMB) 268 * sendfd - for ocsp sockets. 269 */ 270 if (pledge("stdio rpath proc dns inet route sendfd", NULL) == -1) 271 fatal("pledge"); 272 273 config_setstatic(env); 274 config_setcoupled(env, env->sc_decoupled ? 0 : 1); 275 config_setocsp(env); 276 config_setcertpartialchain(env); 277 /* Must be last */ 278 config_setmode(env, env->sc_passive ? 1 : 0); 279 280 return (0); 281 } 282 283 void 284 parent_reload(struct iked *env, int reset, const char *filename) 285 { 286 /* Switch back to the default config file */ 287 if (filename == NULL || *filename == '\0') 288 filename = env->sc_conffile; 289 290 log_debug("%s: level %d config file %s", __func__, reset, filename); 291 292 if (reset == RESET_RELOAD) { 293 config_setreset(env, RESET_POLICY, PROC_IKEV2); 294 if (config_setkeys(env) == -1) 295 fatalx("%s: failed to send keys", __func__); 296 config_setreset(env, RESET_CA, PROC_CERT); 297 298 if (parse_config(filename, env) == -1) { 299 log_debug("%s: failed to load config file %s", 300 __func__, filename); 301 } 302 303 /* Re-compile policies and skip steps */ 304 config_setcompile(env, PROC_IKEV2); 305 306 config_setstatic(env); 307 config_setcoupled(env, env->sc_decoupled ? 0 : 1); 308 config_setocsp(env); 309 config_setcertpartialchain(env); 310 /* Must be last */ 311 config_setmode(env, env->sc_passive ? 1 : 0); 312 } else { 313 config_setreset(env, reset, PROC_IKEV2); 314 config_setreset(env, reset, PROC_CERT); 315 } 316 } 317 318 void 319 parent_sig_handler(int sig, short event, void *arg) 320 { 321 struct privsep *ps = arg; 322 int die = 0, status, fail, id; 323 pid_t pid; 324 char *cause; 325 326 switch (sig) { 327 case SIGHUP: 328 log_info("%s: reload requested with SIGHUP", __func__); 329 330 /* 331 * This is safe because libevent uses async signal handlers 332 * that run in the event loop and not in signal context. 333 */ 334 parent_reload(ps->ps_env, 0, NULL); 335 break; 336 case SIGPIPE: 337 log_info("%s: ignoring SIGPIPE", __func__); 338 break; 339 case SIGUSR1: 340 log_info("%s: ignoring SIGUSR1", __func__); 341 break; 342 case SIGTERM: 343 case SIGINT: 344 die = 1; 345 /* FALLTHROUGH */ 346 case SIGCHLD: 347 do { 348 int len; 349 350 pid = waitpid(-1, &status, WNOHANG); 351 if (pid <= 0) 352 continue; 353 354 fail = 0; 355 if (WIFSIGNALED(status)) { 356 fail = 1; 357 len = asprintf(&cause, "terminated; signal %d", 358 WTERMSIG(status)); 359 } else if (WIFEXITED(status)) { 360 if (WEXITSTATUS(status) != 0) { 361 fail = 1; 362 len = asprintf(&cause, 363 "exited abnormally"); 364 } else 365 len = asprintf(&cause, "exited okay"); 366 } else 367 fatalx("unexpected cause of SIGCHLD"); 368 369 if (len == -1) 370 fatal("asprintf"); 371 372 die = 1; 373 374 for (id = 0; id < PROC_MAX; id++) 375 if (pid == ps->ps_pid[id]) { 376 if (fail) 377 log_warnx("lost child: %s %s", 378 ps->ps_title[id], cause); 379 break; 380 } 381 382 free(cause); 383 } while (pid > 0 || (pid == -1 && errno == EINTR)); 384 385 if (die) 386 parent_shutdown(ps->ps_env); 387 break; 388 default: 389 fatalx("unexpected signal"); 390 } 391 } 392 393 int 394 parent_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg) 395 { 396 struct iked *env = p->p_ps->ps_env; 397 398 switch (imsg->hdr.type) { 399 case IMSG_OCSP_FD: 400 ocsp_connect(env, imsg); 401 break; 402 default: 403 return (-1); 404 } 405 406 return (0); 407 } 408 409 int 410 parent_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg) 411 { 412 struct iked *env = p->p_ps->ps_env; 413 int v; 414 char *str = NULL; 415 unsigned int type = imsg->hdr.type; 416 417 switch (type) { 418 case IMSG_CTL_RESET: 419 IMSG_SIZE_CHECK(imsg, &v); 420 memcpy(&v, imsg->data, sizeof(v)); 421 parent_reload(env, v, NULL); 422 break; 423 case IMSG_CTL_COUPLE: 424 case IMSG_CTL_DECOUPLE: 425 case IMSG_CTL_ACTIVE: 426 case IMSG_CTL_PASSIVE: 427 proc_compose(&env->sc_ps, PROC_IKEV2, type, NULL, 0); 428 break; 429 case IMSG_CTL_RELOAD: 430 if (IMSG_DATA_SIZE(imsg) > 0) 431 str = get_string(imsg->data, IMSG_DATA_SIZE(imsg)); 432 parent_reload(env, 0, str); 433 free(str); 434 break; 435 case IMSG_CTL_VERBOSE: 436 proc_forward_imsg(&env->sc_ps, imsg, PROC_IKEV2, -1); 437 proc_forward_imsg(&env->sc_ps, imsg, PROC_CERT, -1); 438 439 /* return 1 to let proc.c handle it locally */ 440 return (1); 441 default: 442 return (-1); 443 } 444 445 return (0); 446 } 447 448 void 449 parent_shutdown(struct iked *env) 450 { 451 proc_kill(&env->sc_ps); 452 453 free(env); 454 455 log_warnx("parent terminating"); 456 exit(0); 457 } 458