1 /* $OpenBSD: monitor.c,v 1.22 2017/05/21 02:37:52 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2005 H�kan Olsson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/types.h> 29 #include <sys/ioctl.h> 30 #include <sys/socket.h> 31 #include <sys/stat.h> 32 #include <sys/sysctl.h> 33 #include <sys/queue.h> 34 #include <sys/wait.h> 35 #include <sys/un.h> 36 #include <net/pfkeyv2.h> 37 38 #include <errno.h> 39 #include <fcntl.h> 40 #include <pwd.h> 41 #include <signal.h> 42 #include <string.h> 43 #include <stdlib.h> 44 #include <unistd.h> 45 #include <limits.h> 46 #include <imsg.h> 47 48 #include "types.h" /* iked imsg types */ 49 50 #include "monitor.h" 51 #include "sasyncd.h" 52 53 struct m_state { 54 pid_t pid; 55 int s; 56 } m_state; 57 58 volatile sig_atomic_t sigchld = 0; 59 60 static void got_sigchld(int); 61 static void sig_to_child(int); 62 static void m_priv_pfkey_snap(int); 63 static int m_priv_control_activate(void); 64 static int m_priv_control_passivate(void); 65 static ssize_t m_write(int, void *, size_t); 66 static ssize_t m_read(int, void *, size_t); 67 68 pid_t 69 monitor_init(void) 70 { 71 struct passwd *pw = getpwnam(SASYNCD_USER); 72 extern char *__progname; 73 char root[PATH_MAX]; 74 int p[2]; 75 76 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, p) != 0) { 77 log_err("%s: socketpair failed - %s", __progname, 78 strerror(errno)); 79 exit(1); 80 } 81 82 if (!pw) { 83 log_err("%s: getpwnam(\"%s\") failed", __progname, 84 SASYNCD_USER); 85 exit(1); 86 } 87 strlcpy(root, pw->pw_dir, sizeof root); 88 endpwent(); 89 90 signal(SIGCHLD, got_sigchld); 91 signal(SIGTERM, sig_to_child); 92 signal(SIGHUP, sig_to_child); 93 signal(SIGINT, sig_to_child); 94 95 m_state.pid = fork(); 96 97 if (m_state.pid == -1) { 98 log_err("%s: fork failed - %s", __progname, strerror(errno)); 99 exit(1); 100 } else if (m_state.pid == 0) { 101 /* Child */ 102 m_state.s = p[0]; 103 close(p[1]); 104 105 if (chroot(pw->pw_dir) != 0 || chdir("/") != 0) { 106 log_err("%s: chroot failed", __progname); 107 exit(1); 108 } 109 110 if (setgroups(1, &pw->pw_gid) || 111 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 112 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) { 113 log_err("%s: failed to drop privileges", __progname); 114 exit(1); 115 } 116 } else { 117 /* Parent */ 118 setproctitle("[priv]"); 119 m_state.s = p[1]; 120 close(p[0]); 121 } 122 return m_state.pid; 123 } 124 125 static void 126 got_sigchld(int s) 127 { 128 sigchld = 1; 129 } 130 131 static void 132 sig_to_child(int s) 133 { 134 if (m_state.pid != -1) 135 kill(m_state.pid, s); 136 } 137 138 static void 139 monitor_drain_input(void) 140 { 141 int one = 1; 142 u_int8_t tmp; 143 144 ioctl(m_state.s, FIONBIO, &one); 145 while (m_read(m_state.s, &tmp, 1) > 0) 146 ; 147 ioctl(m_state.s, FIONBIO, 0); 148 } 149 150 /* We only use privsep to get in-kernel SADB and SPD snapshots via sysctl */ 151 void 152 monitor_loop(void) 153 { 154 u_int32_t v, vn; 155 ssize_t r; 156 fd_set rfds; 157 int ret; 158 struct timeval *tvp, tv; 159 160 FD_ZERO(&rfds); 161 tvp = NULL; 162 vn = 0; 163 164 for (;;) { 165 ret = 0; 166 v = 0; 167 168 if (sigchld) { 169 pid_t pid; 170 int status; 171 do { 172 pid = waitpid(m_state.pid, &status, WNOHANG); 173 } while (pid == -1 && errno == EINTR); 174 175 if (pid == m_state.pid && 176 (WIFEXITED(status) || WIFSIGNALED(status))) 177 break; 178 } 179 180 FD_SET(m_state.s, &rfds); 181 if (select(m_state.s + 1, &rfds, NULL, NULL, tvp) == -1) { 182 if (errno == EINTR || errno == EAGAIN) 183 continue; 184 log_err("monitor_loop: select()"); 185 break; 186 } 187 188 /* Wait for next task */ 189 if (FD_ISSET(m_state.s, &rfds)) { 190 if ((r = m_read(m_state.s, &v, sizeof v)) < 1) { 191 if (r == -1) 192 log_err("monitor_loop: read()"); 193 break; 194 } 195 } 196 197 /* Retry after timeout */ 198 if (v == 0 && tvp != NULL) { 199 v = vn; 200 tvp = NULL; 201 vn = 0; 202 } 203 204 switch (v) { 205 case MONITOR_GETSNAP: 206 /* Get the data. */ 207 m_priv_pfkey_snap(m_state.s); 208 break; 209 case MONITOR_CARPINC: 210 carp_demote(CARP_INC, 1); 211 break; 212 case MONITOR_CARPDEC: 213 carp_demote(CARP_DEC, 1); 214 break; 215 case MONITOR_CONTROL_ACTIVATE: 216 ret = m_priv_control_activate(); 217 break; 218 case MONITOR_CONTROL_PASSIVATE: 219 ret = m_priv_control_passivate(); 220 break; 221 } 222 223 if (ret == -1) { 224 /* Trigger retry after timeout */ 225 tv.tv_sec = MONITOR_RETRY_TIMEOUT; 226 tv.tv_usec = 0; 227 tvp = &tv; 228 vn = v; 229 } 230 } 231 232 monitor_carpundemote(NULL); 233 234 if (!sigchld) 235 log_msg(0, "monitor_loop: priv process exiting abnormally"); 236 exit(0); 237 } 238 239 void 240 monitor_carpundemote(void *v) 241 { 242 u_int32_t mtype = MONITOR_CARPDEC; 243 if (!carp_demoted) 244 return; 245 if (m_write(m_state.s, &mtype, sizeof mtype) < 1) 246 log_msg(1, "monitor_carpundemote: unable to write to monitor"); 247 else 248 carp_demoted = 0; 249 } 250 251 void 252 monitor_carpdemote(void *v) 253 { 254 u_int32_t mtype = MONITOR_CARPINC; 255 if (carp_demoted) 256 return; 257 if (m_write(m_state.s, &mtype, sizeof mtype) < 1) 258 log_msg(1, "monitor_carpdemote: unable to write to monitor"); 259 else 260 carp_demoted = 1; 261 } 262 263 int 264 monitor_get_pfkey_snap(u_int8_t **sadb, u_int32_t *sadbsize, u_int8_t **spd, 265 u_int32_t *spdsize) 266 { 267 u_int32_t v; 268 ssize_t rbytes; 269 270 v = MONITOR_GETSNAP; 271 if (m_write(m_state.s, &v, sizeof v) < 1) 272 return -1; 273 274 /* Read SADB data. */ 275 *sadb = *spd = NULL; 276 *spdsize = 0; 277 if (m_read(m_state.s, sadbsize, sizeof *sadbsize) < 1) 278 return -1; 279 if (*sadbsize) { 280 *sadb = malloc(*sadbsize); 281 if (!*sadb) { 282 log_err("monitor_get_pfkey_snap: malloc()"); 283 monitor_drain_input(); 284 return -1; 285 } 286 rbytes = m_read(m_state.s, *sadb, *sadbsize); 287 if (rbytes < 1) { 288 freezero(*sadb, *sadbsize); 289 return -1; 290 } 291 } 292 293 /* Read SPD data */ 294 if (m_read(m_state.s, spdsize, sizeof *spdsize) < 1) { 295 freezero(*sadb, *sadbsize); 296 return -1; 297 } 298 if (*spdsize) { 299 *spd = malloc(*spdsize); 300 if (!*spd) { 301 log_err("monitor_get_pfkey_snap: malloc()"); 302 monitor_drain_input(); 303 freezero(*sadb, *sadbsize); 304 return -1; 305 } 306 rbytes = m_read(m_state.s, *spd, *spdsize); 307 if (rbytes < 1) { 308 freezero(*spd, *spdsize); 309 freezero(*sadb, *sadbsize); 310 return -1; 311 } 312 } 313 314 log_msg(2, "monitor_get_pfkey_snap: got %u bytes SADB, %u bytes SPD", 315 *sadbsize, *spdsize); 316 return 0; 317 } 318 319 int 320 monitor_control_active(int active) 321 { 322 u_int32_t cmd = 323 active ? MONITOR_CONTROL_ACTIVATE : MONITOR_CONTROL_PASSIVATE; 324 if (write(m_state.s, &cmd, sizeof cmd) < 1) 325 return -1; 326 return 0; 327 } 328 329 /* Privileged */ 330 static void 331 m_priv_pfkey_snap(int s) 332 { 333 u_int8_t *sadb_buf = NULL, *spd_buf = NULL; 334 size_t sadb_buflen = 0, spd_buflen = 0, sz; 335 int mib[5]; 336 u_int32_t v; 337 338 mib[0] = CTL_NET; 339 mib[1] = PF_KEY; 340 mib[2] = PF_KEY_V2; 341 mib[3] = NET_KEY_SADB_DUMP; 342 mib[4] = 0; /* Unspec SA type */ 343 344 /* First, fetch SADB data */ 345 for (;;) { 346 if (sysctl(mib, sizeof mib / sizeof mib[0], NULL, &sz, NULL, 0) 347 == -1) 348 break; 349 350 if (!sz) 351 break; 352 353 /* Try to catch newly added data */ 354 sz *= 2; 355 356 if ((sadb_buf = malloc(sz)) == NULL) 357 break; 358 359 if (sysctl(mib, sizeof mib / sizeof mib[0], sadb_buf, &sz, NULL, 0) 360 == -1) { 361 free(sadb_buf); 362 sadb_buf = NULL; 363 /* 364 * If new SAs were added meanwhile and the given buffer is 365 * too small, retry. 366 */ 367 if (errno == ENOMEM) 368 continue; 369 break; 370 } 371 372 sadb_buflen = sz; 373 break; 374 } 375 376 /* Next, fetch SPD data */ 377 mib[3] = NET_KEY_SPD_DUMP; 378 379 for (;;) { 380 if (sysctl(mib, sizeof mib / sizeof mib[0], NULL, &sz, NULL, 0) 381 == -1) 382 break; 383 384 if (!sz) 385 break; 386 387 /* Try to catch newly added data */ 388 sz *= 2; 389 390 if ((spd_buf = malloc(sz)) == NULL) 391 break; 392 393 if (sysctl(mib, sizeof mib / sizeof mib[0], spd_buf, &sz, NULL, 0) 394 == -1) { 395 free(spd_buf); 396 spd_buf = NULL; 397 /* 398 * If new SPDs were added meanwhile and the given buffer is 399 * too small, retry. 400 */ 401 if (errno == ENOMEM) 402 continue; 403 break; 404 } 405 406 spd_buflen = sz; 407 break; 408 } 409 410 /* Return SADB data */ 411 v = (u_int32_t)sadb_buflen; 412 if (m_write(s, &v, sizeof v) == -1) { 413 log_err("m_priv_pfkey_snap: write"); 414 goto cleanup; 415 } 416 if (m_write(s, sadb_buf, sadb_buflen) == -1) { 417 log_err("m_priv_pfkey_snap: write"); 418 goto cleanup; 419 } 420 421 /* Return SPD data */ 422 v = (u_int32_t)spd_buflen; 423 if (m_write(s, &v, sizeof v) == -1) { 424 log_err("m_priv_pfkey_snap: write"); 425 goto cleanup; 426 } 427 if (m_write(s, spd_buf, spd_buflen) == -1) { 428 log_err("m_priv_pfkey_snap: write"); 429 goto cleanup; 430 } 431 432 cleanup: 433 freezero(sadb_buf, sadb_buflen); 434 freezero(spd_buf, spd_buflen); 435 } 436 437 static int 438 m_priv_isakmpd_fifocmd(const char *cmd) 439 { 440 struct stat sb; 441 int fd = -1, ret = -1; 442 443 if ((fd = open(ISAKMPD_FIFO, O_WRONLY)) == -1) { 444 log_err("m_priv_isakmpd_fifocmd: open(%s)", ISAKMPD_FIFO); 445 goto out; 446 } 447 if (fstat(fd, &sb) == -1) { 448 log_err("m_priv_isakmpd_fifocmd: fstat(%s)", ISAKMPD_FIFO); 449 goto out; 450 } 451 if (!S_ISFIFO(sb.st_mode)) { 452 log_err("m_priv_isakmpd_fifocmd: %s not a fifo", ISAKMPD_FIFO); 453 goto out; 454 } 455 456 if (write(fd, cmd, strlen(cmd)) == -1) { 457 log_err("m_priv_isakmpd_fifocmd write"); 458 goto out; 459 } 460 461 ret = 0; 462 out: 463 if (fd != -1) 464 close(fd); 465 466 return (ret); 467 } 468 469 static int 470 m_priv_iked_imsg(u_int cmd) 471 { 472 struct sockaddr_un sun; 473 int fd = -1, ret = -1; 474 struct imsgbuf ibuf; 475 476 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 477 log_err("m_priv_iked_imsg: socket"); 478 goto out; 479 } 480 481 bzero(&sun, sizeof(sun)); 482 sun.sun_family = AF_UNIX; 483 strlcpy(sun.sun_path, IKED_SOCKET, sizeof(sun.sun_path)); 484 485 if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { 486 log_err("m_priv_iked_imsg: connect"); 487 goto out; 488 } 489 490 imsg_init(&ibuf, fd); 491 if (imsg_compose(&ibuf, cmd, 0, 0, -1, NULL, 0) == -1) { 492 log_err("m_priv_iked_imsg: compose"); 493 goto err; 494 } 495 if (imsg_flush(&ibuf) == -1) { 496 log_err("m_priv_iked_imsg: flush"); 497 goto err; 498 } 499 500 ret = 0; 501 err: 502 imsg_clear(&ibuf); 503 out: 504 if (fd != -1) 505 close(fd); 506 507 return (ret); 508 } 509 510 static int 511 m_priv_control_activate(void) 512 { 513 if (cfgstate.flags & CTL_ISAKMPD) 514 if (m_priv_isakmpd_fifocmd("M active\n") == -1) 515 return (-1); 516 if (cfgstate.flags & CTL_IKED) 517 if (m_priv_iked_imsg(IMSG_CTL_ACTIVE) == -1) 518 return (-1); 519 return (0); 520 } 521 522 static int 523 m_priv_control_passivate(void) 524 { 525 if (cfgstate.flags & CTL_ISAKMPD) 526 if (m_priv_isakmpd_fifocmd("M passive\n") == -1) 527 return (-1); 528 if (cfgstate.flags & CTL_IKED) 529 if (m_priv_iked_imsg(IMSG_CTL_PASSIVE) == -1) 530 return (-1); 531 return (0); 532 } 533 534 ssize_t 535 m_write(int sock, void *buf, size_t len) 536 { 537 ssize_t n; 538 size_t pos = 0; 539 char *ptr = buf; 540 541 while (len > pos) { 542 switch (n = write(sock, ptr + pos, len - pos)) { 543 case -1: 544 if (errno == EINTR || errno == EAGAIN) 545 continue; 546 /* FALLTHROUGH */ 547 case 0: 548 return n; 549 /* NOTREACHED */ 550 default: 551 pos += n; 552 } 553 } 554 return pos; 555 } 556 557 ssize_t 558 m_read(int sock, void *buf, size_t len) 559 { 560 ssize_t n; 561 size_t pos = 0; 562 char *ptr = buf; 563 564 while (len > pos) { 565 switch (n = read(sock, ptr + pos, len - pos)) { 566 case -1: 567 if (errno == EINTR || errno == EAGAIN) 568 continue; 569 /* FALLTHROUGH */ 570 case 0: 571 return n; 572 /* NOTREACHED */ 573 default: 574 pos += n; 575 } 576 } 577 return pos; 578 } 579