]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - crypto/openssh/log.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / crypto / openssh / log.c
1 /* $OpenBSD: log.c,v 1.45 2013/05/16 09:08:41 dtucker 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 <fcntl.h>
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <syslog.h>
47 #include <unistd.h>
48 #include <errno.h>
49 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
50 # include <vis.h>
51 #endif
52
53 #include "xmalloc.h"
54 #include "log.h"
55
56 static LogLevel log_level = SYSLOG_LEVEL_INFO;
57 static int log_on_stderr = 1;
58 static int log_stderr_fd = STDERR_FILENO;
59 static int log_facility = LOG_AUTH;
60 static char *argv0;
61 static log_handler_fn *log_handler;
62 static void *log_handler_ctx;
63
64 extern char *__progname;
65
66 #define LOG_SYSLOG_VIS  (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL)
67 #define LOG_STDERR_VIS  (VIS_SAFE|VIS_OCTAL)
68
69 /* textual representation of log-facilities/levels */
70
71 static struct {
72         const char *name;
73         SyslogFacility val;
74 } log_facilities[] = {
75         { "DAEMON",     SYSLOG_FACILITY_DAEMON },
76         { "USER",       SYSLOG_FACILITY_USER },
77         { "AUTH",       SYSLOG_FACILITY_AUTH },
78 #ifdef LOG_AUTHPRIV
79         { "AUTHPRIV",   SYSLOG_FACILITY_AUTHPRIV },
80 #endif
81         { "LOCAL0",     SYSLOG_FACILITY_LOCAL0 },
82         { "LOCAL1",     SYSLOG_FACILITY_LOCAL1 },
83         { "LOCAL2",     SYSLOG_FACILITY_LOCAL2 },
84         { "LOCAL3",     SYSLOG_FACILITY_LOCAL3 },
85         { "LOCAL4",     SYSLOG_FACILITY_LOCAL4 },
86         { "LOCAL5",     SYSLOG_FACILITY_LOCAL5 },
87         { "LOCAL6",     SYSLOG_FACILITY_LOCAL6 },
88         { "LOCAL7",     SYSLOG_FACILITY_LOCAL7 },
89         { NULL,         SYSLOG_FACILITY_NOT_SET }
90 };
91
92 static struct {
93         const char *name;
94         LogLevel val;
95 } log_levels[] =
96 {
97         { "QUIET",      SYSLOG_LEVEL_QUIET },
98         { "FATAL",      SYSLOG_LEVEL_FATAL },
99         { "ERROR",      SYSLOG_LEVEL_ERROR },
100         { "INFO",       SYSLOG_LEVEL_INFO },
101         { "VERBOSE",    SYSLOG_LEVEL_VERBOSE },
102         { "DEBUG",      SYSLOG_LEVEL_DEBUG1 },
103         { "DEBUG1",     SYSLOG_LEVEL_DEBUG1 },
104         { "DEBUG2",     SYSLOG_LEVEL_DEBUG2 },
105         { "DEBUG3",     SYSLOG_LEVEL_DEBUG3 },
106         { NULL,         SYSLOG_LEVEL_NOT_SET }
107 };
108
109 SyslogFacility
110 log_facility_number(char *name)
111 {
112         int i;
113
114         if (name != NULL)
115                 for (i = 0; log_facilities[i].name; i++)
116                         if (strcasecmp(log_facilities[i].name, name) == 0)
117                                 return log_facilities[i].val;
118         return SYSLOG_FACILITY_NOT_SET;
119 }
120
121 const char *
122 log_facility_name(SyslogFacility facility)
123 {
124         u_int i;
125
126         for (i = 0;  log_facilities[i].name; i++)
127                 if (log_facilities[i].val == facility)
128                         return log_facilities[i].name;
129         return NULL;
130 }
131
132 LogLevel
133 log_level_number(char *name)
134 {
135         int i;
136
137         if (name != NULL)
138                 for (i = 0; log_levels[i].name; i++)
139                         if (strcasecmp(log_levels[i].name, name) == 0)
140                                 return log_levels[i].val;
141         return SYSLOG_LEVEL_NOT_SET;
142 }
143
144 const char *
145 log_level_name(LogLevel level)
146 {
147         u_int i;
148
149         for (i = 0; log_levels[i].name != NULL; i++)
150                 if (log_levels[i].val == level)
151                         return log_levels[i].name;
152         return NULL;
153 }
154
155 /* Error messages that should be logged. */
156
157 void
158 error(const char *fmt,...)
159 {
160         va_list args;
161
162         va_start(args, fmt);
163         do_log(SYSLOG_LEVEL_ERROR, fmt, args);
164         va_end(args);
165 }
166
167 void
168 sigdie(const char *fmt,...)
169 {
170 #ifdef DO_LOG_SAFE_IN_SIGHAND
171         va_list args;
172
173         va_start(args, fmt);
174         do_log(SYSLOG_LEVEL_FATAL, fmt, args);
175         va_end(args);
176 #endif
177         _exit(1);
178 }
179
180
181 /* Log this message (information that usually should go to the log). */
182
183 void
184 logit(const char *fmt,...)
185 {
186         va_list args;
187
188         va_start(args, fmt);
189         do_log(SYSLOG_LEVEL_INFO, fmt, args);
190         va_end(args);
191 }
192
193 /* More detailed messages (information that does not need to go to the log). */
194
195 void
196 verbose(const char *fmt,...)
197 {
198         va_list args;
199
200         va_start(args, fmt);
201         do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
202         va_end(args);
203 }
204
205 /* Debugging messages that should not be logged during normal operation. */
206
207 void
208 debug(const char *fmt,...)
209 {
210         va_list args;
211
212         va_start(args, fmt);
213         do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
214         va_end(args);
215 }
216
217 void
218 debug2(const char *fmt,...)
219 {
220         va_list args;
221
222         va_start(args, fmt);
223         do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
224         va_end(args);
225 }
226
227 void
228 debug3(const char *fmt,...)
229 {
230         va_list args;
231
232         va_start(args, fmt);
233         do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
234         va_end(args);
235 }
236
237 /*
238  * Initialize the log.
239  */
240
241 void
242 log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
243 {
244 #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
245         struct syslog_data sdata = SYSLOG_DATA_INIT;
246 #endif
247
248         argv0 = av0;
249
250         switch (level) {
251         case SYSLOG_LEVEL_QUIET:
252         case SYSLOG_LEVEL_FATAL:
253         case SYSLOG_LEVEL_ERROR:
254         case SYSLOG_LEVEL_INFO:
255         case SYSLOG_LEVEL_VERBOSE:
256         case SYSLOG_LEVEL_DEBUG1:
257         case SYSLOG_LEVEL_DEBUG2:
258         case SYSLOG_LEVEL_DEBUG3:
259                 log_level = level;
260                 break;
261         default:
262                 fprintf(stderr, "Unrecognized internal syslog level code %d\n",
263                     (int) level);
264                 exit(1);
265         }
266
267         log_handler = NULL;
268         log_handler_ctx = NULL;
269
270         log_on_stderr = on_stderr;
271         if (on_stderr)
272                 return;
273
274         switch (facility) {
275         case SYSLOG_FACILITY_DAEMON:
276                 log_facility = LOG_DAEMON;
277                 break;
278         case SYSLOG_FACILITY_USER:
279                 log_facility = LOG_USER;
280                 break;
281         case SYSLOG_FACILITY_AUTH:
282                 log_facility = LOG_AUTH;
283                 break;
284 #ifdef LOG_AUTHPRIV
285         case SYSLOG_FACILITY_AUTHPRIV:
286                 log_facility = LOG_AUTHPRIV;
287                 break;
288 #endif
289         case SYSLOG_FACILITY_LOCAL0:
290                 log_facility = LOG_LOCAL0;
291                 break;
292         case SYSLOG_FACILITY_LOCAL1:
293                 log_facility = LOG_LOCAL1;
294                 break;
295         case SYSLOG_FACILITY_LOCAL2:
296                 log_facility = LOG_LOCAL2;
297                 break;
298         case SYSLOG_FACILITY_LOCAL3:
299                 log_facility = LOG_LOCAL3;
300                 break;
301         case SYSLOG_FACILITY_LOCAL4:
302                 log_facility = LOG_LOCAL4;
303                 break;
304         case SYSLOG_FACILITY_LOCAL5:
305                 log_facility = LOG_LOCAL5;
306                 break;
307         case SYSLOG_FACILITY_LOCAL6:
308                 log_facility = LOG_LOCAL6;
309                 break;
310         case SYSLOG_FACILITY_LOCAL7:
311                 log_facility = LOG_LOCAL7;
312                 break;
313         default:
314                 fprintf(stderr,
315                     "Unrecognized internal syslog facility code %d\n",
316                     (int) facility);
317                 exit(1);
318         }
319
320         /*
321          * If an external library (eg libwrap) attempts to use syslog
322          * immediately after reexec, syslog may be pointing to the wrong
323          * facility, so we force an open/close of syslog here.
324          */
325 #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
326         openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
327         closelog_r(&sdata);
328 #else
329         openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
330         closelog();
331 #endif
332 }
333
334 void
335 log_change_level(LogLevel new_log_level)
336 {
337         /* no-op if log_init has not been called */
338         if (argv0 == NULL)
339                 return;
340         log_init(argv0, new_log_level, log_facility, log_on_stderr);
341 }
342
343 int
344 log_is_on_stderr(void)
345 {
346         return log_on_stderr;
347 }
348
349 /* redirect what would usually get written to stderr to specified file */
350 void
351 log_redirect_stderr_to(const char *logfile)
352 {
353         int fd;
354
355         if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
356                 fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile,
357                      strerror(errno));
358                 exit(1);
359         }
360         log_stderr_fd = fd;
361 }
362
363 #define MSGBUFSIZ 1024
364
365 void
366 set_log_handler(log_handler_fn *handler, void *ctx)
367 {
368         log_handler = handler;
369         log_handler_ctx = ctx;
370 }
371
372 void
373 do_log2(LogLevel level, const char *fmt,...)
374 {
375         va_list args;
376
377         va_start(args, fmt);
378         do_log(level, fmt, args);
379         va_end(args);
380 }
381
382 void
383 do_log(LogLevel level, const char *fmt, va_list args)
384 {
385 #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
386         struct syslog_data sdata = SYSLOG_DATA_INIT;
387 #endif
388         char msgbuf[MSGBUFSIZ];
389         char fmtbuf[MSGBUFSIZ];
390         char *txt = NULL;
391         int pri = LOG_INFO;
392         int saved_errno = errno;
393         log_handler_fn *tmp_handler;
394
395         if (level > log_level)
396                 return;
397
398         switch (level) {
399         case SYSLOG_LEVEL_FATAL:
400                 if (!log_on_stderr)
401                         txt = "fatal";
402                 pri = LOG_CRIT;
403                 break;
404         case SYSLOG_LEVEL_ERROR:
405                 if (!log_on_stderr)
406                         txt = "error";
407                 pri = LOG_ERR;
408                 break;
409         case SYSLOG_LEVEL_INFO:
410                 pri = LOG_INFO;
411                 break;
412         case SYSLOG_LEVEL_VERBOSE:
413                 pri = LOG_INFO;
414                 break;
415         case SYSLOG_LEVEL_DEBUG1:
416                 txt = "debug1";
417                 pri = LOG_DEBUG;
418                 break;
419         case SYSLOG_LEVEL_DEBUG2:
420                 txt = "debug2";
421                 pri = LOG_DEBUG;
422                 break;
423         case SYSLOG_LEVEL_DEBUG3:
424                 txt = "debug3";
425                 pri = LOG_DEBUG;
426                 break;
427         default:
428                 txt = "internal error";
429                 pri = LOG_ERR;
430                 break;
431         }
432         if (txt != NULL && log_handler == NULL) {
433                 snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt);
434                 vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
435         } else {
436                 vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
437         }
438         strnvis(fmtbuf, msgbuf, sizeof(fmtbuf),
439             log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS);
440         if (log_handler != NULL) {
441                 /* Avoid recursion */
442                 tmp_handler = log_handler;
443                 log_handler = NULL;
444                 tmp_handler(level, fmtbuf, log_handler_ctx);
445                 log_handler = tmp_handler;
446         } else if (log_on_stderr) {
447                 snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf);
448                 (void)write(log_stderr_fd, msgbuf, strlen(msgbuf));
449         } else {
450 #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
451                 openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
452                 syslog_r(pri, &sdata, "%.500s", fmtbuf);
453                 closelog_r(&sdata);
454 #else
455                 openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
456                 syslog(pri, "%.500s", fmtbuf);
457                 closelog();
458 #endif
459         }
460         errno = saved_errno;
461 }