1 /* $OpenBSD: log.c,v 1.4 2013/11/02 13:31:51 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/queue.h> 21 #include <sys/socket.h> 22 #include <sys/time.h> 23 24 #include <errno.h> 25 #include <netdb.h> 26 #include <stdarg.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <syslog.h> 31 #include <time.h> 32 #include <unistd.h> 33 #include <vis.h> 34 35 #include "ldapd.h" 36 37 int debug; 38 int verbose; 39 40 void 41 log_init(int n_debug) 42 { 43 extern char *__progname; 44 45 debug = n_debug; 46 47 if (!debug) 48 openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); 49 50 tzset(); 51 } 52 53 void 54 log_verbose(int v) 55 { 56 verbose = v; 57 } 58 59 void 60 logit(int pri, const char *fmt, ...) 61 { 62 va_list ap; 63 64 va_start(ap, fmt); 65 vlog(pri, fmt, ap); 66 va_end(ap); 67 } 68 69 void 70 vlog(int pri, const char *fmt, va_list ap) 71 { 72 char datebuf[24]; 73 struct timeval tv; 74 struct tm *tm; 75 char *nfmt; 76 size_t rc; 77 time_t now; 78 79 if (debug) { 80 gettimeofday(&tv, NULL); 81 now = tv.tv_sec; 82 tm = localtime(&now); 83 rc = strftime(datebuf, sizeof(datebuf), "%b %e %H:%M:%S", tm); 84 if (rc == 0) 85 datebuf[0] = 0; 86 fprintf(stderr, "%s.%03ld [%d] ", datebuf, 87 tv.tv_usec / 1000, getpid()); 88 89 /* best effort in out of mem situations */ 90 if (asprintf(&nfmt, "%s\n", fmt) == -1) { 91 vfprintf(stderr, fmt, ap); 92 fprintf(stderr, "\n"); 93 } else { 94 vfprintf(stderr, nfmt, ap); 95 free(nfmt); 96 } 97 fflush(stderr); 98 } else 99 vsyslog(pri, fmt, ap); 100 } 101 102 void 103 log_warn(const char *emsg, ...) 104 { 105 char *nfmt; 106 va_list ap; 107 108 /* best effort to even work in out of memory situations */ 109 if (emsg == NULL) 110 logit(LOG_CRIT, "%s", strerror(errno)); 111 else { 112 va_start(ap, emsg); 113 114 if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) { 115 /* we tried it... */ 116 vlog(LOG_CRIT, emsg, ap); 117 logit(LOG_CRIT, "%s", strerror(errno)); 118 } else { 119 vlog(LOG_CRIT, nfmt, ap); 120 free(nfmt); 121 } 122 va_end(ap); 123 } 124 } 125 126 void 127 log_warnx(const char *emsg, ...) 128 { 129 va_list ap; 130 131 va_start(ap, emsg); 132 vlog(LOG_CRIT, emsg, ap); 133 va_end(ap); 134 } 135 136 void 137 log_info(const char *emsg, ...) 138 { 139 va_list ap; 140 141 va_start(ap, emsg); 142 vlog(LOG_INFO, emsg, ap); 143 va_end(ap); 144 } 145 146 void 147 log_debug(const char *emsg, ...) 148 { 149 va_list ap; 150 151 if (verbose) { 152 va_start(ap, emsg); 153 vlog(LOG_DEBUG, emsg, ap); 154 va_end(ap); 155 } 156 } 157 158 void 159 fatal(const char *emsg) 160 { 161 if (emsg == NULL) 162 logit(LOG_CRIT, "fatal: %s", strerror(errno)); 163 else 164 if (errno) 165 logit(LOG_CRIT, "fatal: %s: %s", 166 emsg, strerror(errno)); 167 else 168 logit(LOG_CRIT, "fatal: %s", emsg); 169 170 exit(1); 171 } 172 173 void 174 fatalx(const char *emsg) 175 { 176 errno = 0; 177 fatal(emsg); 178 } 179 180 const char * 181 print_host(struct sockaddr_storage *ss, char *buf, size_t len) 182 { 183 if (getnameinfo((struct sockaddr *)ss, ss->ss_len, 184 buf, len, NULL, 0, NI_NUMERICHOST) != 0) { 185 buf[0] = '\0'; 186 return (NULL); 187 } 188 return (buf); 189 } 190 191 void 192 hexdump(void *data, size_t len, const char *fmt, ...) 193 { 194 uint8_t *p = data; 195 va_list ap; 196 197 if (verbose < 2 || !debug) 198 return; 199 200 va_start(ap, fmt); 201 vlog(LOG_DEBUG, fmt, ap); 202 va_end(ap); 203 204 while (len--) { 205 size_t ofs = p - (uint8_t *)data; 206 if (ofs % 16 == 0) 207 fprintf(stderr, "%s%04lx:", ofs == 0 ? "" : "\n", ofs); 208 else if (ofs % 8 == 0) 209 fprintf(stderr, " "); 210 fprintf(stderr, " %02x", *p++); 211 } 212 fprintf(stderr, "\n"); 213 } 214 215 /* 216 * Display a list of ber elements. 217 * 218 */ 219 void 220 ldap_debug_elements(struct ber_element *root, int context, const char *fmt, ...) 221 { 222 va_list ap; 223 static int indent = 0; 224 long long v; 225 int d; 226 char *buf, *visbuf; 227 size_t len; 228 u_int i; 229 int constructed; 230 struct ber_oid o; 231 232 if (verbose < 2 || !debug) 233 return; 234 235 if (fmt != NULL) { 236 va_start(ap, fmt); 237 vlog(LOG_DEBUG, fmt, ap); 238 va_end(ap); 239 } 240 241 /* calculate lengths */ 242 ber_calc_len(root); 243 244 switch (root->be_encoding) { 245 case BER_TYPE_SEQUENCE: 246 case BER_TYPE_SET: 247 constructed = root->be_encoding; 248 break; 249 default: 250 constructed = 0; 251 break; 252 } 253 254 fprintf(stderr, "%*slen %lu ", indent, "", root->be_len); 255 switch (root->be_class) { 256 case BER_CLASS_UNIVERSAL: 257 fprintf(stderr, "class: universal(%u) type: ", root->be_class); 258 switch (root->be_type) { 259 case BER_TYPE_EOC: 260 fprintf(stderr, "end-of-content"); 261 break; 262 case BER_TYPE_BOOLEAN: 263 fprintf(stderr, "boolean"); 264 break; 265 case BER_TYPE_INTEGER: 266 fprintf(stderr, "integer"); 267 break; 268 case BER_TYPE_BITSTRING: 269 fprintf(stderr, "bit-string"); 270 break; 271 case BER_TYPE_OCTETSTRING: 272 fprintf(stderr, "octet-string"); 273 break; 274 case BER_TYPE_NULL: 275 fprintf(stderr, "null"); 276 break; 277 case BER_TYPE_OBJECT: 278 fprintf(stderr, "object"); 279 break; 280 case BER_TYPE_ENUMERATED: 281 fprintf(stderr, "enumerated"); 282 break; 283 case BER_TYPE_SEQUENCE: 284 fprintf(stderr, "sequence"); 285 break; 286 case BER_TYPE_SET: 287 fprintf(stderr, "set"); 288 break; 289 } 290 break; 291 case BER_CLASS_APPLICATION: 292 fprintf(stderr, "class: application(%u) type: ", 293 root->be_class); 294 switch (root->be_type) { 295 case LDAP_REQ_BIND: 296 case LDAP_RES_BIND: 297 fprintf(stderr, "bind"); 298 break; 299 case LDAP_REQ_UNBIND_30: 300 fprintf(stderr, "unbind"); 301 break; 302 case LDAP_REQ_SEARCH: 303 fprintf(stderr, "search"); 304 break; 305 case LDAP_RES_SEARCH_ENTRY: 306 fprintf(stderr, "search entry"); 307 break; 308 case LDAP_RES_SEARCH_RESULT: 309 fprintf(stderr, "search result"); 310 break; 311 case LDAP_REQ_MODIFY: 312 case LDAP_RES_MODIFY: 313 fprintf(stderr, "modify"); 314 break; 315 case LDAP_REQ_ADD: 316 case LDAP_RES_ADD: 317 fprintf(stderr, "add"); 318 break; 319 case LDAP_REQ_DELETE_30: 320 case LDAP_RES_DELETE: 321 fprintf(stderr, "delete"); 322 break; 323 case LDAP_REQ_MODRDN: 324 case LDAP_RES_MODRDN: 325 fprintf(stderr, "modrdn"); 326 break; 327 case LDAP_REQ_COMPARE: 328 case LDAP_RES_COMPARE: 329 fprintf(stderr, "compare"); 330 break; 331 case LDAP_REQ_ABANDON_30: 332 fprintf(stderr, "abandon"); 333 break; 334 case LDAP_REQ_EXTENDED: 335 case LDAP_RES_EXTENDED: 336 fprintf(stderr, "extended"); 337 break; 338 } 339 break; 340 case BER_CLASS_PRIVATE: 341 fprintf(stderr, "class: private(%u) type: ", root->be_class); 342 fprintf(stderr, "encoding (%lu) type: ", root->be_encoding); 343 break; 344 case BER_CLASS_CONTEXT: 345 fprintf(stderr, "class: context(%u) type: ", root->be_class); 346 switch (context) { 347 case LDAP_REQ_BIND: 348 switch(root->be_type) { 349 case LDAP_AUTH_SIMPLE: 350 fprintf(stderr, "auth simple"); 351 break; 352 } 353 break; 354 case LDAP_REQ_SEARCH: 355 switch(root->be_type) { 356 case LDAP_FILT_AND: 357 fprintf(stderr, "and"); 358 break; 359 case LDAP_FILT_OR: 360 fprintf(stderr, "or"); 361 break; 362 case LDAP_FILT_NOT: 363 fprintf(stderr, "not"); 364 break; 365 case LDAP_FILT_EQ: 366 fprintf(stderr, "equal"); 367 break; 368 case LDAP_FILT_SUBS: 369 fprintf(stderr, "substring"); 370 break; 371 case LDAP_FILT_GE: 372 fprintf(stderr, "greater-or-equal"); 373 break; 374 case LDAP_FILT_LE: 375 fprintf(stderr, "less-or-equal"); 376 break; 377 case LDAP_FILT_PRES: 378 fprintf(stderr, "presence"); 379 break; 380 case LDAP_FILT_APPR: 381 fprintf(stderr, "approximate"); 382 break; 383 } 384 break; 385 } 386 break; 387 default: 388 fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class); 389 break; 390 } 391 fprintf(stderr, "(%lu) encoding %lu ", 392 root->be_type, root->be_encoding); 393 394 if (constructed) 395 root->be_encoding = constructed; 396 397 switch (root->be_encoding) { 398 case BER_TYPE_BOOLEAN: 399 if (ber_get_boolean(root, &d) == -1) { 400 fprintf(stderr, "<INVALID>\n"); 401 break; 402 } 403 fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d); 404 break; 405 case BER_TYPE_INTEGER: 406 if (ber_get_integer(root, &v) == -1) { 407 fprintf(stderr, "<INVALID>\n"); 408 break; 409 } 410 fprintf(stderr, "value %lld\n", v); 411 break; 412 case BER_TYPE_ENUMERATED: 413 if (ber_get_enumerated(root, &v) == -1) { 414 fprintf(stderr, "<INVALID>\n"); 415 break; 416 } 417 fprintf(stderr, "value %lld\n", v); 418 break; 419 case BER_TYPE_BITSTRING: 420 if (ber_get_bitstring(root, (void *)&buf, &len) == -1) { 421 fprintf(stderr, "<INVALID>\n"); 422 break; 423 } 424 fprintf(stderr, "hexdump "); 425 for (i = 0; i < len; i++) 426 fprintf(stderr, "%02x", buf[i]); 427 fprintf(stderr, "\n"); 428 break; 429 case BER_TYPE_OBJECT: 430 if (ber_get_oid(root, &o) == -1) { 431 fprintf(stderr, "<INVALID>\n"); 432 break; 433 } 434 fprintf(stderr, "\n"); 435 break; 436 case BER_TYPE_OCTETSTRING: 437 if (ber_get_nstring(root, (void *)&buf, &len) == -1) { 438 fprintf(stderr, "<INVALID>\n"); 439 break; 440 } 441 if ((visbuf = malloc(len * 4 + 1)) != NULL) { 442 strvisx(visbuf, buf, len, 0); 443 fprintf(stderr, "string \"%s\"\n", visbuf); 444 free(visbuf); 445 } 446 break; 447 case BER_TYPE_NULL: /* no payload */ 448 case BER_TYPE_EOC: 449 case BER_TYPE_SEQUENCE: 450 case BER_TYPE_SET: 451 default: 452 fprintf(stderr, "\n"); 453 break; 454 } 455 456 if (constructed && root->be_sub) { 457 indent += 2; 458 ldap_debug_elements(root->be_sub, context, NULL); 459 indent -= 2; 460 } 461 if (root->be_next) 462 ldap_debug_elements(root->be_next, context, NULL); 463 } 464 465