1 /* $NetBSD: syslogd.c,v 1.158 2026/09/01 20:12:19 andvar Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1988, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993, 1994\ 35 The Regents of the University of California. All rights reserved."); 36 #endif /* not lint */ 37 38 #ifndef lint 39 #if 0 40 static char sccsid[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94"; 41 #else 42 __RCSID("$NetBSD: syslogd.c,v 1.158 2026/09/01 20:12:19 andvar Exp $"); 43 #endif 44 #endif /* not lint */ 45 46 /* 47 * syslogd -- log system messages 48 * 49 * This program implements a system log. It takes a series of lines. 50 * Each line may have a priority, signified as "<n>" as 51 * the first characters of the line. If this is 52 * not present, a default priority is used. 53 * 54 * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will 55 * cause it to reread its configuration file. 56 * 57 * Defined Constants: 58 * 59 * MAXLINE -- the maximum line length that can be handled. 60 * DEFUPRI -- the default priority for user messages 61 * DEFSPRI -- the default priority for kernel messages 62 * 63 * Author: Eric Allman 64 * extensive changes by Ralph Campbell 65 * more extensive changes by Eric Allman (again) 66 * Extension to log by program name as well as facility and priority 67 * by Peter da Silva. 68 * -U and -v by Harlan Stenn. 69 * Priority comparison code by Harlan Stenn. 70 * TLS, syslog-protocol, and syslog-sign code by Martin Schuette. 71 */ 72 #define SYSLOG_NAMES 73 #include <sys/stat.h> 74 #include <poll.h> 75 #include "syslogd.h" 76 #include "extern.h" 77 78 #ifndef DISABLE_SIGN 79 #include "sign.h" 80 struct sign_global_t GlobalSign = { 81 .rsid = 0, 82 .sig2_delims = STAILQ_HEAD_INITIALIZER(GlobalSign.sig2_delims) 83 }; 84 #endif /* !DISABLE_SIGN */ 85 86 #ifndef DISABLE_TLS 87 #include "tls.h" 88 #endif /* !DISABLE_TLS */ 89 90 #ifdef LIBWRAP 91 int allow_severity = LOG_AUTH|LOG_INFO; 92 int deny_severity = LOG_AUTH|LOG_WARNING; 93 #endif 94 95 const char *ConfFile = _PATH_LOGCONF; 96 char ctty[] = _PATH_CONSOLE; 97 98 /* 99 * Queue of about-to-be-dead processes we should watch out for. 100 */ 101 TAILQ_HEAD(, deadq_entry) deadq_head = TAILQ_HEAD_INITIALIZER(deadq_head); 102 103 typedef struct deadq_entry { 104 pid_t dq_pid; 105 int dq_timeout; 106 TAILQ_ENTRY(deadq_entry) dq_entries; 107 } *dq_t; 108 109 /* 110 * The timeout to apply to processes waiting on the dead queue. Unit 111 * of measure is "mark intervals", i.e. 20 minutes by default. 112 * Processes on the dead queue will be terminated after that time. 113 */ 114 #define DQ_TIMO_INIT 2 115 116 #define RCVBUFLEN 16384 117 int buflen = RCVBUFLEN; 118 /* 119 * Intervals at which we flush out "message repeated" messages, 120 * in seconds after previous message is logged. After each flush, 121 * we move to the next interval until we reach the largest. 122 */ 123 int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */ 124 #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1) 125 #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount]) 126 #define BACKOFF(f) { if ((size_t)(++(f)->f_repeatcount) > MAXREPEAT) \ 127 (f)->f_repeatcount = MAXREPEAT; \ 128 } 129 130 /* values for f_type */ 131 #define F_UNUSED 0 /* unused entry */ 132 #define F_FILE 1 /* regular file */ 133 #define F_TTY 2 /* terminal */ 134 #define F_CONSOLE 3 /* console terminal */ 135 #define F_FORW 4 /* remote machine */ 136 #define F_USERS 5 /* list of users */ 137 #define F_WALL 6 /* everyone logged on */ 138 #define F_PIPE 7 /* pipe to program */ 139 #define F_FIFO 8 /* mkfifo(2) file */ 140 #define F_TLS 9 141 142 struct TypeInfo { 143 const char *name; 144 char *queue_length_string; 145 const char *default_length_string; 146 char *queue_size_string; 147 const char *default_size_string; 148 int64_t queue_length; 149 int64_t queue_size; 150 int max_msg_length; 151 } TypeInfo[] = { 152 /* numeric values are set in init() 153 * -1 in length/size or max_msg_length means infinite */ 154 {"UNUSED", NULL, "0", NULL, "0", 0, 0, 0}, 155 {"FILE", NULL, "1024", NULL, "1M", 0, 0, 16384}, 156 {"TTY", NULL, "0", NULL, "0", 0, 0, 1024}, 157 {"CONSOLE", NULL, "0", NULL, "0", 0, 0, 1024}, 158 {"FORW", NULL, "0", NULL, "1M", 0, 0, 16384}, 159 {"USERS", NULL, "0", NULL, "0", 0, 0, 1024}, 160 {"WALL", NULL, "0", NULL, "0", 0, 0, 1024}, 161 {"PIPE", NULL, "1024", NULL, "1M", 0, 0, 16384}, 162 {"FIFO", NULL, "1024", NULL, "1M", 0, 0, 16384}, 163 #ifndef DISABLE_TLS 164 {"TLS", NULL, "-1", NULL, "16M", 0, 0, 16384} 165 #endif /* !DISABLE_TLS */ 166 }; 167 168 struct filed *Files = NULL; 169 struct filed consfile; 170 171 time_t now; 172 int Debug = D_NONE; /* debug flag */ 173 int daemonized = 0; /* we are not daemonized yet */ 174 char *LocalFQDN = NULL; /* our FQDN */ 175 char *oldLocalFQDN = NULL; /* our previous FQDN */ 176 char LocalHostName[MAXHOSTNAMELEN]; /* our hostname */ 177 struct socketEvent *finet; /* Internet datagram sockets and events */ 178 int *funix; /* Unix domain datagram sockets */ 179 #ifndef DISABLE_TLS 180 struct socketEvent *TLS_Listen_Set; /* TLS/TCP sockets and events */ 181 #endif /* !DISABLE_TLS */ 182 int Initialized = 0; /* set when we have initialized ourselves */ 183 int ShuttingDown; /* set when we die() */ 184 int MarkInterval = 20 * 60; /* interval between marks in seconds */ 185 int MarkSeq = 0; /* mark sequence number */ 186 int SecureMode = 0; /* listen only on unix domain socks */ 187 int UseNameService = 1; /* make domain name queries */ 188 int NumForwards = 0; /* number of forwarding actions in conf file */ 189 char **LogPaths; /* array of pathnames to read messages from */ 190 int NoRepeat = 0; /* disable "repeated"; log always */ 191 int RemoteAddDate = 0; /* always add date to messages from network */ 192 int SyncKernel = 0; /* write kernel messages synchronously */ 193 int UniquePriority = 0; /* only log specified priority */ 194 int LogFacPri = 0; /* put facility and priority in log messages: */ 195 /* 0=no, 1=numeric, 2=names */ 196 int LogOverflow = 1; /* 0=no, any other value = yes */ 197 bool BSDOutputFormat = true; /* if true emit traditional BSD Syslog lines, 198 * otherwise new syslog-protocol lines 199 * 200 * Open Issue: having a global flag is the 201 * easiest solution. If we get a more detailed 202 * config file this could/should be changed 203 * into a destination-specific flag. 204 * Most output code should be ready to handle 205 * this, it will only break some syslog-sign 206 * configurations (e.g. with SG="0"). 207 */ 208 bool KernXlat = true; /* translate kern.* -> user.* */ 209 char appname[] = "syslogd";/* the APPNAME for own messages */ 210 char *include_pid; /* include PID in own messages */ 211 char include_pid_buf[11]; 212 213 214 /* init and setup */ 215 void usage(void) __attribute__((__noreturn__)); 216 void set_debug(const char *); 217 void logpath_add(char ***, int *, int *, const char *); 218 void logpath_fileadd(char ***, int *, int *, const char *); 219 void init(int fd, short event, void *ev); /* SIGHUP kevent dispatch routine */ 220 struct socketEvent* 221 socksetup(int, const char *); 222 int getmsgbufsize(void); 223 char *getLocalFQDN(void); 224 void trim_anydomain(char *); 225 /* pipe & subprocess handling */ 226 int p_open(char *, pid_t *); 227 void deadq_enter(pid_t, const char *); 228 int deadq_remove(pid_t); 229 void log_deadchild(pid_t, int, const char *); 230 void reapchild(int fd, short event, void *ev); /* SIGCHLD kevent dispatch routine */ 231 /* input message parsing & formatting */ 232 const char *cvthname(struct sockaddr_storage *); 233 void printsys(char *); 234 struct buf_msg *printline_syslogprotocol(const char*, char*, int, int); 235 struct buf_msg *printline_bsdsyslog(const char*, char*, int, int); 236 struct buf_msg *printline_kernelprintf(const char*, char*, int, int); 237 size_t check_timestamp(unsigned char *, char **, bool, bool); 238 char *copy_utf8_ascii(char*, size_t); 239 uint_fast32_t get_utf8_value(const char*); 240 unsigned valid_utf8(const char *); 241 static unsigned check_sd(char*); 242 static unsigned check_msgid(char *); 243 /* event handling */ 244 static void dispatch_read_klog(int fd, short event, void *ev); 245 static void dispatch_read_finet(int fd, short event, void *ev); 246 static void dispatch_read_funix(int fd, short event, void *ev); 247 static void domark(int fd, short event, void *ev); /* timer kevent dispatch routine */ 248 /* log messages */ 249 void logmsg_async(int, const char *, const char *, int); 250 void logmsg(struct buf_msg *); 251 int matches_spec(const char *, const char *, 252 char *(*)(const char *, const char *)); 253 void udp_send(struct filed *, char *, size_t); 254 void wallmsg(struct filed *, struct iovec *, size_t); 255 /* buffer & queue functions */ 256 size_t message_queue_purge(struct filed *f, size_t, int); 257 size_t message_allqueues_check(void); 258 static struct buf_queue * 259 find_qentry_to_delete(const struct buf_queue_head *, int, bool); 260 struct buf_queue * 261 message_queue_add(struct filed *, struct buf_msg *); 262 size_t buf_queue_obj_size(struct buf_queue*); 263 /* configuration & parsing */ 264 void cfline(size_t, const char *, struct filed *, const char *, 265 const char *); 266 void read_config_file(FILE*, struct filed**); 267 void store_sign_delim_sg2(char*); 268 int decode(const char *, CODE *); 269 bool copy_config_value(const char *, char **, const char **, 270 const char *, int); 271 bool copy_config_value_word(char **, const char **); 272 273 /* config parsing */ 274 #ifndef DISABLE_TLS 275 void free_cred_SLIST(struct peer_cred_head *); 276 static inline void 277 free_incoming_tls_sockets(void); 278 #endif /* !DISABLE_TLS */ 279 static int writev1(int, struct iovec *, size_t); 280 281 static void setsockbuf(int, const char *); 282 283 /* for make_timestamp() */ 284 char timestamp[MAX_TIMESTAMPLEN + 1]; 285 /* 286 * Global line buffer. Since we only process one event at a time, 287 * a global one will do. But for klog, we use own buffer so that 288 * partial line at the end of buffer can be deferred. 289 */ 290 static char *linebuf, *klog_linebuf; 291 static size_t linebufsize, klog_linebufoff; 292 293 static const char *bindhostname = NULL; 294 295 #ifndef DISABLE_TLS 296 struct TLS_Incoming TLS_Incoming_Head = \ 297 SLIST_HEAD_INITIALIZER(TLS_Incoming_Head); 298 extern char *SSL_ERRCODE[]; 299 struct tls_global_options_t tls_opt; 300 #endif /* !DISABLE_TLS */ 301 302 int 303 main(int argc, char *argv[]) 304 { 305 int ch, j, fklog; 306 int funixsize = 0, funixmaxsize = 0; 307 struct sockaddr_un sunx; 308 char **pp; 309 struct event *ev; 310 uid_t uid = 0; 311 gid_t gid = 0; 312 char *user = NULL; 313 char *group = NULL; 314 const char *root = "/"; 315 char *endp; 316 struct group *gr; 317 struct passwd *pw; 318 unsigned long l; 319 char pfpath[PATH_MAX]; 320 321 /* should we set LC_TIME="C" to ensure correct timestamps&parsing? */ 322 (void)setlocale(LC_ALL, ""); 323 324 while ((ch = getopt(argc, argv, "b:B:d::knsSf:m:o:p:P:ru:g:t:TUvX")) != -1) 325 switch (ch) { 326 case 'b': 327 bindhostname = optarg; 328 break; 329 case 'B': 330 buflen = atoi(optarg); 331 if (buflen < RCVBUFLEN) 332 buflen = RCVBUFLEN; 333 break; 334 case 'd': /* debug */ 335 if (optarg != NULL) { 336 /* 337 * getopt passes as optarg everything 338 * after 'd' in -darg, manually accept 339 * -d=arg too. 340 */ 341 if (optarg[0] == '=') 342 ++optarg; 343 } else if (optind < argc) { 344 /* 345 * :: treats "-d ..." as missing 346 * optarg, so look ahead manually and 347 * pick up the next arg if it looks 348 * like one. 349 */ 350 if (argv[optind][0] != '-') { 351 optarg = argv[optind]; 352 ++optind; 353 } 354 } 355 set_debug(optarg); 356 break; 357 case 'f': /* configuration file */ 358 ConfFile = optarg; 359 break; 360 case 'g': 361 group = optarg; 362 if (*group == '\0') 363 usage(); 364 break; 365 case 'k': /* pass-through (remote) kern.* */ 366 KernXlat = false; 367 break; 368 case 'm': /* mark interval */ 369 MarkInterval = atoi(optarg) * 60; 370 break; 371 case 'n': /* turn off DNS queries */ 372 UseNameService = 0; 373 break; 374 case 'o': /* message format */ 375 #define EQ(a) (strncmp(optarg, # a, sizeof(# a) - 1) == 0) 376 if (EQ(bsd) || EQ(rfc3264)) 377 BSDOutputFormat = true; 378 else if (EQ(syslog) || EQ(rfc5424)) 379 BSDOutputFormat = false; 380 else 381 usage(); 382 /* TODO: implement additional output option "osyslog" 383 * for old syslogd behaviour as introduced after 384 * FreeBSD PR#bin/7055. 385 */ 386 break; 387 case 'p': /* path */ 388 logpath_add(&LogPaths, &funixsize, 389 &funixmaxsize, optarg); 390 break; 391 case 'P': /* file of paths */ 392 logpath_fileadd(&LogPaths, &funixsize, 393 &funixmaxsize, optarg); 394 break; 395 case 'r': /* disable "repeated" compression */ 396 NoRepeat++; 397 break; 398 case 's': /* no network listen mode */ 399 SecureMode++; 400 break; 401 case 'S': 402 SyncKernel = 1; 403 break; 404 case 't': 405 root = optarg; 406 if (*root == '\0') 407 usage(); 408 break; 409 case 'T': 410 RemoteAddDate = 1; 411 break; 412 case 'u': 413 user = optarg; 414 if (*user == '\0') 415 usage(); 416 break; 417 case 'U': /* only log specified priority */ 418 UniquePriority = 1; 419 break; 420 case 'v': /* log facility and priority */ 421 if (LogFacPri < 2) 422 LogFacPri++; 423 break; 424 case 'X': 425 LogOverflow = 0; 426 break; 427 default: 428 usage(); 429 } 430 if ((argc -= optind) != 0) 431 usage(); 432 433 setlinebuf(stdout); 434 tzset(); /* init TZ information for localtime. */ 435 436 if (user != NULL) { 437 if (isdigit((unsigned char)*user)) { 438 errno = 0; 439 endp = NULL; 440 l = strtoul(user, &endp, 0); 441 if (errno || *endp != '\0') 442 goto getuser; 443 uid = (uid_t)l; 444 if (uid != l) {/* TODO: never executed */ 445 errno = 0; 446 logerror("UID out of range"); 447 die(0, 0, NULL); 448 } 449 } else { 450 getuser: 451 if ((pw = getpwnam(user)) != NULL) { 452 uid = pw->pw_uid; 453 } else { 454 errno = 0; 455 logerror("Cannot find user `%s'", user); 456 die(0, 0, NULL); 457 } 458 } 459 } 460 461 if (group != NULL) { 462 if (isdigit((unsigned char)*group)) { 463 errno = 0; 464 endp = NULL; 465 l = strtoul(group, &endp, 0); 466 if (errno || *endp != '\0') 467 goto getgroup; 468 gid = (gid_t)l; 469 if (gid != l) {/* TODO: never executed */ 470 errno = 0; 471 logerror("GID out of range"); 472 die(0, 0, NULL); 473 } 474 } else { 475 getgroup: 476 if ((gr = getgrnam(group)) != NULL) { 477 gid = gr->gr_gid; 478 } else { 479 errno = 0; 480 logerror("Cannot find group `%s'", group); 481 die(0, 0, NULL); 482 } 483 } 484 } 485 486 if (access(root, F_OK | R_OK)) { 487 logerror("Cannot access `%s'", root); 488 die(0, 0, NULL); 489 } 490 491 consfile.f_type = F_CONSOLE; 492 (void)strlcpy(consfile.f_un.f_fname, ctty, 493 sizeof(consfile.f_un.f_fname)); 494 linebufsize = getmsgbufsize(); 495 if (linebufsize < MAXLINE) 496 linebufsize = MAXLINE; 497 linebufsize++; 498 499 if (!(linebuf = malloc(linebufsize))) { 500 logerror("Couldn't allocate buffer"); 501 die(0, 0, NULL); 502 } 503 if (!(klog_linebuf = malloc(linebufsize))) { 504 logerror("Couldn't allocate buffer for klog"); 505 die(0, 0, NULL); 506 } 507 508 509 #ifndef SUN_LEN 510 #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2) 511 #endif 512 if (funixsize == 0) 513 logpath_add(&LogPaths, &funixsize, 514 &funixmaxsize, _PATH_LOG); 515 funix = malloc(sizeof(*funix) * funixsize); 516 if (funix == NULL) { 517 logerror("Couldn't allocate funix descriptors"); 518 die(0, 0, NULL); 519 } 520 for (j = 0, pp = LogPaths; *pp; pp++, j++) { 521 DPRINTF(D_NET, "Making unix dgram socket `%s'\n", *pp); 522 unlink(*pp); 523 memset(&sunx, 0, sizeof(sunx)); 524 sunx.sun_family = AF_LOCAL; 525 (void)strncpy(sunx.sun_path, *pp, sizeof(sunx.sun_path)); 526 funix[j] = socket(AF_LOCAL, SOCK_DGRAM, 0); 527 if (funix[j] < 0 || bind(funix[j], 528 (struct sockaddr *)&sunx, SUN_LEN(&sunx)) < 0 || 529 chmod(*pp, 0666) < 0) { 530 logerror("Cannot create `%s'", *pp); 531 die(0, 0, NULL); 532 } 533 setsockbuf(funix[j], *pp); 534 DPRINTF(D_NET, "Listening on unix dgram socket `%s'\n", *pp); 535 } 536 537 if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) < 0) { 538 DPRINTF(D_FILE, "Can't open `%s' (%d)\n", _PATH_KLOG, errno); 539 } else { 540 DPRINTF(D_FILE, "Listening on kernel log `%s' with fd %d\n", 541 _PATH_KLOG, fklog); 542 } 543 544 #if (!defined(DISABLE_TLS) && !defined(DISABLE_SIGN)) 545 /* basic OpenSSL init */ 546 SSL_load_error_strings(); 547 (void) SSL_library_init(); 548 OpenSSL_add_all_digests(); 549 /* OpenSSL PRNG needs /dev/urandom, thus initialize before chroot() */ 550 if (!RAND_status()) { 551 errno = 0; 552 logerror("Unable to initialize OpenSSL PRNG"); 553 } else { 554 DPRINTF(D_TLS, "Initializing PRNG\n"); 555 } 556 #endif /* (!defined(DISABLE_TLS) && !defined(DISABLE_SIGN)) */ 557 #ifndef DISABLE_SIGN 558 /* initialize rsid -- we will use that later to determine 559 * whether sign_global_init() was already called */ 560 GlobalSign.rsid = 0; 561 #endif /* !DISABLE_SIGN */ 562 #if (IETF_NUM_PRIVALUES != (LOG_NFACILITIES<<3)) 563 logerror("Warning: system defines %d priority values, but " 564 "syslog-protocol/syslog-sign specify %d values", 565 LOG_NFACILITIES, IETF_NUM_PRIVALUES>>3); 566 #endif 567 568 #ifdef __NetBSD_Version__ 569 if ((uid != 0) || (gid != 0)) { 570 /* Create the pidfile here so we can chown it to the target 571 * user/group and possibly report any error before daemonizing. 572 * We then call pidfile(3) again to write the actual 573 * daemon pid below. 574 * 575 * Note: this will likely leave the truncated pidfile in 576 * place upon exit, since the effective user is unlikely 577 * to have write permissions to _PATH_VARRUN. */ 578 if (pidfile(NULL)) { 579 logerror("Failed to create pidfile"); 580 die(0, 0, NULL); 581 } 582 j = sizeof(pfpath); 583 if (snprintf(pfpath, j, "%s%s.pid", 584 _PATH_VARRUN, getprogname()) >= j) { 585 logerror("Pidfile path `%s' too long.", pfpath); 586 die(0, 0, NULL); 587 } 588 if (chown(pfpath, uid, gid) < 0) { 589 logerror("Failed to chown pidfile `%s` to `%d:%d`", 590 pfpath, uid, gid); 591 die(0, 0, NULL); 592 } 593 } 594 #endif /* __NetBSD_Version__ */ 595 596 /* 597 * All files are open, we can drop privileges and chroot. 598 */ 599 DPRINTF(D_MISC, "Attempt to chroot to `%s'\n", root); 600 if (chroot(root) == -1) { 601 logerror("Failed to chroot to `%s'", root); 602 die(0, 0, NULL); 603 } 604 DPRINTF(D_MISC, "Attempt to set GID/EGID to `%d'\n", gid); 605 if (setgid(gid) || setegid(gid)) { 606 logerror("Failed to set gid to `%d'", gid); 607 die(0, 0, NULL); 608 } 609 DPRINTF(D_MISC, "Attempt to set UID/EUID to `%d'\n", uid); 610 if (setuid(uid) || seteuid(uid)) { 611 logerror("Failed to set uid to `%d'", uid); 612 die(0, 0, NULL); 613 } 614 /* 615 * We cannot detach from the terminal before we are sure we won't 616 * have a fatal error, because error message would not go to the 617 * terminal and would not be logged because syslogd dies. 618 * All die() calls are behind us, we can call daemon(). 619 */ 620 if (!Debug) { 621 (void)daemon(0, 0); 622 daemonized = 1; 623 /* Tuck my process id away, if I'm not in debug mode. */ 624 #ifdef __NetBSD_Version__ 625 pidfile(NULL); 626 #endif /* __NetBSD_Version__ */ 627 } 628 629 include_pid = include_pid_buf; 630 snprintf(include_pid_buf, sizeof(include_pid_buf), "%d", getpid()); 631 632 /* 633 * Create the global kernel event descriptor. 634 * 635 * NOTE: We MUST do this after daemon(), because the kqueue() 636 * API dictates that kqueue descriptors are not inherited 637 * across forks (lame!). 638 */ 639 (void)event_init(); 640 641 /* 642 * We must read the configuration file for the first time 643 * after the kqueue descriptor is created, because we install 644 * events during this process. 645 */ 646 init(0, 0, NULL); 647 648 /* 649 * Always exit on SIGTERM. Also exit on SIGINT and SIGQUIT 650 * if we're debugging. 651 */ 652 (void)signal(SIGTERM, SIG_IGN); 653 (void)signal(SIGINT, SIG_IGN); 654 (void)signal(SIGQUIT, SIG_IGN); 655 656 ev = allocev(); 657 signal_set(ev, SIGTERM, die, ev); 658 EVENT_ADD(ev); 659 660 if (Debug) { 661 ev = allocev(); 662 signal_set(ev, SIGINT, die, ev); 663 EVENT_ADD(ev); 664 ev = allocev(); 665 signal_set(ev, SIGQUIT, die, ev); 666 EVENT_ADD(ev); 667 } 668 669 ev = allocev(); 670 signal_set(ev, SIGCHLD, reapchild, ev); 671 EVENT_ADD(ev); 672 673 ev = allocev(); 674 schedule_event(&ev, 675 &((struct timeval){TIMERINTVL, 0}), 676 domark, ev); 677 678 (void)signal(SIGPIPE, SIG_IGN); /* We'll catch EPIPE instead. */ 679 680 /* Re-read configuration on SIGHUP. */ 681 (void) signal(SIGHUP, SIG_IGN); 682 ev = allocev(); 683 signal_set(ev, SIGHUP, init, ev); 684 EVENT_ADD(ev); 685 686 #ifndef DISABLE_TLS 687 ev = allocev(); 688 signal_set(ev, SIGUSR1, dispatch_force_tls_reconnect, ev); 689 EVENT_ADD(ev); 690 SLIST_INIT(&tls_opt.fprint_head); 691 SLIST_INIT(&tls_opt.cert_head); 692 #endif /* !DISABLE_TLS */ 693 694 if (fklog >= 0) { 695 ev = allocev(); 696 DPRINTF(D_EVENT, 697 "register klog for fd %d with ev@%p\n", fklog, ev); 698 event_set(ev, fklog, EV_READ | EV_PERSIST, 699 dispatch_read_klog, ev); 700 EVENT_ADD(ev); 701 } 702 for (j = 0, pp = LogPaths; *pp; pp++, j++) { 703 ev = allocev(); 704 event_set(ev, funix[j], EV_READ | EV_PERSIST, 705 dispatch_read_funix, ev); 706 EVENT_ADD(ev); 707 } 708 709 DPRINTF(D_MISC, "Off & running....\n"); 710 711 j = event_dispatch(); 712 /* normal termination via die(), reaching this is an error */ 713 DPRINTF(D_MISC, "event_dispatch() returned %d\n", j); 714 die(0, 0, NULL); 715 /*NOTREACHED*/ 716 return 0; 717 } 718 719 void 720 usage(void) 721 { 722 723 (void)fprintf(stderr, 724 "usage: %s [-dknrSsTUvX] [-B buffer_length] [-b bind_address]\n" 725 "\t[-f config_file] [-g group]\n" 726 "\t[-m mark_interval] [-P file_list] [-p log_socket\n" 727 "\t[-p log_socket2 ...]] [-t chroot_dir] [-u user]\n", 728 getprogname()); 729 exit(1); 730 } 731 732 static void 733 setsockbuf(int fd, const char *name) 734 { 735 int curbuflen; 736 socklen_t socklen = sizeof(buflen); 737 738 if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &curbuflen, &socklen) == -1) { 739 logerror("getsockopt: SO_RCVBUF: `%s'", name); 740 return; 741 } 742 if (curbuflen >= buflen) 743 return; 744 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buflen, socklen) == -1) { 745 logerror("setsockopt: SO_RCVBUF: `%s'", name); 746 return; 747 } 748 } 749 750 /* 751 * Dispatch routine for reading /dev/klog 752 * 753 * Note: slightly different semantic in dispatch_read functions: 754 * - read_klog() might give multiple messages in linebuf and 755 * leaves the task of splitting them to printsys() 756 * - all other read functions receive one message and 757 * then call printline() with one buffer. 758 */ 759 static void 760 dispatch_read_klog(int fd, short event, void *ev) 761 { 762 ssize_t rv; 763 size_t resid = linebufsize - klog_linebufoff; 764 765 DPRINTF((D_CALL|D_EVENT), "Kernel log active (%d, %d, %p)" 766 " with linebuf@%p, length %zu)\n", fd, event, ev, 767 klog_linebuf, linebufsize); 768 769 rv = read(fd, &klog_linebuf[klog_linebufoff], resid - 1); 770 if (rv > 0) { 771 klog_linebuf[klog_linebufoff + rv] = '\0'; 772 printsys(klog_linebuf); 773 } else if (rv < 0 && 774 errno != EINTR && 775 (errno != ENOBUFS || LogOverflow)) 776 { 777 /* 778 * /dev/klog has croaked. Disable the event 779 * so it won't bother us again. 780 */ 781 logerror("klog failed"); 782 event_del(ev); 783 } 784 } 785 786 /* 787 * Dispatch routine for reading Unix domain sockets. 788 */ 789 static void 790 dispatch_read_funix(int fd, short event, void *ev) 791 { 792 struct sockaddr_un myname, fromunix; 793 ssize_t rv; 794 socklen_t sunlen; 795 796 sunlen = sizeof(myname); 797 if (getsockname(fd, (struct sockaddr *)&myname, &sunlen) != 0) { 798 /* 799 * This should never happen, so ensure that it doesn't 800 * happen again. 801 */ 802 logerror("getsockname() unix failed"); 803 event_del(ev); 804 return; 805 } 806 807 #define SUN_PATHLEN(su) \ 808 ((su)->sun_len - (sizeof(*(su)) - sizeof((su)->sun_path))) 809 810 DPRINTF((D_CALL|D_EVENT|D_NET), "Unix socket (%.*s) active (%d, %d %p)" 811 " with linebuf@%p, size %zu)\n", (int)SUN_PATHLEN(&myname), 812 myname.sun_path, fd, event, ev, linebuf, linebufsize-1); 813 814 sunlen = sizeof(fromunix); 815 rv = recvfrom(fd, linebuf, linebufsize-1, 0, 816 (struct sockaddr *)&fromunix, &sunlen); 817 if (rv > 0) { 818 linebuf[rv] = '\0'; 819 printline(LocalFQDN, linebuf, 0); 820 } else if (rv < 0 && 821 errno != EINTR && 822 (errno != ENOBUFS || LogOverflow)) 823 { 824 logerror("recvfrom() unix `%.*s'", 825 (int)SUN_PATHLEN(&myname), myname.sun_path); 826 } 827 } 828 829 /* 830 * Dispatch routine for reading Internet sockets. 831 */ 832 static void 833 dispatch_read_finet(int fd, short event, void *ev) 834 { 835 #ifdef LIBWRAP 836 struct request_info req; 837 #endif 838 struct sockaddr_storage frominet; 839 ssize_t rv; 840 socklen_t len; 841 int reject = 0; 842 843 DPRINTF((D_CALL|D_EVENT|D_NET), "inet socket active (%d, %d %p) " 844 " with linebuf@%p, size %zu)\n", 845 fd, event, ev, linebuf, linebufsize-1); 846 847 #ifdef LIBWRAP 848 request_init(&req, RQ_DAEMON, appname, RQ_FILE, fd, NULL); 849 fromhost(&req); 850 reject = !hosts_access(&req); 851 if (reject) 852 DPRINTF(D_NET, "access denied\n"); 853 #endif 854 855 len = sizeof(frominet); 856 rv = recvfrom(fd, linebuf, linebufsize-1, 0, 857 (struct sockaddr *)&frominet, &len); 858 if (rv == 0 || 859 (rv < 0 && (errno == EINTR || 860 (errno == ENOBUFS && LogOverflow == 0)))) 861 return; 862 else if (rv < 0) { 863 logerror("recvfrom inet"); 864 return; 865 } 866 867 linebuf[rv] = '\0'; 868 if (!reject) 869 printline(cvthname(&frominet), linebuf, 870 RemoteAddDate ? ADDDATE : 0); 871 } 872 873 /* 874 * given a pointer to an array of char *'s, a pointer to its current 875 * size and current allocated max size, and a new char * to add, add 876 * it, update everything as necessary, possibly allocating a new array 877 */ 878 void 879 logpath_add(char ***lp, int *szp, int *maxszp, const char *new) 880 { 881 char **nlp; 882 int newmaxsz; 883 884 DPRINTF(D_FILE, "Adding `%s' to the %p logpath list\n", new, *lp); 885 if (*szp == *maxszp) { 886 if (*maxszp == 0) { 887 newmaxsz = 4; /* start of with enough for now */ 888 *lp = NULL; 889 } else 890 newmaxsz = *maxszp * 2; 891 nlp = realloc(*lp, sizeof(char *) * (newmaxsz + 1)); 892 if (nlp == NULL) { 893 logerror("Couldn't allocate line buffer"); 894 die(0, 0, NULL); 895 } 896 *lp = nlp; 897 *maxszp = newmaxsz; 898 } 899 if (((*lp)[(*szp)++] = strdup(new)) == NULL) { 900 logerror("Couldn't allocate logpath"); 901 die(0, 0, NULL); 902 } 903 (*lp)[(*szp)] = NULL; /* always keep it NULL terminated */ 904 } 905 906 /* do a file of log sockets */ 907 void 908 logpath_fileadd(char ***lp, int *szp, int *maxszp, const char *file) 909 { 910 FILE *fp; 911 char *line; 912 size_t len; 913 914 fp = fopen(file, "r"); 915 if (fp == NULL) { 916 logerror("Could not open socket file list `%s'", file); 917 die(0, 0, NULL); 918 } 919 920 while ((line = fgetln(fp, &len)) != NULL) { 921 line[len - 1] = 0; 922 logpath_add(lp, szp, maxszp, line); 923 } 924 fclose(fp); 925 } 926 927 /* 928 * checks UTF-8 codepoint 929 * returns either its length in bytes or 0 if *input is invalid 930 */ 931 unsigned 932 valid_utf8(const char *c) { 933 unsigned rc, nb; 934 935 /* first byte gives sequence length */ 936 if ((*c & 0x80) == 0x00) return 1; /* 0bbbbbbb -- ASCII */ 937 else if ((*c & 0xc0) == 0x80) return 0; /* 10bbbbbb -- trailing byte */ 938 else if ((*c & 0xe0) == 0xc0) nb = 2; /* 110bbbbb */ 939 else if ((*c & 0xf0) == 0xe0) nb = 3; /* 1110bbbb */ 940 else if ((*c & 0xf8) == 0xf0) nb = 4; /* 11110bbb */ 941 else return 0; /* UTF-8 allows only up to 4 bytes */ 942 943 /* catch overlong encodings */ 944 if ((*c & 0xfe) == 0xc0) 945 return 0; /* 1100000b ... */ 946 else if (((*c & 0xff) == 0xe0) && ((*(c+1) & 0xe0) == 0x80)) 947 return 0; /* 11100000 100bbbbb ... */ 948 else if (((*c & 0xff) == 0xf0) && ((*(c+1) & 0xf0) == 0x80)) 949 return 0; /* 11110000 1000bbbb ... ... */ 950 951 /* and also filter UTF-16 surrogates (=invalid in UTF-8) */ 952 if (((*c & 0xff) == 0xed) && ((*(c+1) & 0xe0) == 0xa0)) 953 return 0; /* 11101101 101bbbbb ... */ 954 955 rc = nb; 956 /* check trailing bytes */ 957 switch (nb) { 958 default: return 0; 959 case 4: if ((*(c+3) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/ 960 case 3: if ((*(c+2) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/ 961 case 2: if ((*(c+1) & 0xc0) != 0x80) return 0; /*FALLTHROUGH*/ 962 } 963 return rc; 964 } 965 #define UTF8CHARMAX 4 966 967 /* 968 * read UTF-8 value 969 * returns a the codepoint number 970 */ 971 uint_fast32_t 972 get_utf8_value(const char *c) { 973 uint_fast32_t sum; 974 unsigned nb, i; 975 976 /* first byte gives sequence length */ 977 if ((*c & 0x80) == 0x00) return *c;/* 0bbbbbbb -- ASCII */ 978 else if ((*c & 0xc0) == 0x80) return 0; /* 10bbbbbb -- trailing byte */ 979 else if ((*c & 0xe0) == 0xc0) { /* 110bbbbb */ 980 nb = 2; 981 sum = (*c & ~0xe0) & 0xff; 982 } else if ((*c & 0xf0) == 0xe0) { /* 1110bbbb */ 983 nb = 3; 984 sum = (*c & ~0xf0) & 0xff; 985 } else if ((*c & 0xf8) == 0xf0) { /* 11110bbb */ 986 nb = 4; 987 sum = (*c & ~0xf8) & 0xff; 988 } else return 0; /* UTF-8 allows only up to 4 bytes */ 989 990 /* check trailing bytes -- 10bbbbbb */ 991 i = 1; 992 while (i < nb) { 993 sum <<= 6; 994 sum |= ((*(c+i) & ~0xc0) & 0xff); 995 i++; 996 } 997 return sum; 998 } 999 1000 /* note previous versions transscribe 1001 * control characters, e.g. \007 --> "^G" 1002 * did anyone rely on that? 1003 * 1004 * this new version works on only one buffer and 1005 * replaces control characters with a space 1006 */ 1007 #define NEXTFIELD(ptr) if (*(p) == ' ') (p)++; /* SP */ \ 1008 else { \ 1009 DPRINTF(D_DATA, "format error\n"); \ 1010 if (*(p) == '\0') start = (p); \ 1011 goto all_syslog_msg; \ 1012 } 1013 #define FORCE2ASCII(c) ((iscntrl((unsigned char)(c)) && (c) != '\t') \ 1014 ? ((c) == '\n' ? ' ' : '?') \ 1015 : (c) & 0177) 1016 1017 /* following syslog-protocol */ 1018 #define printusascii(ch) (ch >= 33 && ch <= 126) 1019 #define sdname(ch) (ch != '=' && ch != ' ' \ 1020 && ch != ']' && ch != '"' \ 1021 && printusascii(ch)) 1022 1023 /* checks whether the first word of string p can be interpreted as 1024 * a syslog-protocol MSGID and if so returns its length. 1025 * 1026 * otherwise returns 0 1027 */ 1028 static unsigned 1029 check_msgid(char *p) 1030 { 1031 char *q = p; 1032 1033 /* consider the NILVALUE to be valid */ 1034 if (*q == '-' && *(q+1) == ' ') 1035 return 1; 1036 1037 for (;;) { 1038 if (*q == ' ') 1039 return q - p; 1040 else if (*q == '\0' || !printusascii(*q) || q - p >= MSGID_MAX) 1041 return 0; 1042 else 1043 q++; 1044 } 1045 } 1046 1047 /* 1048 * returns number of chars found in SD at beginning of string p 1049 * thus returns 0 if no valid SD is found 1050 * 1051 * if ascii == true then substitute all non-ASCII chars 1052 * otherwise use syslog-protocol rules to allow UTF-8 in values 1053 * note: one pass for filtering and scanning, so a found SD 1054 * is always filtered, but an invalid one could be partially 1055 * filtered up to the format error. 1056 */ 1057 static unsigned 1058 check_sd(char* p) 1059 { 1060 char *q = p; 1061 bool esc = false; 1062 1063 /* consider the NILVALUE to be valid */ 1064 if (*q == '-' && (*(q+1) == ' ' || *(q+1) == '\0')) 1065 return 1; 1066 1067 for (;;) { /* SD-ELEMENT */ 1068 if (*q++ != '[') return 0; 1069 /* SD-ID */ 1070 if (!sdname(*q)) return 0; 1071 while (sdname(*q)) { 1072 *q = FORCE2ASCII(*q); 1073 q++; 1074 } 1075 for (;;) { /* SD-PARAM */ 1076 if (*q == ']') { 1077 q++; 1078 if (*q == ' ' || *q == '\0') return q - p; 1079 else if (*q == '[') break; 1080 } else if (*q++ != ' ') return 0; 1081 1082 /* PARAM-NAME */ 1083 if (!sdname(*q)) return 0; 1084 while (sdname(*q)) { 1085 *q = FORCE2ASCII(*q); 1086 q++; 1087 } 1088 1089 if (*q++ != '=') return 0; 1090 if (*q++ != '"') return 0; 1091 1092 for (;;) { /* PARAM-VALUE */ 1093 if (esc) { 1094 esc = false; 1095 if (*q == '\\' || *q == '"' || 1096 *q == ']') { 1097 q++; 1098 continue; 1099 } 1100 /* no else because invalid 1101 * escape sequences are accepted */ 1102 } 1103 else if (*q == '"') break; 1104 else if (*q == '\0' || *q == ']') return 0; 1105 else if (*q == '\\') esc = true; 1106 else { 1107 int i; 1108 i = valid_utf8(q); 1109 if (i == 0) 1110 *q = '?'; 1111 else if (i == 1) 1112 *q = FORCE2ASCII(*q); 1113 else /* multi byte char */ 1114 q += (i-1); 1115 } 1116 q++; 1117 } 1118 q++; 1119 } 1120 } 1121 } 1122 1123 struct buf_msg * 1124 printline_syslogprotocol(const char *hname, char *msg, 1125 int flags, int pri) 1126 { 1127 struct buf_msg *buffer; 1128 char *p, *start; 1129 unsigned sdlen = 0, i = 0; 1130 bool utf8allowed = false; /* for some fields */ 1131 1132 DPRINTF((D_CALL|D_BUFFER|D_DATA), "printline_syslogprotocol(" 1133 "\"%s\", \"%s\", %d, %d)\n", hname, msg, flags, pri); 1134 1135 buffer = buf_msg_new(0); 1136 p = msg; 1137 p += check_timestamp((unsigned char*) p, 1138 &buffer->timestamp, true, !BSDOutputFormat); 1139 DPRINTF(D_DATA, "Got timestamp \"%s\"\n", buffer->timestamp); 1140 1141 if (flags & ADDDATE) { 1142 FREEPTR(buffer->timestamp); 1143 buffer->timestamp = make_timestamp(NULL, !BSDOutputFormat, 0); 1144 } 1145 1146 start = p; 1147 NEXTFIELD(p); 1148 /* extract host */ 1149 for (start = p;; p++) { 1150 if ((*p == ' ' || *p == '\0') 1151 && start == p-1 && *(p-1) == '-') { 1152 /* NILVALUE */ 1153 break; 1154 } else if ((*p == ' ' || *p == '\0') 1155 && (start != p-1 || *(p-1) != '-')) { 1156 buffer->host = strndup(start, p - start); 1157 break; 1158 } else { 1159 *p = FORCE2ASCII(*p); 1160 } 1161 } 1162 /* p @ SP after host */ 1163 DPRINTF(D_DATA, "Got host \"%s\"\n", buffer->host); 1164 1165 /* extract app-name */ 1166 NEXTFIELD(p); 1167 for (start = p;; p++) { 1168 if ((*p == ' ' || *p == '\0') 1169 && start == p-1 && *(p-1) == '-') { 1170 /* NILVALUE */ 1171 break; 1172 } else if ((*p == ' ' || *p == '\0') 1173 && (start != p-1 || *(p-1) != '-')) { 1174 buffer->prog = strndup(start, p - start); 1175 break; 1176 } else { 1177 *p = FORCE2ASCII(*p); 1178 } 1179 } 1180 DPRINTF(D_DATA, "Got prog \"%s\"\n", buffer->prog); 1181 1182 /* extract procid */ 1183 NEXTFIELD(p); 1184 for (start = p;; p++) { 1185 if ((*p == ' ' || *p == '\0') 1186 && start == p-1 && *(p-1) == '-') { 1187 /* NILVALUE */ 1188 break; 1189 } else if ((*p == ' ' || *p == '\0') 1190 && (start != p-1 || *(p-1) != '-')) { 1191 buffer->pid = strndup(start, p - start); 1192 start = p; 1193 break; 1194 } else { 1195 *p = FORCE2ASCII(*p); 1196 } 1197 } 1198 DPRINTF(D_DATA, "Got pid \"%s\"\n", buffer->pid); 1199 1200 /* extract msgid */ 1201 NEXTFIELD(p); 1202 for (start = p;; p++) { 1203 if ((*p == ' ' || *p == '\0') 1204 && start == p-1 && *(p-1) == '-') { 1205 /* NILVALUE */ 1206 start = p+1; 1207 break; 1208 } else if ((*p == ' ' || *p == '\0') 1209 && (start != p-1 || *(p-1) != '-')) { 1210 buffer->msgid = strndup(start, p - start); 1211 start = p+1; 1212 break; 1213 } else { 1214 *p = FORCE2ASCII(*p); 1215 } 1216 } 1217 DPRINTF(D_DATA, "Got msgid \"%s\"\n", buffer->msgid); 1218 1219 /* extract SD */ 1220 NEXTFIELD(p); 1221 start = p; 1222 sdlen = check_sd(p); 1223 DPRINTF(D_DATA, "check_sd(\"%s\") returned %d\n", p, sdlen); 1224 1225 if (sdlen == 1 && *p == '-') { 1226 /* NILVALUE */ 1227 p++; 1228 } else if (sdlen > 1) { 1229 buffer->sd = strndup(p, sdlen); 1230 p += sdlen; 1231 } else { 1232 DPRINTF(D_DATA, "format error\n"); 1233 } 1234 if (*p == '\0') start = p; 1235 else if (*p == ' ') start = ++p; /* SP */ 1236 DPRINTF(D_DATA, "Got SD \"%s\"\n", buffer->sd); 1237 1238 /* and now the message itself 1239 * note: move back to last start to check for BOM 1240 */ 1241 all_syslog_msg: 1242 p = start; 1243 1244 /* check for UTF-8-BOM */ 1245 if (IS_BOM(p)) { 1246 DPRINTF(D_DATA, "UTF-8 BOM\n"); 1247 utf8allowed = true; 1248 p += 3; 1249 } 1250 1251 if (*p != '\0' && !utf8allowed) { 1252 size_t msglen; 1253 1254 msglen = strlen(p); 1255 assert(!buffer->msg); 1256 buffer->msg = copy_utf8_ascii(p, msglen); 1257 buffer->msgorig = buffer->msg; 1258 buffer->msglen = buffer->msgsize = strlen(buffer->msg)+1; 1259 } else if (*p != '\0' && utf8allowed) { 1260 while (*p != '\0') { 1261 i = valid_utf8(p); 1262 if (i == 0) 1263 *p++ = '?'; 1264 else if (i == 1) 1265 *p = FORCE2ASCII(*p); 1266 p += i; 1267 } 1268 assert(p != start); 1269 assert(!buffer->msg); 1270 buffer->msg = strndup(start, p - start); 1271 buffer->msgorig = buffer->msg; 1272 buffer->msglen = buffer->msgsize = 1 + p - start; 1273 } 1274 DPRINTF(D_DATA, "Got msg \"%s\"\n", buffer->msg); 1275 1276 buffer->recvhost = strdup(hname); 1277 buffer->pri = pri; 1278 buffer->flags = flags; 1279 1280 return buffer; 1281 } 1282 1283 /* copies an input into a new ASCII buffer 1284 * ASCII controls are converted to format "^X" 1285 * multi-byte UTF-8 chars are converted to format "<ab><cd>" 1286 */ 1287 #define INIT_BUFSIZE 512 1288 char * 1289 copy_utf8_ascii(char *p, size_t p_len) 1290 { 1291 size_t idst = 0, isrc = 0, dstsize = INIT_BUFSIZE, i; 1292 char *dst, *tmp_dst; 1293 1294 MALLOC(dst, dstsize); 1295 while (isrc < p_len) { 1296 if (dstsize < idst + 10) { 1297 /* check for enough space for \0 and a UTF-8 1298 * conversion; longest possible is <U+123456> */ 1299 tmp_dst = realloc(dst, dstsize + INIT_BUFSIZE); 1300 if (!tmp_dst) 1301 break; 1302 dst = tmp_dst; 1303 dstsize += INIT_BUFSIZE; 1304 } 1305 1306 i = valid_utf8(&p[isrc]); 1307 if (i == 0) { /* invalid encoding */ 1308 dst[idst++] = '?'; 1309 isrc++; 1310 } else if (i == 1) { /* check printable */ 1311 if (iscntrl((unsigned char)p[isrc]) 1312 && p[isrc] != '\t') { 1313 if (p[isrc] == '\n') { 1314 dst[idst++] = ' '; 1315 isrc++; 1316 } else { 1317 dst[idst++] = '^'; 1318 dst[idst++] = p[isrc++] ^ 0100; 1319 } 1320 } else 1321 dst[idst++] = p[isrc++]; 1322 } else { /* convert UTF-8 to ASCII */ 1323 dst[idst++] = '<'; 1324 idst += snprintf(&dst[idst], dstsize - idst, "U+%x", 1325 get_utf8_value(&p[isrc])); 1326 isrc += i; 1327 dst[idst++] = '>'; 1328 } 1329 } 1330 dst[idst] = '\0'; 1331 1332 /* shrink buffer to right size */ 1333 tmp_dst = realloc(dst, idst+1); 1334 if (tmp_dst) 1335 return tmp_dst; 1336 else 1337 return dst; 1338 } 1339 1340 struct buf_msg * 1341 printline_bsdsyslog(const char *hname, char *msg, 1342 int flags, int pri) 1343 { 1344 struct buf_msg *buffer; 1345 char *p, *start; 1346 unsigned msgidlen = 0, sdlen = 0; 1347 1348 DPRINTF((D_CALL|D_BUFFER|D_DATA), "printline_bsdsyslog(" 1349 "\"%s\", \"%s\", %d, %d)\n", hname, msg, flags, pri); 1350 1351 buffer = buf_msg_new(0); 1352 p = msg; 1353 p += check_timestamp((unsigned char*) p, 1354 &buffer->timestamp, false, !BSDOutputFormat); 1355 DPRINTF(D_DATA, "Got timestamp \"%s\"\n", buffer->timestamp); 1356 1357 if (flags & ADDDATE || !buffer->timestamp) { 1358 FREEPTR(buffer->timestamp); 1359 buffer->timestamp = make_timestamp(NULL, !BSDOutputFormat, 0); 1360 } 1361 1362 if (*p == ' ') p++; /* SP */ 1363 else goto all_bsd_msg; 1364 /* in any error case we skip header parsing and 1365 * treat all following data as message content */ 1366 1367 /* extract host */ 1368 for (start = p;; p++) { 1369 if (*p == ' ' || *p == '\0') { 1370 buffer->host = strndup(start, p - start); 1371 break; 1372 } else if (*p == '[' || (*p == ':' 1373 && (*(p+1) == ' ' || *(p+1) == '\0'))) { 1374 /* no host in message */ 1375 buffer->host = strdup(hname); 1376 buffer->prog = strndup(start, p - start); 1377 break; 1378 } else { 1379 *p = FORCE2ASCII(*p); 1380 } 1381 } 1382 DPRINTF(D_DATA, "Got host \"%s\"\n", buffer->host); 1383 /* p @ SP after host, or @ :/[ after prog */ 1384 1385 /* extract program */ 1386 if (!buffer->prog) { 1387 if (*p == ' ') p++; /* SP */ 1388 else goto all_bsd_msg; 1389 1390 for (start = p;; p++) { 1391 if (*p == ' ' || *p == '\0') { /* error */ 1392 goto all_bsd_msg; 1393 } else if (*p == '[' || (*p == ':' 1394 && (*(p+1) == ' ' || *(p+1) == '\0'))) { 1395 buffer->prog = strndup(start, p - start); 1396 break; 1397 } else { 1398 *p = FORCE2ASCII(*p); 1399 } 1400 } 1401 } 1402 DPRINTF(D_DATA, "Got prog \"%s\"\n", buffer->prog); 1403 start = p; 1404 1405 /* p @ :/[ after prog */ 1406 if (*p == '[') { 1407 p++; 1408 if (*p == ' ') p++; /* SP */ 1409 for (start = p;; p++) { 1410 if (*p == ' ' || *p == '\0') { /* error */ 1411 goto all_bsd_msg; 1412 } else if (*p == ']') { 1413 buffer->pid = strndup(start, p - start); 1414 break; 1415 } else { 1416 *p = FORCE2ASCII(*p); 1417 } 1418 } 1419 } 1420 DPRINTF(D_DATA, "Got pid \"%s\"\n", buffer->pid); 1421 1422 if (*p == ']') p++; 1423 if (*p == ':') p++; 1424 if (*p == ' ') p++; 1425 1426 /* p @ msgid, @ opening [ of SD or @ first byte of message 1427 * accept either case and try to detect MSGID and SD fields 1428 * 1429 * only limitation: we do not accept UTF-8 data in 1430 * BSD Syslog messages -- so all SD values are ASCII-filtered 1431 * 1432 * I have found one scenario with 'unexpected' behaviour: 1433 * if there is only a SD intended, but a) it is short enough 1434 * to be a MSGID and b) the first word of the message can also 1435 * be parsed as an SD. 1436 * example: 1437 * "<35>Jul 6 12:39:08 tag[123]: [exampleSDID@0] - hello" 1438 * --> parsed as 1439 * MSGID = "[exampleSDID@0]" 1440 * SD = "-" 1441 * MSG = "hello" 1442 */ 1443 start = p; 1444 msgidlen = check_msgid(p); 1445 if (msgidlen) /* check for SD in 2nd field */ 1446 sdlen = check_sd(p+msgidlen+1); 1447 1448 if (msgidlen && sdlen) { 1449 /* MSGID in 1st and SD in 2nd field 1450 * now check for NILVALUEs and copy */ 1451 if (msgidlen == 1 && *p == '-') { 1452 p++; /* - */ 1453 p++; /* SP */ 1454 DPRINTF(D_DATA, "Got MSGID \"-\"\n"); 1455 } else { 1456 /* only has ASCII chars after check_msgid() */ 1457 buffer->msgid = strndup(p, msgidlen); 1458 p += msgidlen; 1459 p++; /* SP */ 1460 DPRINTF(D_DATA, "Got MSGID \"%s\"\n", 1461 buffer->msgid); 1462 } 1463 } else { 1464 /* either no msgid or no SD in 2nd field 1465 * --> check 1st field for SD */ 1466 DPRINTF(D_DATA, "No MSGID\n"); 1467 sdlen = check_sd(p); 1468 } 1469 1470 if (sdlen == 0) { 1471 DPRINTF(D_DATA, "No SD\n"); 1472 } else if (sdlen > 1) { 1473 buffer->sd = copy_utf8_ascii(p, sdlen); 1474 DPRINTF(D_DATA, "Got SD \"%s\"\n", buffer->sd); 1475 } else if (sdlen == 1 && *p == '-') { 1476 p++; 1477 DPRINTF(D_DATA, "Got SD \"-\"\n"); 1478 } else { 1479 DPRINTF(D_DATA, "Error\n"); 1480 } 1481 1482 if (*p == ' ') p++; 1483 start = p; 1484 /* and now the message itself 1485 * note: do not reset start, because we might come here 1486 * by goto and want to have the incomplete field as part 1487 * of the msg 1488 */ 1489 all_bsd_msg: 1490 if (*p != '\0') { 1491 size_t msglen = strlen(p); 1492 buffer->msg = copy_utf8_ascii(p, msglen); 1493 buffer->msgorig = buffer->msg; 1494 buffer->msglen = buffer->msgsize = strlen(buffer->msg)+1; 1495 } 1496 DPRINTF(D_DATA, "Got msg \"%s\"\n", buffer->msg); 1497 1498 buffer->recvhost = strdup(hname); 1499 buffer->pri = pri; 1500 buffer->flags = flags | BSDSYSLOG; 1501 1502 return buffer; 1503 } 1504 1505 struct buf_msg * 1506 printline_kernelprintf(const char *hname, char *msg, 1507 int flags, int pri) 1508 { 1509 struct buf_msg *buffer; 1510 char *p; 1511 unsigned sdlen = 0; 1512 1513 DPRINTF((D_CALL|D_BUFFER|D_DATA), "printline_kernelprintf(" 1514 "\"%s\", \"%s\", %d, %d)\n", hname, msg, flags, pri); 1515 1516 buffer = buf_msg_new(0); 1517 buffer->timestamp = make_timestamp(NULL, !BSDOutputFormat, 0); 1518 buffer->pri = pri; 1519 buffer->flags = flags; 1520 1521 /* assume there is no MSGID but there might be SD */ 1522 p = msg; 1523 sdlen = check_sd(p); 1524 1525 if (sdlen == 0) { 1526 DPRINTF(D_DATA, "No SD\n"); 1527 } else if (sdlen > 1) { 1528 buffer->sd = copy_utf8_ascii(p, sdlen); 1529 DPRINTF(D_DATA, "Got SD \"%s\"\n", buffer->sd); 1530 } else if (sdlen == 1 && *p == '-') { 1531 p++; 1532 DPRINTF(D_DATA, "Got SD \"-\"\n"); 1533 } else { 1534 DPRINTF(D_DATA, "Error\n"); 1535 } 1536 1537 if (*p == ' ') p++; 1538 if (*p != '\0') { 1539 size_t msglen = strlen(p); 1540 buffer->msg = copy_utf8_ascii(p, msglen); 1541 buffer->msgorig = buffer->msg; 1542 buffer->msglen = buffer->msgsize = strlen(buffer->msg)+1; 1543 } 1544 DPRINTF(D_DATA, "Got msg \"%s\"\n", buffer->msg); 1545 1546 return buffer; 1547 } 1548 1549 /* 1550 * Take a raw input line, read priority and version, call the 1551 * right message parsing function, then call logmsg(). 1552 */ 1553 void 1554 printline(const char *hname, char *msg, int flags) 1555 { 1556 struct buf_msg *buffer; 1557 int pri; 1558 char *p, *q; 1559 long n; 1560 bool bsdsyslog = true; 1561 1562 DPRINTF((D_CALL|D_BUFFER|D_DATA), 1563 "printline(\"%s\", \"%s\", %d)\n", hname, msg, flags); 1564 1565 /* test for special codes */ 1566 pri = DEFUPRI; 1567 p = msg; 1568 if (*p == '<') { 1569 errno = 0; 1570 n = strtol(p + 1, &q, 10); 1571 if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) { 1572 p = q + 1; 1573 pri = (int)n; 1574 /* check for syslog-protocol version */ 1575 if (*p == '1' && p[1] == ' ') { 1576 p += 2; /* skip version and space */ 1577 bsdsyslog = false; 1578 } else { 1579 bsdsyslog = true; 1580 } 1581 } 1582 } 1583 if (pri & ~(LOG_FACMASK|LOG_PRIMASK)) 1584 pri = DEFUPRI; 1585 1586 /* 1587 * Don't (usually) allow users to log kernel messages. 1588 * NOTE: Since LOG_KERN == 0, this will also match 1589 * messages with no facility specified. 1590 */ 1591 if ((pri & LOG_FACMASK) == LOG_KERN && KernXlat) 1592 pri = LOG_USER | LOG_PRI(pri); 1593 1594 if (bsdsyslog) { 1595 buffer = printline_bsdsyslog(hname, p, flags, pri); 1596 } else { 1597 buffer = printline_syslogprotocol(hname, p, flags, pri); 1598 } 1599 logmsg(buffer); 1600 DELREF(buffer); 1601 } 1602 1603 /* 1604 * Take a raw input line from /dev/klog, split and format similar to syslog(). 1605 */ 1606 void 1607 printsys(char *msg) 1608 { 1609 int n, is_printf, pri, flags; 1610 char *p, *q; 1611 struct buf_msg *buffer; 1612 1613 klog_linebufoff = 0; 1614 for (p = msg; *p != '\0'; ) { 1615 bool bsdsyslog = true; 1616 char *line_start = p; 1617 1618 is_printf = 1; 1619 flags = ISKERNEL | ADDDATE | BSDSYSLOG; 1620 if (SyncKernel) 1621 flags |= SYNC_FILE; 1622 if (is_printf) /* kernel printf's come out on console */ 1623 flags |= IGN_CONS; 1624 pri = DEFSPRI; 1625 1626 if (*p == '<') { 1627 errno = 0; 1628 n = (int)strtol(p + 1, &q, 10); 1629 if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) { 1630 p = q + 1; 1631 is_printf = 0; 1632 pri = n; 1633 if (*p == '1') { /* syslog-protocol version */ 1634 p += 2; /* skip version and space */ 1635 bsdsyslog = false; 1636 } else { 1637 bsdsyslog = true; 1638 } 1639 } 1640 } 1641 for (q = p; *q != '\0' && *q != '\n'; q++) 1642 /* look for end of line; no further checks. 1643 * trust the kernel to send ASCII only */; 1644 if (*q != '\0') 1645 *q++ = '\0'; 1646 else { 1647 memcpy(klog_linebuf, line_start, klog_linebufoff = q - line_start); 1648 break; 1649 } 1650 1651 if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) 1652 pri = DEFSPRI; 1653 1654 /* allow all kinds of input from kernel */ 1655 if (is_printf) 1656 buffer = printline_kernelprintf( 1657 LocalFQDN, p, flags, pri); 1658 else { 1659 if (bsdsyslog) 1660 buffer = printline_bsdsyslog( 1661 LocalFQDN, p, flags, pri); 1662 else 1663 buffer = printline_syslogprotocol( 1664 LocalFQDN, p, flags, pri); 1665 } 1666 1667 /* set fields left open */ 1668 if (!buffer->prog) 1669 buffer->prog = strdup(_PATH_UNIX); 1670 if (!buffer->host) 1671 buffer->host = LocalFQDN; 1672 if (!buffer->recvhost) 1673 buffer->recvhost = LocalFQDN; 1674 1675 logmsg(buffer); 1676 DELREF(buffer); 1677 p = q; 1678 } 1679 } 1680 1681 /* 1682 * Check to see if `name' matches the provided specification, using the 1683 * specified strstr function. 1684 */ 1685 int 1686 matches_spec(const char *name, const char *spec, 1687 char *(*check)(const char *, const char *)) 1688 { 1689 const char *s; 1690 const char *cursor; 1691 char prev, next; 1692 size_t len; 1693 1694 if (name[0] == '\0') 1695 return 0; 1696 1697 if (strchr(name, ',')) /* sanity */ 1698 return 0; 1699 1700 len = strlen(name); 1701 cursor = spec; 1702 while ((s = (*check)(cursor, name)) != NULL) { 1703 prev = s == spec ? ',' : *(s - 1); 1704 cursor = s + len; 1705 next = *cursor; 1706 1707 if (prev == ',' && (next == '\0' || next == ',')) 1708 return 1; 1709 } 1710 1711 return 0; 1712 } 1713 1714 /* 1715 * wrapper with old function signature, 1716 * keeps calling code shorter and hides buffer allocation 1717 */ 1718 void 1719 logmsg_async(int pri, const char *sd, const char *msg, int flags) 1720 { 1721 struct buf_msg *buffer; 1722 size_t msglen; 1723 1724 DPRINTF((D_CALL|D_DATA), "logmsg_async(%d, \"%s\", \"%s\", %d)\n", 1725 pri, sd, msg, flags); 1726 1727 if (msg) { 1728 msglen = strlen(msg); 1729 msglen++; /* adds \0 */ 1730 buffer = buf_msg_new(msglen); 1731 buffer->msglen = strlcpy(buffer->msg, msg, msglen) + 1; 1732 } else { 1733 buffer = buf_msg_new(0); 1734 } 1735 if (sd) buffer->sd = strdup(sd); 1736 buffer->timestamp = make_timestamp(NULL, !BSDOutputFormat, 0); 1737 buffer->prog = appname; 1738 buffer->pid = include_pid; 1739 buffer->recvhost = buffer->host = LocalFQDN; 1740 buffer->pri = pri; 1741 buffer->flags = flags; 1742 1743 logmsg(buffer); 1744 DELREF(buffer); 1745 } 1746 1747 /* read timestamp in from_buf, convert into a timestamp in to_buf 1748 * 1749 * returns length of timestamp found in from_buf (= number of bytes consumed) 1750 */ 1751 size_t 1752 check_timestamp(unsigned char *from_buf, char **to_buf, 1753 bool from_iso, bool to_iso) 1754 { 1755 unsigned char *q; 1756 int p; 1757 bool found_ts = false; 1758 1759 DPRINTF((D_CALL|D_DATA), "check_timestamp(%p = \"%s\", from_iso=%d, " 1760 "to_iso=%d)\n", from_buf, from_buf, from_iso, to_iso); 1761 1762 if (!from_buf) return 0; 1763 /* 1764 * Check to see if msg looks non-standard. 1765 * looks at every char because we do not have a msg length yet 1766 */ 1767 /* detailed checking adapted from Albert Mietus' sl_timestamp.c */ 1768 if (from_iso) { 1769 if (from_buf[4] == '-' && from_buf[7] == '-' 1770 && from_buf[10] == 'T' && from_buf[13] == ':' 1771 && from_buf[16] == ':' 1772 && isdigit(from_buf[0]) && isdigit(from_buf[1]) 1773 && isdigit(from_buf[2]) && isdigit(from_buf[3]) /* YYYY */ 1774 && isdigit(from_buf[5]) && isdigit(from_buf[6]) 1775 && isdigit(from_buf[8]) && isdigit(from_buf[9]) /* mm dd */ 1776 && isdigit(from_buf[11]) && isdigit(from_buf[12]) /* HH */ 1777 && isdigit(from_buf[14]) && isdigit(from_buf[15]) /* MM */ 1778 && isdigit(from_buf[17]) && isdigit(from_buf[18]) /* SS */ 1779 ) { 1780 /* time-secfrac */ 1781 if (from_buf[19] == '.') 1782 for (p=20; isdigit(from_buf[p]); p++) /* NOP*/; 1783 else 1784 p = 19; 1785 /* time-offset */ 1786 if (from_buf[p] == 'Z' 1787 || ((from_buf[p] == '+' || from_buf[p] == '-') 1788 && from_buf[p+3] == ':' 1789 && isdigit(from_buf[p+1]) && isdigit(from_buf[p+2]) 1790 && isdigit(from_buf[p+4]) && isdigit(from_buf[p+5]) 1791 )) 1792 found_ts = true; 1793 } 1794 } else { 1795 if (from_buf[3] == ' ' && from_buf[6] == ' ' 1796 && from_buf[9] == ':' && from_buf[12] == ':' 1797 && (from_buf[4] == ' ' || isdigit(from_buf[4])) 1798 && isdigit(from_buf[5]) /* dd */ 1799 && isdigit(from_buf[7]) && isdigit(from_buf[8]) /* HH */ 1800 && isdigit(from_buf[10]) && isdigit(from_buf[11]) /* MM */ 1801 && isdigit(from_buf[13]) && isdigit(from_buf[14]) /* SS */ 1802 && isupper(from_buf[0]) && islower(from_buf[1]) /* month */ 1803 && islower(from_buf[2])) 1804 found_ts = true; 1805 } 1806 if (!found_ts) { 1807 if (from_buf[0] == '-' && from_buf[1] == ' ') { 1808 /* NILVALUE */ 1809 if (to_iso) { 1810 /* with ISO = syslog-protocol output leave 1811 * it as is, because it is better to have 1812 * no timestamp than a wrong one. 1813 */ 1814 *to_buf = strdup("-"); 1815 } else { 1816 /* with BSD Syslog the field is required 1817 * so replace it with current time 1818 */ 1819 *to_buf = make_timestamp(NULL, false, 0); 1820 } 1821 return 2; 1822 } 1823 *to_buf = make_timestamp(NULL, false, 0); 1824 return 0; 1825 } 1826 1827 if (!from_iso && !to_iso) { 1828 /* copy BSD timestamp */ 1829 DPRINTF(D_CALL, "check_timestamp(): copy BSD timestamp\n"); 1830 *to_buf = strndup((char *)from_buf, BSD_TIMESTAMPLEN); 1831 return BSD_TIMESTAMPLEN; 1832 } else if (from_iso && to_iso) { 1833 /* copy ISO timestamp */ 1834 DPRINTF(D_CALL, "check_timestamp(): copy ISO timestamp\n"); 1835 if (!(q = (unsigned char *) strchr((char *)from_buf, ' '))) 1836 q = from_buf + strlen((char *)from_buf); 1837 *to_buf = strndup((char *)from_buf, q - from_buf); 1838 return q - from_buf; 1839 } else if (from_iso && !to_iso) { 1840 /* convert ISO->BSD */ 1841 struct tm parsed; 1842 time_t timeval; 1843 char tsbuf[MAX_TIMESTAMPLEN]; 1844 int i = 0, j; 1845 1846 DPRINTF(D_CALL, "check_timestamp(): convert ISO->BSD\n"); 1847 for (i = 0; i < MAX_TIMESTAMPLEN && from_buf[i] != '\0' 1848 && from_buf[i] != '.' && from_buf[i] != ' '; i++) 1849 tsbuf[i] = from_buf[i]; /* copy date & time */ 1850 j = i; 1851 for (; i < MAX_TIMESTAMPLEN && from_buf[i] != '\0' 1852 && from_buf[i] != '+' && from_buf[i] != '-' 1853 && from_buf[i] != 'Z' && from_buf[i] != ' '; i++) 1854 ; /* skip fraction digits */ 1855 for (; i < MAX_TIMESTAMPLEN && from_buf[i] != '\0' 1856 && from_buf[i] != ':' && from_buf[i] != ' ' ; i++, j++) 1857 tsbuf[j] = from_buf[i]; /* copy TZ */ 1858 if (from_buf[i] == ':') i++; /* skip colon */ 1859 for (; i < MAX_TIMESTAMPLEN && from_buf[i] != '\0' 1860 && from_buf[i] != ' ' ; i++, j++) 1861 tsbuf[j] = from_buf[i]; /* copy TZ */ 1862 1863 (void)memset(&parsed, 0, sizeof(parsed)); 1864 (void)strptime(tsbuf, "%FT%T%z", &parsed); 1865 parsed.tm_isdst = -1; 1866 timeval = mktime(&parsed); 1867 1868 *to_buf = make_timestamp(&timeval, false, BSD_TIMESTAMPLEN); 1869 return i; 1870 } else if (!from_iso && to_iso) { 1871 /* convert BSD->ISO */ 1872 struct tm parsed; 1873 struct tm *current; 1874 time_t timeval; 1875 1876 (void)memset(&parsed, 0, sizeof(parsed)); 1877 parsed.tm_isdst = -1; 1878 DPRINTF(D_CALL, "check_timestamp(): convert BSD->ISO\n"); 1879 strptime((char *)from_buf, "%b %d %T", &parsed); 1880 current = gmtime(&now); 1881 1882 /* use current year and timezone */ 1883 parsed.tm_isdst = current->tm_isdst; 1884 parsed.tm_gmtoff = current->tm_gmtoff; 1885 parsed.tm_year = current->tm_year; 1886 if (current->tm_mon == 0 && parsed.tm_mon == 11) 1887 parsed.tm_year--; 1888 1889 timeval = mktime(&parsed); 1890 *to_buf = make_timestamp(&timeval, true, MAX_TIMESTAMPLEN - 1); 1891 1892 return BSD_TIMESTAMPLEN; 1893 } else { 1894 DPRINTF(D_MISC, 1895 "Executing unreachable code in check_timestamp()\n"); 1896 return 0; 1897 } 1898 } 1899 1900 /* 1901 * Log a message to the appropriate log files, users, etc. based on 1902 * the priority. 1903 */ 1904 void 1905 logmsg(struct buf_msg *buffer) 1906 { 1907 struct filed *f; 1908 int fac, omask, prilev; 1909 1910 DPRINTF((D_CALL|D_BUFFER), "logmsg: buffer@%p, pri 0%o/%d, flags 0x%x," 1911 " timestamp \"%s\", from \"%s\", sd \"%s\", msg \"%s\"\n", 1912 buffer, buffer->pri, buffer->pri, buffer->flags, 1913 buffer->timestamp, buffer->recvhost, buffer->sd, buffer->msg); 1914 1915 omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM)); 1916 1917 /* sanity check */ 1918 assert(buffer->refcount == 1); 1919 assert(buffer->msglen <= buffer->msgsize); 1920 assert(buffer->msgorig <= buffer->msg); 1921 assert((buffer->msg && buffer->msglen == strlen(buffer->msg)+1) 1922 || (!buffer->msg && !buffer->msglen)); 1923 if (!buffer->msg && !buffer->sd && !buffer->msgid) 1924 DPRINTF(D_BUFFER, "Empty message?\n"); 1925 1926 /* extract facility and priority level */ 1927 if (buffer->flags & MARK) 1928 fac = LOG_NFACILITIES; 1929 else 1930 fac = LOG_FAC(buffer->pri); 1931 prilev = LOG_PRI(buffer->pri); 1932 1933 /* log the message to the particular outputs */ 1934 if (!Initialized) { 1935 f = &consfile; 1936 f->f_file = open(ctty, O_WRONLY | O_NDELAY, 0); 1937 1938 if (f->f_file >= 0) { 1939 DELREF(f->f_prevmsg); 1940 f->f_prevmsg = NEWREF(buffer); 1941 fprintlog(f, NEWREF(buffer), NULL); 1942 DELREF(buffer); 1943 (void)close(f->f_file); 1944 } 1945 (void)sigsetmask(omask); 1946 return; 1947 } 1948 1949 for (f = Files; f; f = f->f_next) { 1950 char *h; /* host to use for comparing */ 1951 1952 /* skip messages that are incorrect priority */ 1953 if (!MATCH_PRI(f, fac, prilev) 1954 || f->f_pmask[fac] == INTERNAL_NOPRI) 1955 continue; 1956 1957 /* skip messages with the incorrect host name */ 1958 /* compare with host (which is supposedly more correct), */ 1959 /* but fallback to recvhost if host is NULL */ 1960 h = (buffer->host != NULL) ? buffer->host : buffer->recvhost; 1961 if (f->f_host != NULL && h != NULL) { 1962 char shost[MAXHOSTNAMELEN + 1]; 1963 1964 if (BSDOutputFormat) { 1965 (void)strlcpy(shost, h, sizeof(shost)); 1966 trim_anydomain(shost); 1967 h = shost; 1968 } 1969 switch (f->f_host[0]) { 1970 case '+': 1971 if (! matches_spec(h, f->f_host + 1, 1972 strcasestr)) 1973 continue; 1974 break; 1975 case '-': 1976 if (matches_spec(h, f->f_host + 1, 1977 strcasestr)) 1978 continue; 1979 break; 1980 } 1981 } 1982 1983 /* skip messages with the incorrect program name */ 1984 if (f->f_program != NULL && buffer->prog != NULL) { 1985 switch (f->f_program[0]) { 1986 case '+': 1987 if (!matches_spec(buffer->prog, 1988 f->f_program + 1, strstr)) 1989 continue; 1990 break; 1991 case '-': 1992 if (matches_spec(buffer->prog, 1993 f->f_program + 1, strstr)) 1994 continue; 1995 break; 1996 default: 1997 if (!matches_spec(buffer->prog, 1998 f->f_program, strstr)) 1999 continue; 2000 break; 2001 } 2002 } 2003 2004 if (f->f_type == F_CONSOLE && (buffer->flags & IGN_CONS)) 2005 continue; 2006 2007 /* don't output marks to recently written files */ 2008 if ((buffer->flags & MARK) 2009 && (now - f->f_time) < MarkInterval / 2) 2010 continue; 2011 2012 /* 2013 * suppress duplicate lines to this file unless NoRepeat 2014 */ 2015 #define MSG_FIELD_EQ(x) ((!buffer->x && !f->f_prevmsg->x) || \ 2016 (buffer->x && f->f_prevmsg->x && !strcmp(buffer->x, f->f_prevmsg->x))) 2017 2018 if ((buffer->flags & MARK) == 0 && 2019 f->f_prevmsg && 2020 buffer->msglen == f->f_prevmsg->msglen && 2021 !NoRepeat && 2022 MSG_FIELD_EQ(host) && 2023 MSG_FIELD_EQ(sd) && 2024 MSG_FIELD_EQ(msg) 2025 ) { 2026 f->f_prevcount++; 2027 DPRINTF(D_DATA, 2028 "Msg repeated %d times, %ld sec of %d\n", 2029 f->f_prevcount, (long)(now - f->f_time), 2030 repeatinterval[f->f_repeatcount]); 2031 /* 2032 * If domark would have logged this by now, 2033 * flush it now (so we don't hold isolated messages), 2034 * but back off so we'll flush less often 2035 * in the future. 2036 */ 2037 if (now > REPEATTIME(f)) { 2038 fprintlog(f, NEWREF(buffer), NULL); 2039 DELREF(buffer); 2040 BACKOFF(f); 2041 } 2042 } else { 2043 /* new line, save it */ 2044 if (f->f_prevcount) 2045 fprintlog(f, NULL, NULL); 2046 f->f_repeatcount = 0; 2047 DELREF(f->f_prevmsg); 2048 f->f_prevmsg = NEWREF(buffer); 2049 fprintlog(f, NEWREF(buffer), NULL); 2050 DELREF(buffer); 2051 } 2052 } 2053 (void)sigsetmask(omask); 2054 } 2055 2056 /* 2057 * format one buffer into output format given by flag BSDOutputFormat 2058 * line is allocated and has to be free()d by caller 2059 * size_t pointers are optional, if not NULL then they will return 2060 * different lengths used for formatting and output 2061 */ 2062 #define OUT(x) ((x)?(x):"-") 2063 bool 2064 format_buffer(struct buf_msg *buffer, char **line, size_t *ptr_linelen, 2065 size_t *ptr_msglen, size_t *ptr_tlsprefixlen, size_t *ptr_prilen) 2066 { 2067 #define FPBUFSIZE 30 2068 static char ascii_empty[] = ""; 2069 char fp_buf[FPBUFSIZE] = "\0"; 2070 char *hostname, *shorthostname = NULL; 2071 char *ascii_sd = ascii_empty; 2072 char *ascii_msg = ascii_empty; 2073 size_t linelen, msglen, tlsprefixlen, prilen, j; 2074 2075 DPRINTF(D_CALL, "format_buffer(%p)\n", buffer); 2076 if (!buffer) return false; 2077 2078 /* All buffer fields are set with strdup(). To avoid problems 2079 * on memory exhaustion we allow them to be empty and replace 2080 * the essential fields with already allocated generic values. 2081 */ 2082 if (!buffer->timestamp) 2083 buffer->timestamp = timestamp; 2084 if (!buffer->host && !buffer->recvhost) 2085 buffer->host = LocalFQDN; 2086 2087 if (LogFacPri) { 2088 const char *f_s = NULL, *p_s = NULL; 2089 int fac = buffer->pri & LOG_FACMASK; 2090 int pri = LOG_PRI(buffer->pri); 2091 char f_n[5], p_n[5]; 2092 2093 if (LogFacPri > 1) { 2094 CODE *c; 2095 2096 for (c = facilitynames; c->c_name != NULL; c++) { 2097 if (c->c_val == fac) { 2098 f_s = c->c_name; 2099 break; 2100 } 2101 } 2102 for (c = prioritynames; c->c_name != NULL; c++) { 2103 if (c->c_val == pri) { 2104 p_s = c->c_name; 2105 break; 2106 } 2107 } 2108 } 2109 if (f_s == NULL) { 2110 snprintf(f_n, sizeof(f_n), "%d", LOG_FAC(fac)); 2111 f_s = f_n; 2112 } 2113 if (p_s == NULL) { 2114 snprintf(p_n, sizeof(p_n), "%d", pri); 2115 p_s = p_n; 2116 } 2117 snprintf(fp_buf, sizeof(fp_buf), "<%s.%s>", f_s, p_s); 2118 } 2119 2120 /* hostname or FQDN */ 2121 hostname = (buffer->host ? buffer->host : buffer->recvhost); 2122 if (BSDOutputFormat 2123 && (shorthostname = strdup(hostname))) { 2124 /* if the previous BSD output format with "host [recvhost]:" 2125 * gets implemented, this is the right place to distinguish 2126 * between buffer->host and buffer->recvhost 2127 */ 2128 trim_anydomain(shorthostname); 2129 hostname = shorthostname; 2130 } 2131 2132 /* new message formatting: 2133 * instead of using iov always assemble one complete TLS-ready line 2134 * with length and priority (depending on BSDOutputFormat either in 2135 * BSD Syslog or syslog-protocol format) 2136 * 2137 * additionally save the length of the prefixes, 2138 * so UDP destinations can skip the length prefix and 2139 * file/pipe/wall destinations can omit length and priority 2140 */ 2141 /* first determine required space */ 2142 if (BSDOutputFormat) { 2143 /* only output ASCII chars */ 2144 if (buffer->sd) 2145 ascii_sd = copy_utf8_ascii(buffer->sd, 2146 strlen(buffer->sd)); 2147 if (buffer->msg) { 2148 if (IS_BOM(buffer->msg)) 2149 ascii_msg = copy_utf8_ascii(buffer->msg, 2150 buffer->msglen - 1); 2151 else /* assume already converted at input */ 2152 ascii_msg = buffer->msg; 2153 } 2154 msglen = snprintf(NULL, 0, "<%d>%s%.15s %s %s%s%s%s: %s%s%s", 2155 buffer->pri, fp_buf, buffer->timestamp, 2156 hostname, OUT(buffer->prog), 2157 buffer->pid ? "[" : "", 2158 buffer->pid ? buffer->pid : "", 2159 buffer->pid ? "]" : "", ascii_sd, 2160 (buffer->sd && buffer->msg ? " ": ""), ascii_msg); 2161 } else 2162 msglen = snprintf(NULL, 0, "<%d>1 %s%s %s %s %s %s %s%s%s", 2163 buffer->pri, fp_buf, buffer->timestamp, 2164 hostname, OUT(buffer->prog), OUT(buffer->pid), 2165 OUT(buffer->msgid), OUT(buffer->sd), 2166 (buffer->msg ? " ": ""), 2167 (buffer->msg ? buffer->msg: "")); 2168 /* add space for length prefix */ 2169 tlsprefixlen = 0; 2170 for (j = msglen; j; j /= 10) 2171 tlsprefixlen++; 2172 /* one more for the space */ 2173 tlsprefixlen++; 2174 2175 prilen = snprintf(NULL, 0, "<%d>", buffer->pri); 2176 if (!BSDOutputFormat) 2177 prilen += 2; /* version char and space */ 2178 MALLOC(*line, msglen + tlsprefixlen + 1); 2179 if (BSDOutputFormat) 2180 linelen = snprintf(*line, 2181 msglen + tlsprefixlen + 1, 2182 "%zu <%d>%s%.15s %s %s%s%s%s: %s%s%s", 2183 msglen, buffer->pri, fp_buf, buffer->timestamp, 2184 hostname, OUT(buffer->prog), 2185 (buffer->pid ? "[" : ""), 2186 (buffer->pid ? buffer->pid : ""), 2187 (buffer->pid ? "]" : ""), ascii_sd, 2188 (buffer->sd && buffer->msg ? " ": ""), ascii_msg); 2189 else 2190 linelen = snprintf(*line, 2191 msglen + tlsprefixlen + 1, 2192 "%zu <%d>1 %s%s %s %s %s %s %s%s%s", 2193 msglen, buffer->pri, fp_buf, buffer->timestamp, 2194 hostname, OUT(buffer->prog), OUT(buffer->pid), 2195 OUT(buffer->msgid), OUT(buffer->sd), 2196 (buffer->msg ? " ": ""), 2197 (buffer->msg ? buffer->msg: "")); 2198 DPRINTF(D_DATA, "formatted %zu octets to: '%.*s' (linelen %zu, " 2199 "msglen %zu, tlsprefixlen %zu, prilen %zu)\n", linelen, 2200 (int)linelen, *line, linelen, msglen, tlsprefixlen, prilen); 2201 2202 FREEPTR(shorthostname); 2203 if (ascii_sd != ascii_empty) 2204 FREEPTR(ascii_sd); 2205 if (ascii_msg != ascii_empty && ascii_msg != buffer->msg) 2206 FREEPTR(ascii_msg); 2207 2208 if (ptr_linelen) *ptr_linelen = linelen; 2209 if (ptr_msglen) *ptr_msglen = msglen; 2210 if (ptr_tlsprefixlen) *ptr_tlsprefixlen = tlsprefixlen; 2211 if (ptr_prilen) *ptr_prilen = prilen; 2212 return true; 2213 } 2214 2215 /* 2216 * if qentry == NULL: new message, if temporarily undeliverable it will be enqueued 2217 * if qentry != NULL: a temporarily undeliverable message will not be enqueued, 2218 * but after delivery be removed from the queue 2219 */ 2220 void 2221 fprintlog(struct filed *f, struct buf_msg *passedbuffer, 2222 struct buf_queue *qentry) 2223 { 2224 static char crnl[] = "\r\n"; 2225 struct buf_msg *buffer = passedbuffer; 2226 struct iovec iov[4]; 2227 struct iovec *v = iov; 2228 bool error = false; 2229 int e = 0, len = 0; 2230 size_t msglen, linelen, tlsprefixlen, prilen; 2231 char *p, *line = NULL, *lineptr = NULL; 2232 #ifndef DISABLE_SIGN 2233 bool newhash = false; 2234 #endif 2235 #define REPBUFSIZE 80 2236 char greetings[200]; 2237 #define ADDEV() do { v++; assert((size_t)(v - iov) < A_CNT(iov)); } while(/*CONSTCOND*/0) 2238 2239 DPRINTF(D_CALL, "fprintlog(%p, %p, %p)\n", f, buffer, qentry); 2240 2241 f->f_time = now; 2242 2243 /* increase refcount here and lower again at return. 2244 * this enables the buffer in the else branch to be freed 2245 * --> every branch needs one NEWREF() or buf_msg_new()! */ 2246 if (buffer) { 2247 (void)NEWREF(buffer); 2248 } else { 2249 if (f->f_prevcount > 1) { 2250 /* possible syslog-sign incompatibility: 2251 * assume destinations f1 and f2 share one SG and 2252 * get the same message sequence. 2253 * 2254 * now both f1 and f2 generate "repeated" messages 2255 * "repeated" messages are different due to different 2256 * timestamps 2257 * the SG will get hashes for the two "repeated" messages 2258 * 2259 * now both f1 and f2 are just fine, but a verification 2260 * will report that each 'lost' a message, i.e. the 2261 * other's "repeated" message 2262 * 2263 * conditions for 'safe configurations': 2264 * - use NoRepeat option, 2265 * - use SG 3, or 2266 * - have exactly one destination for every PRI 2267 */ 2268 buffer = buf_msg_new(REPBUFSIZE); 2269 buffer->msglen = snprintf(buffer->msg, REPBUFSIZE, 2270 "last message repeated %d times", f->f_prevcount); 2271 buffer->timestamp = make_timestamp(NULL, 2272 !BSDOutputFormat, 0); 2273 buffer->pri = f->f_prevmsg->pri; 2274 buffer->host = LocalFQDN; 2275 buffer->prog = appname; 2276 buffer->pid = include_pid; 2277 2278 } else { 2279 buffer = NEWREF(f->f_prevmsg); 2280 } 2281 } 2282 2283 /* no syslog-sign messages to tty/console/... */ 2284 if ((buffer->flags & SIGN_MSG) 2285 && ((f->f_type == F_UNUSED) 2286 || (f->f_type == F_TTY) 2287 || (f->f_type == F_CONSOLE) 2288 || (f->f_type == F_USERS) 2289 || (f->f_type == F_WALL) 2290 || (f->f_type == F_FIFO))) { 2291 DELREF(buffer); 2292 return; 2293 } 2294 2295 /* buffering works only for few types */ 2296 if (qentry 2297 && (f->f_type != F_TLS) 2298 && (f->f_type != F_PIPE) 2299 && (f->f_type != F_FILE) 2300 && (f->f_type != F_FIFO)) { 2301 errno = 0; 2302 logerror("Warning: unexpected message type %d in buffer", 2303 f->f_type); 2304 DELREF(buffer); 2305 return; 2306 } 2307 2308 if (!format_buffer(buffer, &line, 2309 &linelen, &msglen, &tlsprefixlen, &prilen)) { 2310 DPRINTF(D_CALL, "format_buffer() failed, skip message\n"); 2311 DELREF(buffer); 2312 return; 2313 } 2314 /* assert maximum message length */ 2315 if (TypeInfo[f->f_type].max_msg_length != -1 2316 && (size_t)TypeInfo[f->f_type].max_msg_length 2317 < linelen - tlsprefixlen - prilen) { 2318 linelen = TypeInfo[f->f_type].max_msg_length 2319 + tlsprefixlen + prilen; 2320 DPRINTF(D_DATA, "truncating oversized message to %zu octets\n", 2321 linelen); 2322 } 2323 2324 #ifndef DISABLE_SIGN 2325 /* keep state between appending the hash (before buffer is sent) 2326 * and possibly sending a SB (after buffer is sent): */ 2327 /* get hash */ 2328 if (!(buffer->flags & SIGN_MSG) && !qentry) { 2329 char *hash = NULL; 2330 struct signature_group_t *sg; 2331 2332 if ((sg = sign_get_sg(buffer->pri, f)) != NULL) { 2333 if (sign_msg_hash(line + tlsprefixlen, &hash)) 2334 newhash = sign_append_hash(hash, sg); 2335 else 2336 DPRINTF(D_SIGN, 2337 "Unable to hash line \"%s\"\n", line); 2338 } 2339 } 2340 #endif /* !DISABLE_SIGN */ 2341 2342 /* set start and length of buffer and/or fill iovec */ 2343 switch (f->f_type) { 2344 case F_UNUSED: 2345 /* nothing */ 2346 break; 2347 case F_TLS: 2348 /* nothing, as TLS uses whole buffer to send */ 2349 lineptr = line; 2350 len = linelen; 2351 break; 2352 case F_FORW: 2353 lineptr = line + tlsprefixlen; 2354 len = linelen - tlsprefixlen; 2355 break; 2356 case F_PIPE: 2357 case F_FIFO: 2358 case F_FILE: /* fallthrough */ 2359 if (f->f_flags & FFLAG_FULL) { 2360 v->iov_base = line + tlsprefixlen; 2361 v->iov_len = linelen - tlsprefixlen; 2362 } else { 2363 v->iov_base = line + tlsprefixlen + prilen; 2364 v->iov_len = linelen - tlsprefixlen - prilen; 2365 } 2366 ADDEV(); 2367 v->iov_base = &crnl[1]; 2368 v->iov_len = 1; 2369 ADDEV(); 2370 break; 2371 case F_CONSOLE: 2372 case F_TTY: 2373 /* filter non-ASCII */ 2374 p = line; 2375 while (*p) { 2376 *p = FORCE2ASCII(*p); 2377 p++; 2378 } 2379 v->iov_base = line + tlsprefixlen + prilen; 2380 v->iov_len = linelen - tlsprefixlen - prilen; 2381 ADDEV(); 2382 v->iov_base = crnl; 2383 v->iov_len = 2; 2384 ADDEV(); 2385 break; 2386 case F_WALL: 2387 v->iov_base = greetings; 2388 v->iov_len = snprintf(greetings, sizeof(greetings), 2389 "\r\n\7Message from syslogd@%s at %s ...\r\n", 2390 (buffer->host ? buffer->host : buffer->recvhost), 2391 buffer->timestamp); 2392 ADDEV(); 2393 /* FALLTHROUGH */ 2394 case F_USERS: /* fallthrough */ 2395 /* filter non-ASCII */ 2396 p = line; 2397 while (*p) { 2398 *p = FORCE2ASCII(*p); 2399 p++; 2400 } 2401 v->iov_base = line + tlsprefixlen + prilen; 2402 v->iov_len = linelen - tlsprefixlen - prilen; 2403 ADDEV(); 2404 v->iov_base = &crnl[1]; 2405 v->iov_len = 1; 2406 ADDEV(); 2407 break; 2408 } 2409 2410 /* send */ 2411 switch (f->f_type) { 2412 case F_UNUSED: 2413 DPRINTF(D_MISC, "Logging to %s\n", TypeInfo[f->f_type].name); 2414 break; 2415 2416 case F_FORW: 2417 DPRINTF(D_MISC, "Logging to %s %s\n", 2418 TypeInfo[f->f_type].name, f->f_un.f_forw.f_hname); 2419 udp_send(f, lineptr, len); 2420 break; 2421 2422 #ifndef DISABLE_TLS 2423 case F_TLS: 2424 DPRINTF(D_MISC, "Logging to %s %s\n", 2425 TypeInfo[f->f_type].name, 2426 f->f_un.f_tls.tls_conn->hostname); 2427 /* make sure every message gets queued once 2428 * it will be removed when sendmsg is sent and free()d */ 2429 if (!qentry) 2430 qentry = message_queue_add(f, NEWREF(buffer)); 2431 (void)tls_send(f, lineptr, len, qentry); 2432 break; 2433 #endif /* !DISABLE_TLS */ 2434 2435 case F_PIPE: 2436 DPRINTF(D_MISC, "Logging to %s %s\n", 2437 TypeInfo[f->f_type].name, f->f_un.f_pipe.f_pname); 2438 if (f->f_un.f_pipe.f_pid == 0) { 2439 /* (re-)open */ 2440 if ((f->f_file = p_open(f->f_un.f_pipe.f_pname, 2441 &f->f_un.f_pipe.f_pid)) < 0) { 2442 f->f_type = F_UNUSED; 2443 logerror("%s", f->f_un.f_pipe.f_pname); 2444 message_queue_freeall(f); 2445 break; 2446 } else if (!qentry) /* prevent recursion */ 2447 SEND_QUEUE(f); 2448 } 2449 if (writev(f->f_file, iov, v - iov) < 0) { 2450 e = errno; 2451 if (f->f_un.f_pipe.f_pid > 0) { 2452 (void) close(f->f_file); 2453 deadq_enter(f->f_un.f_pipe.f_pid, 2454 f->f_un.f_pipe.f_pname); 2455 } 2456 f->f_un.f_pipe.f_pid = 0; 2457 /* 2458 * If the error was EPIPE, then what is likely 2459 * has happened is we have a command that is 2460 * designed to take a single message line and 2461 * then exit, but we tried to feed it another 2462 * one before we reaped the child and thus 2463 * reset our state. 2464 * 2465 * Well, now we've reset our state, so try opening 2466 * the pipe and sending the message again if EPIPE 2467 * was the error. 2468 */ 2469 if (e == EPIPE) { 2470 if ((f->f_file = p_open(f->f_un.f_pipe.f_pname, 2471 &f->f_un.f_pipe.f_pid)) < 0) { 2472 f->f_type = F_UNUSED; 2473 logerror("%s", f->f_un.f_pipe.f_pname); 2474 message_queue_freeall(f); 2475 break; 2476 } 2477 if (writev(f->f_file, iov, v - iov) < 0) { 2478 e = errno; 2479 if (f->f_un.f_pipe.f_pid > 0) { 2480 (void) close(f->f_file); 2481 deadq_enter(f->f_un.f_pipe.f_pid, 2482 f->f_un.f_pipe.f_pname); 2483 } 2484 f->f_un.f_pipe.f_pid = 0; 2485 error = true; /* enqueue on return */ 2486 } else 2487 e = 0; 2488 } 2489 if (e != 0 && !error) { 2490 errno = e; 2491 logerror("%s", f->f_un.f_pipe.f_pname); 2492 } 2493 } 2494 if (e == 0 && qentry) { /* sent buffered msg */ 2495 message_queue_remove(f, qentry); 2496 } 2497 break; 2498 2499 case F_CONSOLE: 2500 if (buffer->flags & IGN_CONS) { 2501 DPRINTF(D_MISC, "Logging to %s (ignored)\n", 2502 TypeInfo[f->f_type].name); 2503 break; 2504 } 2505 /* FALLTHROUGH */ 2506 2507 case F_TTY: 2508 case F_FILE: 2509 DPRINTF(D_MISC, "Logging to %s %s\n", 2510 TypeInfo[f->f_type].name, f->f_un.f_fname); 2511 again: 2512 if ((f->f_type == F_FILE ? writev(f->f_file, iov, v - iov) : 2513 writev1(f->f_file, iov, v - iov)) < 0) { 2514 e = errno; 2515 if (f->f_type == F_FILE && e == ENOSPC) { 2516 int lasterror = f->f_lasterror; 2517 f->f_lasterror = e; 2518 if (lasterror != e) 2519 logerror("%s", f->f_un.f_fname); 2520 error = true; /* enqueue on return */ 2521 } 2522 (void)close(f->f_file); 2523 /* 2524 * Check for errors on TTY's due to loss of tty 2525 */ 2526 if ((e == EIO || e == EBADF) && f->f_type != F_FILE) { 2527 f->f_file = open(f->f_un.f_fname, 2528 O_WRONLY|O_APPEND|O_NONBLOCK, 0); 2529 if (f->f_file < 0) { 2530 f->f_type = F_UNUSED; 2531 logerror("%s", f->f_un.f_fname); 2532 message_queue_freeall(f); 2533 } else 2534 goto again; 2535 } else { 2536 f->f_type = F_UNUSED; 2537 errno = e; 2538 f->f_lasterror = e; 2539 logerror("%s", f->f_un.f_fname); 2540 message_queue_freeall(f); 2541 } 2542 } else { 2543 f->f_lasterror = 0; 2544 if ((buffer->flags & SYNC_FILE) 2545 && (f->f_flags & FFLAG_SYNC)) 2546 (void)fsync(f->f_file); 2547 /* Problem with files: We cannot check beforehand if 2548 * they would be writeable and call send_queue() first. 2549 * So we call send_queue() after a successful write, 2550 * which means the first message will be out of order. 2551 */ 2552 if (!qentry) /* prevent recursion */ 2553 SEND_QUEUE(f); 2554 else if (qentry) /* sent buffered msg */ 2555 message_queue_remove(f, qentry); 2556 } 2557 break; 2558 2559 case F_FIFO: 2560 DPRINTF(D_MISC, "Logging to %s %s\n", 2561 TypeInfo[f->f_type].name, f->f_un.f_fname); 2562 if (f->f_file < 0) { 2563 f->f_file = 2564 open(f->f_un.f_fname, O_WRONLY|O_NONBLOCK, 0); 2565 e = errno; 2566 if (f->f_file < 0 && e == ENXIO) { 2567 /* Drop messages with no reader */ 2568 if (qentry) 2569 message_queue_remove(f, qentry); 2570 break; 2571 } 2572 } 2573 2574 if (f->f_file >= 0 && writev(f->f_file, iov, v - iov) < 0) { 2575 e = errno; 2576 2577 /* Enqueue if the fifo buffer is full */ 2578 if (e == EAGAIN) { 2579 if (f->f_lasterror != e) 2580 logerror("%s", f->f_un.f_fname); 2581 f->f_lasterror = e; 2582 error = true; /* enqueue on return */ 2583 break; 2584 } 2585 2586 close(f->f_file); 2587 f->f_file = -1; 2588 2589 /* Drop messages with no reader */ 2590 if (e == EPIPE) { 2591 if (qentry) 2592 message_queue_remove(f, qentry); 2593 break; 2594 } 2595 } 2596 2597 if (f->f_file < 0) { 2598 f->f_type = F_UNUSED; 2599 errno = e; 2600 f->f_lasterror = e; 2601 logerror("%s", f->f_un.f_fname); 2602 message_queue_freeall(f); 2603 break; 2604 } 2605 2606 f->f_lasterror = 0; 2607 if (!qentry) /* prevent recursion (see comment for F_FILE) */ 2608 SEND_QUEUE(f); 2609 if (qentry) /* sent buffered msg */ 2610 message_queue_remove(f, qentry); 2611 break; 2612 2613 case F_USERS: 2614 case F_WALL: 2615 DPRINTF(D_MISC, "Logging to %s\n", TypeInfo[f->f_type].name); 2616 wallmsg(f, iov, v - iov); 2617 break; 2618 } 2619 f->f_prevcount = 0; 2620 2621 if (error && !qentry) 2622 message_queue_add(f, NEWREF(buffer)); 2623 #ifndef DISABLE_SIGN 2624 if (newhash) { 2625 struct signature_group_t *sg; 2626 sg = sign_get_sg(buffer->pri, f); 2627 (void)sign_send_signature_block(sg, false); 2628 } 2629 #endif /* !DISABLE_SIGN */ 2630 /* this belongs to the ad-hoc buffer at the first if(buffer) */ 2631 DELREF(buffer); 2632 /* TLS frees on its own */ 2633 if (f->f_type != F_TLS) 2634 FREEPTR(line); 2635 } 2636 2637 /* send one line by UDP */ 2638 void 2639 udp_send(struct filed *f, char *line, size_t len) 2640 { 2641 int lsent, fail, retry, j; 2642 struct addrinfo *r; 2643 2644 DPRINTF((D_NET|D_CALL), "udp_send(f=%p, line=\"%s\", " 2645 "len=%zu) to dest.\n", f, line, len); 2646 2647 if (!finet) 2648 return; 2649 2650 lsent = -1; 2651 fail = 0; 2652 assert(f->f_type == F_FORW); 2653 for (r = f->f_un.f_forw.f_addr; r; r = r->ai_next) { 2654 retry = 0; 2655 for (j = 0; j < finet->fd; j++) { 2656 if (finet[j+1].af != r->ai_family) 2657 continue; 2658 sendagain: 2659 lsent = sendto(finet[j+1].fd, line, len, 0, 2660 r->ai_addr, r->ai_addrlen); 2661 if (lsent == -1) { 2662 switch (errno) { 2663 case EBUSY: 2664 case ENOBUFS: 2665 /* wait/retry/drop */ 2666 if (++retry < 5) { 2667 usleep(1000); 2668 goto sendagain; 2669 } 2670 break; 2671 case EHOSTDOWN: 2672 case EHOSTUNREACH: 2673 case ENETDOWN: 2674 /* drop */ 2675 break; 2676 default: 2677 /* busted */ 2678 fail++; 2679 break; 2680 } 2681 } else if ((size_t)lsent == len) 2682 break; 2683 } 2684 if ((size_t)lsent != len && fail) { 2685 f->f_type = F_UNUSED; 2686 logerror("sendto() failed"); 2687 } 2688 } 2689 } 2690 2691 /* 2692 * WALLMSG -- Write a message to the world at large 2693 * 2694 * Write the specified message to either the entire 2695 * world, or a list of approved users. 2696 */ 2697 void 2698 wallmsg(struct filed *f, struct iovec *iov, size_t iovcnt) 2699 { 2700 #ifdef __NetBSD_Version__ 2701 static int reenter; /* avoid calling ourselves */ 2702 int i; 2703 char *p; 2704 struct utmpentry *ep; 2705 2706 if (reenter++) 2707 return; 2708 2709 (void)getutentries(NULL, &ep); 2710 /* NOSTRICT */ 2711 for (; ep; ep = ep->next) { 2712 if (f->f_type == F_WALL) { 2713 if ((p = ttymsg(iov, iovcnt, ep->line, TTYMSGTIME)) 2714 != NULL) { 2715 errno = 0; /* already in msg */ 2716 logerror("%s", p); 2717 } 2718 continue; 2719 } 2720 /* should we send the message to this user? */ 2721 for (i = 0; i < MAXUNAMES; i++) { 2722 if (!f->f_un.f_uname[i][0]) 2723 break; 2724 if (strcmp(f->f_un.f_uname[i], ep->name) == 0) { 2725 struct stat st; 2726 char tty[MAXPATHLEN]; 2727 snprintf(tty, sizeof(tty), "%s/%s", _PATH_DEV, 2728 ep->line); 2729 if (stat(tty, &st) != -1 && 2730 (st.st_mode & S_IWGRP) == 0) 2731 break; 2732 2733 if ((p = ttymsg(iov, iovcnt, ep->line, 2734 TTYMSGTIME)) != NULL) { 2735 errno = 0; /* already in msg */ 2736 logerror("%s", p); 2737 } 2738 break; 2739 } 2740 } 2741 } 2742 reenter = 0; 2743 #endif /* __NetBSD_Version__ */ 2744 } 2745 2746 void 2747 /*ARGSUSED*/ 2748 reapchild(int fd, short event, void *ev) 2749 { 2750 int status; 2751 pid_t pid; 2752 struct filed *f; 2753 2754 while ((pid = wait3(&status, WNOHANG, NULL)) > 0) { 2755 if (!Initialized || ShuttingDown) { 2756 /* 2757 * Be silent while we are initializing or 2758 * shutting down. 2759 */ 2760 continue; 2761 } 2762 2763 if (deadq_remove(pid)) 2764 continue; 2765 2766 /* Now, look in the list of active processes. */ 2767 for (f = Files; f != NULL; f = f->f_next) { 2768 if (f->f_type == F_PIPE && 2769 f->f_un.f_pipe.f_pid == pid) { 2770 (void) close(f->f_file); 2771 f->f_un.f_pipe.f_pid = 0; 2772 log_deadchild(pid, status, 2773 f->f_un.f_pipe.f_pname); 2774 break; 2775 } 2776 } 2777 } 2778 } 2779 2780 /* 2781 * Return a printable representation of a host address (FQDN if available) 2782 */ 2783 const char * 2784 cvthname(struct sockaddr_storage *f) 2785 { 2786 int error; 2787 int niflag = NI_DGRAM; 2788 static char host[NI_MAXHOST], ip[NI_MAXHOST]; 2789 2790 error = getnameinfo((struct sockaddr*)f, ((struct sockaddr*)f)->sa_len, 2791 ip, sizeof ip, NULL, 0, NI_NUMERICHOST|niflag); 2792 2793 DPRINTF(D_CALL, "cvthname(%s)\n", ip); 2794 2795 if (error) { 2796 DPRINTF(D_NET, "Malformed from address %s\n", 2797 gai_strerror(error)); 2798 return "???"; 2799 } 2800 2801 if (!UseNameService) 2802 return ip; 2803 2804 error = getnameinfo((struct sockaddr*)f, ((struct sockaddr*)f)->sa_len, 2805 host, sizeof host, NULL, 0, niflag); 2806 if (error) { 2807 DPRINTF(D_NET, "Host name for your address (%s) unknown\n", ip); 2808 return ip; 2809 } 2810 2811 return host; 2812 } 2813 2814 void 2815 trim_anydomain(char *host) 2816 { 2817 bool onlydigits = true; 2818 int i; 2819 2820 if (!BSDOutputFormat) 2821 return; 2822 2823 /* if non-digits found, then assume hostname and cut at first dot (this 2824 * case also covers IPv6 addresses which should not contain dots), 2825 * if only digits then assume IPv4 address and do not cut at all */ 2826 for (i = 0; host[i]; i++) { 2827 if (host[i] == '.' && !onlydigits) 2828 host[i] = '\0'; 2829 else if (!isdigit((unsigned char)host[i]) && host[i] != '.') 2830 onlydigits = false; 2831 } 2832 } 2833 2834 static void 2835 /*ARGSUSED*/ 2836 domark(int fd, short event, void *ev) 2837 { 2838 struct event *ev_pass = (struct event *)ev; 2839 struct filed *f; 2840 dq_t q, nextq; 2841 sigset_t newmask, omask; 2842 2843 schedule_event(&ev_pass, 2844 &((struct timeval){TIMERINTVL, 0}), 2845 domark, ev_pass); 2846 DPRINTF((D_CALL|D_EVENT), "domark()\n"); 2847 2848 BLOCK_SIGNALS(omask, newmask); 2849 now = time(NULL); 2850 MarkSeq += TIMERINTVL; 2851 if (MarkSeq >= MarkInterval) { 2852 logmsg_async(LOG_INFO, NULL, "-- MARK --", ADDDATE|MARK); 2853 MarkSeq = 0; 2854 } 2855 2856 for (f = Files; f; f = f->f_next) { 2857 if (f->f_prevcount && now >= REPEATTIME(f)) { 2858 DPRINTF(D_DATA, 2859 "Flush %s: repeated %d times, %d sec.\n", 2860 TypeInfo[f->f_type].name, f->f_prevcount, 2861 repeatinterval[f->f_repeatcount]); 2862 fprintlog(f, NULL, NULL); 2863 BACKOFF(f); 2864 } 2865 } 2866 message_allqueues_check(); 2867 RESTORE_SIGNALS(omask); 2868 2869 /* Walk the dead queue, and see if we should signal somebody. */ 2870 for (q = TAILQ_FIRST(&deadq_head); q != NULL; q = nextq) { 2871 nextq = TAILQ_NEXT(q, dq_entries); 2872 switch (q->dq_timeout) { 2873 case 0: 2874 /* Already signalled once, try harder now. */ 2875 if (kill(q->dq_pid, SIGKILL) != 0) 2876 (void) deadq_remove(q->dq_pid); 2877 break; 2878 2879 case 1: 2880 /* 2881 * Timed out on the dead queue, send terminate 2882 * signal. Note that we leave the removal from 2883 * the dead queue to reapchild(), which will 2884 * also log the event (unless the process 2885 * didn't even really exist, in case we simply 2886 * drop it from the dead queue). 2887 */ 2888 if (kill(q->dq_pid, SIGTERM) != 0) { 2889 (void) deadq_remove(q->dq_pid); 2890 break; 2891 } 2892 /* FALLTHROUGH */ 2893 2894 default: 2895 q->dq_timeout--; 2896 } 2897 } 2898 #ifndef DISABLE_SIGN 2899 if (GlobalSign.rsid) { /* check if initialized */ 2900 struct signature_group_t *sg; 2901 STAILQ_FOREACH(sg, &GlobalSign.SigGroups, entries) { 2902 sign_send_certificate_block(sg); 2903 } 2904 } 2905 #endif /* !DISABLE_SIGN */ 2906 } 2907 2908 /* 2909 * Print syslogd errors some place. 2910 */ 2911 void 2912 logerror(const char *fmt, ...) 2913 { 2914 static int logerror_running; 2915 va_list ap; 2916 char tmpbuf[BUFSIZ]; 2917 char buf[BUFSIZ]; 2918 char *outbuf; 2919 2920 /* If there's an error while trying to log an error, give up. */ 2921 if (logerror_running) 2922 return; 2923 logerror_running = 1; 2924 2925 va_start(ap, fmt); 2926 (void)vsnprintf(tmpbuf, sizeof(tmpbuf), fmt, ap); 2927 va_end(ap); 2928 2929 if (errno) { 2930 (void)snprintf(buf, sizeof(buf), "%s: %s", 2931 tmpbuf, strerror(errno)); 2932 outbuf = buf; 2933 } else { 2934 (void)snprintf(buf, sizeof(buf), "%s", tmpbuf); 2935 outbuf = tmpbuf; 2936 } 2937 2938 if (daemonized) 2939 logmsg_async(LOG_SYSLOG|LOG_ERR, NULL, outbuf, ADDDATE); 2940 if (!daemonized && Debug) 2941 DPRINTF(D_MISC, "%s\n", outbuf); 2942 if (!daemonized && !Debug) 2943 printf("%s: %s\n", getprogname(), outbuf); 2944 2945 logerror_running = 0; 2946 } 2947 2948 /* 2949 * Print syslogd info some place. 2950 */ 2951 void 2952 loginfo(const char *fmt, ...) 2953 { 2954 va_list ap; 2955 char buf[BUFSIZ]; 2956 2957 va_start(ap, fmt); 2958 (void)vsnprintf(buf, sizeof(buf), fmt, ap); 2959 va_end(ap); 2960 2961 DPRINTF(D_MISC, "%s\n", buf); 2962 logmsg_async(LOG_SYSLOG|LOG_INFO, NULL, buf, ADDDATE); 2963 } 2964 2965 #ifndef DISABLE_TLS 2966 static inline void 2967 free_incoming_tls_sockets(void) 2968 { 2969 struct TLS_Incoming_Conn *tls_in; 2970 int i; 2971 2972 /* 2973 * close all listening and connected TLS sockets 2974 */ 2975 if (TLS_Listen_Set) 2976 for (i = 0; i < TLS_Listen_Set->fd; i++) { 2977 if (close(TLS_Listen_Set[i+1].fd) == -1) 2978 logerror("close() failed"); 2979 DEL_EVENT(TLS_Listen_Set[i+1].ev); 2980 FREEPTR(TLS_Listen_Set[i+1].ev); 2981 } 2982 FREEPTR(TLS_Listen_Set); 2983 /* close/free incoming TLS connections */ 2984 while (!SLIST_EMPTY(&TLS_Incoming_Head)) { 2985 tls_in = SLIST_FIRST(&TLS_Incoming_Head); 2986 SLIST_REMOVE_HEAD(&TLS_Incoming_Head, entries); 2987 FREEPTR(tls_in->inbuf); 2988 free_tls_conn(tls_in->tls_conn); 2989 FREEPTR(tls_in); 2990 } 2991 } 2992 #endif /* !DISABLE_TLS */ 2993 2994 void 2995 /*ARGSUSED*/ 2996 die(int fd, short event, void *ev) 2997 { 2998 struct filed *f, *next; 2999 char **p; 3000 sigset_t newmask, omask; 3001 int i; 3002 size_t j; 3003 3004 ShuttingDown = 1; /* Don't log SIGCHLDs. */ 3005 /* prevent recursive signals */ 3006 BLOCK_SIGNALS(omask, newmask); 3007 3008 errno = 0; 3009 if (ev != NULL) 3010 logerror("Exiting on signal %d", fd); 3011 else 3012 logerror("Fatal error, exiting"); 3013 3014 /* 3015 * flush any pending output 3016 */ 3017 for (f = Files; f != NULL; f = f->f_next) { 3018 /* flush any pending output */ 3019 if (f->f_prevcount) 3020 fprintlog(f, NULL, NULL); 3021 SEND_QUEUE(f); 3022 } 3023 3024 #ifndef DISABLE_TLS 3025 free_incoming_tls_sockets(); 3026 #endif /* !DISABLE_TLS */ 3027 #ifndef DISABLE_SIGN 3028 sign_global_free(); 3029 #endif /* !DISABLE_SIGN */ 3030 3031 /* 3032 * Close all open log files. 3033 */ 3034 for (f = Files; f != NULL; f = next) { 3035 message_queue_freeall(f); 3036 3037 switch (f->f_type) { 3038 case F_FILE: 3039 case F_TTY: 3040 case F_CONSOLE: 3041 case F_FIFO: 3042 if (f->f_file >= 0) 3043 (void)close(f->f_file); 3044 break; 3045 case F_PIPE: 3046 if (f->f_un.f_pipe.f_pid > 0) { 3047 (void)close(f->f_file); 3048 } 3049 f->f_un.f_pipe.f_pid = 0; 3050 break; 3051 case F_FORW: 3052 if (f->f_un.f_forw.f_addr) 3053 freeaddrinfo(f->f_un.f_forw.f_addr); 3054 break; 3055 #ifndef DISABLE_TLS 3056 case F_TLS: 3057 free_tls_conn(f->f_un.f_tls.tls_conn); 3058 break; 3059 #endif /* !DISABLE_TLS */ 3060 } 3061 next = f->f_next; 3062 DELREF(f->f_prevmsg); 3063 FREEPTR(f->f_program); 3064 FREEPTR(f->f_host); 3065 DEL_EVENT(f->f_sq_event); 3066 FREEPTR(f); 3067 } 3068 3069 /* 3070 * Close all open UDP sockets 3071 */ 3072 if (finet) { 3073 for (i = 0; i < finet->fd; i++) { 3074 (void)close(finet[i+1].fd); 3075 DEL_EVENT(finet[i+1].ev); 3076 FREEPTR(finet[i+1].ev); 3077 } 3078 FREEPTR(finet); 3079 } 3080 3081 /* free config options */ 3082 for (j = 0; j < A_CNT(TypeInfo); j++) { 3083 FREEPTR(TypeInfo[j].queue_length_string); 3084 FREEPTR(TypeInfo[j].queue_size_string); 3085 } 3086 3087 #ifndef DISABLE_TLS 3088 FREEPTR(tls_opt.CAdir); 3089 FREEPTR(tls_opt.CAfile); 3090 FREEPTR(tls_opt.keyfile); 3091 FREEPTR(tls_opt.certfile); 3092 FREEPTR(tls_opt.x509verify); 3093 FREEPTR(tls_opt.bindhost); 3094 FREEPTR(tls_opt.bindport); 3095 FREEPTR(tls_opt.server); 3096 FREEPTR(tls_opt.gen_cert); 3097 free_cred_SLIST(&tls_opt.cert_head); 3098 free_cred_SLIST(&tls_opt.fprint_head); 3099 FREE_SSL_CTX(tls_opt.global_TLS_CTX); 3100 #endif /* !DISABLE_TLS */ 3101 3102 FREEPTR(funix); 3103 for (p = LogPaths; p && *p; p++) 3104 unlink(*p); 3105 exit(0); 3106 } 3107 3108 #ifndef DISABLE_SIGN 3109 /* 3110 * get one "sign_delim_sg2" item, convert and store in ordered queue 3111 */ 3112 void 3113 store_sign_delim_sg2(char *tmp_buf) 3114 { 3115 struct string_queue *sqentry, *sqe1, *sqe2; 3116 3117 if (!(sqentry = malloc(sizeof(*sqentry)))) { 3118 logerror("Unable to allocate memory"); 3119 return; 3120 } 3121 /*LINTED constcond/null effect */ 3122 assert(sizeof(int64_t) == sizeof(uint_fast64_t)); 3123 if (dehumanize_number(tmp_buf, (int64_t*) &(sqentry->key)) == -1 3124 || sqentry->key > (LOG_NFACILITIES<<3)) { 3125 DPRINTF(D_PARSE, "invalid sign_delim_sg2: %s\n", tmp_buf); 3126 FREEPTR(sqentry); 3127 FREEPTR(tmp_buf); 3128 return; 3129 } 3130 sqentry->data = tmp_buf; 3131 3132 if (STAILQ_EMPTY(&GlobalSign.sig2_delims)) { 3133 STAILQ_INSERT_HEAD(&GlobalSign.sig2_delims, 3134 sqentry, entries); 3135 return; 3136 } 3137 3138 /* keep delimiters sorted */ 3139 sqe1 = sqe2 = STAILQ_FIRST(&GlobalSign.sig2_delims); 3140 if (sqe1->key > sqentry->key) { 3141 STAILQ_INSERT_HEAD(&GlobalSign.sig2_delims, 3142 sqentry, entries); 3143 return; 3144 } 3145 3146 while ((sqe1 = sqe2) 3147 && (sqe2 = STAILQ_NEXT(sqe1, entries))) { 3148 if (sqe2->key > sqentry->key) { 3149 break; 3150 } else if (sqe2->key == sqentry->key) { 3151 DPRINTF(D_PARSE, "duplicate sign_delim_sg2: %s\n", 3152 tmp_buf); 3153 FREEPTR(sqentry); 3154 FREEPTR(tmp_buf); 3155 return; 3156 } 3157 } 3158 STAILQ_INSERT_AFTER(&GlobalSign.sig2_delims, sqe1, sqentry, entries); 3159 } 3160 #endif /* !DISABLE_SIGN */ 3161 3162 /* 3163 * read syslog.conf 3164 */ 3165 void 3166 read_config_file(FILE *cf, struct filed **f_ptr) 3167 { 3168 size_t linenum = 0; 3169 size_t i; 3170 struct filed *f, **nextp; 3171 char cline[LINE_MAX]; 3172 char prog[NAME_MAX + 1]; 3173 char host[MAXHOSTNAMELEN]; 3174 const char *p; 3175 char *q; 3176 bool found_keyword; 3177 #ifndef DISABLE_TLS 3178 struct peer_cred *cred = NULL; 3179 struct peer_cred_head *credhead = NULL; 3180 #endif /* !DISABLE_TLS */ 3181 #ifndef DISABLE_SIGN 3182 char *sign_sg_str = NULL; 3183 #endif /* !DISABLE_SIGN */ 3184 #if (!defined(DISABLE_TLS) || !defined(DISABLE_SIGN)) 3185 char *tmp_buf = NULL; 3186 #endif /* (!defined(DISABLE_TLS) || !defined(DISABLE_SIGN)) */ 3187 /* central list of recognized configuration keywords 3188 * and an address for their values as strings */ 3189 const struct config_keywords { 3190 const char *keyword; 3191 char **variable; 3192 } config_keywords[] = { 3193 #ifndef DISABLE_TLS 3194 /* TLS settings */ 3195 {"tls_cadir", &tls_opt.CAdir}, 3196 {"tls_ca", &tls_opt.CAfile}, 3197 {"tls_cert", &tls_opt.certfile}, 3198 {"tls_key", &tls_opt.keyfile}, 3199 {"tls_verify", &tls_opt.x509verify}, 3200 {"tls_bindport", &tls_opt.bindport}, 3201 {"tls_bindhost", &tls_opt.bindhost}, 3202 {"tls_server", &tls_opt.server}, 3203 {"tls_gen_cert", &tls_opt.gen_cert}, 3204 /* special cases in parsing */ 3205 {"tls_allow_fingerprints",&tmp_buf}, 3206 {"tls_allow_clientcerts", &tmp_buf}, 3207 /* buffer settings */ 3208 {"tls_queue_length", &TypeInfo[F_TLS].queue_length_string}, 3209 {"tls_queue_size", &TypeInfo[F_TLS].queue_size_string}, 3210 #endif /* !DISABLE_TLS */ 3211 {"file_queue_length", &TypeInfo[F_FILE].queue_length_string}, 3212 {"pipe_queue_length", &TypeInfo[F_PIPE].queue_length_string}, 3213 {"fifo_queue_length", &TypeInfo[F_FIFO].queue_length_string}, 3214 {"file_queue_size", &TypeInfo[F_FILE].queue_size_string}, 3215 {"pipe_queue_size", &TypeInfo[F_PIPE].queue_size_string}, 3216 {"fifo_queue_size", &TypeInfo[F_FIFO].queue_size_string}, 3217 #ifndef DISABLE_SIGN 3218 /* syslog-sign setting */ 3219 {"sign_sg", &sign_sg_str}, 3220 /* also special case in parsing */ 3221 {"sign_delim_sg2", &tmp_buf}, 3222 #endif /* !DISABLE_SIGN */ 3223 }; 3224 3225 DPRINTF(D_CALL, "read_config_file()\n"); 3226 3227 /* free all previous config options */ 3228 for (i = 0; i < A_CNT(TypeInfo); i++) { 3229 if (TypeInfo[i].queue_length_string 3230 && TypeInfo[i].queue_length_string 3231 != TypeInfo[i].default_length_string) { 3232 FREEPTR(TypeInfo[i].queue_length_string); 3233 TypeInfo[i].queue_length_string = 3234 strdup(TypeInfo[i].default_length_string); 3235 } 3236 if (TypeInfo[i].queue_size_string 3237 && TypeInfo[i].queue_size_string 3238 != TypeInfo[i].default_size_string) { 3239 FREEPTR(TypeInfo[i].queue_size_string); 3240 TypeInfo[i].queue_size_string = 3241 strdup(TypeInfo[i].default_size_string); 3242 } 3243 } 3244 for (i = 0; i < A_CNT(config_keywords); i++) 3245 FREEPTR(*config_keywords[i].variable); 3246 /* 3247 * global settings 3248 */ 3249 while (fgets(cline, sizeof(cline), cf) != NULL) { 3250 linenum++; 3251 for (p = cline; isspace((unsigned char)*p); ++p) 3252 continue; 3253 if ((*p == '\0') || (*p == '#')) 3254 continue; 3255 3256 for (i = 0; i < A_CNT(config_keywords); i++) { 3257 if (copy_config_value(config_keywords[i].keyword, 3258 config_keywords[i].variable, &p, ConfFile, 3259 linenum)) { 3260 DPRINTF((D_PARSE|D_MEM), 3261 "found option %s, saved @%p\n", 3262 config_keywords[i].keyword, 3263 *config_keywords[i].variable); 3264 #ifndef DISABLE_SIGN 3265 if (!strcmp("sign_delim_sg2", 3266 config_keywords[i].keyword)) 3267 do { 3268 store_sign_delim_sg2(tmp_buf); 3269 } while (copy_config_value_word( 3270 &tmp_buf, &p)); 3271 3272 #endif /* !DISABLE_SIGN */ 3273 3274 #ifndef DISABLE_TLS 3275 /* special cases with multiple parameters */ 3276 if (!strcmp("tls_allow_fingerprints", 3277 config_keywords[i].keyword)) 3278 credhead = &tls_opt.fprint_head; 3279 else if (!strcmp("tls_allow_clientcerts", 3280 config_keywords[i].keyword)) 3281 credhead = &tls_opt.cert_head; 3282 3283 if (credhead) do { 3284 if (!(cred = malloc(sizeof(*cred)))) { 3285 logerror("Unable to " 3286 "allocate memory"); 3287 break; 3288 } 3289 cred->data = tmp_buf; 3290 tmp_buf = NULL; 3291 SLIST_INSERT_HEAD(credhead, 3292 cred, entries); 3293 } while /* additional values? */ 3294 (copy_config_value_word(&tmp_buf, &p)); 3295 credhead = NULL; 3296 break; 3297 #endif /* !DISABLE_TLS */ 3298 } 3299 } 3300 } 3301 /* convert strings to integer values */ 3302 for (i = 0; i < A_CNT(TypeInfo); i++) { 3303 if (!TypeInfo[i].queue_length_string 3304 || dehumanize_number(TypeInfo[i].queue_length_string, 3305 &TypeInfo[i].queue_length) == -1) 3306 if (dehumanize_number(TypeInfo[i].default_length_string, 3307 &TypeInfo[i].queue_length) == -1) 3308 abort(); 3309 if (!TypeInfo[i].queue_size_string 3310 || dehumanize_number(TypeInfo[i].queue_size_string, 3311 &TypeInfo[i].queue_size) == -1) 3312 if (dehumanize_number(TypeInfo[i].default_size_string, 3313 &TypeInfo[i].queue_size) == -1) 3314 abort(); 3315 } 3316 3317 #ifndef DISABLE_SIGN 3318 if (sign_sg_str) { 3319 if (sign_sg_str[1] == '\0' 3320 && (sign_sg_str[0] == '0' || sign_sg_str[0] == '1' 3321 || sign_sg_str[0] == '2' || sign_sg_str[0] == '3')) 3322 GlobalSign.sg = sign_sg_str[0] - '0'; 3323 else { 3324 GlobalSign.sg = SIGN_SG; 3325 DPRINTF(D_MISC, "Invalid sign_sg value `%s', " 3326 "use default value `%d'\n", 3327 sign_sg_str, GlobalSign.sg); 3328 } 3329 } else /* disable syslog-sign */ 3330 GlobalSign.sg = -1; 3331 #endif /* !DISABLE_SIGN */ 3332 3333 rewind(cf); 3334 linenum = 0; 3335 /* 3336 * Foreach line in the conf table, open that file. 3337 */ 3338 f = NULL; 3339 nextp = &f; 3340 3341 strcpy(prog, "*"); 3342 strcpy(host, "*"); 3343 while (fgets(cline, sizeof(cline), cf) != NULL) { 3344 linenum++; 3345 found_keyword = false; 3346 /* 3347 * check for end-of-section, comments, strip off trailing 3348 * spaces and newline character. #!prog is treated specially: 3349 * following lines apply only to that program. 3350 */ 3351 for (p = cline; isspace((unsigned char)*p); ++p) 3352 continue; 3353 if (*p == '\0') 3354 continue; 3355 if (*p == '#') { 3356 p++; 3357 if (*p != '!' && *p != '+' && *p != '-') 3358 continue; 3359 } 3360 3361 for (i = 0; i < A_CNT(config_keywords); i++) { 3362 if (!strncasecmp(p, config_keywords[i].keyword, 3363 strlen(config_keywords[i].keyword))) { 3364 DPRINTF(D_PARSE, 3365 "skip cline %zu with keyword %s\n", 3366 linenum, config_keywords[i].keyword); 3367 found_keyword = true; 3368 } 3369 } 3370 if (found_keyword) 3371 continue; 3372 3373 if (*p == '+' || *p == '-') { 3374 host[0] = *p++; 3375 while (isspace((unsigned char)*p)) 3376 p++; 3377 if (*p == '\0' || *p == '*') { 3378 strcpy(host, "*"); 3379 continue; 3380 } 3381 /* the +hostname expression will continue 3382 * to use the LocalHostName, not the FQDN */ 3383 for (i = 1; i < MAXHOSTNAMELEN - 1; i++) { 3384 if (*p == '@') { 3385 (void)strncpy(&host[i], LocalHostName, 3386 sizeof(host) - 1 - i); 3387 host[sizeof(host) - 1] = '\0'; 3388 i = strlen(host) - 1; 3389 p++; 3390 continue; 3391 } 3392 if (!isalnum((unsigned char)*p) && 3393 *p != '.' && *p != '-' && *p != ',') 3394 break; 3395 host[i] = *p++; 3396 } 3397 host[i] = '\0'; 3398 continue; 3399 } 3400 if (*p == '!') { 3401 p++; 3402 while (isspace((unsigned char)*p)) 3403 p++; 3404 if (*p == '\0' || *p == '*') { 3405 strcpy(prog, "*"); 3406 continue; 3407 } 3408 for (i = 0; i < NAME_MAX; i++) { 3409 if (!isprint((unsigned char)p[i])) 3410 break; 3411 prog[i] = p[i]; 3412 } 3413 prog[i] = '\0'; 3414 continue; 3415 } 3416 for (q = strchr(cline, '\0'); isspace((unsigned char)*--q);) 3417 continue; 3418 *++q = '\0'; 3419 if ((f = calloc(1, sizeof(*f))) == NULL) { 3420 logerror("alloc failed"); 3421 die(0, 0, NULL); 3422 } 3423 if (!*f_ptr) *f_ptr = f; /* return first node */ 3424 *nextp = f; 3425 nextp = &f->f_next; 3426 cfline(linenum, cline, f, prog, host); 3427 } 3428 } 3429 3430 /* 3431 * INIT -- Initialize syslogd from configuration table 3432 */ 3433 void 3434 /*ARGSUSED*/ 3435 init(int fd, short event, void *ev) 3436 { 3437 FILE *cf; 3438 int i; 3439 struct filed *f, *newf, **nextp, *f2; 3440 char *p; 3441 sigset_t newmask, omask; 3442 #ifndef DISABLE_TLS 3443 char *tls_status_msg = NULL; 3444 struct peer_cred *cred = NULL; 3445 #endif /* !DISABLE_TLS */ 3446 3447 /* prevent recursive signals */ 3448 BLOCK_SIGNALS(omask, newmask); 3449 3450 DPRINTF((D_EVENT|D_CALL), "init\n"); 3451 3452 /* 3453 * be careful about dependencies and order of actions: 3454 * 1. flush buffer queues 3455 * 2. flush -sign SBs 3456 * 3. flush/delete buffer queue again, in case an SB got there 3457 * 4. close files/connections 3458 */ 3459 3460 /* 3461 * flush any pending output 3462 */ 3463 for (f = Files; f != NULL; f = f->f_next) { 3464 /* flush any pending output */ 3465 if (f->f_prevcount) 3466 fprintlog(f, NULL, NULL); 3467 SEND_QUEUE(f); 3468 } 3469 /* some actions only on SIGHUP and not on first start */ 3470 if (Initialized) { 3471 #ifndef DISABLE_SIGN 3472 sign_global_free(); 3473 #endif /* !DISABLE_SIGN */ 3474 #ifndef DISABLE_TLS 3475 free_incoming_tls_sockets(); 3476 #endif /* !DISABLE_TLS */ 3477 Initialized = 0; 3478 } 3479 /* 3480 * Close all open log files. 3481 */ 3482 for (f = Files; f != NULL; f = f->f_next) { 3483 switch (f->f_type) { 3484 case F_FILE: 3485 case F_TTY: 3486 case F_CONSOLE: 3487 (void)close(f->f_file); 3488 break; 3489 case F_PIPE: 3490 if (f->f_un.f_pipe.f_pid > 0) { 3491 (void)close(f->f_file); 3492 deadq_enter(f->f_un.f_pipe.f_pid, 3493 f->f_un.f_pipe.f_pname); 3494 } 3495 f->f_un.f_pipe.f_pid = 0; 3496 break; 3497 case F_FORW: 3498 if (f->f_un.f_forw.f_addr) 3499 freeaddrinfo(f->f_un.f_forw.f_addr); 3500 break; 3501 #ifndef DISABLE_TLS 3502 case F_TLS: 3503 free_tls_sslptr(f->f_un.f_tls.tls_conn); 3504 break; 3505 #endif /* !DISABLE_TLS */ 3506 } 3507 } 3508 3509 /* 3510 * Close all open UDP sockets 3511 */ 3512 if (finet) { 3513 for (i = 0; i < finet->fd; i++) { 3514 if (close(finet[i+1].fd) < 0) { 3515 logerror("close() failed"); 3516 die(0, 0, NULL); 3517 } 3518 DEL_EVENT(finet[i+1].ev); 3519 FREEPTR(finet[i+1].ev); 3520 } 3521 FREEPTR(finet); 3522 } 3523 3524 /* get FQDN and hostname/domain */ 3525 FREEPTR(oldLocalFQDN); 3526 oldLocalFQDN = LocalFQDN; 3527 LocalFQDN = getLocalFQDN(); 3528 if ((p = strchr(LocalFQDN, '.')) != NULL) 3529 (void)strlcpy(LocalHostName, LocalFQDN, 1+p-LocalFQDN); 3530 else 3531 (void)strlcpy(LocalHostName, LocalFQDN, sizeof(LocalHostName)); 3532 3533 /* 3534 * Reset counter of forwarding actions 3535 */ 3536 3537 NumForwards=0; 3538 3539 /* new destination list to replace Files */ 3540 newf = NULL; 3541 nextp = &newf; 3542 3543 /* open the configuration file */ 3544 if ((cf = fopen(ConfFile, "r")) == NULL) { 3545 DPRINTF(D_FILE, "Cannot open `%s'\n", ConfFile); 3546 *nextp = (struct filed *)calloc(1, sizeof(*f)); 3547 cfline(0, "*.ERR\t/dev/console", *nextp, "*", "*"); 3548 (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f)); 3549 cfline(0, "*.PANIC\t*", (*nextp)->f_next, "*", "*"); 3550 Initialized = 1; 3551 RESTORE_SIGNALS(omask); 3552 return; 3553 } 3554 3555 #ifndef DISABLE_TLS 3556 /* init with new TLS_CTX 3557 * as far as I see one cannot change the cert/key of an existing CTX 3558 */ 3559 FREE_SSL_CTX(tls_opt.global_TLS_CTX); 3560 3561 free_cred_SLIST(&tls_opt.cert_head); 3562 free_cred_SLIST(&tls_opt.fprint_head); 3563 #endif /* !DISABLE_TLS */ 3564 3565 /* read and close configuration file */ 3566 read_config_file(cf, &newf); 3567 newf = *nextp; 3568 (void)fclose(cf); 3569 DPRINTF(D_MISC, "read_config_file() returned newf=%p\n", newf); 3570 3571 #define MOVE_QUEUE(dst, src) do { \ 3572 struct buf_queue *buf; \ 3573 STAILQ_CONCAT(&dst->f_qhead, &src->f_qhead); \ 3574 STAILQ_FOREACH(buf, &dst->f_qhead, entries) { \ 3575 dst->f_qelements++; \ 3576 dst->f_qsize += buf_queue_obj_size(buf); \ 3577 } \ 3578 src->f_qsize = 0; \ 3579 src->f_qelements = 0; \ 3580 } while (0) 3581 3582 /* 3583 * Free old log files. 3584 */ 3585 for (f = Files; f != NULL;) { 3586 struct filed *ftmp; 3587 3588 /* check if a new logfile is equal, if so pass the queue */ 3589 for (f2 = newf; f2 != NULL; f2 = f2->f_next) { 3590 if (f->f_type == f2->f_type 3591 && ((f->f_type == F_PIPE 3592 && !strcmp(f->f_un.f_pipe.f_pname, 3593 f2->f_un.f_pipe.f_pname)) 3594 #ifndef DISABLE_TLS 3595 || (f->f_type == F_TLS 3596 && !strcmp(f->f_un.f_tls.tls_conn->hostname, 3597 f2->f_un.f_tls.tls_conn->hostname) 3598 && !strcmp(f->f_un.f_tls.tls_conn->port, 3599 f2->f_un.f_tls.tls_conn->port)) 3600 #endif /* !DISABLE_TLS */ 3601 || (f->f_type == F_FORW 3602 && !strcmp(f->f_un.f_forw.f_hname, 3603 f2->f_un.f_forw.f_hname)))) { 3604 DPRINTF(D_BUFFER, "move queue from f@%p " 3605 "to f2@%p\n", f, f2); 3606 MOVE_QUEUE(f2, f); 3607 } 3608 } 3609 message_queue_freeall(f); 3610 DELREF(f->f_prevmsg); 3611 #ifndef DISABLE_TLS 3612 if (f->f_type == F_TLS) 3613 free_tls_conn(f->f_un.f_tls.tls_conn); 3614 #endif /* !DISABLE_TLS */ 3615 FREEPTR(f->f_program); 3616 FREEPTR(f->f_host); 3617 DEL_EVENT(f->f_sq_event); 3618 3619 ftmp = f->f_next; 3620 FREEPTR(f); 3621 f = ftmp; 3622 } 3623 Files = newf; 3624 Initialized = 1; 3625 3626 if (Debug) { 3627 for (f = Files; f; f = f->f_next) { 3628 for (i = 0; i <= LOG_NFACILITIES; i++) 3629 if (f->f_pmask[i] == INTERNAL_NOPRI) 3630 printf("X "); 3631 else 3632 printf("%d ", f->f_pmask[i]); 3633 printf("%s: ", TypeInfo[f->f_type].name); 3634 switch (f->f_type) { 3635 case F_FILE: 3636 case F_TTY: 3637 case F_CONSOLE: 3638 case F_FIFO: 3639 printf("%s", f->f_un.f_fname); 3640 break; 3641 3642 case F_FORW: 3643 printf("%s", f->f_un.f_forw.f_hname); 3644 break; 3645 #ifndef DISABLE_TLS 3646 case F_TLS: 3647 printf("[%s]", f->f_un.f_tls.tls_conn->hostname); 3648 break; 3649 #endif /* !DISABLE_TLS */ 3650 case F_PIPE: 3651 printf("%s", f->f_un.f_pipe.f_pname); 3652 break; 3653 3654 case F_USERS: 3655 for (i = 0; 3656 i < MAXUNAMES && *f->f_un.f_uname[i]; i++) 3657 printf("%s, ", f->f_un.f_uname[i]); 3658 break; 3659 } 3660 if (f->f_program != NULL) 3661 printf(" (%s)", f->f_program); 3662 printf("\n"); 3663 } 3664 } 3665 3666 finet = socksetup(PF_UNSPEC, bindhostname); 3667 if (finet) { 3668 if (SecureMode) { 3669 for (i = 0; i < finet->fd; i++) { 3670 if (shutdown(finet[i+1].fd, SHUT_RD) < 0) { 3671 logerror("shutdown() failed"); 3672 die(0, 0, NULL); 3673 } 3674 } 3675 } else 3676 DPRINTF(D_NET, 3677 "Listening on inet and/or inet6 socket\n"); 3678 3679 DPRINTF(D_NET, "Sending on inet and/or inet6 socket\n"); 3680 } 3681 3682 #ifndef DISABLE_TLS 3683 /* TLS setup -- after all local destinations opened */ 3684 DPRINTF(D_PARSE, "Parsed options: tls_ca: %s, tls_cadir: %s, " 3685 "tls_cert: %s, tls_key: %s, tls_verify: %s, " 3686 "bind: %s:%s, max. queue_lengths: %" 3687 PRId64 ", %" PRId64 ", %" PRId64 ", " 3688 "max. queue_sizes: %" 3689 PRId64 ", %" PRId64 ", %" PRId64 "\n", 3690 tls_opt.CAfile, tls_opt.CAdir, 3691 tls_opt.certfile, tls_opt.keyfile, tls_opt.x509verify, 3692 tls_opt.bindhost, tls_opt.bindport, 3693 TypeInfo[F_TLS].queue_length, TypeInfo[F_FILE].queue_length, 3694 TypeInfo[F_PIPE].queue_length, 3695 TypeInfo[F_TLS].queue_size, TypeInfo[F_FILE].queue_size, 3696 TypeInfo[F_PIPE].queue_size); 3697 SLIST_FOREACH(cred, &tls_opt.cert_head, entries) { 3698 DPRINTF(D_PARSE, "Accepting peer certificate " 3699 "from file: \"%s\"\n", cred->data); 3700 } 3701 SLIST_FOREACH(cred, &tls_opt.fprint_head, entries) { 3702 DPRINTF(D_PARSE, "Accepting peer certificate with " 3703 "fingerprint: \"%s\"\n", cred->data); 3704 } 3705 3706 /* Note: The order of initialization is important because syslog-sign 3707 * should use the TLS cert for signing. -- So we check first if TLS 3708 * will be used and initialize it before starting -sign. 3709 * 3710 * This means that if we are a client without TLS destinations TLS 3711 * will not be initialized and syslog-sign will generate a new key. 3712 * -- Even if the user has set a usable tls_cert. 3713 * Is this the expected behaviour? The alternative would be to always 3714 * initialize the TLS structures, even if they will not be needed 3715 * (or only needed to read the DSA key for -sign). 3716 */ 3717 3718 /* Initialize TLS only if used */ 3719 if (tls_opt.server) 3720 tls_status_msg = init_global_TLS_CTX(); 3721 else 3722 for (f = Files; f; f = f->f_next) { 3723 if (f->f_type != F_TLS) 3724 continue; 3725 tls_status_msg = init_global_TLS_CTX(); 3726 break; 3727 } 3728 3729 #endif /* !DISABLE_TLS */ 3730 3731 #ifndef DISABLE_SIGN 3732 /* only initialize -sign if actually used */ 3733 if (GlobalSign.sg == 0 || GlobalSign.sg == 1 || GlobalSign.sg == 2) 3734 (void)sign_global_init(Files); 3735 else if (GlobalSign.sg == 3) 3736 for (f = Files; f; f = f->f_next) 3737 if (f->f_flags & FFLAG_SIGN) { 3738 (void)sign_global_init(Files); 3739 break; 3740 } 3741 #endif /* !DISABLE_SIGN */ 3742 3743 #ifndef DISABLE_TLS 3744 if (tls_status_msg) { 3745 loginfo("%s", tls_status_msg); 3746 free(tls_status_msg); 3747 } 3748 DPRINTF((D_NET|D_TLS), "Preparing sockets for TLS\n"); 3749 TLS_Listen_Set = 3750 socksetup_tls(PF_UNSPEC, tls_opt.bindhost, tls_opt.bindport); 3751 3752 for (f = Files; f; f = f->f_next) { 3753 if (f->f_type != F_TLS) 3754 continue; 3755 if (!tls_connect(f->f_un.f_tls.tls_conn)) { 3756 logerror("Unable to connect to TLS server %s", 3757 f->f_un.f_tls.tls_conn->hostname); 3758 /* Reconnect after x seconds */ 3759 schedule_event(&f->f_un.f_tls.tls_conn->event, 3760 &((struct timeval){TLS_RECONNECT_SEC, 0}), 3761 tls_reconnect, f->f_un.f_tls.tls_conn); 3762 } 3763 } 3764 #endif /* !DISABLE_TLS */ 3765 3766 loginfo("restart"); 3767 /* 3768 * Log a change in hostname, but only on a restart (we detect this 3769 * by checking to see if we're passed a kevent). 3770 */ 3771 if (oldLocalFQDN && strcmp(oldLocalFQDN, LocalFQDN) != 0) 3772 loginfo("host name changed, \"%s\" to \"%s\"", 3773 oldLocalFQDN, LocalFQDN); 3774 3775 RESTORE_SIGNALS(omask); 3776 } 3777 3778 /* 3779 * Crack a configuration file line 3780 */ 3781 void 3782 cfline(size_t linenum, const char *line, struct filed *f, const char *prog, 3783 const char *host) 3784 { 3785 struct addrinfo hints, *res; 3786 int error, i, pri, syncfile; 3787 const char *p, *q; 3788 char *bp; 3789 char buf[MAXLINE]; 3790 struct stat sb; 3791 3792 DPRINTF((D_CALL|D_PARSE), 3793 "cfline(%zu, \"%s\", f, \"%s\", \"%s\")\n", 3794 linenum, line, prog, host); 3795 3796 errno = 0; /* keep strerror() stuff out of logerror messages */ 3797 3798 /* clear out file entry */ 3799 memset(f, 0, sizeof(*f)); 3800 for (i = 0; i <= LOG_NFACILITIES; i++) 3801 f->f_pmask[i] = INTERNAL_NOPRI; 3802 STAILQ_INIT(&f->f_qhead); 3803 3804 /* 3805 * There should not be any space before the log facility. 3806 * Check this is okay, complain and fix if it is not. 3807 */ 3808 q = line; 3809 if (isblank((unsigned char)*line)) { 3810 errno = 0; 3811 logerror("Warning: `%s' space or tab before the log facility", 3812 line); 3813 /* Fix: strip all spaces/tabs before the log facility */ 3814 while (*q++ && isblank((unsigned char)*q)) 3815 /* skip blanks */; 3816 line = q; 3817 } 3818 3819 /* 3820 * q is now at the first char of the log facility 3821 * There should be at least one tab after the log facility 3822 * Check this is okay, and complain and fix if it is not. 3823 */ 3824 q = line + strlen(line); 3825 while (!isblank((unsigned char)*q) && (q != line)) 3826 q--; 3827 if ((q == line) && strlen(line)) { 3828 /* No tabs or space in a non empty line: complain */ 3829 errno = 0; 3830 logerror( 3831 "Error: `%s' log facility or log target missing", 3832 line); 3833 return; 3834 } 3835 3836 /* save host name, if any */ 3837 if (*host == '*') 3838 f->f_host = NULL; 3839 else { 3840 f->f_host = strdup(host); 3841 trim_anydomain(&f->f_host[1]); /* skip +/- at beginning */ 3842 } 3843 3844 /* save program name, if any */ 3845 if (*prog == '*') 3846 f->f_program = NULL; 3847 else 3848 f->f_program = strdup(prog); 3849 3850 /* scan through the list of selectors */ 3851 for (p = line; *p && !isblank((unsigned char)*p);) { 3852 int pri_done, pri_cmp, pri_invert; 3853 3854 /* find the end of this facility name list */ 3855 for (q = p; *q && !isblank((unsigned char)*q) && *q++ != '.'; ) 3856 continue; 3857 3858 /* get the priority comparison */ 3859 pri_cmp = 0; 3860 pri_done = 0; 3861 pri_invert = 0; 3862 if (*q == '!') { 3863 pri_invert = 1; 3864 q++; 3865 } 3866 while (! pri_done) { 3867 switch (*q) { 3868 case '<': 3869 pri_cmp = PRI_LT; 3870 q++; 3871 break; 3872 case '=': 3873 pri_cmp = PRI_EQ; 3874 q++; 3875 break; 3876 case '>': 3877 pri_cmp = PRI_GT; 3878 q++; 3879 break; 3880 default: 3881 pri_done = 1; 3882 break; 3883 } 3884 } 3885 3886 /* collect priority name */ 3887 for (bp = buf; *q && !strchr("\t ,;", *q); ) 3888 *bp++ = *q++; 3889 *bp = '\0'; 3890 3891 /* skip cruft */ 3892 while (strchr(",;", *q)) 3893 q++; 3894 3895 /* decode priority name */ 3896 if (*buf == '*') { 3897 pri = LOG_PRIMASK + 1; 3898 pri_cmp = PRI_LT | PRI_EQ | PRI_GT; 3899 } else { 3900 pri = decode(buf, prioritynames); 3901 if (pri < 0) { 3902 errno = 0; 3903 logerror("Unknown priority name `%s'", buf); 3904 return; 3905 } 3906 } 3907 if (pri_cmp == 0) 3908 pri_cmp = UniquePriority ? PRI_EQ 3909 : PRI_EQ | PRI_GT; 3910 if (pri_invert) 3911 pri_cmp ^= PRI_LT | PRI_EQ | PRI_GT; 3912 3913 /* scan facilities */ 3914 while (*p && !strchr("\t .;", *p)) { 3915 for (bp = buf; *p && !strchr("\t ,;.", *p); ) 3916 *bp++ = *p++; 3917 *bp = '\0'; 3918 if (*buf == '*') 3919 for (i = 0; i < LOG_NFACILITIES; i++) { 3920 f->f_pmask[i] = pri; 3921 f->f_pcmp[i] = pri_cmp; 3922 } 3923 else { 3924 i = decode(buf, facilitynames); 3925 if (i < 0) { 3926 errno = 0; 3927 logerror("Unknown facility name `%s'", 3928 buf); 3929 return; 3930 } 3931 f->f_pmask[i >> 3] = pri; 3932 f->f_pcmp[i >> 3] = pri_cmp; 3933 } 3934 while (*p == ',' || *p == ' ') 3935 p++; 3936 } 3937 3938 p = q; 3939 } 3940 3941 /* skip to action part */ 3942 while (isblank((unsigned char)*p)) 3943 p++; 3944 3945 /* 3946 * should this be "#ifndef DISABLE_SIGN" or is it a general option? 3947 * '+' before file destination: write with PRI field for later 3948 * verification 3949 */ 3950 if (*p == '+') { 3951 f->f_flags |= FFLAG_FULL; 3952 p++; 3953 } 3954 if (*p == '-') { 3955 syncfile = 0; 3956 p++; 3957 } else 3958 syncfile = 1; 3959 3960 switch (*p) { 3961 case '@': 3962 #ifndef DISABLE_SIGN 3963 if (GlobalSign.sg == 3) 3964 f->f_flags |= FFLAG_SIGN; 3965 #endif /* !DISABLE_SIGN */ 3966 #ifndef DISABLE_TLS 3967 if (*(p+1) == '[') { 3968 /* TLS destination */ 3969 if (!parse_tls_destination(p, f, linenum)) { 3970 logerror("Unable to parse action %s", p); 3971 break; 3972 } 3973 f->f_type = F_TLS; 3974 break; 3975 } 3976 #endif /* !DISABLE_TLS */ 3977 (void)strlcpy(f->f_un.f_forw.f_hname, ++p, 3978 sizeof(f->f_un.f_forw.f_hname)); 3979 memset(&hints, 0, sizeof(hints)); 3980 hints.ai_family = AF_UNSPEC; 3981 hints.ai_socktype = SOCK_DGRAM; 3982 hints.ai_protocol = 0; 3983 error = getaddrinfo(f->f_un.f_forw.f_hname, "syslog", &hints, 3984 &res); 3985 if (error) { 3986 errno = 0; 3987 logerror("%s", gai_strerror(error)); 3988 break; 3989 } 3990 f->f_un.f_forw.f_addr = res; 3991 f->f_type = F_FORW; 3992 NumForwards++; 3993 break; 3994 3995 case '/': 3996 #ifndef DISABLE_SIGN 3997 if (GlobalSign.sg == 3) 3998 f->f_flags |= FFLAG_SIGN; 3999 #endif /* !DISABLE_SIGN */ 4000 (void)strlcpy(f->f_un.f_fname, p, sizeof(f->f_un.f_fname)); 4001 if ((f->f_file = open(p, O_WRONLY|O_APPEND|O_NONBLOCK, 0)) < 0) 4002 { 4003 f->f_type = F_UNUSED; 4004 logerror("%s", p); 4005 break; 4006 } 4007 if (!fstat(f->f_file, &sb) && S_ISFIFO(sb.st_mode)) { 4008 f->f_file = -1; 4009 f->f_type = F_FIFO; 4010 break; 4011 } 4012 4013 if (isatty(f->f_file)) { 4014 f->f_type = F_TTY; 4015 if (strcmp(p, ctty) == 0) 4016 f->f_type = F_CONSOLE; 4017 } else 4018 f->f_type = F_FILE; 4019 4020 if (syncfile) 4021 f->f_flags |= FFLAG_SYNC; 4022 break; 4023 4024 case '|': 4025 #ifndef DISABLE_SIGN 4026 if (GlobalSign.sg == 3) 4027 f->f_flags |= FFLAG_SIGN; 4028 #endif 4029 f->f_un.f_pipe.f_pid = 0; 4030 (void) strlcpy(f->f_un.f_pipe.f_pname, p + 1, 4031 sizeof(f->f_un.f_pipe.f_pname)); 4032 f->f_type = F_PIPE; 4033 break; 4034 4035 case '*': 4036 f->f_type = F_WALL; 4037 break; 4038 4039 default: 4040 for (i = 0; i < MAXUNAMES && *p; i++) { 4041 for (q = p; *q && *q != ','; ) 4042 q++; 4043 (void)strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE); 4044 if ((q - p) > UT_NAMESIZE) 4045 f->f_un.f_uname[i][UT_NAMESIZE] = '\0'; 4046 else 4047 f->f_un.f_uname[i][q - p] = '\0'; 4048 while (*q == ',' || *q == ' ') 4049 q++; 4050 p = q; 4051 } 4052 f->f_type = F_USERS; 4053 break; 4054 } 4055 } 4056 4057 4058 /* 4059 * Decode a symbolic name to a numeric value 4060 */ 4061 int 4062 decode(const char *name, CODE *codetab) 4063 { 4064 CODE *c; 4065 char *p, buf[40]; 4066 4067 if (isdigit((unsigned char)*name)) 4068 return atoi(name); 4069 4070 for (p = buf; *name && p < &buf[sizeof(buf) - 1]; p++, name++) { 4071 if (isupper((unsigned char)*name)) 4072 *p = tolower((unsigned char)*name); 4073 else 4074 *p = *name; 4075 } 4076 *p = '\0'; 4077 for (c = codetab; c->c_name; c++) 4078 if (!strcmp(buf, c->c_name)) 4079 return c->c_val; 4080 4081 return -1; 4082 } 4083 4084 /* 4085 * Retrieve the size of the kernel message buffer, via sysctl. 4086 */ 4087 int 4088 getmsgbufsize(void) 4089 { 4090 #ifdef __NetBSD_Version__ 4091 int msgbufsize, mib[2]; 4092 size_t size; 4093 4094 mib[0] = CTL_KERN; 4095 mib[1] = KERN_MSGBUFSIZE; 4096 size = sizeof msgbufsize; 4097 if (sysctl(mib, 2, &msgbufsize, &size, NULL, 0) == -1) { 4098 DPRINTF(D_MISC, "Couldn't get kern.msgbufsize\n"); 4099 return 0; 4100 } 4101 return msgbufsize; 4102 #else 4103 return MAXLINE; 4104 #endif /* __NetBSD_Version__ */ 4105 } 4106 4107 /* 4108 * Retrieve the hostname, via sysctl. 4109 */ 4110 char * 4111 getLocalFQDN(void) 4112 { 4113 int mib[2]; 4114 char *hostname; 4115 size_t len; 4116 4117 mib[0] = CTL_KERN; 4118 mib[1] = KERN_HOSTNAME; 4119 sysctl(mib, 2, NULL, &len, NULL, 0); 4120 4121 if (!(hostname = malloc(len))) { 4122 logerror("Unable to allocate memory"); 4123 die(0,0,NULL); 4124 } else if (sysctl(mib, 2, hostname, &len, NULL, 0) == -1) { 4125 DPRINTF(D_MISC, "Couldn't get kern.hostname\n"); 4126 (void)gethostname(hostname, sizeof(len)); 4127 } 4128 return hostname; 4129 } 4130 4131 struct socketEvent * 4132 socksetup(int af, const char *hostname) 4133 { 4134 struct addrinfo hints, *res, *r; 4135 int error, maxs; 4136 int on = 1; 4137 struct socketEvent *s, *socks; 4138 4139 if (SecureMode && !NumForwards) 4140 return NULL; 4141 4142 memset(&hints, 0, sizeof(hints)); 4143 hints.ai_flags = AI_PASSIVE; 4144 hints.ai_family = af; 4145 hints.ai_socktype = SOCK_DGRAM; 4146 error = getaddrinfo(hostname, "syslog", &hints, &res); 4147 if (error) { 4148 errno = 0; 4149 logerror("%s", gai_strerror(error)); 4150 die(0, 0, NULL); 4151 } 4152 4153 /* Count max number of sockets we may open */ 4154 for (maxs = 0, r = res; r; r = r->ai_next, maxs++) 4155 continue; 4156 socks = calloc(maxs+1, sizeof(*socks)); 4157 if (!socks) { 4158 logerror("Couldn't allocate memory for sockets"); 4159 die(0, 0, NULL); 4160 } 4161 4162 socks->fd = 0; /* num of sockets counter at start of array */ 4163 s = socks + 1; 4164 for (r = res; r; r = r->ai_next) { 4165 s->fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol); 4166 if (s->fd < 0) { 4167 logerror("socket() failed"); 4168 continue; 4169 } 4170 s->af = r->ai_family; 4171 if (r->ai_family == AF_INET6 && setsockopt(s->fd, IPPROTO_IPV6, 4172 IPV6_V6ONLY, &on, sizeof(on)) < 0) { 4173 logerror("setsockopt(IPV6_V6ONLY) failed"); 4174 close(s->fd); 4175 continue; 4176 } 4177 4178 if (!SecureMode) { 4179 if (bind(s->fd, r->ai_addr, r->ai_addrlen) < 0) { 4180 logerror("bind() failed"); 4181 close(s->fd); 4182 continue; 4183 } 4184 s->ev = allocev(); 4185 event_set(s->ev, s->fd, EV_READ | EV_PERSIST, 4186 dispatch_read_finet, s->ev); 4187 if (event_add(s->ev, NULL) == -1) { 4188 DPRINTF((D_EVENT|D_NET), 4189 "Failure in event_add()\n"); 4190 } else { 4191 DPRINTF((D_EVENT|D_NET), 4192 "Listen on UDP port " 4193 "(event@%p)\n", s->ev); 4194 } 4195 } 4196 4197 socks->fd++; /* num counter */ 4198 s++; 4199 } 4200 4201 if (res) 4202 freeaddrinfo(res); 4203 if (socks->fd == 0) { 4204 free (socks); 4205 if (Debug) 4206 return NULL; 4207 else 4208 die(0, 0, NULL); 4209 } 4210 return socks; 4211 } 4212 4213 /* 4214 * Fairly similar to popen(3), but returns an open descriptor, as opposed 4215 * to a FILE *. 4216 */ 4217 int 4218 p_open(char *prog, pid_t *rpid) 4219 { 4220 static char sh[] = "sh", mc[] = "-c"; 4221 int pfd[2], nulldesc, i; 4222 pid_t pid; 4223 char *argv[4]; /* sh -c cmd NULL */ 4224 4225 if (pipe(pfd) == -1) 4226 return -1; 4227 if ((nulldesc = open(_PATH_DEVNULL, O_RDWR)) == -1) { 4228 /* We are royally screwed anyway. */ 4229 return -1; 4230 } 4231 4232 switch ((pid = fork())) { 4233 case -1: 4234 (void) close(nulldesc); 4235 return -1; 4236 4237 case 0: 4238 argv[0] = sh; 4239 argv[1] = mc; 4240 argv[2] = prog; 4241 argv[3] = NULL; 4242 4243 (void) setsid(); /* avoid catching SIGHUPs. */ 4244 4245 /* 4246 * Reset ignored signals to their default behavior. 4247 */ 4248 (void)signal(SIGTERM, SIG_DFL); 4249 (void)signal(SIGINT, SIG_DFL); 4250 (void)signal(SIGQUIT, SIG_DFL); 4251 (void)signal(SIGPIPE, SIG_DFL); 4252 (void)signal(SIGHUP, SIG_DFL); 4253 4254 dup2(pfd[0], STDIN_FILENO); 4255 dup2(nulldesc, STDOUT_FILENO); 4256 dup2(nulldesc, STDERR_FILENO); 4257 for (i = getdtablesize(); i > 2; i--) 4258 (void) close(i); 4259 4260 (void) execvp(_PATH_BSHELL, argv); 4261 _exit(255); 4262 } 4263 4264 (void) close(nulldesc); 4265 (void) close(pfd[0]); 4266 4267 /* 4268 * Avoid blocking on a hung pipe. With O_NONBLOCK, we are 4269 * supposed to get an EWOULDBLOCK on writev(2), which is 4270 * caught by the logic above anyway, which will in turn 4271 * close the pipe, and fork a new logging subprocess if 4272 * necessary. The stale subprocess will be killed some 4273 * time later unless it terminated itself due to closing 4274 * its input pipe. 4275 */ 4276 if (fcntl(pfd[1], F_SETFL, O_NONBLOCK) == -1) { 4277 /* This is bad. */ 4278 logerror("Warning: cannot change pipe to pid %d to " 4279 "non-blocking.", (int) pid); 4280 } 4281 *rpid = pid; 4282 return pfd[1]; 4283 } 4284 4285 void 4286 deadq_enter(pid_t pid, const char *name) 4287 { 4288 dq_t p; 4289 int status; 4290 4291 /* 4292 * Be paranoid: if we can't signal the process, don't enter it 4293 * into the dead queue (perhaps it's already dead). If possible, 4294 * we try to fetch and log the child's status. 4295 */ 4296 if (kill(pid, 0) != 0) { 4297 if (waitpid(pid, &status, WNOHANG) > 0) 4298 log_deadchild(pid, status, name); 4299 return; 4300 } 4301 4302 p = malloc(sizeof(*p)); 4303 if (p == NULL) { 4304 logerror("panic: out of memory!"); 4305 exit(1); 4306 } 4307 4308 p->dq_pid = pid; 4309 p->dq_timeout = DQ_TIMO_INIT; 4310 TAILQ_INSERT_TAIL(&deadq_head, p, dq_entries); 4311 } 4312 4313 int 4314 deadq_remove(pid_t pid) 4315 { 4316 dq_t q; 4317 4318 for (q = TAILQ_FIRST(&deadq_head); q != NULL; 4319 q = TAILQ_NEXT(q, dq_entries)) { 4320 if (q->dq_pid == pid) { 4321 TAILQ_REMOVE(&deadq_head, q, dq_entries); 4322 free(q); 4323 return 1; 4324 } 4325 } 4326 return 0; 4327 } 4328 4329 void 4330 log_deadchild(pid_t pid, int status, const char *name) 4331 { 4332 int code; 4333 char buf[256]; 4334 const char *reason; 4335 4336 /* Keep strerror() struff out of logerror messages. */ 4337 errno = 0; 4338 if (WIFSIGNALED(status)) { 4339 reason = "due to signal"; 4340 code = WTERMSIG(status); 4341 } else { 4342 reason = "with status"; 4343 code = WEXITSTATUS(status); 4344 if (code == 0) 4345 return; 4346 } 4347 (void) snprintf(buf, sizeof(buf), 4348 "Logging subprocess %d (%s) exited %s %d.", 4349 pid, name, reason, code); 4350 logerror("%s", buf); 4351 } 4352 4353 struct event * 4354 allocev(void) 4355 { 4356 struct event *ev; 4357 4358 if (!(ev = calloc(1, sizeof(*ev)))) 4359 logerror("Unable to allocate memory"); 4360 return ev; 4361 } 4362 4363 /* *ev is allocated if necessary */ 4364 void 4365 schedule_event(struct event **ev, struct timeval *tv, 4366 void (*cb)(int, short, void *), void *arg) 4367 { 4368 if (!*ev && !(*ev = allocev())) { 4369 return; 4370 } 4371 event_set(*ev, 0, 0, cb, arg); 4372 DPRINTF(D_EVENT, "event_add(%s@%p)\n", "schedule_ev", *ev); \ 4373 if (event_add(*ev, tv) == -1) { 4374 DPRINTF(D_EVENT, "Failure in event_add()\n"); 4375 } 4376 } 4377 4378 #ifndef DISABLE_TLS 4379 /* abbreviation for freeing credential lists */ 4380 void 4381 free_cred_SLIST(struct peer_cred_head *head) 4382 { 4383 struct peer_cred *cred; 4384 4385 while (!SLIST_EMPTY(head)) { 4386 cred = SLIST_FIRST(head); 4387 SLIST_REMOVE_HEAD(head, entries); 4388 FREEPTR(cred->data); 4389 FREEPTR(cred); 4390 } 4391 } 4392 #endif /* !DISABLE_TLS */ 4393 4394 /* 4395 * send message queue after reconnect 4396 */ 4397 /*ARGSUSED*/ 4398 void 4399 send_queue(int fd, short event, void *arg) 4400 { 4401 struct filed *f = (struct filed *) arg; 4402 struct buf_queue *qentry; 4403 #define SQ_CHUNK_SIZE 250 4404 size_t cnt = 0; 4405 4406 #ifndef DISABLE_TLS 4407 if (f->f_type == F_TLS) { 4408 /* use a flag to prevent recursive calls to send_queue() */ 4409 if (f->f_un.f_tls.tls_conn->send_queue) 4410 return; 4411 else 4412 f->f_un.f_tls.tls_conn->send_queue = true; 4413 } 4414 DPRINTF((D_DATA|D_CALL), "send_queue(f@%p with %zu msgs, " 4415 "cnt@%p = %zu)\n", f, f->f_qelements, &cnt, cnt); 4416 #endif /* !DISABLE_TLS */ 4417 4418 while ((qentry = STAILQ_FIRST(&f->f_qhead))) { 4419 #ifndef DISABLE_TLS 4420 /* send_queue() might be called with an unconnected destination 4421 * from init() or die() or one message might take longer, 4422 * leaving the connection in state ST_WAITING and thus not 4423 * ready for the next message. 4424 * this check is a shortcut to skip these unnecessary calls */ 4425 if (f->f_type == F_TLS 4426 && f->f_un.f_tls.tls_conn->state != ST_TLS_EST) { 4427 DPRINTF(D_TLS, "abort send_queue(cnt@%p = %zu) " 4428 "on TLS connection in state %d\n", 4429 &cnt, cnt, f->f_un.f_tls.tls_conn->state); 4430 return; 4431 } 4432 #endif /* !DISABLE_TLS */ 4433 fprintlog(f, qentry->msg, qentry); 4434 4435 /* Sending a long queue can take some time during which 4436 * SIGHUP and SIGALRM are blocked and no events are handled. 4437 * To avoid that we only send SQ_CHUNK_SIZE messages at once 4438 * and then reschedule ourselves to continue. Thus the control 4439 * will return first from all signal-protected functions so a 4440 * possible SIGHUP/SIGALRM is handled and then back to the 4441 * main loop which can handle possible input. 4442 */ 4443 if (++cnt >= SQ_CHUNK_SIZE) { 4444 if (!f->f_sq_event) { /* alloc on demand */ 4445 f->f_sq_event = allocev(); 4446 event_set(f->f_sq_event, 0, 0, send_queue, f); 4447 } 4448 if (event_add(f->f_sq_event, &((struct timeval){0, 1})) == -1) { 4449 DPRINTF(D_EVENT, "Failure in event_add()\n"); 4450 } 4451 break; 4452 } 4453 } 4454 #ifndef DISABLE_TLS 4455 if (f->f_type == F_TLS) 4456 f->f_un.f_tls.tls_conn->send_queue = false; 4457 #endif 4458 4459 } 4460 4461 /* 4462 * finds the next queue element to delete 4463 * 4464 * has stateful behaviour, before using it call once with reset = true 4465 * after that every call will return one next queue element to delete, 4466 * depending on strategy either the oldest or the one with the lowest priority 4467 */ 4468 static struct buf_queue * 4469 find_qentry_to_delete(const struct buf_queue_head *head, int strategy, 4470 bool reset) 4471 { 4472 static int pri; 4473 static struct buf_queue *qentry_static; 4474 4475 struct buf_queue *qentry_tmp; 4476 4477 if (reset || STAILQ_EMPTY(head)) { 4478 pri = LOG_DEBUG; 4479 qentry_static = STAILQ_FIRST(head); 4480 return NULL; 4481 } 4482 4483 /* find elements to delete */ 4484 if (strategy == PURGE_BY_PRIORITY) { 4485 qentry_tmp = qentry_static; 4486 if (!qentry_tmp) return NULL; 4487 while ((qentry_tmp = STAILQ_NEXT(qentry_tmp, entries)) != NULL) 4488 { 4489 if (LOG_PRI(qentry_tmp->msg->pri) == pri) { 4490 /* save the successor, because qentry_tmp 4491 * is probably deleted by the caller */ 4492 qentry_static = STAILQ_NEXT(qentry_tmp, entries); 4493 return qentry_tmp; 4494 } 4495 } 4496 /* nothing found in while loop --> next pri */ 4497 if (--pri) 4498 return find_qentry_to_delete(head, strategy, false); 4499 else 4500 return NULL; 4501 } else /* strategy == PURGE_OLDEST or other value */ { 4502 qentry_tmp = qentry_static; 4503 qentry_static = STAILQ_NEXT(qentry_tmp, entries); 4504 return qentry_tmp; /* is NULL on empty queue */ 4505 } 4506 } 4507 4508 /* note on TAILQ: newest message added at TAIL, 4509 * oldest to be removed is FIRST 4510 */ 4511 /* 4512 * checks length of a destination's message queue 4513 * if del_entries == 0 then assert queue length is 4514 * less or equal to configured number of queue elements 4515 * otherwise del_entries tells how many entries to delete 4516 * 4517 * returns the number of removed queue elements 4518 * (which not necessarily means free'd messages) 4519 * 4520 * strategy PURGE_OLDEST to delete oldest entry, e.g. after it was resent 4521 * strategy PURGE_BY_PRIORITY to delete messages with lowest priority first, 4522 * this is much slower but might be desirable when unsent messages have 4523 * to be deleted, e.g. in call from domark() 4524 */ 4525 size_t 4526 message_queue_purge(struct filed *f, size_t del_entries, int strategy) 4527 { 4528 size_t removed = 0; 4529 struct buf_queue *qentry = NULL; 4530 4531 DPRINTF((D_CALL|D_BUFFER), "purge_message_queue(%p, %zu, %d) with " 4532 "f_qelements=%zu and f_qsize=%zu\n", 4533 f, del_entries, strategy, 4534 f->f_qelements, f->f_qsize); 4535 4536 /* reset state */ 4537 (void)find_qentry_to_delete(&f->f_qhead, strategy, true); 4538 4539 while (removed < del_entries 4540 || (TypeInfo[f->f_type].queue_length != -1 4541 && (size_t)TypeInfo[f->f_type].queue_length <= f->f_qelements) 4542 || (TypeInfo[f->f_type].queue_size != -1 4543 && (size_t)TypeInfo[f->f_type].queue_size <= f->f_qsize)) { 4544 qentry = find_qentry_to_delete(&f->f_qhead, strategy, 0); 4545 if (message_queue_remove(f, qentry)) 4546 removed++; 4547 else 4548 break; 4549 } 4550 return removed; 4551 } 4552 4553 /* run message_queue_purge() for all destinations to free memory */ 4554 size_t 4555 message_allqueues_purge(void) 4556 { 4557 size_t sum = 0; 4558 struct filed *f; 4559 4560 for (f = Files; f; f = f->f_next) 4561 sum += message_queue_purge(f, 4562 f->f_qelements/10, PURGE_BY_PRIORITY); 4563 4564 DPRINTF(D_BUFFER, 4565 "message_allqueues_purge(): removed %zu buffer entries\n", sum); 4566 return sum; 4567 } 4568 4569 /* run message_queue_purge() for all destinations to check limits */ 4570 size_t 4571 message_allqueues_check(void) 4572 { 4573 size_t sum = 0; 4574 struct filed *f; 4575 4576 for (f = Files; f; f = f->f_next) 4577 sum += message_queue_purge(f, 0, PURGE_BY_PRIORITY); 4578 DPRINTF(D_BUFFER, 4579 "message_allqueues_check(): removed %zu buffer entries\n", sum); 4580 return sum; 4581 } 4582 4583 struct buf_msg * 4584 buf_msg_new(const size_t len) 4585 { 4586 struct buf_msg *newbuf; 4587 4588 CALLOC(newbuf, sizeof(*newbuf)); 4589 4590 if (len) { /* len = 0 is valid */ 4591 MALLOC(newbuf->msg, len); 4592 newbuf->msgorig = newbuf->msg; 4593 newbuf->msgsize = len; 4594 } 4595 return NEWREF(newbuf); 4596 } 4597 4598 void 4599 buf_msg_free(struct buf_msg *buf) 4600 { 4601 if (!buf) 4602 return; 4603 4604 buf->refcount--; 4605 if (buf->refcount == 0) { 4606 FREEPTR(buf->timestamp); 4607 /* small optimizations: the host/recvhost may point to the 4608 * global HostName/FQDN. of course this must not be free()d 4609 * same goes for appname and include_pid 4610 */ 4611 if (buf->recvhost != buf->host 4612 && buf->recvhost != LocalHostName 4613 && buf->recvhost != LocalFQDN 4614 && buf->recvhost != oldLocalFQDN) 4615 FREEPTR(buf->recvhost); 4616 if (buf->host != LocalHostName 4617 && buf->host != LocalFQDN 4618 && buf->host != oldLocalFQDN) 4619 FREEPTR(buf->host); 4620 if (buf->prog != appname) 4621 FREEPTR(buf->prog); 4622 if (buf->pid != include_pid) 4623 FREEPTR(buf->pid); 4624 FREEPTR(buf->msgid); 4625 FREEPTR(buf->sd); 4626 FREEPTR(buf->msgorig); /* instead of msg */ 4627 FREEPTR(buf); 4628 } 4629 } 4630 4631 size_t 4632 buf_queue_obj_size(struct buf_queue *qentry) 4633 { 4634 size_t sum = 0; 4635 4636 if (!qentry) 4637 return 0; 4638 sum += sizeof(*qentry) 4639 + sizeof(*qentry->msg) 4640 + qentry->msg->msgsize 4641 + SAFEstrlen(qentry->msg->timestamp)+1 4642 + SAFEstrlen(qentry->msg->msgid)+1; 4643 if (qentry->msg->prog 4644 && qentry->msg->prog != appname) 4645 sum += strlen(qentry->msg->prog)+1; 4646 if (qentry->msg->pid 4647 && qentry->msg->pid != include_pid) 4648 sum += strlen(qentry->msg->pid)+1; 4649 if (qentry->msg->recvhost 4650 && qentry->msg->recvhost != LocalHostName 4651 && qentry->msg->recvhost != LocalFQDN 4652 && qentry->msg->recvhost != oldLocalFQDN) 4653 sum += strlen(qentry->msg->recvhost)+1; 4654 if (qentry->msg->host 4655 && qentry->msg->host != LocalHostName 4656 && qentry->msg->host != LocalFQDN 4657 && qentry->msg->host != oldLocalFQDN) 4658 sum += strlen(qentry->msg->host)+1; 4659 4660 return sum; 4661 } 4662 4663 bool 4664 message_queue_remove(struct filed *f, struct buf_queue *qentry) 4665 { 4666 if (!f || !qentry || !qentry->msg) 4667 return false; 4668 4669 assert(!STAILQ_EMPTY(&f->f_qhead)); 4670 STAILQ_REMOVE(&f->f_qhead, qentry, buf_queue, entries); 4671 f->f_qelements--; 4672 f->f_qsize -= buf_queue_obj_size(qentry); 4673 4674 DPRINTF(D_BUFFER, "msg @%p removed from queue @%p, new qlen = %zu\n", 4675 qentry->msg, f, f->f_qelements); 4676 DELREF(qentry->msg); 4677 FREEPTR(qentry); 4678 return true; 4679 } 4680 4681 /* 4682 * returns *qentry on success and NULL on error 4683 */ 4684 struct buf_queue * 4685 message_queue_add(struct filed *f, struct buf_msg *buffer) 4686 { 4687 struct buf_queue *qentry; 4688 4689 /* check on every call or only every n-th time? */ 4690 message_queue_purge(f, 0, PURGE_BY_PRIORITY); 4691 4692 while (!(qentry = malloc(sizeof(*qentry))) 4693 && message_queue_purge(f, 1, PURGE_OLDEST)) 4694 continue; 4695 if (!qentry) { 4696 logerror("Unable to allocate memory"); 4697 DPRINTF(D_BUFFER, "queue empty, no memory, msg dropped\n"); 4698 return NULL; 4699 } else { 4700 qentry->msg = buffer; 4701 f->f_qelements++; 4702 f->f_qsize += buf_queue_obj_size(qentry); 4703 STAILQ_INSERT_TAIL(&f->f_qhead, qentry, entries); 4704 4705 DPRINTF(D_BUFFER, "msg @%p queued @%p, qlen = %zu\n", 4706 buffer, f, f->f_qelements); 4707 return qentry; 4708 } 4709 } 4710 4711 void 4712 message_queue_freeall(struct filed *f) 4713 { 4714 struct buf_queue *qentry; 4715 4716 if (!f) return; 4717 DPRINTF(D_MEM, "message_queue_freeall(f@%p) with f_qhead@%p\n", f, 4718 &f->f_qhead); 4719 4720 while (!STAILQ_EMPTY(&f->f_qhead)) { 4721 qentry = STAILQ_FIRST(&f->f_qhead); 4722 STAILQ_REMOVE(&f->f_qhead, qentry, buf_queue, entries); 4723 DELREF(qentry->msg); 4724 FREEPTR(qentry); 4725 } 4726 4727 f->f_qelements = 0; 4728 f->f_qsize = 0; 4729 } 4730 4731 #ifndef DISABLE_TLS 4732 /* utility function for tls_reconnect() */ 4733 struct filed * 4734 get_f_by_conninfo(struct tls_conn_settings *conn_info) 4735 { 4736 struct filed *f; 4737 4738 for (f = Files; f; f = f->f_next) { 4739 if ((f->f_type == F_TLS) && f->f_un.f_tls.tls_conn == conn_info) 4740 return f; 4741 } 4742 DPRINTF(D_TLS, "get_f_by_conninfo() called on invalid conn_info\n"); 4743 return NULL; 4744 } 4745 4746 /* 4747 * Called on signal. 4748 * Lets the admin reconnect without waiting for the reconnect timer expires. 4749 */ 4750 /*ARGSUSED*/ 4751 void 4752 dispatch_force_tls_reconnect(int fd, short event, void *ev) 4753 { 4754 struct filed *f; 4755 DPRINTF((D_TLS|D_CALL|D_EVENT), "dispatch_force_tls_reconnect()\n"); 4756 for (f = Files; f; f = f->f_next) { 4757 if (f->f_type == F_TLS && 4758 f->f_un.f_tls.tls_conn->state == ST_NONE) 4759 tls_reconnect(fd, event, f->f_un.f_tls.tls_conn); 4760 } 4761 } 4762 #endif /* !DISABLE_TLS */ 4763 4764 /* 4765 * return a timestamp in a static buffer, 4766 * either format the timestamp given by parameter in_now 4767 * or use the current time if in_now is NULL. 4768 */ 4769 char * 4770 make_timestamp(time_t *in_now, bool iso, size_t tlen) 4771 { 4772 int frac_digits = 6; 4773 struct timeval tv; 4774 time_t mytime; 4775 struct tm ltime; 4776 int len = 0; 4777 int tzlen = 0; 4778 /* uses global var: time_t now; */ 4779 4780 if (in_now) { 4781 mytime = *in_now; 4782 } else { 4783 gettimeofday(&tv, NULL); 4784 mytime = now = tv.tv_sec; 4785 } 4786 4787 if (!iso) { 4788 strlcpy(timestamp, ctime(&mytime) + 4, sizeof(timestamp)); 4789 timestamp[BSD_TIMESTAMPLEN] = '\0'; 4790 } else { 4791 localtime_r(&mytime, <ime); 4792 len += strftime(timestamp, sizeof(timestamp), "%FT%T", <ime); 4793 snprintf(×tamp[len], frac_digits + 2, ".%.*jd", 4794 frac_digits, (intmax_t)tv.tv_usec); 4795 len += frac_digits + 1; 4796 tzlen = strftime(×tamp[len], sizeof(timestamp) - len, 4797 "%z", <ime); 4798 len += tzlen; 4799 4800 if (tzlen == 5) { 4801 /* strftime gives "+0200", but we need "+02:00" */ 4802 timestamp[len + 2] = '\0'; 4803 timestamp[len + 1] = timestamp[len]; 4804 timestamp[len] = timestamp[len - 1]; 4805 timestamp[len - 1] = timestamp[len - 2]; 4806 timestamp[len - 2] = ':'; 4807 } 4808 } 4809 4810 switch (tlen) { 4811 case (size_t)-1: 4812 return timestamp; 4813 case 0: 4814 return strdup(timestamp); 4815 default: 4816 return strndup(timestamp, tlen); 4817 } 4818 } 4819 4820 /* auxiliary code to allocate memory and copy a string */ 4821 bool 4822 copy_string(char **mem, const char *p, const char *q) 4823 { 4824 const size_t len = 1 + q - p; 4825 if (!(*mem = malloc(len))) { 4826 logerror("Unable to allocate memory for config"); 4827 return false; 4828 } 4829 strlcpy(*mem, p, len); 4830 return true; 4831 } 4832 4833 /* keyword has to end with ", everything until next " is copied */ 4834 bool 4835 copy_config_value_quoted(const char *keyword, char **mem, const char **p) 4836 { 4837 const char *q; 4838 if (strncasecmp(*p, keyword, strlen(keyword))) 4839 return false; 4840 q = *p += strlen(keyword); 4841 if (!(q = strchr(*p, '"'))) { 4842 errno = 0; 4843 logerror("unterminated \"\n"); 4844 return false; 4845 } 4846 if (!(copy_string(mem, *p, q))) 4847 return false; 4848 *p = ++q; 4849 return true; 4850 } 4851 4852 /* for config file: 4853 * following = required but whitespace allowed, quotes optional 4854 * if numeric, then conversion to integer and no memory allocation 4855 */ 4856 bool 4857 copy_config_value(const char *keyword, char **mem, 4858 const char **p, const char *file, int line) 4859 { 4860 if (strncasecmp(*p, keyword, strlen(keyword))) 4861 return false; 4862 *p += strlen(keyword); 4863 4864 while (isspace((unsigned char)**p)) 4865 *p += 1; 4866 if (**p != '=') { 4867 errno = 0; 4868 logerror("expected \"=\" in file %s, line %d", file, line); 4869 return false; 4870 } 4871 *p += 1; 4872 4873 return copy_config_value_word(mem, p); 4874 } 4875 4876 /* copy next parameter from a config line */ 4877 bool 4878 copy_config_value_word(char **mem, const char **p) 4879 { 4880 const char *q; 4881 while (isspace((unsigned char)**p)) 4882 *p += 1; 4883 if (**p == '"') 4884 return copy_config_value_quoted("\"", mem, p); 4885 4886 /* without quotes: find next whitespace or end of line */ 4887 (void)((q = strchr(*p, ' ')) || (q = strchr(*p, '\t')) 4888 || (q = strchr(*p, '\n')) || (q = strchr(*p, '\0'))); 4889 4890 if (q-*p == 0 || !(copy_string(mem, *p, q))) 4891 return false; 4892 4893 *p = ++q; 4894 return true; 4895 } 4896 4897 static int 4898 writev1(int fd, struct iovec *iov, size_t count) 4899 { 4900 ssize_t nw = 0, tot = 0; 4901 size_t ntries = 5; 4902 4903 if (count == 0) 4904 return 0; 4905 while (ntries--) { 4906 switch ((nw = writev(fd, iov, count))) { 4907 case -1: 4908 if (errno == EAGAIN || errno == EWOULDBLOCK) { 4909 struct pollfd pfd; 4910 pfd.fd = fd; 4911 pfd.events = POLLOUT; 4912 pfd.revents = 0; 4913 (void)poll(&pfd, 1, 500); 4914 continue; 4915 } 4916 return -1; 4917 case 0: 4918 return 0; 4919 default: 4920 tot += nw; 4921 while (nw > 0) { 4922 if (iov->iov_len > (size_t)nw) { 4923 iov->iov_len -= nw; 4924 iov->iov_base = 4925 (char *)iov->iov_base + nw; 4926 break; 4927 } else { 4928 if (--count == 0) 4929 return tot; 4930 nw -= iov->iov_len; 4931 iov++; 4932 } 4933 } 4934 } 4935 } 4936 return tot == 0 ? nw : tot; 4937 } 4938 4939 4940 #ifdef NDEBUG 4941 /* 4942 * -d also controls daemoniziation, so it makes sense even with 4943 * NDEBUG, but if the user also tries to specify the logging details 4944 * with an argument, warn them it's not compiled into this binary. 4945 */ 4946 void 4947 set_debug(const char *level) 4948 { 4949 Debug = D_DEFAULT; 4950 if (level == NULL) 4951 return; 4952 4953 /* don't bother parsing the argument */ 4954 fprintf(stderr, 4955 "%s: debug logging is not compiled\n", 4956 getprogname()); 4957 } 4958 4959 #else /* !NDEBUG */ 4960 void 4961 set_debug(const char *level) 4962 { 4963 if (level == NULL) { 4964 Debug = D_DEFAULT; /* compat */ 4965 return; 4966 } 4967 4968 /* skip initial whitespace for consistency with strto*l */ 4969 while (isspace((unsigned char)*level)) 4970 ++level; 4971 4972 /* accept ~num to mean "all except num" */ 4973 bool invert = level[0] == '~'; 4974 if (invert) 4975 ++level; 4976 4977 errno = 0; 4978 char *endp = NULL; 4979 unsigned long bits = strtoul(level, &endp, 0); 4980 if (errno || endp == level || *endp != '\0') { 4981 fprintf(stderr, "%s: bad argument to -d\n", getprogname()); 4982 usage(); 4983 } 4984 if (invert) 4985 bits = ~bits; 4986 4987 Debug = bits & D_ALL; 4988 4989 /* 4990 * make it possible to use -d to stay in the foreground but 4991 * suppress all dbprintf output (there better be free bits in 4992 * typeof(Debug) that are not in D_ALL). 4993 */ 4994 if (Debug == 0) 4995 Debug = ~D_ALL; 4996 } 4997 #endif /* !NDEBUG */ 4998 4999 5000 #ifndef NDEBUG 5001 void 5002 dbprintf(const char *fname, const char *funname, 5003 size_t lnum, const char *fmt, ...) 5004 { 5005 va_list ap; 5006 char *ts; 5007 5008 ts = make_timestamp(NULL, true, (size_t)-1); 5009 printf("%s:%s:%s:%.4zu\t", ts, fname, funname, lnum); 5010 5011 va_start(ap, fmt); 5012 vprintf(fmt, ap); 5013 va_end(ap); 5014 } 5015 #endif 5016