xref: /freebsd/contrib/libfido2/src/log.c (revision 81b22a98)
1 /*
2  * Copyright (c) 2018-2021 Yubico AB. All rights reserved.
3  * Use of this source code is governed by a BSD-style
4  * license that can be found in the LICENSE file.
5  */
6 
7 #undef _GNU_SOURCE /* XSI strerror_r() */
8 
9 #include <stdarg.h>
10 #include <stdio.h>
11 
12 #include "fido.h"
13 
14 #ifndef FIDO_NO_DIAGNOSTIC
15 
16 #define XXDLEN	32
17 #define XXDROW	128
18 #define LINELEN	256
19 
20 #ifndef TLS
21 #define TLS
22 #endif
23 
24 static TLS int logging;
25 static TLS fido_log_handler_t *log_handler;
26 
27 static void
28 log_on_stderr(const char *str)
29 {
30 	fprintf(stderr, "%s", str);
31 }
32 
33 static void
34 do_log(const char *suffix, const char *fmt, va_list args)
35 {
36 	char line[LINELEN], body[LINELEN];
37 
38 	vsnprintf(body, sizeof(body), fmt, args);
39 
40 	if (suffix != NULL)
41 		snprintf(line, sizeof(line), "%.180s: %.70s\n", body, suffix);
42 	else
43 		snprintf(line, sizeof(line), "%.180s\n", body);
44 
45 	log_handler(line);
46 }
47 
48 void
49 fido_log_init(void)
50 {
51 	logging = 1;
52 	log_handler = log_on_stderr;
53 }
54 
55 void
56 fido_log_debug(const char *fmt, ...)
57 {
58 	va_list args;
59 
60 	if (!logging || log_handler == NULL)
61 		return;
62 
63 	va_start(args, fmt);
64 	do_log(NULL, fmt, args);
65 	va_end(args);
66 }
67 
68 void
69 fido_log_xxd(const void *buf, size_t count, const char *fmt, ...)
70 {
71 	const uint8_t *ptr = buf;
72 	char row[XXDROW], xxd[XXDLEN];
73 	va_list args;
74 
75 	if (!logging || log_handler == NULL)
76 		return;
77 
78 	snprintf(row, sizeof(row), "buf=%p, len=%zu", buf, count);
79 	va_start(args, fmt);
80 	do_log(row, fmt, args);
81 	va_end(args);
82 	*row = '\0';
83 
84 	for (size_t i = 0; i < count; i++) {
85 		*xxd = '\0';
86 		if (i % 16 == 0)
87 			snprintf(xxd, sizeof(xxd), "%04zu: %02x", i, *ptr++);
88 		else
89 			snprintf(xxd, sizeof(xxd), " %02x", *ptr++);
90 		strlcat(row, xxd, sizeof(row));
91 		if (i % 16 == 15 || i == count - 1) {
92 			fido_log_debug("%s", row);
93 			*row = '\0';
94 		}
95 	}
96 }
97 
98 void
99 fido_log_error(int errnum, const char *fmt, ...)
100 {
101 	char errstr[LINELEN];
102 	va_list args;
103 
104 	if (!logging || log_handler == NULL)
105 		return;
106 	if (strerror_r(errnum, errstr, sizeof(errstr)) != 0)
107 		snprintf(errstr, sizeof(errstr), "error %d", errnum);
108 
109 	va_start(args, fmt);
110 	do_log(errstr, fmt, args);
111 	va_end(args);
112 }
113 
114 void
115 fido_set_log_handler(fido_log_handler_t *handler)
116 {
117 	if (handler != NULL)
118 		log_handler = handler;
119 }
120 
121 #endif /* !FIDO_NO_DIAGNOSTIC */
122