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