Annotation of src/usr.bin/ssh/log.c, Revision 1.40
1.40 ! djm 1: /* $OpenBSD: log.c,v 1.39 2006/08/18 09:13:25 deraadt Exp $ */
1.1 markus 2: /*
1.9 markus 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: /*
1.8 deraadt 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.
1.6 markus 35: */
1.1 markus 36:
1.38 deraadt 37: #include <sys/types.h>
1.1 markus 38:
1.33 stevesk 39: #include <stdarg.h>
1.37 stevesk 40: #include <stdio.h>
1.36 stevesk 41: #include <stdlib.h>
1.35 stevesk 42: #include <string.h>
1.32 stevesk 43: #include <syslog.h>
1.34 stevesk 44: #include <unistd.h>
1.40 ! djm 45: #include <errno.h>
1.32 stevesk 46: #include <vis.h>
47:
1.38 deraadt 48: #include "xmalloc.h"
1.15 markus 49: #include "log.h"
1.16 markus 50:
51: static LogLevel log_level = SYSLOG_LEVEL_INFO;
52: static int log_on_stderr = 1;
53: static int log_facility = LOG_AUTH;
54: static char *argv0;
55:
56: extern char *__progname;
57:
58: /* textual representation of log-facilities/levels */
59:
60: static struct {
61: const char *name;
62: SyslogFacility val;
63: } log_facilities[] = {
64: { "DAEMON", SYSLOG_FACILITY_DAEMON },
65: { "USER", SYSLOG_FACILITY_USER },
66: { "AUTH", SYSLOG_FACILITY_AUTH },
67: { "LOCAL0", SYSLOG_FACILITY_LOCAL0 },
68: { "LOCAL1", SYSLOG_FACILITY_LOCAL1 },
69: { "LOCAL2", SYSLOG_FACILITY_LOCAL2 },
70: { "LOCAL3", SYSLOG_FACILITY_LOCAL3 },
71: { "LOCAL4", SYSLOG_FACILITY_LOCAL4 },
72: { "LOCAL5", SYSLOG_FACILITY_LOCAL5 },
73: { "LOCAL6", SYSLOG_FACILITY_LOCAL6 },
74: { "LOCAL7", SYSLOG_FACILITY_LOCAL7 },
1.21 markus 75: { NULL, SYSLOG_FACILITY_NOT_SET }
1.16 markus 76: };
77:
78: static struct {
79: const char *name;
80: LogLevel val;
81: } log_levels[] =
82: {
83: { "QUIET", SYSLOG_LEVEL_QUIET },
84: { "FATAL", SYSLOG_LEVEL_FATAL },
85: { "ERROR", SYSLOG_LEVEL_ERROR },
86: { "INFO", SYSLOG_LEVEL_INFO },
87: { "VERBOSE", SYSLOG_LEVEL_VERBOSE },
88: { "DEBUG", SYSLOG_LEVEL_DEBUG1 },
89: { "DEBUG1", SYSLOG_LEVEL_DEBUG1 },
90: { "DEBUG2", SYSLOG_LEVEL_DEBUG2 },
91: { "DEBUG3", SYSLOG_LEVEL_DEBUG3 },
1.21 markus 92: { NULL, SYSLOG_LEVEL_NOT_SET }
1.16 markus 93: };
94:
95: SyslogFacility
96: log_facility_number(char *name)
97: {
98: int i;
1.23 deraadt 99:
1.16 markus 100: if (name != NULL)
101: for (i = 0; log_facilities[i].name; i++)
102: if (strcasecmp(log_facilities[i].name, name) == 0)
103: return log_facilities[i].val;
1.21 markus 104: return SYSLOG_FACILITY_NOT_SET;
1.16 markus 105: }
106:
107: LogLevel
108: log_level_number(char *name)
109: {
110: int i;
1.23 deraadt 111:
1.16 markus 112: if (name != NULL)
113: for (i = 0; log_levels[i].name; i++)
114: if (strcasecmp(log_levels[i].name, name) == 0)
115: return log_levels[i].val;
1.21 markus 116: return SYSLOG_LEVEL_NOT_SET;
1.16 markus 117: }
1.1 markus 118:
119: /* Error messages that should be logged. */
120:
121: void
1.4 markus 122: error(const char *fmt,...)
1.1 markus 123: {
1.4 markus 124: va_list args;
1.23 deraadt 125:
1.4 markus 126: va_start(args, fmt);
127: do_log(SYSLOG_LEVEL_ERROR, fmt, args);
128: va_end(args);
1.1 markus 129: }
1.39 deraadt 130:
131: void
132: sigdie(const char *fmt,...)
133: {
134: va_list args;
135:
136: va_start(args, fmt);
137: do_log(SYSLOG_LEVEL_FATAL, fmt, args);
138: va_end(args);
139: _exit(1);
140: }
141:
1.1 markus 142:
143: /* Log this message (information that usually should go to the log). */
144:
145: void
1.26 itojun 146: logit(const char *fmt,...)
1.1 markus 147: {
1.4 markus 148: va_list args;
1.23 deraadt 149:
1.4 markus 150: va_start(args, fmt);
1.14 markus 151: do_log(SYSLOG_LEVEL_INFO, fmt, args);
1.4 markus 152: va_end(args);
1.1 markus 153: }
154:
155: /* More detailed messages (information that does not need to go to the log). */
156:
157: void
1.4 markus 158: verbose(const char *fmt,...)
1.1 markus 159: {
1.4 markus 160: va_list args;
1.23 deraadt 161:
1.4 markus 162: va_start(args, fmt);
163: do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
164: va_end(args);
1.1 markus 165: }
166:
167: /* Debugging messages that should not be logged during normal operation. */
168:
169: void
1.4 markus 170: debug(const char *fmt,...)
1.1 markus 171: {
1.4 markus 172: va_list args;
1.23 deraadt 173:
1.4 markus 174: va_start(args, fmt);
1.10 markus 175: do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
176: va_end(args);
177: }
178:
179: void
180: debug2(const char *fmt,...)
181: {
182: va_list args;
1.23 deraadt 183:
1.10 markus 184: va_start(args, fmt);
185: do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
186: va_end(args);
187: }
188:
189: void
190: debug3(const char *fmt,...)
191: {
192: va_list args;
1.23 deraadt 193:
1.10 markus 194: va_start(args, fmt);
195: do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
1.4 markus 196: va_end(args);
1.1 markus 197: }
1.2 markus 198:
1.16 markus 199: /*
200: * Initialize the log.
201: */
1.2 markus 202:
1.16 markus 203: void
204: log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
1.2 markus 205: {
1.16 markus 206: argv0 = av0;
207:
208: switch (level) {
209: case SYSLOG_LEVEL_QUIET:
210: case SYSLOG_LEVEL_FATAL:
211: case SYSLOG_LEVEL_ERROR:
212: case SYSLOG_LEVEL_INFO:
213: case SYSLOG_LEVEL_VERBOSE:
214: case SYSLOG_LEVEL_DEBUG1:
215: case SYSLOG_LEVEL_DEBUG2:
216: case SYSLOG_LEVEL_DEBUG3:
217: log_level = level;
218: break;
219: default:
220: fprintf(stderr, "Unrecognized internal syslog level code %d\n",
221: (int) level);
222: exit(1);
223: }
1.2 markus 224:
1.16 markus 225: log_on_stderr = on_stderr;
226: if (on_stderr)
227: return;
228:
229: switch (facility) {
230: case SYSLOG_FACILITY_DAEMON:
231: log_facility = LOG_DAEMON;
232: break;
233: case SYSLOG_FACILITY_USER:
234: log_facility = LOG_USER;
235: break;
236: case SYSLOG_FACILITY_AUTH:
237: log_facility = LOG_AUTH;
238: break;
239: case SYSLOG_FACILITY_LOCAL0:
240: log_facility = LOG_LOCAL0;
241: break;
242: case SYSLOG_FACILITY_LOCAL1:
243: log_facility = LOG_LOCAL1;
244: break;
245: case SYSLOG_FACILITY_LOCAL2:
246: log_facility = LOG_LOCAL2;
247: break;
248: case SYSLOG_FACILITY_LOCAL3:
249: log_facility = LOG_LOCAL3;
250: break;
251: case SYSLOG_FACILITY_LOCAL4:
252: log_facility = LOG_LOCAL4;
253: break;
254: case SYSLOG_FACILITY_LOCAL5:
255: log_facility = LOG_LOCAL5;
256: break;
257: case SYSLOG_FACILITY_LOCAL6:
258: log_facility = LOG_LOCAL6;
259: break;
260: case SYSLOG_FACILITY_LOCAL7:
261: log_facility = LOG_LOCAL7;
262: break;
263: default:
264: fprintf(stderr,
265: "Unrecognized internal syslog facility code %d\n",
266: (int) facility);
267: exit(1);
268: }
1.2 markus 269: }
270:
1.16 markus 271: #define MSGBUFSIZ 1024
272:
1.22 markus 273: void
1.16 markus 274: do_log(LogLevel level, const char *fmt, va_list args)
1.2 markus 275: {
1.27 deraadt 276: struct syslog_data sdata = SYSLOG_DATA_INIT;
1.16 markus 277: char msgbuf[MSGBUFSIZ];
278: char fmtbuf[MSGBUFSIZ];
279: char *txt = NULL;
280: int pri = LOG_INFO;
1.40 ! djm 281: int saved_errno = errno;
1.16 markus 282:
283: if (level > log_level)
284: return;
285:
286: switch (level) {
287: case SYSLOG_LEVEL_FATAL:
288: if (!log_on_stderr)
289: txt = "fatal";
290: pri = LOG_CRIT;
291: break;
292: case SYSLOG_LEVEL_ERROR:
293: if (!log_on_stderr)
294: txt = "error";
295: pri = LOG_ERR;
296: break;
297: case SYSLOG_LEVEL_INFO:
298: pri = LOG_INFO;
299: break;
300: case SYSLOG_LEVEL_VERBOSE:
301: pri = LOG_INFO;
302: break;
303: case SYSLOG_LEVEL_DEBUG1:
304: txt = "debug1";
305: pri = LOG_DEBUG;
306: break;
307: case SYSLOG_LEVEL_DEBUG2:
308: txt = "debug2";
309: pri = LOG_DEBUG;
310: break;
311: case SYSLOG_LEVEL_DEBUG3:
312: txt = "debug3";
313: pri = LOG_DEBUG;
314: break;
315: default:
316: txt = "internal error";
317: pri = LOG_ERR;
318: break;
319: }
320: if (txt != NULL) {
321: snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt);
322: vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
323: } else {
324: vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
325: }
1.28 djm 326: strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), VIS_SAFE|VIS_OCTAL);
1.16 markus 327: if (log_on_stderr) {
1.28 djm 328: snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf);
329: write(STDERR_FILENO, msgbuf, strlen(msgbuf));
1.16 markus 330: } else {
1.27 deraadt 331: openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
1.28 djm 332: syslog_r(pri, &sdata, "%.500s", fmtbuf);
1.27 deraadt 333: closelog_r(&sdata);
1.16 markus 334: }
1.40 ! djm 335: errno = saved_errno;
1.1 markus 336: }