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