1 /* $OpenBSD: log.c,v 1.67 2026/02/14 00:18:34 jsg Exp $ */ 2 /* 3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5 * All rights reserved 6 * 7 * As far as I am concerned, the code I have written for this software 8 * can be used freely for any purpose. Any derived versions of this 9 * software must be clearly marked as such, and if the derived work is 10 * incompatible with the protocol description in the RFC file, it must be 11 * called by a name other than "ssh" or "Secure Shell". 12 */ 13 /* 14 * Copyright (c) 2000 Markus Friedl. All rights reserved. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 #include "includes.h" 38 39 #include <sys/types.h> 40 41 #include <errno.h> 42 #include <fcntl.h> 43 #include <limits.h> 44 #include <stdarg.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <syslog.h> 49 #include <unistd.h> 50 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) 51 # include <vis.h> 52 #endif 53 54 #include "log.h" 55 #include "match.h" 56 57 static LogLevel log_level = SYSLOG_LEVEL_INFO; 58 static int log_on_stderr = 1; 59 static int log_stderr_fd = STDERR_FILENO; 60 static int log_facility = LOG_AUTH; 61 static const char *argv0; 62 static log_handler_fn *log_handler; 63 static void *log_handler_ctx; 64 static char **log_verbose; 65 static size_t nlog_verbose; 66 extern char *__progname; 67 68 #define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL) 69 #define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL) 70 71 /* textual representation of log-facilities/levels */ 72 73 static struct { 74 const char *name; 75 SyslogFacility val; 76 } log_facilities[] = { 77 { "DAEMON", SYSLOG_FACILITY_DAEMON }, 78 { "USER", SYSLOG_FACILITY_USER }, 79 { "AUTH", SYSLOG_FACILITY_AUTH }, 80 #ifdef LOG_AUTHPRIV 81 { "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV }, 82 #endif 83 { "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, 84 { "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, 85 { "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, 86 { "LOCAL3", SYSLOG_FACILITY_LOCAL3 }, 87 { "LOCAL4", SYSLOG_FACILITY_LOCAL4 }, 88 { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, 89 { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, 90 { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, 91 { NULL, SYSLOG_FACILITY_NOT_SET } 92 }; 93 94 static struct { 95 const char *name; 96 LogLevel val; 97 } log_levels[] = 98 { 99 { "QUIET", SYSLOG_LEVEL_QUIET }, 100 { "FATAL", SYSLOG_LEVEL_FATAL }, 101 { "ERROR", SYSLOG_LEVEL_ERROR }, 102 { "INFO", SYSLOG_LEVEL_INFO }, 103 { "VERBOSE", SYSLOG_LEVEL_VERBOSE }, 104 { "DEBUG", SYSLOG_LEVEL_DEBUG1 }, 105 { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, 106 { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, 107 { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, 108 { NULL, SYSLOG_LEVEL_NOT_SET } 109 }; 110 111 LogLevel 112 log_level_get(void) 113 { 114 return log_level; 115 } 116 117 SyslogFacility 118 log_facility_number(char *name) 119 { 120 int i; 121 122 if (name != NULL) 123 for (i = 0; log_facilities[i].name; i++) 124 if (strcasecmp(log_facilities[i].name, name) == 0) 125 return log_facilities[i].val; 126 return SYSLOG_FACILITY_NOT_SET; 127 } 128 129 const char * 130 log_facility_name(SyslogFacility facility) 131 { 132 u_int i; 133 134 for (i = 0; log_facilities[i].name; i++) 135 if (log_facilities[i].val == facility) 136 return log_facilities[i].name; 137 return NULL; 138 } 139 140 LogLevel 141 log_level_number(char *name) 142 { 143 int i; 144 145 if (name != NULL) 146 for (i = 0; log_levels[i].name; i++) 147 if (strcasecmp(log_levels[i].name, name) == 0) 148 return log_levels[i].val; 149 return SYSLOG_LEVEL_NOT_SET; 150 } 151 152 const char * 153 log_level_name(LogLevel level) 154 { 155 u_int i; 156 157 for (i = 0; log_levels[i].name != NULL; i++) 158 if (log_levels[i].val == level) 159 return log_levels[i].name; 160 return NULL; 161 } 162 163 void 164 log_verbose_add(const char *s) 165 { 166 char **tmp; 167 168 /* Ignore failures here */ 169 if ((tmp = recallocarray(log_verbose, nlog_verbose, nlog_verbose + 1, 170 sizeof(*log_verbose))) != NULL) { 171 log_verbose = tmp; 172 if ((log_verbose[nlog_verbose] = strdup(s)) != NULL) 173 nlog_verbose++; 174 } 175 } 176 177 void 178 log_verbose_reset(void) 179 { 180 size_t i; 181 182 for (i = 0; i < nlog_verbose; i++) 183 free(log_verbose[i]); 184 free(log_verbose); 185 log_verbose = NULL; 186 nlog_verbose = 0; 187 } 188 189 /* 190 * Initialize the log. 191 */ 192 193 void 194 log_init(const char *av0, LogLevel level, SyslogFacility facility, 195 int on_stderr) 196 { 197 #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 198 struct syslog_data sdata = SYSLOG_DATA_INIT; 199 #endif 200 201 argv0 = av0; 202 203 if (log_change_level(level) != 0) { 204 fprintf(stderr, "Unrecognized internal syslog level code %d\n", 205 (int) level); 206 exit(1); 207 } 208 209 log_handler = NULL; 210 log_handler_ctx = NULL; 211 212 log_on_stderr = on_stderr; 213 if (on_stderr) 214 return; 215 216 switch (facility) { 217 case SYSLOG_FACILITY_DAEMON: 218 log_facility = LOG_DAEMON; 219 break; 220 case SYSLOG_FACILITY_USER: 221 log_facility = LOG_USER; 222 break; 223 case SYSLOG_FACILITY_AUTH: 224 log_facility = LOG_AUTH; 225 break; 226 #ifdef LOG_AUTHPRIV 227 case SYSLOG_FACILITY_AUTHPRIV: 228 log_facility = LOG_AUTHPRIV; 229 break; 230 #endif 231 case SYSLOG_FACILITY_LOCAL0: 232 log_facility = LOG_LOCAL0; 233 break; 234 case SYSLOG_FACILITY_LOCAL1: 235 log_facility = LOG_LOCAL1; 236 break; 237 case SYSLOG_FACILITY_LOCAL2: 238 log_facility = LOG_LOCAL2; 239 break; 240 case SYSLOG_FACILITY_LOCAL3: 241 log_facility = LOG_LOCAL3; 242 break; 243 case SYSLOG_FACILITY_LOCAL4: 244 log_facility = LOG_LOCAL4; 245 break; 246 case SYSLOG_FACILITY_LOCAL5: 247 log_facility = LOG_LOCAL5; 248 break; 249 case SYSLOG_FACILITY_LOCAL6: 250 log_facility = LOG_LOCAL6; 251 break; 252 case SYSLOG_FACILITY_LOCAL7: 253 log_facility = LOG_LOCAL7; 254 break; 255 default: 256 fprintf(stderr, 257 "Unrecognized internal syslog facility code %d\n", 258 (int) facility); 259 exit(1); 260 } 261 262 /* 263 * If an external library (eg libwrap) attempts to use syslog 264 * immediately after reexec, syslog may be pointing to the wrong 265 * facility, so we force an open/close of syslog here. 266 */ 267 #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 268 openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); 269 closelog_r(&sdata); 270 #else 271 openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); 272 closelog(); 273 #endif 274 } 275 276 int 277 log_change_level(LogLevel new_log_level) 278 { 279 /* no-op if log_init has not been called */ 280 if (argv0 == NULL) 281 return 0; 282 283 switch (new_log_level) { 284 case SYSLOG_LEVEL_QUIET: 285 case SYSLOG_LEVEL_FATAL: 286 case SYSLOG_LEVEL_ERROR: 287 case SYSLOG_LEVEL_INFO: 288 case SYSLOG_LEVEL_VERBOSE: 289 case SYSLOG_LEVEL_DEBUG1: 290 case SYSLOG_LEVEL_DEBUG2: 291 case SYSLOG_LEVEL_DEBUG3: 292 log_level = new_log_level; 293 return 0; 294 default: 295 return -1; 296 } 297 } 298 299 int 300 log_is_on_stderr(void) 301 { 302 return log_on_stderr && log_stderr_fd == STDERR_FILENO; 303 } 304 305 /* redirect what would usually get written to stderr to specified file */ 306 void 307 log_redirect_stderr_to(const char *logfile) 308 { 309 int fd; 310 311 if (logfile == NULL) { 312 if (log_stderr_fd != STDERR_FILENO) { 313 close(log_stderr_fd); 314 log_stderr_fd = STDERR_FILENO; 315 } 316 return; 317 } 318 319 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) { 320 fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile, 321 strerror(errno)); 322 exit(1); 323 } 324 log_stderr_fd = fd; 325 } 326 327 #define MSGBUFSIZ 1024 328 329 void 330 set_log_handler(log_handler_fn *handler, void *ctx) 331 { 332 log_handler = handler; 333 log_handler_ctx = ctx; 334 } 335 336 static void 337 do_log(LogLevel level, int force, const char *suffix, const char *fmt, 338 va_list args) 339 { 340 #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 341 struct syslog_data sdata = SYSLOG_DATA_INIT; 342 #endif 343 char msgbuf[MSGBUFSIZ]; 344 char fmtbuf[MSGBUFSIZ]; 345 char *txt = NULL; 346 int pri = LOG_INFO; 347 int saved_errno = errno; 348 log_handler_fn *tmp_handler; 349 const char *progname = argv0 != NULL ? argv0 : __progname; 350 351 if (!force && level > log_level) 352 return; 353 354 switch (level) { 355 case SYSLOG_LEVEL_FATAL: 356 if (!log_on_stderr) 357 txt = "fatal"; 358 pri = LOG_CRIT; 359 break; 360 case SYSLOG_LEVEL_ERROR: 361 if (!log_on_stderr) 362 txt = "error"; 363 pri = LOG_ERR; 364 break; 365 case SYSLOG_LEVEL_INFO: 366 pri = LOG_INFO; 367 break; 368 case SYSLOG_LEVEL_VERBOSE: 369 pri = LOG_INFO; 370 break; 371 case SYSLOG_LEVEL_DEBUG1: 372 txt = "debug1"; 373 pri = LOG_DEBUG; 374 break; 375 case SYSLOG_LEVEL_DEBUG2: 376 txt = "debug2"; 377 pri = LOG_DEBUG; 378 break; 379 case SYSLOG_LEVEL_DEBUG3: 380 txt = "debug3"; 381 pri = LOG_DEBUG; 382 break; 383 default: 384 txt = "internal error"; 385 pri = LOG_ERR; 386 break; 387 } 388 if (txt != NULL && log_handler == NULL) { 389 snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt); 390 vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args); 391 } else { 392 vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); 393 } 394 if (suffix != NULL) { 395 snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", msgbuf, suffix); 396 strlcpy(msgbuf, fmtbuf, sizeof(msgbuf)); 397 } 398 strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), 399 log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS); 400 if (log_handler != NULL) { 401 /* Avoid recursion */ 402 tmp_handler = log_handler; 403 log_handler = NULL; 404 /* Note: this sends the raw (i.e. no strnvis) log message */ 405 tmp_handler(level, force, msgbuf, log_handler_ctx); 406 log_handler = tmp_handler; 407 } else if (log_on_stderr) { 408 snprintf(msgbuf, sizeof msgbuf, "%s%s%.*s\r\n", 409 (log_on_stderr > 1) ? progname : "", 410 (log_on_stderr > 1) ? ": " : "", 411 (int)sizeof msgbuf - 3, fmtbuf); 412 (void)write(log_stderr_fd, msgbuf, strlen(msgbuf)); 413 } else { 414 #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 415 openlog_r(progname, LOG_PID, log_facility, &sdata); 416 syslog_r(pri, &sdata, "%.500s", fmtbuf); 417 closelog_r(&sdata); 418 #else 419 openlog(progname, LOG_PID, log_facility); 420 syslog(pri, "%.500s", fmtbuf); 421 closelog(); 422 #endif 423 } 424 errno = saved_errno; 425 } 426 427 void 428 sshlog(const char *file, const char *func, int line, int showfunc, 429 LogLevel level, const char *suffix, const char *fmt, ...) 430 { 431 va_list args; 432 433 va_start(args, fmt); 434 sshlogv(file, func, line, showfunc, level, suffix, fmt, args); 435 va_end(args); 436 } 437 438 void 439 sshlogdie(const char *file, const char *func, int line, int showfunc, 440 LogLevel level, const char *suffix, const char *fmt, ...) 441 { 442 va_list args; 443 444 va_start(args, fmt); 445 sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_INFO, 446 suffix, fmt, args); 447 va_end(args); 448 cleanup_exit(255); 449 } 450 451 void 452 sshlogv(const char *file, const char *func, int line, int showfunc, 453 LogLevel level, const char *suffix, const char *fmt, va_list args) 454 { 455 char tag[128], fmt2[MSGBUFSIZ + 128]; 456 int forced = 0; 457 const char *cp; 458 size_t i; 459 460 /* short circuit processing early if we're not going to log anything */ 461 if (nlog_verbose == 0 && level > log_level) 462 return; 463 464 snprintf(tag, sizeof(tag), "%.48s:%.48s():%d (bin=%s, pid=%ld)", 465 (cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line, 466 argv0 == NULL ? "UNKNOWN" : argv0, (long)getpid()); 467 for (i = 0; i < nlog_verbose; i++) { 468 if (match_pattern_list(tag, log_verbose[i], 0) == 1) { 469 forced = 1; 470 break; 471 } 472 } 473 474 if (forced) 475 snprintf(fmt2, sizeof(fmt2), "%s: %s", tag, fmt); 476 else if (showfunc) 477 snprintf(fmt2, sizeof(fmt2), "%s: %s", func, fmt); 478 else 479 strlcpy(fmt2, fmt, sizeof(fmt2)); 480 481 do_log(level, forced, suffix, fmt2, args); 482 } 483 484 void 485 sshlogdirect(LogLevel level, int forced, const char *fmt, ...) 486 { 487 va_list args; 488 489 va_start(args, fmt); 490 do_log(level, forced, NULL, fmt, args); 491 va_end(args); 492 } 493 494 495 /* 496 * A simple system for ratelimiting aperiodic events such as logs, without 497 * needing to be hooked into a mainloop/timer. A running total of events is 498 * maintained and when it exceeds a threshold further events are dropped 499 * until the rate falls back below that threshold. 500 * 501 * To prevent flipping in and out of rate-limiting, there is a hysteresis 502 * timer that delays leaving the rate-limited state. 503 * 504 * While in the rate-limited state, events can be periodically allowed through 505 * and the number of dropped events since the last log obtained. 506 * 507 * XXX a moving average rate of events might be a better approach here rather 508 * than linear decay, which can suppress events for a while after large 509 * bursts. 510 */ 511 512 /* #define RATELIMIT_DEBUG 1 */ 513 514 #ifdef RATELIMIT_DEBUG 515 # define RLDBG(x) do { \ 516 printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ 517 printf x; \ 518 printf("\n"); \ 519 fflush(stdout); \ 520 } while (0) 521 #else 522 # define RLDBG(x) 523 #endif 524 525 /* set up a ratelimit */ 526 void 527 log_ratelimit_init(struct log_ratelimit_ctx *rl, u_int threshold, 528 u_int max_accum, u_int hysteresis, u_int log_every) 529 { 530 memset(rl, 0, sizeof(*rl)); 531 rl->threshold = threshold; 532 rl->max_accum = max_accum; 533 rl->hysteresis = hysteresis; 534 rl->log_every = log_every; 535 RLDBG(("called: rl=%p thresh=%u max=%u hys=%u log_every=%u", 536 rl, rl->threshold, rl->max_accum, rl->hysteresis, rl->log_every)); 537 } 538 539 /* 540 * check whether a log event should be dropped because of rate-limiting. 541 * returns non-zero if the event should be dropped. If events_since_last 542 * is supplied then, for periodic logs, it will be set to the number of 543 * dropped events since the last message. 544 */ 545 int 546 log_ratelimit(struct log_ratelimit_ctx *rl, time_t now, int *active, 547 u_int *events_dropped) 548 { 549 time_t olast_event; 550 551 RLDBG(("called: rl=%p thresh=%u max=%u hys=%u log_every=%u " 552 "accum=%u since=%ld since_last=%u", rl, rl->threshold, 553 rl->max_accum, rl->hysteresis, 554 rl->log_every, rl->accumulated_events, 555 rl->last_event == 0 ? -1 : (long)(now - rl->last_event), 556 rl->ratelimited_events)); 557 558 if (now < 0) 559 return 0; 560 if (events_dropped != NULL) 561 *events_dropped = 0; 562 if (active != NULL) 563 *active = rl->ratelimit_active; 564 565 /* First, decay accumulated events */ 566 if (rl->last_event <= 0) 567 rl->last_event = now; 568 if (now > rl->last_event) { 569 uint64_t n = now - rl->last_event; 570 571 if (n > UINT_MAX) 572 n = UINT_MAX; 573 if (rl->accumulated_events < (u_int)n) 574 rl->accumulated_events = 0; 575 else 576 rl->accumulated_events -= (u_int)n; 577 RLDBG(("decay: accum=%u", rl->accumulated_events)); 578 } 579 rl->accumulated_events++; /* add this event */ 580 if (rl->accumulated_events > rl->max_accum) 581 rl->accumulated_events = rl->max_accum; 582 olast_event = rl->last_event; 583 rl->last_event = now; 584 RLDBG(("check threshold: accum=%u vs thresh=%u", 585 rl->accumulated_events, rl->threshold)); 586 587 /* Are we under threshold? */ 588 if (rl->accumulated_events < rl->threshold) { 589 if (!rl->ratelimit_active) 590 return 0; 591 RLDBG(("under threshold: hys=%u since_hys=%ld since_last=%ld", 592 rl->hysteresis, rl->hysteresis_start == 0 ? -1 : 593 (long)(now - rl->hysteresis_start), 594 olast_event == 0 ? -1 : (long)(now - olast_event))); 595 if (rl->hysteresis_start == 0) { 596 /* active, but under threshold; hysteresis */ 597 if (olast_event + rl->hysteresis < now) { 598 /* hysteresis expired before this event */ 599 RLDBG(("hysteresis preexpired")); 600 goto inactive; 601 } 602 RLDBG(("start hysteresis")); 603 rl->hysteresis_start = now; 604 } else if (rl->hysteresis_start + rl->hysteresis < now) { 605 /* Hysteresis period expired, transition to inactive */ 606 RLDBG(("complete hysteresis")); 607 inactive: 608 if (events_dropped != NULL) 609 *events_dropped = rl->ratelimited_events; 610 if (active != NULL) 611 *active = 0; 612 rl->ratelimit_active = 0; 613 rl->ratelimit_start = 0; 614 rl->last_log = 0; 615 rl->hysteresis_start = 0; 616 rl->ratelimited_events = 0; 617 return 0; 618 } 619 /* ratelimiting active, but in hysteresis period */ 620 } else if (!rl->ratelimit_active) { 621 /* Transition to rate-limiting */ 622 RLDBG(("start ratelimit")); 623 rl->ratelimit_active = 1; 624 rl->ratelimit_start = now; 625 rl->last_log = now; 626 rl->hysteresis_start = 0; 627 rl->ratelimited_events = 1; 628 if (active != NULL) 629 *active = 1; 630 return 1; 631 } else if (rl->hysteresis_start != 0) { 632 /* active and over threshold; reset hysteresis timer */ 633 RLDBG(("clear hysteresis")); 634 rl->hysteresis_start = 0; 635 } 636 637 /* over threshold or in hysteresis period; log periodically */ 638 if (active != NULL) 639 *active = 1; 640 RLDBG(("log_every=%u since_log=%ld", rl->log_every, 641 (long)(now - rl->last_log))); 642 if (rl->log_every > 0 && now >= rl->last_log + rl->log_every) { 643 RLDBG(("periodic: since_last=%u", rl->ratelimited_events)); 644 rl->last_log = now; 645 if (events_dropped != NULL) { 646 *events_dropped = rl->ratelimited_events; 647 rl->ratelimited_events = 0; 648 } 649 return 0; 650 } 651 652 /* drop event */ 653 rl->ratelimited_events++; 654 RLDBG(("drop: ratelimited_events=%u", rl->ratelimited_events)); 655 return 1; 656 } 657