xref: /openbsd/usr.sbin/ldapd/log.c (revision 48318e0b)
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