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
log_on_stderr(const char * str)28 log_on_stderr(const char *str)
29 {
30 fprintf(stderr, "%s", str);
31 }
32
33 static void
do_log(const char * suffix,const char * fmt,va_list args)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
fido_log_init(void)49 fido_log_init(void)
50 {
51 logging = 1;
52 log_handler = log_on_stderr;
53 }
54
55 void
fido_log_debug(const char * fmt,...)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
fido_log_xxd(const void * buf,size_t count,const char * fmt,...)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
fido_log_error(int errnum,const char * fmt,...)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
fido_set_log_handler(fido_log_handler_t * handler)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