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