log.c revision 3109:393fae270b2d
11556Srgrimes/*
21556Srgrimes * Author: Tatu Ylonen <ylo@cs.hut.fi>
31556Srgrimes * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
41556Srgrimes *                    All rights reserved
51556Srgrimes *
61556Srgrimes * As far as I am concerned, the code I have written for this software
71556Srgrimes * can be used freely for any purpose.  Any derived versions of this
81556Srgrimes * software must be clearly marked as such, and if the derived work is
91556Srgrimes * incompatible with the protocol description in the RFC file, it must be
101556Srgrimes * called by a name other than "ssh" or "Secure Shell".
111556Srgrimes */
121556Srgrimes/*
131556Srgrimes * Copyright (c) 2000 Markus Friedl.  All rights reserved.
141556Srgrimes *
151556Srgrimes * Redistribution and use in source and binary forms, with or without
161556Srgrimes * modification, are permitted provided that the following conditions
171556Srgrimes * are met:
181556Srgrimes * 1. Redistributions of source code must retain the above copyright
191556Srgrimes *    notice, this list of conditions and the following disclaimer.
201556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
211556Srgrimes *    notice, this list of conditions and the following disclaimer in the
221556Srgrimes *    documentation and/or other materials provided with the distribution.
231556Srgrimes *
241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
251556Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
261556Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
271556Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
281556Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
291556Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30114433Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
311556Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3227959Ssteve * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
331556Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
341556Srgrimes */
3527964Ssteve/*
3627964Ssteve * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
3727964Ssteve * Use is subject to license terms.
3827964Ssteve */
39114433Sobrien
4027964Ssteve#include "includes.h"
4199110SobrienRCSID("$OpenBSD: log.c,v 1.24 2002/07/19 15:43:33 markus Exp $");
4299110Sobrien
431556Srgrimes#pragma ident	"%Z%%M%	%I%	%E% SMI"
441556Srgrimes
4547584Skris#include "log.h"
4647584Skris#include "xmalloc.h"
471556Srgrimes
481556Srgrimes#include <atomic.h>
491556Srgrimes#include <syslog.h>
501556Srgrimes
511556Srgrimesstatic LogLevel log_level = SYSLOG_LEVEL_INFO;
5290644Simpstatic int log_on_stderr = 1;
5390644Simpstatic int log_facility = LOG_AUTH;
541556Srgrimesstatic char *argv0;
551556Srgrimes
561556Srgrimesextern char *__progname;
5750539Smharo
581556Srgrimesstatic const char *log_txt_prefix = "";
591556Srgrimes
6050872Smharo/* textual representation of log-facilities/levels */
61137009Sdelphij
627798Sachestatic struct {
63191670Simp	const char *name;
641556Srgrimes	SyslogFacility val;
6590110Simp} log_facilities[] = {
66137009Sdelphij	{ "DAEMON",	SYSLOG_FACILITY_DAEMON },
6790110Simp	{ "USER",	SYSLOG_FACILITY_USER },
68136113Sdes	{ "AUTH",	SYSLOG_FACILITY_AUTH },
6990110Simp#ifdef LOG_AUTHPRIV
70122409Sguido	{ "AUTHPRIV",	SYSLOG_FACILITY_AUTHPRIV },
7190110Simp#endif
72191670Simp	{ "LOCAL0",	SYSLOG_FACILITY_LOCAL0 },
7390110Simp	{ "LOCAL1",	SYSLOG_FACILITY_LOCAL1 },
741556Srgrimes	{ "LOCAL2",	SYSLOG_FACILITY_LOCAL2 },
751556Srgrimes	{ "LOCAL3",	SYSLOG_FACILITY_LOCAL3 },
761556Srgrimes	{ "LOCAL4",	SYSLOG_FACILITY_LOCAL4 },
771556Srgrimes	{ "LOCAL5",	SYSLOG_FACILITY_LOCAL5 },
78136112Sdes	{ "LOCAL6",	SYSLOG_FACILITY_LOCAL6 },
791556Srgrimes	{ "LOCAL7",	SYSLOG_FACILITY_LOCAL7 },
80136112Sdes	{ NULL,		SYSLOG_FACILITY_NOT_SET }
811556Srgrimes};
821556Srgrimes
8390110Simpstatic struct {
841556Srgrimes	const char *name;
85137009Sdelphij	LogLevel val;
8654895Ssheldonh} log_levels[] =
871556Srgrimes{
8854895Ssheldonh	{ "QUIET",	SYSLOG_LEVEL_QUIET },
8954895Ssheldonh	{ "FATAL",	SYSLOG_LEVEL_FATAL },
9054895Ssheldonh	{ "ERROR",	SYSLOG_LEVEL_ERROR },
9154895Ssheldonh	{ "NOTICE",	SYSLOG_LEVEL_NOTICE },
9254895Ssheldonh	{ "INFO",	SYSLOG_LEVEL_INFO },
9354895Ssheldonh	{ "VERBOSE",	SYSLOG_LEVEL_VERBOSE },
9454895Ssheldonh	{ "DEBUG",	SYSLOG_LEVEL_DEBUG1 },
9554895Ssheldonh	{ "DEBUG1",	SYSLOG_LEVEL_DEBUG1 },
9654895Ssheldonh	{ "DEBUG2",	SYSLOG_LEVEL_DEBUG2 },
9754895Ssheldonh	{ "DEBUG3",	SYSLOG_LEVEL_DEBUG3 },
9897533Stjr	{ NULL,		SYSLOG_LEVEL_NOT_SET }
9954895Ssheldonh};
10097533Stjr
10197533StjrSyslogFacility
10299858Stjrlog_facility_number(char *name)
10397533Stjr{
10497533Stjr	int i;
10597533Stjr
10654895Ssheldonh	if (name != NULL)
10754895Ssheldonh		for (i = 0; log_facilities[i].name; i++)
10820421Ssteve			if (strcasecmp(log_facilities[i].name, name) == 0)
109137009Sdelphij				return log_facilities[i].val;
1101556Srgrimes	return SYSLOG_FACILITY_NOT_SET;
1111556Srgrimes}
1121556Srgrimes
1131556SrgrimesLogLevel
1141556Srgrimeslog_level_number(char *name)
1151556Srgrimes{
1161556Srgrimes	int i;
1171556Srgrimes
1181556Srgrimes	if (name != NULL)
1191556Srgrimes		for (i = 0; log_levels[i].name; i++)
1201556Srgrimes			if (strcasecmp(log_levels[i].name, name) == 0)
1211556Srgrimes				return log_levels[i].val;
122137009Sdelphij	return SYSLOG_LEVEL_NOT_SET;
123137009Sdelphij}
124137009Sdelphij
1251556Srgrimesvoid
1261556Srgrimesset_log_txt_prefix(const char *txt)
1271556Srgrimes{
1281556Srgrimes	log_txt_prefix = txt;
1291556Srgrimes}
1301556Srgrimes
1311556Srgrimes/* Error messages that should be logged. */
13250872Smharo
13350872Smharovoid
13450872Smharoerror(const char *fmt,...)
13520421Ssteve{
13620421Ssteve	va_list args;
13720421Ssteve
1381556Srgrimes	va_start(args, fmt);
1391556Srgrimes	do_log(SYSLOG_LEVEL_ERROR, fmt, args);
1401556Srgrimes	va_end(args);
1411556Srgrimes}
1421556Srgrimes
1431556Srgrimesvoid
14444282Sjkhnotice(const char *fmt,...)
14544282Sjkh{
146122409Sguido	va_list args;
1471556Srgrimes
14844282Sjkh	va_start(args, fmt);
1491556Srgrimes	do_log(SYSLOG_LEVEL_NOTICE, fmt, args);
1501556Srgrimes	va_end(args);
151136124Sdes}
152136124Sdes
1537798Sache/* Log this message (information that usually should go to the log). */
1541556Srgrimes
155191670Simpvoid
15620421Sstevelog(const char *fmt,...)
15720421Ssteve{
15820421Ssteve	va_list args;
159137009Sdelphij
160137009Sdelphij	va_start(args, fmt);
161137009Sdelphij	do_log(SYSLOG_LEVEL_INFO, fmt, args);
162137009Sdelphij	va_end(args);
16320421Ssteve}
16420421Ssteve
16520421Ssteve/* More detailed messages (information that does not need to go to the log). */
16620421Ssteve
16720421Sstevevoid
16820421Ssteveverbose(const char *fmt,...)
1691556Srgrimes{
1701556Srgrimes	va_list args;
1711556Srgrimes
1721556Srgrimes	va_start(args, fmt);
17390110Simp	do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
1741556Srgrimes	va_end(args);
1751556Srgrimes}
1761556Srgrimes
1771556Srgrimes/* Debugging messages that should not be logged during normal operation. */
17820421Ssteve
1797798Sachevoid
1801556Srgrimesdebug(const char *fmt,...)
1811556Srgrimes{
1821556Srgrimes	va_list args;
1831556Srgrimes
1841556Srgrimes	va_start(args, fmt);
18520421Ssteve	do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
1861556Srgrimes	va_end(args);
1871556Srgrimes}
1881556Srgrimes
1891556Srgrimesvoid
1901556Srgrimesdebug2(const char *fmt,...)
1911556Srgrimes{
1921556Srgrimes	va_list args;
19351230Sbde
19420421Ssteve	va_start(args, fmt);
19520421Ssteve	do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
19620421Ssteve	va_end(args);
19720421Ssteve}
198137639Sjkh
199137639Sjkhvoid
200137639Sjkhdebug3(const char *fmt,...)
20199744Sdillon{
202137639Sjkh	va_list args;
2031556Srgrimes
2041556Srgrimes	va_start(args, fmt);
2051556Srgrimes	do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
2061556Srgrimes	va_end(args);
2071556Srgrimes}
2081556Srgrimes
2091556Srgrimes/* Fatal cleanup */
2101556Srgrimes
2111556Srgrimesstruct fatal_cleanup {
2121556Srgrimes	struct fatal_cleanup *next;
2131556Srgrimes	void (*proc) (void *);
2141556Srgrimes	void *context;
2151556Srgrimes};
216124041Skuriyama
217124041Skuriyamastatic struct fatal_cleanup *fatal_cleanups = NULL;
2181556Srgrimes
2191556Srgrimes/* Registers a cleanup function to be called by fatal() before exiting. */
2201556Srgrimes
2211556Srgrimesvoid
2221556Srgrimesfatal_add_cleanup(void (*proc) (void *), void *context)
2231556Srgrimes{
2241556Srgrimes	struct fatal_cleanup *cu;
2251556Srgrimes
2261556Srgrimes	cu = xmalloc(sizeof(*cu));
2271556Srgrimes	cu->proc = proc;
2281556Srgrimes	cu->context = context;
22920421Ssteve	cu->next = fatal_cleanups;
2301556Srgrimes	fatal_cleanups = cu;
2311556Srgrimes}
2321556Srgrimes
2331556Srgrimes/* Removes a cleanup function to be called at fatal(). */
2347798Sache
2357798Sachevoid
2367798Sachefatal_remove_cleanup(void (*proc) (void *context), void *context)
237193087Sjilles{
2387798Sache	struct fatal_cleanup **cup, *cu;
2397798Sache
2401556Srgrimes	for (cup = &fatal_cleanups; *cup; cup = &cu->next) {
2411556Srgrimes		cu = *cup;
2421556Srgrimes		if (cu->proc == proc && cu->context == context) {
2431556Srgrimes			*cup = cu->next;
2441556Srgrimes			xfree(cu);
2451556Srgrimes			return;
24620421Ssteve		}
24720421Ssteve	}
24820421Ssteve	debug3("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx",
24920421Ssteve	    (u_long) proc, (u_long) context);
2501556Srgrimes}
2511556Srgrimes
2527798Sache/* Remove all cleanups, to be called after fork() */
2537798Sachevoid
2547798Sachefatal_remove_all_cleanups(void)
2557798Sache{
256193087Sjilles	struct fatal_cleanup *cu, *next_cu;
2577798Sache
25853819Smharo	for (cu = fatal_cleanups; cu; cu = next_cu) {
2597798Sache		next_cu = cu->next;
2607798Sache		xfree(cu);
2617798Sache	}
2627798Sache
2637798Sache	fatal_cleanups = NULL;
26420421Ssteve}
26520421Ssteve
26620421Ssteve/* Cleanup and exit. Make sure each cleanup is called only once. */
26753819Smharovoid
26853819Smharofatal_cleanup(void)
26953819Smharo{
27050872Smharo	struct fatal_cleanup *cu, *next_cu;
27170219Sobrien	static volatile u_int called = 0;
272191670Simp
273191670Simp	if (atomic_cas_uint(&called, 0, 1) == 1)
274191670Simp		exit(255);
275191670Simp	/* Call cleanup functions. */
276191670Simp	for (cu = fatal_cleanups; cu; cu = next_cu) {
2771556Srgrimes		next_cu = cu->next;
27850539Smharo		debug("Calling cleanup 0x%lx(0x%lx)",
27920421Ssteve		    (u_long) cu->proc, (u_long) cu->context);
28020421Ssteve		(*cu->proc) (cu->context);
28120421Ssteve	}
28253819Smharo	exit(255);
28353819Smharo}
28453819Smharo
28550872Smharo
28670219Sobrien/*
287191670Simp * Initialize the log.
288191670Simp */
289191670Simp
290191670Simpvoid
291191670Simplog_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
29220421Ssteve{
29350539Smharo	argv0 = av0;
29420421Ssteve
29520421Ssteve	switch (level) {
296124041Skuriyama	case SYSLOG_LEVEL_QUIET:
297124041Skuriyama	case SYSLOG_LEVEL_FATAL:
298124041Skuriyama	case SYSLOG_LEVEL_ERROR:
299124041Skuriyama	case SYSLOG_LEVEL_NOTICE:
300124041Skuriyama	case SYSLOG_LEVEL_INFO:
301124041Skuriyama	case SYSLOG_LEVEL_VERBOSE:
302124041Skuriyama	case SYSLOG_LEVEL_DEBUG1:
303124041Skuriyama	case SYSLOG_LEVEL_DEBUG2:
30420421Ssteve	case SYSLOG_LEVEL_DEBUG3:
3057798Sache		log_level = level;
306122409Sguido		break;
307122409Sguido	default:
30853819Smharo		fprintf(stderr, "Unrecognized internal syslog level code %d\n",
30953819Smharo		    (int) level);
31053819Smharo		exit(1);
31150872Smharo	}
31270219Sobrien
313191670Simp	log_on_stderr = on_stderr;
314191670Simp	if (on_stderr)
315191670Simp		return;
316191670Simp
317191670Simp	switch (facility) {
3187798Sache	case SYSLOG_FACILITY_DAEMON:
31950539Smharo		log_facility = LOG_DAEMON;
3207798Sache		break;
3211556Srgrimes	case SYSLOG_FACILITY_USER:
3227798Sache		log_facility = LOG_USER;
3231556Srgrimes		break;
3241556Srgrimes	case SYSLOG_FACILITY_AUTH:
3251556Srgrimes		log_facility = LOG_AUTH;
3261556Srgrimes		break;
3271556Srgrimes#ifdef LOG_AUTHPRIV
328157770Smaxim	case SYSLOG_FACILITY_AUTHPRIV:
3291556Srgrimes		log_facility = LOG_AUTHPRIV;
3301556Srgrimes		break;
3311556Srgrimes#endif
33290110Simp	case SYSLOG_FACILITY_LOCAL0:
3331556Srgrimes		log_facility = LOG_LOCAL0;
3341556Srgrimes		break;
33520421Ssteve	case SYSLOG_FACILITY_LOCAL1:
3361556Srgrimes		log_facility = LOG_LOCAL1;
3371556Srgrimes		break;
3381556Srgrimes	case SYSLOG_FACILITY_LOCAL2:
3391556Srgrimes		log_facility = LOG_LOCAL2;
3401556Srgrimes		break;
3411556Srgrimes	case SYSLOG_FACILITY_LOCAL3:
3421556Srgrimes		log_facility = LOG_LOCAL3;
3431556Srgrimes		break;
3441556Srgrimes	case SYSLOG_FACILITY_LOCAL4:
34520421Ssteve		log_facility = LOG_LOCAL4;
34620421Ssteve		break;
34720421Ssteve	case SYSLOG_FACILITY_LOCAL5:
34820421Ssteve		log_facility = LOG_LOCAL5;
34920421Ssteve		break;
35020421Ssteve	case SYSLOG_FACILITY_LOCAL6:
35120421Ssteve		log_facility = LOG_LOCAL6;
35220421Ssteve		break;
3531556Srgrimes	case SYSLOG_FACILITY_LOCAL7:
35420421Ssteve		log_facility = LOG_LOCAL7;
35520421Ssteve		break;
35620421Ssteve	default:
3571556Srgrimes		fprintf(stderr,
3581556Srgrimes		    "Unrecognized internal syslog facility code %d\n",
35920421Ssteve		    (int) facility);
36020421Ssteve		exit(1);
3611556Srgrimes	}
3621556Srgrimes}
3631556Srgrimes
3641556Srgrimes#define MSGBUFSIZ 1024
36520421Ssteve
3661556Srgrimes/* PRINTFLIKE2 */
3677798Sachevoid
368163485Smaximdo_log(LogLevel level, const char *fmt, va_list args)
3697798Sache{
3707798Sache	char msgbuf[MSGBUFSIZ];
371193087Sjilles	char fmtbuf[MSGBUFSIZ];
37253819Smharo	char *txt = NULL;
37320421Ssteve	int pri = LOG_INFO;
37420421Ssteve	int do_gettext = log_on_stderr; /*
37520421Ssteve					 * Localize user messages - not
3767798Sache					 * syslog()ed messages.
3777798Sache					 */
3787798Sache
379122409Sguido	if (level > log_level)
380122409Sguido		return;
3817798Sache
3827798Sache	switch (level) {
3831556Srgrimes	case SYSLOG_LEVEL_FATAL:
3841556Srgrimes		if (!log_on_stderr)
3851556Srgrimes			txt = "fatal";
3861556Srgrimes		pri = LOG_CRIT;
3871556Srgrimes		break;
38853819Smharo	case SYSLOG_LEVEL_ERROR:
38950539Smharo		if (!log_on_stderr)
390191670Simp			txt = "error";
391191670Simp		pri = LOG_ERR;
392191670Simp		break;
393191670Simp	case SYSLOG_LEVEL_NOTICE:
3941556Srgrimes		pri = LOG_NOTICE;
3951556Srgrimes		break;
3961556Srgrimes	case SYSLOG_LEVEL_INFO:
3971556Srgrimes		pri = LOG_INFO;
3981556Srgrimes		break;
3991556Srgrimes	case SYSLOG_LEVEL_VERBOSE:
4001556Srgrimes		pri = LOG_INFO;
4011556Srgrimes		break;
4021556Srgrimes	case SYSLOG_LEVEL_DEBUG1:
4031556Srgrimes		txt = "debug1";
404102230Strhodes		pri = LOG_DEBUG;
405102230Strhodes		/*
4061556Srgrimes		 * Don't localize debug messages - such are not intended
4071556Srgrimes		 * for users but for support staff whose preferred
408122409Sguido		 * language is unknown, therefore we default to the
40990110Simp		 * language used in the source code: English.
4101556Srgrimes		 */
4111556Srgrimes		do_gettext = 0;
41247584Skris		break;
4131556Srgrimes	case SYSLOG_LEVEL_DEBUG2:
41447584Skris		txt = "debug2";
41547584Skris		pri = LOG_DEBUG;
4161556Srgrimes		do_gettext = 0;	    /* Don't localize debug messages. */
4171556Srgrimes		break;
4181556Srgrimes	case SYSLOG_LEVEL_DEBUG3:
4191556Srgrimes		txt = "debug3";
4201556Srgrimes		pri = LOG_DEBUG;
4211556Srgrimes		do_gettext = 0;	    /* Don't localize debug messages. */
4221556Srgrimes		break;
4231556Srgrimes	default:
424122409Sguido		txt = "internal error";
425163812Sdelphij		pri = LOG_ERR;
426163777Sdelphij		break;
427163777Sdelphij	}
428163812Sdelphij	if (txt != NULL) {
429163777Sdelphij		snprintf(fmtbuf, sizeof(fmtbuf), "%s%s: %s", log_txt_prefix,
4301556Srgrimes			 do_gettext ? gettext(txt) : txt,
4311556Srgrimes			 do_gettext ? gettext(fmt) : fmt);
43247584Skris		vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
43347584Skris	} else {
43447584Skris		vsnprintf(msgbuf, sizeof(msgbuf),
43547584Skris			  do_gettext ? gettext(fmt) : fmt,
436122304Sbde			  args);
4371556Srgrimes	}
4381556Srgrimes	if (log_on_stderr) {
43947584Skris		fprintf(stderr, "%s\r\n", msgbuf);
4401556Srgrimes	} else {
44147584Skris		openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
4421556Srgrimes		syslog(pri, "%.500s", msgbuf);
4431556Srgrimes		closelog();
4441556Srgrimes	}
4451556Srgrimes}
4461556Srgrimes