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 <sys/types.h> 38 39 #include <stdarg.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <syslog.h> 44 #include <unistd.h> 45 #include <errno.h> 46 #include <vis.h> 47 48 #include "xmalloc.h" 49 #include "log.h" 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 }, 75 { NULL, SYSLOG_FACILITY_NOT_SET } 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 }, 92 { NULL, SYSLOG_LEVEL_NOT_SET } 93 }; 94 95 SyslogFacility 96 log_facility_number(char *name) 97 { 98 int i; 99 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; 104 return SYSLOG_FACILITY_NOT_SET; 105 } 106 107 const char * 108 log_facility_name(SyslogFacility facility) 109 { 110 u_int i; 111 112 for (i = 0; log_facilities[i].name; i++) 113 if (log_facilities[i].val == facility) 114 return log_facilities[i].name; 115 return NULL; 116 } 117 118 LogLevel 119 log_level_number(char *name) 120 { 121 int i; 122 123 if (name != NULL) 124 for (i = 0; log_levels[i].name; i++) 125 if (strcasecmp(log_levels[i].name, name) == 0) 126 return log_levels[i].val; 127 return SYSLOG_LEVEL_NOT_SET; 128 } 129 130 const char * 131 log_level_name(LogLevel level) 132 { 133 u_int i; 134 135 for (i = 0; log_levels[i].name != NULL; i++) 136 if (log_levels[i].val == level) 137 return log_levels[i].name; 138 return NULL; 139 } 140 141 /* Error messages that should be logged. */ 142 143 void 144 error(const char *fmt,...) 145 { 146 va_list args; 147 148 va_start(args, fmt); 149 do_log(SYSLOG_LEVEL_ERROR, fmt, args); 150 va_end(args); 151 } 152 153 void 154 sigdie(const char *fmt,...) 155 { 156 va_list args; 157 158 va_start(args, fmt); 159 do_log(SYSLOG_LEVEL_FATAL, fmt, args); 160 va_end(args); 161 _exit(1); 162 } 163 164 165 /* Log this message (information that usually should go to the log). */ 166 167 void 168 logit(const char *fmt,...) 169 { 170 va_list args; 171 172 va_start(args, fmt); 173 do_log(SYSLOG_LEVEL_INFO, fmt, args); 174 va_end(args); 175 } 176 177 /* More detailed messages (information that does not need to go to the log). */ 178 179 void 180 verbose(const char *fmt,...) 181 { 182 va_list args; 183 184 va_start(args, fmt); 185 do_log(SYSLOG_LEVEL_VERBOSE, fmt, args); 186 va_end(args); 187 } 188 189 /* Debugging messages that should not be logged during normal operation. */ 190 191 void 192 debug(const char *fmt,...) 193 { 194 va_list args; 195 196 va_start(args, fmt); 197 do_log(SYSLOG_LEVEL_DEBUG1, fmt, args); 198 va_end(args); 199 } 200 201 void 202 debug2(const char *fmt,...) 203 { 204 va_list args; 205 206 va_start(args, fmt); 207 do_log(SYSLOG_LEVEL_DEBUG2, fmt, args); 208 va_end(args); 209 } 210 211 void 212 debug3(const char *fmt,...) 213 { 214 va_list args; 215 216 va_start(args, fmt); 217 do_log(SYSLOG_LEVEL_DEBUG3, fmt, args); 218 va_end(args); 219 } 220 221 /* 222 * Initialize the log. 223 */ 224 225 void 226 log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) 227 { 228 argv0 = av0; 229 230 switch (level) { 231 case SYSLOG_LEVEL_QUIET: 232 case SYSLOG_LEVEL_FATAL: 233 case SYSLOG_LEVEL_ERROR: 234 case SYSLOG_LEVEL_INFO: 235 case SYSLOG_LEVEL_VERBOSE: 236 case SYSLOG_LEVEL_DEBUG1: 237 case SYSLOG_LEVEL_DEBUG2: 238 case SYSLOG_LEVEL_DEBUG3: 239 log_level = level; 240 break; 241 default: 242 fprintf(stderr, "Unrecognized internal syslog level code %d\n", 243 (int) level); 244 exit(1); 245 } 246 247 log_on_stderr = on_stderr; 248 if (on_stderr) 249 return; 250 251 switch (facility) { 252 case SYSLOG_FACILITY_DAEMON: 253 log_facility = LOG_DAEMON; 254 break; 255 case SYSLOG_FACILITY_USER: 256 log_facility = LOG_USER; 257 break; 258 case SYSLOG_FACILITY_AUTH: 259 log_facility = LOG_AUTH; 260 break; 261 case SYSLOG_FACILITY_LOCAL0: 262 log_facility = LOG_LOCAL0; 263 break; 264 case SYSLOG_FACILITY_LOCAL1: 265 log_facility = LOG_LOCAL1; 266 break; 267 case SYSLOG_FACILITY_LOCAL2: 268 log_facility = LOG_LOCAL2; 269 break; 270 case SYSLOG_FACILITY_LOCAL3: 271 log_facility = LOG_LOCAL3; 272 break; 273 case SYSLOG_FACILITY_LOCAL4: 274 log_facility = LOG_LOCAL4; 275 break; 276 case SYSLOG_FACILITY_LOCAL5: 277 log_facility = LOG_LOCAL5; 278 break; 279 case SYSLOG_FACILITY_LOCAL6: 280 log_facility = LOG_LOCAL6; 281 break; 282 case SYSLOG_FACILITY_LOCAL7: 283 log_facility = LOG_LOCAL7; 284 break; 285 default: 286 fprintf(stderr, 287 "Unrecognized internal syslog facility code %d\n", 288 (int) facility); 289 exit(1); 290 } 291 } 292 293 #define MSGBUFSIZ 1024 294 295 void 296 do_log(LogLevel level, const char *fmt, va_list args) 297 { 298 struct syslog_data sdata = SYSLOG_DATA_INIT; 299 char msgbuf[MSGBUFSIZ]; 300 char fmtbuf[MSGBUFSIZ]; 301 char *txt = NULL; 302 int pri = LOG_INFO; 303 int saved_errno = errno; 304 305 if (level > log_level) 306 return; 307 308 switch (level) { 309 case SYSLOG_LEVEL_FATAL: 310 if (!log_on_stderr) 311 txt = "fatal"; 312 pri = LOG_CRIT; 313 break; 314 case SYSLOG_LEVEL_ERROR: 315 if (!log_on_stderr) 316 txt = "error"; 317 pri = LOG_ERR; 318 break; 319 case SYSLOG_LEVEL_INFO: 320 pri = LOG_INFO; 321 break; 322 case SYSLOG_LEVEL_VERBOSE: 323 pri = LOG_INFO; 324 break; 325 case SYSLOG_LEVEL_DEBUG1: 326 txt = "debug1"; 327 pri = LOG_DEBUG; 328 break; 329 case SYSLOG_LEVEL_DEBUG2: 330 txt = "debug2"; 331 pri = LOG_DEBUG; 332 break; 333 case SYSLOG_LEVEL_DEBUG3: 334 txt = "debug3"; 335 pri = LOG_DEBUG; 336 break; 337 default: 338 txt = "internal error"; 339 pri = LOG_ERR; 340 break; 341 } 342 if (txt != NULL) { 343 snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt); 344 vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args); 345 } else { 346 vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); 347 } 348 strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), VIS_SAFE|VIS_OCTAL); 349 if (log_on_stderr) { 350 snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf); 351 write(STDERR_FILENO, msgbuf, strlen(msgbuf)); 352 } else { 353 openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); 354 syslog_r(pri, &sdata, "%.500s", fmtbuf); 355 closelog_r(&sdata); 356 } 357 errno = saved_errno; 358 } 359