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