1 /* $OpenBSD: monitor.c,v 1.21 2015/10/18 02:39:04 mmcc 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 explicit_bzero(*sadb, *sadbsize); 289 free(*sadb); 290 return -1; 291 } 292 } 293 294 /* Read SPD data */ 295 if (m_read(m_state.s, spdsize, sizeof *spdsize) < 1) { 296 if (*sadbsize) { 297 explicit_bzero(*sadb, *sadbsize); 298 free(*sadb); 299 } 300 return -1; 301 } 302 if (*spdsize) { 303 *spd = malloc(*spdsize); 304 if (!*spd) { 305 log_err("monitor_get_pfkey_snap: malloc()"); 306 monitor_drain_input(); 307 if (*sadbsize) { 308 explicit_bzero(*sadb, *sadbsize); 309 free(*sadb); 310 } 311 return -1; 312 } 313 rbytes = m_read(m_state.s, *spd, *spdsize); 314 if (rbytes < 1) { 315 explicit_bzero(*spd, *spdsize); 316 free(*spd); 317 if (*sadbsize) { 318 explicit_bzero(*sadb, *sadbsize); 319 free(*sadb); 320 } 321 return -1; 322 } 323 } 324 325 log_msg(2, "monitor_get_pfkey_snap: got %u bytes SADB, %u bytes SPD", 326 *sadbsize, *spdsize); 327 return 0; 328 } 329 330 int 331 monitor_control_active(int active) 332 { 333 u_int32_t cmd = 334 active ? MONITOR_CONTROL_ACTIVATE : MONITOR_CONTROL_PASSIVATE; 335 if (write(m_state.s, &cmd, sizeof cmd) < 1) 336 return -1; 337 return 0; 338 } 339 340 /* Privileged */ 341 static void 342 m_priv_pfkey_snap(int s) 343 { 344 u_int8_t *sadb_buf = NULL, *spd_buf = NULL; 345 size_t sadb_buflen = 0, spd_buflen = 0, sz; 346 int mib[5]; 347 u_int32_t v; 348 349 mib[0] = CTL_NET; 350 mib[1] = PF_KEY; 351 mib[2] = PF_KEY_V2; 352 mib[3] = NET_KEY_SADB_DUMP; 353 mib[4] = 0; /* Unspec SA type */ 354 355 /* First, fetch SADB data */ 356 for (;;) { 357 if (sysctl(mib, sizeof mib / sizeof mib[0], NULL, &sz, NULL, 0) 358 == -1) 359 break; 360 361 if (!sz) 362 break; 363 364 /* Try to catch newly added data */ 365 sz *= 2; 366 367 if ((sadb_buf = malloc(sz)) == NULL) 368 break; 369 370 if (sysctl(mib, sizeof mib / sizeof mib[0], sadb_buf, &sz, NULL, 0) 371 == -1) { 372 free(sadb_buf); 373 sadb_buf = NULL; 374 /* 375 * If new SAs were added meanwhile and the given buffer is 376 * too small, retry. 377 */ 378 if (errno == ENOMEM) 379 continue; 380 break; 381 } 382 383 sadb_buflen = sz; 384 break; 385 } 386 387 /* Next, fetch SPD data */ 388 mib[3] = NET_KEY_SPD_DUMP; 389 390 for (;;) { 391 if (sysctl(mib, sizeof mib / sizeof mib[0], NULL, &sz, NULL, 0) 392 == -1) 393 break; 394 395 if (!sz) 396 break; 397 398 /* Try to catch newly added data */ 399 sz *= 2; 400 401 if ((spd_buf = malloc(sz)) == NULL) 402 break; 403 404 if (sysctl(mib, sizeof mib / sizeof mib[0], spd_buf, &sz, NULL, 0) 405 == -1) { 406 free(spd_buf); 407 spd_buf = NULL; 408 /* 409 * If new SPDs were added meanwhile and the given buffer is 410 * too small, retry. 411 */ 412 if (errno == ENOMEM) 413 continue; 414 break; 415 } 416 417 spd_buflen = sz; 418 break; 419 } 420 421 /* Return SADB data */ 422 v = (u_int32_t)sadb_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, sadb_buf, sadb_buflen) == -1) { 428 log_err("m_priv_pfkey_snap: write"); 429 goto cleanup; 430 } 431 432 /* Return SPD data */ 433 v = (u_int32_t)spd_buflen; 434 if (m_write(s, &v, sizeof v) == -1) { 435 log_err("m_priv_pfkey_snap: write"); 436 goto cleanup; 437 } 438 if (m_write(s, spd_buf, spd_buflen) == -1) { 439 log_err("m_priv_pfkey_snap: write"); 440 goto cleanup; 441 } 442 443 cleanup: 444 if (sadb_buf) { 445 explicit_bzero(sadb_buf, sadb_buflen); 446 free(sadb_buf); 447 } 448 if (spd_buf) { 449 explicit_bzero(spd_buf, spd_buflen); 450 free(spd_buf); 451 } 452 } 453 454 static int 455 m_priv_isakmpd_fifocmd(const char *cmd) 456 { 457 struct stat sb; 458 int fd = -1, ret = -1; 459 460 if ((fd = open(ISAKMPD_FIFO, O_WRONLY)) == -1) { 461 log_err("m_priv_isakmpd_fifocmd: open(%s)", ISAKMPD_FIFO); 462 goto out; 463 } 464 if (fstat(fd, &sb) == -1) { 465 log_err("m_priv_isakmpd_fifocmd: fstat(%s)", ISAKMPD_FIFO); 466 goto out; 467 } 468 if (!S_ISFIFO(sb.st_mode)) { 469 log_err("m_priv_isakmpd_fifocmd: %s not a fifo", ISAKMPD_FIFO); 470 goto out; 471 } 472 473 if (write(fd, cmd, strlen(cmd)) == -1) { 474 log_err("m_priv_isakmpd_fifocmd write"); 475 goto out; 476 } 477 478 ret = 0; 479 out: 480 if (fd != -1) 481 close(fd); 482 483 return (ret); 484 } 485 486 static int 487 m_priv_iked_imsg(u_int cmd) 488 { 489 struct sockaddr_un sun; 490 int fd = -1, ret = -1; 491 struct imsgbuf ibuf; 492 493 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 494 log_err("m_priv_iked_imsg: socket"); 495 goto out; 496 } 497 498 bzero(&sun, sizeof(sun)); 499 sun.sun_family = AF_UNIX; 500 strlcpy(sun.sun_path, IKED_SOCKET, sizeof(sun.sun_path)); 501 502 if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { 503 log_err("m_priv_iked_imsg: connect"); 504 goto out; 505 } 506 507 imsg_init(&ibuf, fd); 508 if (imsg_compose(&ibuf, cmd, 0, 0, -1, NULL, 0) == -1) { 509 log_err("m_priv_iked_imsg: compose"); 510 goto err; 511 } 512 if (imsg_flush(&ibuf) == -1) { 513 log_err("m_priv_iked_imsg: flush"); 514 goto err; 515 } 516 517 ret = 0; 518 err: 519 imsg_clear(&ibuf); 520 out: 521 if (fd != -1) 522 close(fd); 523 524 return (ret); 525 } 526 527 static int 528 m_priv_control_activate(void) 529 { 530 if (cfgstate.flags & CTL_ISAKMPD) 531 if (m_priv_isakmpd_fifocmd("M active\n") == -1) 532 return (-1); 533 if (cfgstate.flags & CTL_IKED) 534 if (m_priv_iked_imsg(IMSG_CTL_ACTIVE) == -1) 535 return (-1); 536 return (0); 537 } 538 539 static int 540 m_priv_control_passivate(void) 541 { 542 if (cfgstate.flags & CTL_ISAKMPD) 543 if (m_priv_isakmpd_fifocmd("M passive\n") == -1) 544 return (-1); 545 if (cfgstate.flags & CTL_IKED) 546 if (m_priv_iked_imsg(IMSG_CTL_PASSIVE) == -1) 547 return (-1); 548 return (0); 549 } 550 551 ssize_t 552 m_write(int sock, void *buf, size_t len) 553 { 554 ssize_t n; 555 size_t pos = 0; 556 char *ptr = buf; 557 558 while (len > pos) { 559 switch (n = write(sock, ptr + pos, len - pos)) { 560 case -1: 561 if (errno == EINTR || errno == EAGAIN) 562 continue; 563 /* FALLTHROUGH */ 564 case 0: 565 return n; 566 /* NOTREACHED */ 567 default: 568 pos += n; 569 } 570 } 571 return pos; 572 } 573 574 ssize_t 575 m_read(int sock, void *buf, size_t len) 576 { 577 ssize_t n; 578 size_t pos = 0; 579 char *ptr = buf; 580 581 while (len > pos) { 582 switch (n = read(sock, ptr + pos, len - pos)) { 583 case -1: 584 if (errno == EINTR || errno == EAGAIN) 585 continue; 586 /* FALLTHROUGH */ 587 case 0: 588 return n; 589 /* NOTREACHED */ 590 default: 591 pos += n; 592 } 593 } 594 return pos; 595 } 596