1 /*- 2 * Copyright (c) 2012 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Pawel Jakub Dawidek under sponsorship from 6 * the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/receiver.c#3 $ 30 */ 31 32 #include <config/config.h> 33 34 #include <sys/param.h> 35 #if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BSWAP) 36 #include <sys/endian.h> 37 #else /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ 38 #ifdef HAVE_MACHINE_ENDIAN_H 39 #include <machine/endian.h> 40 #else /* !HAVE_MACHINE_ENDIAN_H */ 41 #ifdef HAVE_ENDIAN_H 42 #include <endian.h> 43 #else /* !HAVE_ENDIAN_H */ 44 #error "No supported endian.h" 45 #endif /* !HAVE_ENDIAN_H */ 46 #endif /* !HAVE_MACHINE_ENDIAN_H */ 47 #include <compat/endian.h> 48 #endif /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ 49 #include <sys/queue.h> 50 #include <sys/stat.h> 51 #include <sys/time.h> 52 53 #include <err.h> 54 #include <errno.h> 55 #include <fcntl.h> 56 #ifdef HAVE_LIBUTIL_H 57 #include <libutil.h> 58 #endif 59 #include <pthread.h> 60 #include <pwd.h> 61 #include <signal.h> 62 #include <stdint.h> 63 #include <stdio.h> 64 #include <string.h> 65 #include <sysexits.h> 66 #include <unistd.h> 67 68 #ifndef HAVE_STRLCPY 69 #include <compat/strlcpy.h> 70 #endif 71 #ifndef HAVE_FSTATAT 72 #include "fstatat.h" 73 #endif 74 #ifndef HAVE_OPENAT 75 #include "openat.h" 76 #endif 77 #ifndef HAVE_RENAMEAT 78 #include "renameat.h" 79 #endif 80 81 #include "auditdistd.h" 82 #include "pjdlog.h" 83 #include "proto.h" 84 #include "sandbox.h" 85 #include "subr.h" 86 #include "synch.h" 87 #include "trail.h" 88 89 static struct adist_config *adcfg; 90 static struct adist_host *adhost; 91 92 static TAILQ_HEAD(, adreq) adist_free_list; 93 static pthread_mutex_t adist_free_list_lock; 94 static pthread_cond_t adist_free_list_cond; 95 static TAILQ_HEAD(, adreq) adist_disk_list; 96 static pthread_mutex_t adist_disk_list_lock; 97 static pthread_cond_t adist_disk_list_cond; 98 static TAILQ_HEAD(, adreq) adist_send_list; 99 static pthread_mutex_t adist_send_list_lock; 100 static pthread_cond_t adist_send_list_cond; 101 102 static void 103 adreq_clear(struct adreq *adreq) 104 { 105 106 adreq->adr_error = -1; 107 adreq->adr_byteorder = ADIST_BYTEORDER_UNDEFINED; 108 adreq->adr_cmd = ADIST_CMD_UNDEFINED; 109 adreq->adr_seq = 0; 110 adreq->adr_datasize = 0; 111 } 112 113 static void 114 init_environment(void) 115 { 116 struct adreq *adreq; 117 unsigned int ii; 118 119 TAILQ_INIT(&adist_free_list); 120 mtx_init(&adist_free_list_lock); 121 cv_init(&adist_free_list_cond); 122 TAILQ_INIT(&adist_disk_list); 123 mtx_init(&adist_disk_list_lock); 124 cv_init(&adist_disk_list_cond); 125 TAILQ_INIT(&adist_send_list); 126 mtx_init(&adist_send_list_lock); 127 cv_init(&adist_send_list_cond); 128 129 for (ii = 0; ii < ADIST_QUEUE_SIZE; ii++) { 130 adreq = malloc(sizeof(*adreq) + ADIST_BUF_SIZE); 131 if (adreq == NULL) { 132 pjdlog_exitx(EX_TEMPFAIL, 133 "Unable to allocate %zu bytes of memory for adreq object.", 134 sizeof(*adreq) + ADIST_BUF_SIZE); 135 } 136 adreq_clear(adreq); 137 TAILQ_INSERT_TAIL(&adist_free_list, adreq, adr_next); 138 } 139 } 140 141 static void 142 adreq_decode_and_validate_header(struct adreq *adreq) 143 { 144 145 /* Byte-swap only is the sender is using different byte order. */ 146 if (adreq->adr_byteorder != ADIST_BYTEORDER) { 147 adreq->adr_byteorder = ADIST_BYTEORDER; 148 adreq->adr_seq = bswap64(adreq->adr_seq); 149 adreq->adr_datasize = bswap32(adreq->adr_datasize); 150 } 151 152 /* Validate packet header. */ 153 154 if (adreq->adr_datasize > ADIST_BUF_SIZE) { 155 pjdlog_exitx(EX_PROTOCOL, "Invalid datasize received (%ju).", 156 (uintmax_t)adreq->adr_datasize); 157 } 158 159 switch (adreq->adr_cmd) { 160 case ADIST_CMD_OPEN: 161 case ADIST_CMD_APPEND: 162 case ADIST_CMD_CLOSE: 163 if (adreq->adr_datasize == 0) { 164 pjdlog_exitx(EX_PROTOCOL, 165 "Invalid datasize received (%ju).", 166 (uintmax_t)adreq->adr_datasize); 167 } 168 break; 169 case ADIST_CMD_KEEPALIVE: 170 case ADIST_CMD_ERROR: 171 if (adreq->adr_datasize > 0) { 172 pjdlog_exitx(EX_PROTOCOL, 173 "Invalid datasize received (%ju).", 174 (uintmax_t)adreq->adr_datasize); 175 } 176 break; 177 default: 178 pjdlog_exitx(EX_PROTOCOL, "Invalid command received (%hhu).", 179 adreq->adr_cmd); 180 } 181 } 182 183 static void 184 adreq_validate_data(const struct adreq *adreq) 185 { 186 187 /* Validate packet data. */ 188 189 switch (adreq->adr_cmd) { 190 case ADIST_CMD_OPEN: 191 case ADIST_CMD_CLOSE: 192 /* 193 * File name must end up with '\0' and there must be no '\0' 194 * in the middle. 195 */ 196 if (adreq->adr_data[adreq->adr_datasize - 1] != '\0' || 197 strchr(adreq->adr_data, '\0') != 198 (const char *)adreq->adr_data + adreq->adr_datasize - 1) { 199 pjdlog_exitx(EX_PROTOCOL, 200 "Invalid file name received."); 201 } 202 break; 203 } 204 } 205 206 /* 207 * Thread receives requests from the sender. 208 */ 209 static void * 210 recv_thread(void *arg __unused) 211 { 212 struct adreq *adreq; 213 214 for (;;) { 215 pjdlog_debug(3, "recv: Taking free request."); 216 QUEUE_TAKE(adreq, &adist_free_list, 0); 217 pjdlog_debug(3, "recv: (%p) Got request.", adreq); 218 219 if (proto_recv(adhost->adh_remote, &adreq->adr_packet, 220 sizeof(adreq->adr_packet)) == -1) { 221 pjdlog_exit(EX_TEMPFAIL, 222 "Unable to receive request header"); 223 } 224 adreq_decode_and_validate_header(adreq); 225 226 switch (adreq->adr_cmd) { 227 case ADIST_CMD_KEEPALIVE: 228 adreq->adr_error = 0; 229 adreq_log(LOG_DEBUG, 2, -1, adreq, 230 "recv: (%p) Got request header: ", adreq); 231 pjdlog_debug(3, 232 "recv: (%p) Moving request to the send queue.", 233 adreq); 234 QUEUE_INSERT(adreq, &adist_send_list); 235 continue; 236 case ADIST_CMD_ERROR: 237 pjdlog_error("An error occured on the sender while reading \"%s/%s\".", 238 adhost->adh_directory, adhost->adh_trail_name); 239 adreq_log(LOG_DEBUG, 2, ADIST_ERROR_READ, adreq, 240 "recv: (%p) Got request header: ", adreq); 241 pjdlog_debug(3, 242 "recv: (%p) Moving request to the send queue.", 243 adreq); 244 QUEUE_INSERT(adreq, &adist_disk_list); 245 continue; 246 case ADIST_CMD_OPEN: 247 case ADIST_CMD_APPEND: 248 case ADIST_CMD_CLOSE: 249 if (proto_recv(adhost->adh_remote, adreq->adr_data, 250 adreq->adr_datasize) == -1) { 251 pjdlog_exit(EX_TEMPFAIL, 252 "Unable to receive request data"); 253 } 254 adreq_validate_data(adreq); 255 adreq_log(LOG_DEBUG, 2, -1, adreq, 256 "recv: (%p) Got request header: ", adreq); 257 pjdlog_debug(3, 258 "recv: (%p) Moving request to the disk queue.", 259 adreq); 260 QUEUE_INSERT(adreq, &adist_disk_list); 261 break; 262 default: 263 PJDLOG_ABORT("Invalid condition."); 264 } 265 } 266 /* NOTREACHED */ 267 return (NULL); 268 } 269 270 /* 271 * Function that opens trail file requested by the sender. 272 * If the file already exist, it has to be the most recent file and it can 273 * only be open for append. 274 * If the file doesn't already exist, it has to be "older" than all existing 275 * files. 276 */ 277 static int 278 receiver_open(const char *filename) 279 { 280 int fd; 281 282 /* 283 * Previous file should be closed by now. Sending OPEN request without 284 * sending CLOSE for the previous file is a sender bug. 285 */ 286 if (adhost->adh_trail_fd != -1) { 287 pjdlog_error("Sender requested opening file \"%s\" without first closing \"%s\".", 288 filename, adhost->adh_trail_name); 289 return (ADIST_ERROR_WRONG_ORDER); 290 } 291 292 if (!trail_validate_name(filename, NULL)) { 293 pjdlog_error("Sender wants to open file \"%s\", which has invalid name.", 294 filename); 295 return (ADIST_ERROR_INVALID_NAME); 296 } 297 298 switch (trail_name_compare(filename, adhost->adh_trail_name)) { 299 case TRAIL_RENAMED: 300 if (!trail_is_not_terminated(adhost->adh_trail_name)) { 301 pjdlog_error("Terminated trail \"%s/%s\" was unterminated on the sender as \"%s/%s\"?", 302 adhost->adh_directory, adhost->adh_trail_name, 303 adhost->adh_directory, filename); 304 return (ADIST_ERROR_INVALID_NAME); 305 } 306 if (renameat(adhost->adh_trail_dirfd, adhost->adh_trail_name, 307 adhost->adh_trail_dirfd, filename) == -1) { 308 pjdlog_errno(LOG_ERR, 309 "Unable to rename file \"%s/%s\" to \"%s/%s\"", 310 adhost->adh_directory, adhost->adh_trail_name, 311 adhost->adh_directory, filename); 312 PJDLOG_ASSERT(errno > 0); 313 return (ADIST_ERROR_RENAME); 314 } 315 pjdlog_debug(1, "Renamed file \"%s/%s\" to \"%s/%s\".", 316 adhost->adh_directory, adhost->adh_trail_name, 317 adhost->adh_directory, filename); 318 /* FALLTHROUGH */ 319 case TRAIL_IDENTICAL: 320 /* Opening existing file. */ 321 fd = openat(adhost->adh_trail_dirfd, filename, 322 O_WRONLY | O_APPEND | O_NOFOLLOW); 323 if (fd == -1) { 324 pjdlog_errno(LOG_ERR, 325 "Unable to open file \"%s/%s\" for append", 326 adhost->adh_directory, filename); 327 PJDLOG_ASSERT(errno > 0); 328 return (ADIST_ERROR_OPEN); 329 } 330 pjdlog_debug(1, "Opened file \"%s/%s\".", 331 adhost->adh_directory, filename); 332 break; 333 case TRAIL_NEWER: 334 /* Opening new file. */ 335 fd = openat(adhost->adh_trail_dirfd, filename, 336 O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); 337 if (fd == -1) { 338 pjdlog_errno(LOG_ERR, 339 "Unable to create file \"%s/%s\"", 340 adhost->adh_directory, filename); 341 PJDLOG_ASSERT(errno > 0); 342 return (ADIST_ERROR_CREATE); 343 } 344 pjdlog_debug(1, "Created file \"%s/%s\".", 345 adhost->adh_directory, filename); 346 break; 347 case TRAIL_OLDER: 348 /* Trying to open old file. */ 349 pjdlog_error("Sender wants to open an old file \"%s\".", filename); 350 return (ADIST_ERROR_OPEN_OLD); 351 default: 352 PJDLOG_ABORT("Unknown return value from trail_name_compare()."); 353 } 354 PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename, 355 sizeof(adhost->adh_trail_name)) < sizeof(adhost->adh_trail_name)); 356 adhost->adh_trail_fd = fd; 357 return (0); 358 } 359 360 /* 361 * Function appends data to the trail file that is currently open. 362 */ 363 static int 364 receiver_append(const unsigned char *data, size_t size) 365 { 366 ssize_t done; 367 size_t osize; 368 369 /* We should have opened trail file. */ 370 if (adhost->adh_trail_fd == -1) { 371 pjdlog_error("Sender requested append without first opening file."); 372 return (ADIST_ERROR_WRONG_ORDER); 373 } 374 375 osize = size; 376 while (size > 0) { 377 done = write(adhost->adh_trail_fd, data, size); 378 if (done == -1) { 379 if (errno == EINTR) 380 continue; 381 pjdlog_errno(LOG_ERR, "Write to \"%s/%s\" failed", 382 adhost->adh_directory, adhost->adh_trail_name); 383 PJDLOG_ASSERT(errno > 0); 384 return (ADIST_ERROR_WRITE); 385 } 386 pjdlog_debug(3, "Wrote %zd bytes into \"%s/%s\".", done, 387 adhost->adh_directory, adhost->adh_trail_name); 388 size -= done; 389 } 390 pjdlog_debug(2, "Appended %zu bytes to file \"%s/%s\".", 391 osize, adhost->adh_directory, adhost->adh_trail_name); 392 return (0); 393 } 394 395 static int 396 receiver_close(const char *filename) 397 { 398 399 /* We should have opened trail file. */ 400 if (adhost->adh_trail_fd == -1) { 401 pjdlog_error("Sender requested closing file without first opening it."); 402 return (ADIST_ERROR_WRONG_ORDER); 403 } 404 405 /* Validate if we can do the rename. */ 406 if (!trail_validate_name(adhost->adh_trail_name, filename)) { 407 pjdlog_error("Sender wants to close file \"%s\" using name \"%s\".", 408 adhost->adh_trail_name, filename); 409 return (ADIST_ERROR_INVALID_NAME); 410 } 411 412 PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0); 413 adhost->adh_trail_fd = -1; 414 415 pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory, 416 adhost->adh_trail_name); 417 418 if (strcmp(adhost->adh_trail_name, filename) == 0) { 419 /* File name didn't change, we are done here. */ 420 return (0); 421 } 422 423 if (renameat(adhost->adh_trail_dirfd, adhost->adh_trail_name, 424 adhost->adh_trail_dirfd, filename) == -1) { 425 pjdlog_errno(LOG_ERR, "Unable to rename \"%s\" to \"%s\"", 426 adhost->adh_trail_name, filename); 427 PJDLOG_ASSERT(errno > 0); 428 return (ADIST_ERROR_RENAME); 429 } 430 pjdlog_debug(1, "Renamed file \"%s/%s\" to \"%s/%s\".", 431 adhost->adh_directory, adhost->adh_trail_name, 432 adhost->adh_directory, filename); 433 PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename, 434 sizeof(adhost->adh_trail_name)) < sizeof(adhost->adh_trail_name)); 435 436 return (0); 437 } 438 439 static int 440 receiver_error(void) 441 { 442 443 /* We should have opened trail file. */ 444 if (adhost->adh_trail_fd == -1) { 445 pjdlog_error("Sender send read error, but file is not open."); 446 return (ADIST_ERROR_WRONG_ORDER); 447 } 448 449 PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0); 450 adhost->adh_trail_fd = -1; 451 452 pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory, 453 adhost->adh_trail_name); 454 455 return (0); 456 } 457 458 static void * 459 disk_thread(void *arg __unused) 460 { 461 struct adreq *adreq; 462 463 for (;;) { 464 pjdlog_debug(3, "disk: Taking request."); 465 QUEUE_TAKE(adreq, &adist_disk_list, 0); 466 adreq_log(LOG_DEBUG, 3, -1, adreq, "disk: (%p) Got request: ", 467 adreq); 468 /* Handle the actual request. */ 469 switch (adreq->adr_cmd) { 470 case ADIST_CMD_OPEN: 471 adreq->adr_error = receiver_open(adreq->adr_data); 472 break; 473 case ADIST_CMD_APPEND: 474 adreq->adr_error = receiver_append(adreq->adr_data, 475 adreq->adr_datasize); 476 break; 477 case ADIST_CMD_CLOSE: 478 adreq->adr_error = receiver_close(adreq->adr_data); 479 break; 480 case ADIST_CMD_ERROR: 481 adreq->adr_error = receiver_error(); 482 break; 483 default: 484 PJDLOG_ABORT("Unexpected command (cmd=%hhu).", 485 adreq->adr_cmd); 486 } 487 if (adreq->adr_error != 0) { 488 adreq_log(LOG_ERR, 0, adreq->adr_error, adreq, 489 "Request failed: "); 490 } 491 pjdlog_debug(3, "disk: (%p) Moving request to the send queue.", 492 adreq); 493 QUEUE_INSERT(adreq, &adist_send_list); 494 } 495 /* NOTREACHED */ 496 return (NULL); 497 } 498 499 /* 500 * Thread sends requests back to primary node. 501 */ 502 static void * 503 send_thread(void *arg __unused) 504 { 505 struct adreq *adreq; 506 struct adrep adrep; 507 508 for (;;) { 509 pjdlog_debug(3, "send: Taking request."); 510 QUEUE_TAKE(adreq, &adist_send_list, 0); 511 adreq_log(LOG_DEBUG, 3, -1, adreq, "send: (%p) Got request: ", 512 adreq); 513 adrep.adrp_byteorder = ADIST_BYTEORDER; 514 adrep.adrp_seq = adreq->adr_seq; 515 adrep.adrp_error = adreq->adr_error; 516 if (proto_send(adhost->adh_remote, &adrep, 517 sizeof(adrep)) == -1) { 518 pjdlog_exit(EX_TEMPFAIL, "Unable to send reply"); 519 } 520 pjdlog_debug(3, "send: (%p) Moving request to the free queue.", 521 adreq); 522 adreq_clear(adreq); 523 QUEUE_INSERT(adreq, &adist_free_list); 524 } 525 /* NOTREACHED */ 526 return (NULL); 527 } 528 529 static void 530 receiver_directory_create(void) 531 { 532 struct passwd *pw; 533 534 /* 535 * According to getpwnam(3) we have to clear errno before calling the 536 * function to be able to distinguish between an error and missing 537 * entry (with is not treated as error by getpwnam(3)). 538 */ 539 errno = 0; 540 pw = getpwnam(ADIST_USER); 541 if (pw == NULL) { 542 if (errno != 0) { 543 pjdlog_exit(EX_NOUSER, 544 "Unable to find info about '%s' user", ADIST_USER); 545 } else { 546 pjdlog_exitx(EX_NOUSER, "User '%s' doesn't exist.", 547 ADIST_USER); 548 } 549 } 550 551 if (mkdir(adhost->adh_directory, 0700) == -1) { 552 pjdlog_exit(EX_OSFILE, "Unable to create directory \"%s\"", 553 adhost->adh_directory); 554 } 555 if (chown(adhost->adh_directory, pw->pw_uid, pw->pw_gid) == -1) { 556 pjdlog_errno(LOG_ERR, 557 "Unable to change owner of the directory \"%s\"", 558 adhost->adh_directory); 559 (void)rmdir(adhost->adh_directory); 560 exit(EX_OSFILE); 561 } 562 } 563 564 static void 565 receiver_directory_open(void) 566 { 567 568 #ifdef HAVE_FDOPENDIR 569 adhost->adh_trail_dirfd = open(adhost->adh_directory, 570 O_RDONLY | O_DIRECTORY); 571 if (adhost->adh_trail_dirfd == -1) { 572 if (errno == ENOENT) { 573 receiver_directory_create(); 574 adhost->adh_trail_dirfd = open(adhost->adh_directory, 575 O_RDONLY | O_DIRECTORY); 576 } 577 if (adhost->adh_trail_dirfd == -1) { 578 pjdlog_exit(EX_CONFIG, 579 "Unable to open directory \"%s\"", 580 adhost->adh_directory); 581 } 582 } 583 adhost->adh_trail_dirfp = fdopendir(adhost->adh_trail_dirfd); 584 if (adhost->adh_trail_dirfp == NULL) { 585 pjdlog_exit(EX_CONFIG, "Unable to fdopen directory \"%s\"", 586 adhost->adh_directory); 587 } 588 #else 589 struct stat sb; 590 591 if (stat(adhost->adh_directory, &sb) == -1) { 592 if (errno == ENOENT) { 593 receiver_directory_create(); 594 } else { 595 pjdlog_exit(EX_CONFIG, 596 "Unable to stat directory \"%s\"", 597 adhost->adh_directory); 598 } 599 } 600 adhost->adh_trail_dirfp = opendir(adhost->adh_directory); 601 if (adhost->adh_trail_dirfp == NULL) { 602 pjdlog_exit(EX_CONFIG, "Unable to open directory \"%s\"", 603 adhost->adh_directory); 604 } 605 adhost->adh_trail_dirfd = dirfd(adhost->adh_trail_dirfp); 606 #endif 607 } 608 609 static void 610 receiver_connect(void) 611 { 612 uint64_t trail_size; 613 struct stat sb; 614 615 PJDLOG_ASSERT(adhost->adh_trail_dirfp != NULL); 616 617 trail_last(adhost->adh_trail_dirfp, adhost->adh_trail_name, 618 sizeof(adhost->adh_trail_name)); 619 620 if (adhost->adh_trail_name[0] == '\0') { 621 trail_size = 0; 622 } else { 623 if (fstatat(adhost->adh_trail_dirfd, adhost->adh_trail_name, 624 &sb, AT_SYMLINK_NOFOLLOW) == -1) { 625 pjdlog_exit(EX_CONFIG, "Unable to stat \"%s/%s\"", 626 adhost->adh_directory, adhost->adh_trail_name); 627 } 628 if (!S_ISREG(sb.st_mode)) { 629 pjdlog_exitx(EX_CONFIG, 630 "File \"%s/%s\" is not a regular file.", 631 adhost->adh_directory, adhost->adh_trail_name); 632 } 633 trail_size = sb.st_size; 634 } 635 trail_size = htole64(trail_size); 636 if (proto_send(adhost->adh_remote, &trail_size, 637 sizeof(trail_size)) == -1) { 638 pjdlog_exit(EX_TEMPFAIL, 639 "Unable to send size of the most recent trail file"); 640 } 641 if (proto_send(adhost->adh_remote, adhost->adh_trail_name, 642 sizeof(adhost->adh_trail_name)) == -1) { 643 pjdlog_exit(EX_TEMPFAIL, 644 "Unable to send name of the most recent trail file"); 645 } 646 } 647 648 void 649 adist_receiver(struct adist_config *config, struct adist_host *adh) 650 { 651 sigset_t mask; 652 pthread_t td; 653 pid_t pid; 654 int error, mode, debuglevel; 655 656 pid = fork(); 657 if (pid == -1) { 658 pjdlog_errno(LOG_ERR, "Unable to fork"); 659 proto_close(adh->adh_remote); 660 adh->adh_remote = NULL; 661 return; 662 } 663 664 if (pid > 0) { 665 /* This is parent. */ 666 proto_close(adh->adh_remote); 667 adh->adh_remote = NULL; 668 adh->adh_worker_pid = pid; 669 return; 670 } 671 672 adcfg = config; 673 adhost = adh; 674 mode = pjdlog_mode_get(); 675 debuglevel = pjdlog_debug_get(); 676 677 descriptors_cleanup(adhost); 678 679 // descriptors_assert(adhost, mode); 680 681 pjdlog_init(mode); 682 pjdlog_debug_set(debuglevel); 683 pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, 684 role2str(adhost->adh_role)); 685 #ifdef HAVE_SETPROCTITLE 686 setproctitle("%s (%s)", adhost->adh_name, role2str(adhost->adh_role)); 687 #endif 688 689 PJDLOG_VERIFY(sigemptyset(&mask) == 0); 690 PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); 691 692 /* Error in setting timeout is not critical, but why should it fail? */ 693 if (proto_timeout(adhost->adh_remote, adcfg->adc_timeout) == -1) 694 pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); 695 696 init_environment(); 697 698 adhost->adh_trail_fd = -1; 699 receiver_directory_open(); 700 701 if (sandbox(ADIST_USER, true, "auditdistd: %s (%s)", 702 role2str(adhost->adh_role), adhost->adh_name) != 0) { 703 exit(EX_CONFIG); 704 } 705 pjdlog_info("Privileges successfully dropped."); 706 707 receiver_connect(); 708 709 error = pthread_create(&td, NULL, recv_thread, adhost); 710 PJDLOG_ASSERT(error == 0); 711 error = pthread_create(&td, NULL, disk_thread, adhost); 712 PJDLOG_ASSERT(error == 0); 713 (void)send_thread(adhost); 714 } 715