xref: /openbsd-src/usr.sbin/ldapd/log.c (revision 48950c12d106c85f315112191a0228d7b83b9510)
1 /*	$OpenBSD: log.c,v 1.3 2010/11/10 08:00:54 martinh 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.%03li [%i] ", datebuf, tv.tv_usec / 1000, getpid());
87 
88 		/* best effort in out of mem situations */
89 		if (asprintf(&nfmt, "%s\n", fmt) == -1) {
90 			vfprintf(stderr, fmt, ap);
91 			fprintf(stderr, "\n");
92 		} else {
93 			vfprintf(stderr, nfmt, ap);
94 			free(nfmt);
95 		}
96 		fflush(stderr);
97 	} else
98 		vsyslog(pri, fmt, ap);
99 }
100 
101 void
102 log_warn(const char *emsg, ...)
103 {
104 	char	*nfmt;
105 	va_list	 ap;
106 
107 	/* best effort to even work in out of memory situations */
108 	if (emsg == NULL)
109 		logit(LOG_CRIT, "%s", strerror(errno));
110 	else {
111 		va_start(ap, emsg);
112 
113 		if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
114 			/* we tried it... */
115 			vlog(LOG_CRIT, emsg, ap);
116 			logit(LOG_CRIT, "%s", strerror(errno));
117 		} else {
118 			vlog(LOG_CRIT, nfmt, ap);
119 			free(nfmt);
120 		}
121 		va_end(ap);
122 	}
123 }
124 
125 void
126 log_warnx(const char *emsg, ...)
127 {
128 	va_list	 ap;
129 
130 	va_start(ap, emsg);
131 	vlog(LOG_CRIT, emsg, ap);
132 	va_end(ap);
133 }
134 
135 void
136 log_info(const char *emsg, ...)
137 {
138 	va_list	 ap;
139 
140 	va_start(ap, emsg);
141 	vlog(LOG_INFO, emsg, ap);
142 	va_end(ap);
143 }
144 
145 void
146 log_debug(const char *emsg, ...)
147 {
148 	va_list	 ap;
149 
150 	if (verbose) {
151 		va_start(ap, emsg);
152 		vlog(LOG_DEBUG, emsg, ap);
153 		va_end(ap);
154 	}
155 }
156 
157 void
158 fatal(const char *emsg)
159 {
160 	if (emsg == NULL)
161 		logit(LOG_CRIT, "fatal: %s", strerror(errno));
162 	else
163 		if (errno)
164 			logit(LOG_CRIT, "fatal: %s: %s",
165 			    emsg, strerror(errno));
166 		else
167 			logit(LOG_CRIT, "fatal: %s", emsg);
168 
169 	exit(1);
170 }
171 
172 void
173 fatalx(const char *emsg)
174 {
175 	errno = 0;
176 	fatal(emsg);
177 }
178 
179 const char *
180 print_host(struct sockaddr_storage *ss, char *buf, size_t len)
181 {
182 	if (getnameinfo((struct sockaddr *)ss, ss->ss_len,
183 	    buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
184 		buf[0] = '\0';
185 		return (NULL);
186 	}
187 	return (buf);
188 }
189 
190 void
191 hexdump(void *data, size_t len, const char *fmt, ...)
192 {
193 	uint8_t *p = data;
194 	va_list ap;
195 
196 	if (verbose < 2 || !debug)
197 		return;
198 
199 	va_start(ap, fmt);
200 	vlog(LOG_DEBUG, fmt, ap);
201 	va_end(ap);
202 
203 	while (len--) {
204 		size_t ofs = p - (uint8_t *)data;
205 		if (ofs % 16 == 0)
206 			fprintf(stderr, "%s%04lx:", ofs == 0 ? "" : "\n", ofs);
207 		else if (ofs % 8 == 0)
208 			fprintf(stderr, " ");
209 		fprintf(stderr, " %02x", *p++);
210 	}
211 	fprintf(stderr, "\n");
212 }
213 
214 /*
215  * Display a list of ber elements.
216  *
217  */
218 void
219 ldap_debug_elements(struct ber_element *root, int context, const char *fmt, ...)
220 {
221 	va_list		 ap;
222 	static int	 indent = 0;
223 	long long	 v;
224 	int		 d;
225 	char		*buf, *visbuf;
226 	size_t		 len;
227 	u_int		 i;
228 	int		 constructed;
229 	struct ber_oid	 o;
230 
231 	if (verbose < 2 || !debug)
232 		return;
233 
234 	if (fmt != NULL) {
235 		va_start(ap, fmt);
236 		vlog(LOG_DEBUG, fmt, ap);
237 		va_end(ap);
238 	}
239 
240 	/* calculate lengths */
241 	ber_calc_len(root);
242 
243 	switch (root->be_encoding) {
244 	case BER_TYPE_SEQUENCE:
245 	case BER_TYPE_SET:
246 		constructed = root->be_encoding;
247 		break;
248 	default:
249 		constructed = 0;
250 		break;
251 	}
252 
253 	fprintf(stderr, "%*slen %lu ", indent, "", root->be_len);
254 	switch (root->be_class) {
255 	case BER_CLASS_UNIVERSAL:
256 		fprintf(stderr, "class: universal(%u) type: ", root->be_class);
257 		switch (root->be_type) {
258 		case BER_TYPE_EOC:
259 			fprintf(stderr, "end-of-content");
260 			break;
261 		case BER_TYPE_BOOLEAN:
262 			fprintf(stderr, "boolean");
263 			break;
264 		case BER_TYPE_INTEGER:
265 			fprintf(stderr, "integer");
266 			break;
267 		case BER_TYPE_BITSTRING:
268 			fprintf(stderr, "bit-string");
269 			break;
270 		case BER_TYPE_OCTETSTRING:
271 			fprintf(stderr, "octet-string");
272 			break;
273 		case BER_TYPE_NULL:
274 			fprintf(stderr, "null");
275 			break;
276 		case BER_TYPE_OBJECT:
277 			fprintf(stderr, "object");
278 			break;
279 		case BER_TYPE_ENUMERATED:
280 			fprintf(stderr, "enumerated");
281 			break;
282 		case BER_TYPE_SEQUENCE:
283 			fprintf(stderr, "sequence");
284 			break;
285 		case BER_TYPE_SET:
286 			fprintf(stderr, "set");
287 			break;
288 		}
289 		break;
290 	case BER_CLASS_APPLICATION:
291 		fprintf(stderr, "class: application(%u) type: ",
292 		    root->be_class);
293 		switch (root->be_type) {
294 		case LDAP_REQ_BIND:
295 		case LDAP_RES_BIND:
296 			fprintf(stderr, "bind");
297 			break;
298 		case LDAP_REQ_UNBIND_30:
299 			fprintf(stderr, "unbind");
300 			break;
301 		case LDAP_REQ_SEARCH:
302 			fprintf(stderr, "search");
303 			break;
304 		case LDAP_RES_SEARCH_ENTRY:
305 			fprintf(stderr, "search entry");
306 			break;
307 		case LDAP_RES_SEARCH_RESULT:
308 			fprintf(stderr, "search result");
309 			break;
310 		case LDAP_REQ_MODIFY:
311 		case LDAP_RES_MODIFY:
312 			fprintf(stderr, "modify");
313 			break;
314 		case LDAP_REQ_ADD:
315 		case LDAP_RES_ADD:
316 			fprintf(stderr, "add");
317 			break;
318 		case LDAP_REQ_DELETE_30:
319 		case LDAP_RES_DELETE:
320 			fprintf(stderr, "delete");
321 			break;
322 		case LDAP_REQ_MODRDN:
323 		case LDAP_RES_MODRDN:
324 			fprintf(stderr, "modrdn");
325 			break;
326 		case LDAP_REQ_COMPARE:
327 		case LDAP_RES_COMPARE:
328 			fprintf(stderr, "compare");
329 			break;
330 		case LDAP_REQ_ABANDON_30:
331 			fprintf(stderr, "abandon");
332 			break;
333 		case LDAP_REQ_EXTENDED:
334 		case LDAP_RES_EXTENDED:
335 			fprintf(stderr, "extended");
336 			break;
337 		}
338 		break;
339 	case BER_CLASS_PRIVATE:
340 		fprintf(stderr, "class: private(%u) type: ", root->be_class);
341 		fprintf(stderr, "encoding (%lu) type: ", root->be_encoding);
342 		break;
343 	case BER_CLASS_CONTEXT:
344 		fprintf(stderr, "class: context(%u) type: ", root->be_class);
345 		switch (context) {
346 		case LDAP_REQ_BIND:
347 			switch(root->be_type) {
348 			case LDAP_AUTH_SIMPLE:
349 				fprintf(stderr, "auth simple");
350 				break;
351 			}
352 			break;
353 		case LDAP_REQ_SEARCH:
354 			switch(root->be_type) {
355 			case LDAP_FILT_AND:
356 				fprintf(stderr, "and");
357 				break;
358 			case LDAP_FILT_OR:
359 				fprintf(stderr, "or");
360 				break;
361 			case LDAP_FILT_NOT:
362 				fprintf(stderr, "not");
363 				break;
364 			case LDAP_FILT_EQ:
365 				fprintf(stderr, "equal");
366 				break;
367 			case LDAP_FILT_SUBS:
368 				fprintf(stderr, "substring");
369 				break;
370 			case LDAP_FILT_GE:
371 				fprintf(stderr, "greater-or-equal");
372 				break;
373 			case LDAP_FILT_LE:
374 				fprintf(stderr, "less-or-equal");
375 				break;
376 			case LDAP_FILT_PRES:
377 				fprintf(stderr, "presence");
378 				break;
379 			case LDAP_FILT_APPR:
380 				fprintf(stderr, "approximate");
381 				break;
382 			}
383 			break;
384 		}
385 		break;
386 	default:
387 		fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class);
388 		break;
389 	}
390 	fprintf(stderr, "(%lu) encoding %lu ",
391 	    root->be_type, root->be_encoding);
392 
393 	if (constructed)
394 		root->be_encoding = constructed;
395 
396 	switch (root->be_encoding) {
397 	case BER_TYPE_BOOLEAN:
398 		if (ber_get_boolean(root, &d) == -1) {
399 			fprintf(stderr, "<INVALID>\n");
400 			break;
401 		}
402 		fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d);
403 		break;
404 	case BER_TYPE_INTEGER:
405 		if (ber_get_integer(root, &v) == -1) {
406 			fprintf(stderr, "<INVALID>\n");
407 			break;
408 		}
409 		fprintf(stderr, "value %lld\n", v);
410 		break;
411 	case BER_TYPE_ENUMERATED:
412 		if (ber_get_enumerated(root, &v) == -1) {
413 			fprintf(stderr, "<INVALID>\n");
414 			break;
415 		}
416 		fprintf(stderr, "value %lld\n", v);
417 		break;
418 	case BER_TYPE_BITSTRING:
419 		if (ber_get_bitstring(root, (void *)&buf, &len) == -1) {
420 			fprintf(stderr, "<INVALID>\n");
421 			break;
422 		}
423 		fprintf(stderr, "hexdump ");
424 		for (i = 0; i < len; i++)
425 			fprintf(stderr, "%02x", buf[i]);
426 		fprintf(stderr, "\n");
427 		break;
428 	case BER_TYPE_OBJECT:
429 		if (ber_get_oid(root, &o) == -1) {
430 			fprintf(stderr, "<INVALID>\n");
431 			break;
432 		}
433 		fprintf(stderr, "\n");
434 		break;
435 	case BER_TYPE_OCTETSTRING:
436 		if (ber_get_nstring(root, (void *)&buf, &len) == -1) {
437 			fprintf(stderr, "<INVALID>\n");
438 			break;
439 		}
440 		if ((visbuf = malloc(len * 4 + 1)) != NULL) {
441 			strvisx(visbuf, buf, len, 0);
442 			fprintf(stderr, "string \"%s\"\n",  visbuf);
443 			free(visbuf);
444 		}
445 		break;
446 	case BER_TYPE_NULL:	/* no payload */
447 	case BER_TYPE_EOC:
448 	case BER_TYPE_SEQUENCE:
449 	case BER_TYPE_SET:
450 	default:
451 		fprintf(stderr, "\n");
452 		break;
453 	}
454 
455 	if (constructed && root->be_sub) {
456 		indent += 2;
457 		ldap_debug_elements(root->be_sub, context, NULL);
458 		indent -= 2;
459 	}
460 	if (root->be_next)
461 		ldap_debug_elements(root->be_next, context, NULL);
462 }
463 
464