1*ba1276acSMatthew Dillon /* $OpenBSD: log.c,v 1.62 2024/06/27 22:36:44 djm Exp $ */
218de8d7fSPeter Avalos /*
318de8d7fSPeter Avalos * Author: Tatu Ylonen <ylo@cs.hut.fi>
418de8d7fSPeter Avalos * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
518de8d7fSPeter Avalos * All rights reserved
618de8d7fSPeter Avalos *
718de8d7fSPeter Avalos * As far as I am concerned, the code I have written for this software
818de8d7fSPeter Avalos * can be used freely for any purpose. Any derived versions of this
918de8d7fSPeter Avalos * software must be clearly marked as such, and if the derived work is
1018de8d7fSPeter Avalos * incompatible with the protocol description in the RFC file, it must be
1118de8d7fSPeter Avalos * called by a name other than "ssh" or "Secure Shell".
1218de8d7fSPeter Avalos */
1318de8d7fSPeter Avalos /*
1418de8d7fSPeter Avalos * Copyright (c) 2000 Markus Friedl. All rights reserved.
1518de8d7fSPeter Avalos *
1618de8d7fSPeter Avalos * Redistribution and use in source and binary forms, with or without
1718de8d7fSPeter Avalos * modification, are permitted provided that the following conditions
1818de8d7fSPeter Avalos * are met:
1918de8d7fSPeter Avalos * 1. Redistributions of source code must retain the above copyright
2018de8d7fSPeter Avalos * notice, this list of conditions and the following disclaimer.
2118de8d7fSPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright
2218de8d7fSPeter Avalos * notice, this list of conditions and the following disclaimer in the
2318de8d7fSPeter Avalos * documentation and/or other materials provided with the distribution.
2418de8d7fSPeter Avalos *
2518de8d7fSPeter Avalos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2618de8d7fSPeter Avalos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2718de8d7fSPeter Avalos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2818de8d7fSPeter Avalos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2918de8d7fSPeter Avalos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3018de8d7fSPeter Avalos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3118de8d7fSPeter Avalos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3218de8d7fSPeter Avalos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3318de8d7fSPeter Avalos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3418de8d7fSPeter Avalos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3518de8d7fSPeter Avalos */
3618de8d7fSPeter Avalos
3718de8d7fSPeter Avalos #include "includes.h"
3818de8d7fSPeter Avalos
3918de8d7fSPeter Avalos #include <sys/types.h>
4018de8d7fSPeter Avalos
4136e94dc5SPeter Avalos #include <fcntl.h>
4218de8d7fSPeter Avalos #include <stdarg.h>
4318de8d7fSPeter Avalos #include <stdio.h>
4418de8d7fSPeter Avalos #include <stdlib.h>
4518de8d7fSPeter Avalos #include <string.h>
4618de8d7fSPeter Avalos #include <syslog.h>
4718de8d7fSPeter Avalos #include <unistd.h>
4818de8d7fSPeter Avalos #include <errno.h>
4936e94dc5SPeter Avalos #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
5018de8d7fSPeter Avalos # include <vis.h>
5118de8d7fSPeter Avalos #endif
5218de8d7fSPeter Avalos
5318de8d7fSPeter Avalos #include "log.h"
5450a69bb5SSascha Wildner #include "match.h"
5518de8d7fSPeter Avalos
5618de8d7fSPeter Avalos static LogLevel log_level = SYSLOG_LEVEL_INFO;
5718de8d7fSPeter Avalos static int log_on_stderr = 1;
5836e94dc5SPeter Avalos static int log_stderr_fd = STDERR_FILENO;
5918de8d7fSPeter Avalos static int log_facility = LOG_AUTH;
6050a69bb5SSascha Wildner static const char *argv0;
611c188a7fSPeter Avalos static log_handler_fn *log_handler;
621c188a7fSPeter Avalos static void *log_handler_ctx;
6350a69bb5SSascha Wildner static char **log_verbose;
6450a69bb5SSascha Wildner static size_t nlog_verbose;
6518de8d7fSPeter Avalos
6618de8d7fSPeter Avalos extern char *__progname;
6718de8d7fSPeter Avalos
6818de8d7fSPeter Avalos #define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL)
6918de8d7fSPeter Avalos #define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL)
7018de8d7fSPeter Avalos
7118de8d7fSPeter Avalos /* textual representation of log-facilities/levels */
7218de8d7fSPeter Avalos
7318de8d7fSPeter Avalos static struct {
7418de8d7fSPeter Avalos const char *name;
7518de8d7fSPeter Avalos SyslogFacility val;
7618de8d7fSPeter Avalos } log_facilities[] = {
7718de8d7fSPeter Avalos { "DAEMON", SYSLOG_FACILITY_DAEMON },
7818de8d7fSPeter Avalos { "USER", SYSLOG_FACILITY_USER },
7918de8d7fSPeter Avalos { "AUTH", SYSLOG_FACILITY_AUTH },
8018de8d7fSPeter Avalos #ifdef LOG_AUTHPRIV
8118de8d7fSPeter Avalos { "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV },
8218de8d7fSPeter Avalos #endif
8318de8d7fSPeter Avalos { "LOCAL0", SYSLOG_FACILITY_LOCAL0 },
8418de8d7fSPeter Avalos { "LOCAL1", SYSLOG_FACILITY_LOCAL1 },
8518de8d7fSPeter Avalos { "LOCAL2", SYSLOG_FACILITY_LOCAL2 },
8618de8d7fSPeter Avalos { "LOCAL3", SYSLOG_FACILITY_LOCAL3 },
8718de8d7fSPeter Avalos { "LOCAL4", SYSLOG_FACILITY_LOCAL4 },
8818de8d7fSPeter Avalos { "LOCAL5", SYSLOG_FACILITY_LOCAL5 },
8918de8d7fSPeter Avalos { "LOCAL6", SYSLOG_FACILITY_LOCAL6 },
9018de8d7fSPeter Avalos { "LOCAL7", SYSLOG_FACILITY_LOCAL7 },
9118de8d7fSPeter Avalos { NULL, SYSLOG_FACILITY_NOT_SET }
9218de8d7fSPeter Avalos };
9318de8d7fSPeter Avalos
9418de8d7fSPeter Avalos static struct {
9518de8d7fSPeter Avalos const char *name;
9618de8d7fSPeter Avalos LogLevel val;
9718de8d7fSPeter Avalos } log_levels[] =
9818de8d7fSPeter Avalos {
9918de8d7fSPeter Avalos { "QUIET", SYSLOG_LEVEL_QUIET },
10018de8d7fSPeter Avalos { "FATAL", SYSLOG_LEVEL_FATAL },
10118de8d7fSPeter Avalos { "ERROR", SYSLOG_LEVEL_ERROR },
10218de8d7fSPeter Avalos { "INFO", SYSLOG_LEVEL_INFO },
10318de8d7fSPeter Avalos { "VERBOSE", SYSLOG_LEVEL_VERBOSE },
10418de8d7fSPeter Avalos { "DEBUG", SYSLOG_LEVEL_DEBUG1 },
10518de8d7fSPeter Avalos { "DEBUG1", SYSLOG_LEVEL_DEBUG1 },
10618de8d7fSPeter Avalos { "DEBUG2", SYSLOG_LEVEL_DEBUG2 },
10718de8d7fSPeter Avalos { "DEBUG3", SYSLOG_LEVEL_DEBUG3 },
10818de8d7fSPeter Avalos { NULL, SYSLOG_LEVEL_NOT_SET }
10918de8d7fSPeter Avalos };
11018de8d7fSPeter Avalos
111664f4763Szrj LogLevel
log_level_get(void)112664f4763Szrj log_level_get(void)
113664f4763Szrj {
114664f4763Szrj return log_level;
115664f4763Szrj }
116664f4763Szrj
11718de8d7fSPeter Avalos SyslogFacility
log_facility_number(char * name)11818de8d7fSPeter Avalos log_facility_number(char *name)
11918de8d7fSPeter Avalos {
12018de8d7fSPeter Avalos int i;
12118de8d7fSPeter Avalos
12218de8d7fSPeter Avalos if (name != NULL)
12318de8d7fSPeter Avalos for (i = 0; log_facilities[i].name; i++)
12418de8d7fSPeter Avalos if (strcasecmp(log_facilities[i].name, name) == 0)
12518de8d7fSPeter Avalos return log_facilities[i].val;
12618de8d7fSPeter Avalos return SYSLOG_FACILITY_NOT_SET;
12718de8d7fSPeter Avalos }
12818de8d7fSPeter Avalos
12918de8d7fSPeter Avalos const char *
log_facility_name(SyslogFacility facility)13018de8d7fSPeter Avalos log_facility_name(SyslogFacility facility)
13118de8d7fSPeter Avalos {
13218de8d7fSPeter Avalos u_int i;
13318de8d7fSPeter Avalos
13418de8d7fSPeter Avalos for (i = 0; log_facilities[i].name; i++)
13518de8d7fSPeter Avalos if (log_facilities[i].val == facility)
13618de8d7fSPeter Avalos return log_facilities[i].name;
13718de8d7fSPeter Avalos return NULL;
13818de8d7fSPeter Avalos }
13918de8d7fSPeter Avalos
14018de8d7fSPeter Avalos LogLevel
log_level_number(char * name)14118de8d7fSPeter Avalos log_level_number(char *name)
14218de8d7fSPeter Avalos {
14318de8d7fSPeter Avalos int i;
14418de8d7fSPeter Avalos
14518de8d7fSPeter Avalos if (name != NULL)
14618de8d7fSPeter Avalos for (i = 0; log_levels[i].name; i++)
14718de8d7fSPeter Avalos if (strcasecmp(log_levels[i].name, name) == 0)
14818de8d7fSPeter Avalos return log_levels[i].val;
14918de8d7fSPeter Avalos return SYSLOG_LEVEL_NOT_SET;
15018de8d7fSPeter Avalos }
15118de8d7fSPeter Avalos
15218de8d7fSPeter Avalos const char *
log_level_name(LogLevel level)15318de8d7fSPeter Avalos log_level_name(LogLevel level)
15418de8d7fSPeter Avalos {
15518de8d7fSPeter Avalos u_int i;
15618de8d7fSPeter Avalos
15718de8d7fSPeter Avalos for (i = 0; log_levels[i].name != NULL; i++)
15818de8d7fSPeter Avalos if (log_levels[i].val == level)
15918de8d7fSPeter Avalos return log_levels[i].name;
16018de8d7fSPeter Avalos return NULL;
16118de8d7fSPeter Avalos }
16218de8d7fSPeter Avalos
16318de8d7fSPeter Avalos void
log_verbose_add(const char * s)16450a69bb5SSascha Wildner log_verbose_add(const char *s)
16518de8d7fSPeter Avalos {
16650a69bb5SSascha Wildner char **tmp;
16718de8d7fSPeter Avalos
16850a69bb5SSascha Wildner /* Ignore failures here */
16950a69bb5SSascha Wildner if ((tmp = recallocarray(log_verbose, nlog_verbose, nlog_verbose + 1,
17050a69bb5SSascha Wildner sizeof(*log_verbose))) != NULL) {
17150a69bb5SSascha Wildner log_verbose = tmp;
17250a69bb5SSascha Wildner if ((log_verbose[nlog_verbose] = strdup(s)) != NULL)
17350a69bb5SSascha Wildner nlog_verbose++;
17450a69bb5SSascha Wildner }
17518de8d7fSPeter Avalos }
17618de8d7fSPeter Avalos
17718de8d7fSPeter Avalos void
log_verbose_reset(void)17850a69bb5SSascha Wildner log_verbose_reset(void)
17918de8d7fSPeter Avalos {
18050a69bb5SSascha Wildner size_t i;
18118de8d7fSPeter Avalos
18250a69bb5SSascha Wildner for (i = 0; i < nlog_verbose; i++)
18350a69bb5SSascha Wildner free(log_verbose[i]);
18450a69bb5SSascha Wildner free(log_verbose);
18550a69bb5SSascha Wildner log_verbose = NULL;
18650a69bb5SSascha Wildner nlog_verbose = 0;
18718de8d7fSPeter Avalos }
18818de8d7fSPeter Avalos
18918de8d7fSPeter Avalos /*
19018de8d7fSPeter Avalos * Initialize the log.
19118de8d7fSPeter Avalos */
19218de8d7fSPeter Avalos
19318de8d7fSPeter Avalos void
log_init(const char * av0,LogLevel level,SyslogFacility facility,int on_stderr)19450a69bb5SSascha Wildner log_init(const char *av0, LogLevel level, SyslogFacility facility,
19550a69bb5SSascha Wildner int on_stderr)
19618de8d7fSPeter Avalos {
19718de8d7fSPeter Avalos #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
19818de8d7fSPeter Avalos struct syslog_data sdata = SYSLOG_DATA_INIT;
19918de8d7fSPeter Avalos #endif
20018de8d7fSPeter Avalos
20118de8d7fSPeter Avalos argv0 = av0;
20218de8d7fSPeter Avalos
203ce74bacaSMatthew Dillon if (log_change_level(level) != 0) {
20418de8d7fSPeter Avalos fprintf(stderr, "Unrecognized internal syslog level code %d\n",
20518de8d7fSPeter Avalos (int) level);
20618de8d7fSPeter Avalos exit(1);
20718de8d7fSPeter Avalos }
20818de8d7fSPeter Avalos
2091c188a7fSPeter Avalos log_handler = NULL;
2101c188a7fSPeter Avalos log_handler_ctx = NULL;
2111c188a7fSPeter Avalos
21218de8d7fSPeter Avalos log_on_stderr = on_stderr;
21318de8d7fSPeter Avalos if (on_stderr)
21418de8d7fSPeter Avalos return;
21518de8d7fSPeter Avalos
21618de8d7fSPeter Avalos switch (facility) {
21718de8d7fSPeter Avalos case SYSLOG_FACILITY_DAEMON:
21818de8d7fSPeter Avalos log_facility = LOG_DAEMON;
21918de8d7fSPeter Avalos break;
22018de8d7fSPeter Avalos case SYSLOG_FACILITY_USER:
22118de8d7fSPeter Avalos log_facility = LOG_USER;
22218de8d7fSPeter Avalos break;
22318de8d7fSPeter Avalos case SYSLOG_FACILITY_AUTH:
22418de8d7fSPeter Avalos log_facility = LOG_AUTH;
22518de8d7fSPeter Avalos break;
22618de8d7fSPeter Avalos #ifdef LOG_AUTHPRIV
22718de8d7fSPeter Avalos case SYSLOG_FACILITY_AUTHPRIV:
22818de8d7fSPeter Avalos log_facility = LOG_AUTHPRIV;
22918de8d7fSPeter Avalos break;
23018de8d7fSPeter Avalos #endif
23118de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL0:
23218de8d7fSPeter Avalos log_facility = LOG_LOCAL0;
23318de8d7fSPeter Avalos break;
23418de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL1:
23518de8d7fSPeter Avalos log_facility = LOG_LOCAL1;
23618de8d7fSPeter Avalos break;
23718de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL2:
23818de8d7fSPeter Avalos log_facility = LOG_LOCAL2;
23918de8d7fSPeter Avalos break;
24018de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL3:
24118de8d7fSPeter Avalos log_facility = LOG_LOCAL3;
24218de8d7fSPeter Avalos break;
24318de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL4:
24418de8d7fSPeter Avalos log_facility = LOG_LOCAL4;
24518de8d7fSPeter Avalos break;
24618de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL5:
24718de8d7fSPeter Avalos log_facility = LOG_LOCAL5;
24818de8d7fSPeter Avalos break;
24918de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL6:
25018de8d7fSPeter Avalos log_facility = LOG_LOCAL6;
25118de8d7fSPeter Avalos break;
25218de8d7fSPeter Avalos case SYSLOG_FACILITY_LOCAL7:
25318de8d7fSPeter Avalos log_facility = LOG_LOCAL7;
25418de8d7fSPeter Avalos break;
25518de8d7fSPeter Avalos default:
25618de8d7fSPeter Avalos fprintf(stderr,
25718de8d7fSPeter Avalos "Unrecognized internal syslog facility code %d\n",
25818de8d7fSPeter Avalos (int) facility);
25918de8d7fSPeter Avalos exit(1);
26018de8d7fSPeter Avalos }
26118de8d7fSPeter Avalos
26218de8d7fSPeter Avalos /*
26318de8d7fSPeter Avalos * If an external library (eg libwrap) attempts to use syslog
26418de8d7fSPeter Avalos * immediately after reexec, syslog may be pointing to the wrong
26518de8d7fSPeter Avalos * facility, so we force an open/close of syslog here.
26618de8d7fSPeter Avalos */
26718de8d7fSPeter Avalos #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
26818de8d7fSPeter Avalos openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
26918de8d7fSPeter Avalos closelog_r(&sdata);
27018de8d7fSPeter Avalos #else
27118de8d7fSPeter Avalos openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
27218de8d7fSPeter Avalos closelog();
27318de8d7fSPeter Avalos #endif
27418de8d7fSPeter Avalos }
27518de8d7fSPeter Avalos
276ce74bacaSMatthew Dillon int
log_change_level(LogLevel new_log_level)27736e94dc5SPeter Avalos log_change_level(LogLevel new_log_level)
27836e94dc5SPeter Avalos {
27936e94dc5SPeter Avalos /* no-op if log_init has not been called */
28036e94dc5SPeter Avalos if (argv0 == NULL)
281ce74bacaSMatthew Dillon return 0;
282ce74bacaSMatthew Dillon
283ce74bacaSMatthew Dillon switch (new_log_level) {
284ce74bacaSMatthew Dillon case SYSLOG_LEVEL_QUIET:
285ce74bacaSMatthew Dillon case SYSLOG_LEVEL_FATAL:
286ce74bacaSMatthew Dillon case SYSLOG_LEVEL_ERROR:
287ce74bacaSMatthew Dillon case SYSLOG_LEVEL_INFO:
288ce74bacaSMatthew Dillon case SYSLOG_LEVEL_VERBOSE:
289ce74bacaSMatthew Dillon case SYSLOG_LEVEL_DEBUG1:
290ce74bacaSMatthew Dillon case SYSLOG_LEVEL_DEBUG2:
291ce74bacaSMatthew Dillon case SYSLOG_LEVEL_DEBUG3:
292ce74bacaSMatthew Dillon log_level = new_log_level;
293ce74bacaSMatthew Dillon return 0;
294ce74bacaSMatthew Dillon default:
295ce74bacaSMatthew Dillon return -1;
296ce74bacaSMatthew Dillon }
29736e94dc5SPeter Avalos }
29836e94dc5SPeter Avalos
29936e94dc5SPeter Avalos int
log_is_on_stderr(void)30036e94dc5SPeter Avalos log_is_on_stderr(void)
30136e94dc5SPeter Avalos {
302e9778795SPeter Avalos return log_on_stderr && log_stderr_fd == STDERR_FILENO;
30336e94dc5SPeter Avalos }
30436e94dc5SPeter Avalos
30536e94dc5SPeter Avalos /* redirect what would usually get written to stderr to specified file */
30636e94dc5SPeter Avalos void
log_redirect_stderr_to(const char * logfile)30736e94dc5SPeter Avalos log_redirect_stderr_to(const char *logfile)
30836e94dc5SPeter Avalos {
30936e94dc5SPeter Avalos int fd;
31036e94dc5SPeter Avalos
31150a69bb5SSascha Wildner if (logfile == NULL) {
31250a69bb5SSascha Wildner if (log_stderr_fd != STDERR_FILENO) {
31350a69bb5SSascha Wildner close(log_stderr_fd);
31450a69bb5SSascha Wildner log_stderr_fd = STDERR_FILENO;
31550a69bb5SSascha Wildner }
31650a69bb5SSascha Wildner return;
31750a69bb5SSascha Wildner }
31850a69bb5SSascha Wildner
31936e94dc5SPeter Avalos if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
32036e94dc5SPeter Avalos fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile,
32136e94dc5SPeter Avalos strerror(errno));
32236e94dc5SPeter Avalos exit(1);
32336e94dc5SPeter Avalos }
32436e94dc5SPeter Avalos log_stderr_fd = fd;
32536e94dc5SPeter Avalos }
32636e94dc5SPeter Avalos
32718de8d7fSPeter Avalos #define MSGBUFSIZ 1024
32818de8d7fSPeter Avalos
32918de8d7fSPeter Avalos void
set_log_handler(log_handler_fn * handler,void * ctx)3301c188a7fSPeter Avalos set_log_handler(log_handler_fn *handler, void *ctx)
3311c188a7fSPeter Avalos {
3321c188a7fSPeter Avalos log_handler = handler;
3331c188a7fSPeter Avalos log_handler_ctx = ctx;
3341c188a7fSPeter Avalos }
3351c188a7fSPeter Avalos
33650a69bb5SSascha Wildner static void
do_log(LogLevel level,int force,const char * suffix,const char * fmt,va_list args)33750a69bb5SSascha Wildner do_log(LogLevel level, int force, const char *suffix, const char *fmt,
33850a69bb5SSascha Wildner va_list args)
33918de8d7fSPeter Avalos {
34018de8d7fSPeter Avalos #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
34118de8d7fSPeter Avalos struct syslog_data sdata = SYSLOG_DATA_INIT;
34218de8d7fSPeter Avalos #endif
34318de8d7fSPeter Avalos char msgbuf[MSGBUFSIZ];
34418de8d7fSPeter Avalos char fmtbuf[MSGBUFSIZ];
34518de8d7fSPeter Avalos char *txt = NULL;
34618de8d7fSPeter Avalos int pri = LOG_INFO;
34718de8d7fSPeter Avalos int saved_errno = errno;
3481c188a7fSPeter Avalos log_handler_fn *tmp_handler;
34950a69bb5SSascha Wildner const char *progname = argv0 != NULL ? argv0 : __progname;
35018de8d7fSPeter Avalos
35150a69bb5SSascha Wildner if (!force && level > log_level)
35218de8d7fSPeter Avalos return;
35318de8d7fSPeter Avalos
35418de8d7fSPeter Avalos switch (level) {
35518de8d7fSPeter Avalos case SYSLOG_LEVEL_FATAL:
35618de8d7fSPeter Avalos if (!log_on_stderr)
35718de8d7fSPeter Avalos txt = "fatal";
35818de8d7fSPeter Avalos pri = LOG_CRIT;
35918de8d7fSPeter Avalos break;
36018de8d7fSPeter Avalos case SYSLOG_LEVEL_ERROR:
36118de8d7fSPeter Avalos if (!log_on_stderr)
36218de8d7fSPeter Avalos txt = "error";
36318de8d7fSPeter Avalos pri = LOG_ERR;
36418de8d7fSPeter Avalos break;
36518de8d7fSPeter Avalos case SYSLOG_LEVEL_INFO:
36618de8d7fSPeter Avalos pri = LOG_INFO;
36718de8d7fSPeter Avalos break;
36818de8d7fSPeter Avalos case SYSLOG_LEVEL_VERBOSE:
36918de8d7fSPeter Avalos pri = LOG_INFO;
37018de8d7fSPeter Avalos break;
37118de8d7fSPeter Avalos case SYSLOG_LEVEL_DEBUG1:
37218de8d7fSPeter Avalos txt = "debug1";
37318de8d7fSPeter Avalos pri = LOG_DEBUG;
37418de8d7fSPeter Avalos break;
37518de8d7fSPeter Avalos case SYSLOG_LEVEL_DEBUG2:
37618de8d7fSPeter Avalos txt = "debug2";
37718de8d7fSPeter Avalos pri = LOG_DEBUG;
37818de8d7fSPeter Avalos break;
37918de8d7fSPeter Avalos case SYSLOG_LEVEL_DEBUG3:
38018de8d7fSPeter Avalos txt = "debug3";
38118de8d7fSPeter Avalos pri = LOG_DEBUG;
38218de8d7fSPeter Avalos break;
38318de8d7fSPeter Avalos default:
38418de8d7fSPeter Avalos txt = "internal error";
38518de8d7fSPeter Avalos pri = LOG_ERR;
38618de8d7fSPeter Avalos break;
38718de8d7fSPeter Avalos }
3881c188a7fSPeter Avalos if (txt != NULL && log_handler == NULL) {
38918de8d7fSPeter Avalos snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt);
39018de8d7fSPeter Avalos vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
39118de8d7fSPeter Avalos } else {
39218de8d7fSPeter Avalos vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
39318de8d7fSPeter Avalos }
39450a69bb5SSascha Wildner if (suffix != NULL) {
39550a69bb5SSascha Wildner snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", msgbuf, suffix);
39650a69bb5SSascha Wildner strlcpy(msgbuf, fmtbuf, sizeof(msgbuf));
39750a69bb5SSascha Wildner }
39818de8d7fSPeter Avalos strnvis(fmtbuf, msgbuf, sizeof(fmtbuf),
39918de8d7fSPeter Avalos log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS);
4001c188a7fSPeter Avalos if (log_handler != NULL) {
4011c188a7fSPeter Avalos /* Avoid recursion */
4021c188a7fSPeter Avalos tmp_handler = log_handler;
4031c188a7fSPeter Avalos log_handler = NULL;
40450a69bb5SSascha Wildner tmp_handler(level, force, fmtbuf, log_handler_ctx);
4051c188a7fSPeter Avalos log_handler = tmp_handler;
4061c188a7fSPeter Avalos } else if (log_on_stderr) {
40750a69bb5SSascha Wildner snprintf(msgbuf, sizeof msgbuf, "%s%s%.*s\r\n",
40850a69bb5SSascha Wildner (log_on_stderr > 1) ? progname : "",
40950a69bb5SSascha Wildner (log_on_stderr > 1) ? ": " : "",
410ce74bacaSMatthew Dillon (int)sizeof msgbuf - 3, fmtbuf);
41136e94dc5SPeter Avalos (void)write(log_stderr_fd, msgbuf, strlen(msgbuf));
41218de8d7fSPeter Avalos } else {
41318de8d7fSPeter Avalos #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
41450a69bb5SSascha Wildner openlog_r(progname, LOG_PID, log_facility, &sdata);
41518de8d7fSPeter Avalos syslog_r(pri, &sdata, "%.500s", fmtbuf);
41618de8d7fSPeter Avalos closelog_r(&sdata);
41718de8d7fSPeter Avalos #else
41850a69bb5SSascha Wildner openlog(progname, LOG_PID, log_facility);
41918de8d7fSPeter Avalos syslog(pri, "%.500s", fmtbuf);
42018de8d7fSPeter Avalos closelog();
42118de8d7fSPeter Avalos #endif
42218de8d7fSPeter Avalos }
42318de8d7fSPeter Avalos errno = saved_errno;
42418de8d7fSPeter Avalos }
42550a69bb5SSascha Wildner
42650a69bb5SSascha Wildner void
sshlog(const char * file,const char * func,int line,int showfunc,LogLevel level,const char * suffix,const char * fmt,...)42750a69bb5SSascha Wildner sshlog(const char *file, const char *func, int line, int showfunc,
42850a69bb5SSascha Wildner LogLevel level, const char *suffix, const char *fmt, ...)
42950a69bb5SSascha Wildner {
43050a69bb5SSascha Wildner va_list args;
43150a69bb5SSascha Wildner
43250a69bb5SSascha Wildner va_start(args, fmt);
43350a69bb5SSascha Wildner sshlogv(file, func, line, showfunc, level, suffix, fmt, args);
43450a69bb5SSascha Wildner va_end(args);
43550a69bb5SSascha Wildner }
43650a69bb5SSascha Wildner
43750a69bb5SSascha Wildner void
sshlogdie(const char * file,const char * func,int line,int showfunc,LogLevel level,const char * suffix,const char * fmt,...)43850a69bb5SSascha Wildner sshlogdie(const char *file, const char *func, int line, int showfunc,
43950a69bb5SSascha Wildner LogLevel level, const char *suffix, const char *fmt, ...)
44050a69bb5SSascha Wildner {
44150a69bb5SSascha Wildner va_list args;
44250a69bb5SSascha Wildner
44350a69bb5SSascha Wildner va_start(args, fmt);
44450a69bb5SSascha Wildner sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_INFO,
44550a69bb5SSascha Wildner suffix, fmt, args);
44650a69bb5SSascha Wildner va_end(args);
44750a69bb5SSascha Wildner cleanup_exit(255);
44850a69bb5SSascha Wildner }
44950a69bb5SSascha Wildner
45050a69bb5SSascha Wildner void
sshlogv(const char * file,const char * func,int line,int showfunc,LogLevel level,const char * suffix,const char * fmt,va_list args)45150a69bb5SSascha Wildner sshlogv(const char *file, const char *func, int line, int showfunc,
45250a69bb5SSascha Wildner LogLevel level, const char *suffix, const char *fmt, va_list args)
45350a69bb5SSascha Wildner {
45450a69bb5SSascha Wildner char tag[128], fmt2[MSGBUFSIZ + 128];
45550a69bb5SSascha Wildner int forced = 0;
45650a69bb5SSascha Wildner const char *cp;
45750a69bb5SSascha Wildner size_t i;
45850a69bb5SSascha Wildner
459*ba1276acSMatthew Dillon /* short circuit processing early if we're not going to log anything */
460*ba1276acSMatthew Dillon if (nlog_verbose == 0 && level > log_level)
461*ba1276acSMatthew Dillon return;
462*ba1276acSMatthew Dillon
46350a69bb5SSascha Wildner snprintf(tag, sizeof(tag), "%.48s:%.48s():%d (pid=%ld)",
46450a69bb5SSascha Wildner (cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line,
46550a69bb5SSascha Wildner (long)getpid());
46650a69bb5SSascha Wildner for (i = 0; i < nlog_verbose; i++) {
46750a69bb5SSascha Wildner if (match_pattern_list(tag, log_verbose[i], 0) == 1) {
46850a69bb5SSascha Wildner forced = 1;
46950a69bb5SSascha Wildner break;
47050a69bb5SSascha Wildner }
47150a69bb5SSascha Wildner }
47250a69bb5SSascha Wildner
47350a69bb5SSascha Wildner if (forced)
47450a69bb5SSascha Wildner snprintf(fmt2, sizeof(fmt2), "%s: %s", tag, fmt);
47550a69bb5SSascha Wildner else if (showfunc)
47650a69bb5SSascha Wildner snprintf(fmt2, sizeof(fmt2), "%s: %s", func, fmt);
47750a69bb5SSascha Wildner else
47850a69bb5SSascha Wildner strlcpy(fmt2, fmt, sizeof(fmt2));
47950a69bb5SSascha Wildner
48050a69bb5SSascha Wildner do_log(level, forced, suffix, fmt2, args);
48150a69bb5SSascha Wildner }
48250a69bb5SSascha Wildner
48350a69bb5SSascha Wildner void
sshlogdirect(LogLevel level,int forced,const char * fmt,...)48450a69bb5SSascha Wildner sshlogdirect(LogLevel level, int forced, const char *fmt, ...)
48550a69bb5SSascha Wildner {
48650a69bb5SSascha Wildner va_list args;
48750a69bb5SSascha Wildner
48850a69bb5SSascha Wildner va_start(args, fmt);
48950a69bb5SSascha Wildner do_log(level, forced, NULL, fmt, args);
49050a69bb5SSascha Wildner va_end(args);
49150a69bb5SSascha Wildner }
492