1323124Sdes/* $OpenBSD: log.c,v 1.48 2016/07/15 05:01:58 dtucker Exp $ */ 257429Smarkm/* 365668Skris * Author: Tatu Ylonen <ylo@cs.hut.fi> 465668Skris * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 565668Skris * All rights reserved 665668Skris * 765668Skris * As far as I am concerned, the code I have written for this software 865668Skris * can be used freely for any purpose. Any derived versions of this 965668Skris * software must be clearly marked as such, and if the derived work is 1065668Skris * incompatible with the protocol description in the RFC file, it must be 1165668Skris * called by a name other than "ssh" or "Secure Shell". 1265668Skris */ 1365668Skris/* 1465668Skris * Copyright (c) 2000 Markus Friedl. All rights reserved. 1565668Skris * 1665668Skris * Redistribution and use in source and binary forms, with or without 1765668Skris * modification, are permitted provided that the following conditions 1865668Skris * are met: 1965668Skris * 1. Redistributions of source code must retain the above copyright 2065668Skris * notice, this list of conditions and the following disclaimer. 2165668Skris * 2. Redistributions in binary form must reproduce the above copyright 2265668Skris * notice, this list of conditions and the following disclaimer in the 2365668Skris * documentation and/or other materials provided with the distribution. 2465668Skris * 2565668Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2665668Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2765668Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2865668Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2965668Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 3065668Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3165668Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3265668Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3365668Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3465668Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3557429Smarkm */ 3657429Smarkm 3757429Smarkm#include "includes.h" 3857429Smarkm 39162852Sdes#include <sys/types.h> 4057429Smarkm 41255767Sdes#include <fcntl.h> 42162852Sdes#include <stdarg.h> 43162852Sdes#include <stdio.h> 44162852Sdes#include <stdlib.h> 45162852Sdes#include <string.h> 4676259Sgreen#include <syslog.h> 47162852Sdes#include <unistd.h> 48181111Sdes#include <errno.h> 49248619Sdes#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) 50124208Sdes# include <vis.h> 51124208Sdes#endif 5276259Sgreen 53162852Sdes#include "log.h" 54162852Sdes 5576259Sgreenstatic LogLevel log_level = SYSLOG_LEVEL_INFO; 5676259Sgreenstatic int log_on_stderr = 1; 57255767Sdesstatic int log_stderr_fd = STDERR_FILENO; 5876259Sgreenstatic int log_facility = LOG_AUTH; 5976259Sgreenstatic char *argv0; 60226046Sdesstatic log_handler_fn *log_handler; 61226046Sdesstatic void *log_handler_ctx; 6276259Sgreen 6376259Sgreenextern char *__progname; 6476259Sgreen 65137015Sdes#define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL) 66137015Sdes#define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL) 67137015Sdes 6876259Sgreen/* textual representation of log-facilities/levels */ 6976259Sgreen 7076259Sgreenstatic struct { 7176259Sgreen const char *name; 7276259Sgreen SyslogFacility val; 7376259Sgreen} log_facilities[] = { 7476259Sgreen { "DAEMON", SYSLOG_FACILITY_DAEMON }, 7576259Sgreen { "USER", SYSLOG_FACILITY_USER }, 7676259Sgreen { "AUTH", SYSLOG_FACILITY_AUTH }, 7798937Sdes#ifdef LOG_AUTHPRIV 7898937Sdes { "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV }, 7998937Sdes#endif 8076259Sgreen { "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, 8176259Sgreen { "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, 8276259Sgreen { "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, 8376259Sgreen { "LOCAL3", SYSLOG_FACILITY_LOCAL3 }, 8476259Sgreen { "LOCAL4", SYSLOG_FACILITY_LOCAL4 }, 8576259Sgreen { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, 8676259Sgreen { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, 8776259Sgreen { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, 8892555Sdes { NULL, SYSLOG_FACILITY_NOT_SET } 8976259Sgreen}; 9076259Sgreen 9176259Sgreenstatic struct { 9276259Sgreen const char *name; 9376259Sgreen LogLevel val; 9476259Sgreen} log_levels[] = 9576259Sgreen{ 9676259Sgreen { "QUIET", SYSLOG_LEVEL_QUIET }, 9776259Sgreen { "FATAL", SYSLOG_LEVEL_FATAL }, 9876259Sgreen { "ERROR", SYSLOG_LEVEL_ERROR }, 9976259Sgreen { "INFO", SYSLOG_LEVEL_INFO }, 10076259Sgreen { "VERBOSE", SYSLOG_LEVEL_VERBOSE }, 10176259Sgreen { "DEBUG", SYSLOG_LEVEL_DEBUG1 }, 10276259Sgreen { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, 10376259Sgreen { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, 10476259Sgreen { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, 10592555Sdes { NULL, SYSLOG_LEVEL_NOT_SET } 10676259Sgreen}; 10776259Sgreen 10876259SgreenSyslogFacility 10976259Sgreenlog_facility_number(char *name) 11076259Sgreen{ 11176259Sgreen int i; 112106121Sdes 11376259Sgreen if (name != NULL) 11476259Sgreen for (i = 0; log_facilities[i].name; i++) 11576259Sgreen if (strcasecmp(log_facilities[i].name, name) == 0) 11676259Sgreen return log_facilities[i].val; 11792555Sdes return SYSLOG_FACILITY_NOT_SET; 11876259Sgreen} 11976259Sgreen 120181111Sdesconst char * 121181111Sdeslog_facility_name(SyslogFacility facility) 122181111Sdes{ 123181111Sdes u_int i; 124181111Sdes 125181111Sdes for (i = 0; log_facilities[i].name; i++) 126181111Sdes if (log_facilities[i].val == facility) 127181111Sdes return log_facilities[i].name; 128181111Sdes return NULL; 129181111Sdes} 130181111Sdes 13176259SgreenLogLevel 13276259Sgreenlog_level_number(char *name) 13376259Sgreen{ 13476259Sgreen int i; 135106121Sdes 13676259Sgreen if (name != NULL) 13776259Sgreen for (i = 0; log_levels[i].name; i++) 13876259Sgreen if (strcasecmp(log_levels[i].name, name) == 0) 13976259Sgreen return log_levels[i].val; 14092555Sdes return SYSLOG_LEVEL_NOT_SET; 14176259Sgreen} 14257429Smarkm 143181111Sdesconst char * 144181111Sdeslog_level_name(LogLevel level) 145181111Sdes{ 146181111Sdes u_int i; 147181111Sdes 148181111Sdes for (i = 0; log_levels[i].name != NULL; i++) 149181111Sdes if (log_levels[i].val == level) 150181111Sdes return log_levels[i].name; 151181111Sdes return NULL; 152181111Sdes} 153181111Sdes 15457429Smarkm/* Error messages that should be logged. */ 15557429Smarkm 15657429Smarkmvoid 15757429Smarkmerror(const char *fmt,...) 15857429Smarkm{ 15957429Smarkm va_list args; 160106121Sdes 16157429Smarkm va_start(args, fmt); 16257429Smarkm do_log(SYSLOG_LEVEL_ERROR, fmt, args); 16357429Smarkm va_end(args); 16457429Smarkm} 16557429Smarkm 166162852Sdesvoid 167162852Sdessigdie(const char *fmt,...) 168162852Sdes{ 169162852Sdes#ifdef DO_LOG_SAFE_IN_SIGHAND 170162852Sdes va_list args; 171162852Sdes 172162852Sdes va_start(args, fmt); 173162852Sdes do_log(SYSLOG_LEVEL_FATAL, fmt, args); 174162852Sdes va_end(args); 175162852Sdes#endif 176162852Sdes _exit(1); 177162852Sdes} 178162852Sdes 179323124Sdesvoid 180323124Sdeslogdie(const char *fmt,...) 181323124Sdes{ 182323124Sdes va_list args; 183162852Sdes 184323124Sdes va_start(args, fmt); 185323124Sdes do_log(SYSLOG_LEVEL_INFO, fmt, args); 186323124Sdes va_end(args); 187323124Sdes cleanup_exit(255); 188323124Sdes} 189323124Sdes 19057429Smarkm/* Log this message (information that usually should go to the log). */ 19157429Smarkm 19257429Smarkmvoid 193124208Sdeslogit(const char *fmt,...) 19457429Smarkm{ 19557429Smarkm va_list args; 196106121Sdes 19757429Smarkm va_start(args, fmt); 19857429Smarkm do_log(SYSLOG_LEVEL_INFO, fmt, args); 19957429Smarkm va_end(args); 20057429Smarkm} 20157429Smarkm 20257429Smarkm/* More detailed messages (information that does not need to go to the log). */ 20357429Smarkm 20457429Smarkmvoid 20557429Smarkmverbose(const char *fmt,...) 20657429Smarkm{ 20757429Smarkm va_list args; 208106121Sdes 20957429Smarkm va_start(args, fmt); 21057429Smarkm do_log(SYSLOG_LEVEL_VERBOSE, fmt, args); 21157429Smarkm va_end(args); 21257429Smarkm} 21357429Smarkm 21457429Smarkm/* Debugging messages that should not be logged during normal operation. */ 21557429Smarkm 21657429Smarkmvoid 21757429Smarkmdebug(const char *fmt,...) 21857429Smarkm{ 21957429Smarkm va_list args; 220106121Sdes 22157429Smarkm va_start(args, fmt); 22269587Sgreen do_log(SYSLOG_LEVEL_DEBUG1, fmt, args); 22357429Smarkm va_end(args); 22457429Smarkm} 22557429Smarkm 22669587Sgreenvoid 22769587Sgreendebug2(const char *fmt,...) 22869587Sgreen{ 22969587Sgreen va_list args; 230106121Sdes 23169587Sgreen va_start(args, fmt); 23269587Sgreen do_log(SYSLOG_LEVEL_DEBUG2, fmt, args); 23369587Sgreen va_end(args); 23469587Sgreen} 23569587Sgreen 23669587Sgreenvoid 23769587Sgreendebug3(const char *fmt,...) 23869587Sgreen{ 23969587Sgreen va_list args; 240106121Sdes 24169587Sgreen va_start(args, fmt); 24269587Sgreen do_log(SYSLOG_LEVEL_DEBUG3, fmt, args); 24369587Sgreen va_end(args); 24469587Sgreen} 24569587Sgreen 24676259Sgreen/* 24776259Sgreen * Initialize the log. 24876259Sgreen */ 24957429Smarkm 25076259Sgreenvoid 25176259Sgreenlog_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) 25257429Smarkm{ 253146998Sdes#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 254146998Sdes struct syslog_data sdata = SYSLOG_DATA_INIT; 255146998Sdes#endif 256147001Sdes 25776259Sgreen argv0 = av0; 25857429Smarkm 25976259Sgreen switch (level) { 26076259Sgreen case SYSLOG_LEVEL_QUIET: 26176259Sgreen case SYSLOG_LEVEL_FATAL: 26276259Sgreen case SYSLOG_LEVEL_ERROR: 26376259Sgreen case SYSLOG_LEVEL_INFO: 26476259Sgreen case SYSLOG_LEVEL_VERBOSE: 26576259Sgreen case SYSLOG_LEVEL_DEBUG1: 26676259Sgreen case SYSLOG_LEVEL_DEBUG2: 26776259Sgreen case SYSLOG_LEVEL_DEBUG3: 26876259Sgreen log_level = level; 26976259Sgreen break; 27076259Sgreen default: 27176259Sgreen fprintf(stderr, "Unrecognized internal syslog level code %d\n", 27276259Sgreen (int) level); 27376259Sgreen exit(1); 27476259Sgreen } 27576259Sgreen 276226046Sdes log_handler = NULL; 277226046Sdes log_handler_ctx = NULL; 278226046Sdes 27976259Sgreen log_on_stderr = on_stderr; 28076259Sgreen if (on_stderr) 28176259Sgreen return; 28276259Sgreen 28376259Sgreen switch (facility) { 28476259Sgreen case SYSLOG_FACILITY_DAEMON: 28576259Sgreen log_facility = LOG_DAEMON; 28676259Sgreen break; 28776259Sgreen case SYSLOG_FACILITY_USER: 28876259Sgreen log_facility = LOG_USER; 28976259Sgreen break; 29076259Sgreen case SYSLOG_FACILITY_AUTH: 29176259Sgreen log_facility = LOG_AUTH; 29276259Sgreen break; 29398937Sdes#ifdef LOG_AUTHPRIV 29498937Sdes case SYSLOG_FACILITY_AUTHPRIV: 29598937Sdes log_facility = LOG_AUTHPRIV; 29698937Sdes break; 29798937Sdes#endif 29876259Sgreen case SYSLOG_FACILITY_LOCAL0: 29976259Sgreen log_facility = LOG_LOCAL0; 30076259Sgreen break; 30176259Sgreen case SYSLOG_FACILITY_LOCAL1: 30276259Sgreen log_facility = LOG_LOCAL1; 30376259Sgreen break; 30476259Sgreen case SYSLOG_FACILITY_LOCAL2: 30576259Sgreen log_facility = LOG_LOCAL2; 30676259Sgreen break; 30776259Sgreen case SYSLOG_FACILITY_LOCAL3: 30876259Sgreen log_facility = LOG_LOCAL3; 30976259Sgreen break; 31076259Sgreen case SYSLOG_FACILITY_LOCAL4: 31176259Sgreen log_facility = LOG_LOCAL4; 31276259Sgreen break; 31376259Sgreen case SYSLOG_FACILITY_LOCAL5: 31476259Sgreen log_facility = LOG_LOCAL5; 31576259Sgreen break; 31676259Sgreen case SYSLOG_FACILITY_LOCAL6: 31776259Sgreen log_facility = LOG_LOCAL6; 31876259Sgreen break; 31976259Sgreen case SYSLOG_FACILITY_LOCAL7: 32076259Sgreen log_facility = LOG_LOCAL7; 32176259Sgreen break; 32276259Sgreen default: 32376259Sgreen fprintf(stderr, 32476259Sgreen "Unrecognized internal syslog facility code %d\n", 32576259Sgreen (int) facility); 32676259Sgreen exit(1); 32776259Sgreen } 328146998Sdes 329146998Sdes /* 330146998Sdes * If an external library (eg libwrap) attempts to use syslog 331146998Sdes * immediately after reexec, syslog may be pointing to the wrong 332146998Sdes * facility, so we force an open/close of syslog here. 333146998Sdes */ 334146998Sdes#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 335146998Sdes openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); 336146998Sdes closelog_r(&sdata); 337146998Sdes#else 338146998Sdes openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); 339146998Sdes closelog(); 340146998Sdes#endif 34157429Smarkm} 34257429Smarkm 343248619Sdesvoid 344248619Sdeslog_change_level(LogLevel new_log_level) 345248619Sdes{ 346248619Sdes /* no-op if log_init has not been called */ 347248619Sdes if (argv0 == NULL) 348248619Sdes return; 349248619Sdes log_init(argv0, new_log_level, log_facility, log_on_stderr); 350248619Sdes} 351248619Sdes 352248619Sdesint 353248619Sdeslog_is_on_stderr(void) 354248619Sdes{ 355323124Sdes return log_on_stderr && log_stderr_fd == STDERR_FILENO; 356248619Sdes} 357248619Sdes 358255767Sdes/* redirect what would usually get written to stderr to specified file */ 359255767Sdesvoid 360255767Sdeslog_redirect_stderr_to(const char *logfile) 361255767Sdes{ 362255767Sdes int fd; 363255767Sdes 364255767Sdes if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) { 365255767Sdes fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile, 366255767Sdes strerror(errno)); 367255767Sdes exit(1); 368255767Sdes } 369255767Sdes log_stderr_fd = fd; 370255767Sdes} 371255767Sdes 37276259Sgreen#define MSGBUFSIZ 1024 37376259Sgreen 37476259Sgreenvoid 375226046Sdesset_log_handler(log_handler_fn *handler, void *ctx) 376226046Sdes{ 377226046Sdes log_handler = handler; 378226046Sdes log_handler_ctx = ctx; 379226046Sdes} 380226046Sdes 381226046Sdesvoid 382226046Sdesdo_log2(LogLevel level, const char *fmt,...) 383226046Sdes{ 384226046Sdes va_list args; 385226046Sdes 386226046Sdes va_start(args, fmt); 387226046Sdes do_log(level, fmt, args); 388226046Sdes va_end(args); 389226046Sdes} 390226046Sdes 391226046Sdesvoid 39276259Sgreendo_log(LogLevel level, const char *fmt, va_list args) 39357429Smarkm{ 394126274Sdes#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 395124208Sdes struct syslog_data sdata = SYSLOG_DATA_INIT; 396124208Sdes#endif 39776259Sgreen char msgbuf[MSGBUFSIZ]; 39876259Sgreen char fmtbuf[MSGBUFSIZ]; 39976259Sgreen char *txt = NULL; 40076259Sgreen int pri = LOG_INFO; 401181111Sdes int saved_errno = errno; 402226046Sdes log_handler_fn *tmp_handler; 40376259Sgreen 40476259Sgreen if (level > log_level) 40576259Sgreen return; 40676259Sgreen 40776259Sgreen switch (level) { 40876259Sgreen case SYSLOG_LEVEL_FATAL: 40976259Sgreen if (!log_on_stderr) 41076259Sgreen txt = "fatal"; 41176259Sgreen pri = LOG_CRIT; 41276259Sgreen break; 41376259Sgreen case SYSLOG_LEVEL_ERROR: 41476259Sgreen if (!log_on_stderr) 41576259Sgreen txt = "error"; 41676259Sgreen pri = LOG_ERR; 41776259Sgreen break; 41876259Sgreen case SYSLOG_LEVEL_INFO: 41976259Sgreen pri = LOG_INFO; 42076259Sgreen break; 42176259Sgreen case SYSLOG_LEVEL_VERBOSE: 42276259Sgreen pri = LOG_INFO; 42376259Sgreen break; 42476259Sgreen case SYSLOG_LEVEL_DEBUG1: 42576259Sgreen txt = "debug1"; 42676259Sgreen pri = LOG_DEBUG; 42776259Sgreen break; 42876259Sgreen case SYSLOG_LEVEL_DEBUG2: 42976259Sgreen txt = "debug2"; 43076259Sgreen pri = LOG_DEBUG; 43176259Sgreen break; 43276259Sgreen case SYSLOG_LEVEL_DEBUG3: 43376259Sgreen txt = "debug3"; 43476259Sgreen pri = LOG_DEBUG; 43576259Sgreen break; 43676259Sgreen default: 43776259Sgreen txt = "internal error"; 43876259Sgreen pri = LOG_ERR; 43976259Sgreen break; 44076259Sgreen } 441226046Sdes if (txt != NULL && log_handler == NULL) { 44276259Sgreen snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt); 44376259Sgreen vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args); 44476259Sgreen } else { 44576259Sgreen vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); 44676259Sgreen } 447137015Sdes strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), 448137015Sdes log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS); 449226046Sdes if (log_handler != NULL) { 450226046Sdes /* Avoid recursion */ 451226046Sdes tmp_handler = log_handler; 452226046Sdes log_handler = NULL; 453226046Sdes tmp_handler(level, fmtbuf, log_handler_ctx); 454226046Sdes log_handler = tmp_handler; 455226046Sdes } else if (log_on_stderr) { 456124208Sdes snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf); 457255767Sdes (void)write(log_stderr_fd, msgbuf, strlen(msgbuf)); 45876259Sgreen } else { 459126274Sdes#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) 460124208Sdes openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); 461124208Sdes syslog_r(pri, &sdata, "%.500s", fmtbuf); 462124208Sdes closelog_r(&sdata); 463124208Sdes#else 46476259Sgreen openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); 465113908Sdes syslog(pri, "%.500s", fmtbuf); 46676259Sgreen closelog(); 467124208Sdes#endif 46876259Sgreen } 469181111Sdes errno = saved_errno; 47057429Smarkm} 471