Coverage Report

Created: 2026-03-01 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/log.c
Line
Count
Source
1
/*
2
 * log.c: Miscellaneous logging functions
3
 *
4
 * Copyright (C) 2001, 2002  Juha Yrjölä <juha.yrjola@iki.fi>
5
 * Copyright (C) 2003  Antti Tapaninen <aet@cc.hut.fi>
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
#ifdef HAVE_CONFIG_H
23
#include "config.h"
24
#endif
25
26
#include <stdarg.h>
27
#include <stdlib.h>
28
#include <assert.h>
29
#include <ctype.h>
30
#include <string.h>
31
#include <time.h>
32
#ifdef HAVE_UNISTD_H
33
#include <unistd.h>
34
#endif
35
#ifdef HAVE_SYS_TIME_H
36
#include <sys/time.h>
37
#endif
38
#ifdef HAVE_IO_H
39
#include <io.h>
40
#endif
41
#ifdef HAVE_PTHREAD
42
#include <pthread.h>
43
#endif
44
#ifdef _WIN32
45
#include <windows.h>
46
#endif
47
#ifdef ENABLE_OPENSSL
48
#include <openssl/err.h>
49
#endif /* ENABLE_OPENSSL */
50
#include "common/compat_strlcat.h"
51
52
#include "internal.h"
53
54
static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int line, const char *func, int color, const char *format, va_list args);
55
static int sc_color_fprintf_va(int colors, struct sc_context *ctx, FILE * stream, const char *format, va_list args);
56
57
void sc_do_log(sc_context_t *ctx, int level, const char *file, int line, const char *func, const char *format, ...)
58
14.2M
{
59
14.2M
  va_list ap;
60
61
14.2M
  va_start(ap, format);
62
14.2M
  sc_do_log_va(ctx, level, file, line, func, 0, format, ap);
63
14.2M
  va_end(ap);
64
14.2M
}
65
66
void sc_do_log_color(sc_context_t *ctx, int level, const char *file, int line, const char *func, int color, const char *format, ...)
67
4.20M
{
68
4.20M
  va_list ap;
69
70
4.20M
  va_start(ap, format);
71
4.20M
  sc_do_log_va(ctx, level, file, line, func, color, format, ap);
72
4.20M
  va_end(ap);
73
4.20M
}
74
75
#ifdef ENABLE_OPENSSL
76
void sc_do_log_openssl(sc_context_t *ctx, int level, const char *file, int line, const char *func)
77
4.60k
{
78
4.60k
  BIO *bio = NULL;
79
4.60k
  int length, rc;
80
4.60k
  char *buffer = NULL;
81
82
4.60k
  if ((bio = BIO_new(BIO_s_mem())) == NULL) {
83
0
    sc_do_log(ctx, level, file, line, func, "Cannot log OpenSSL error");
84
0
    goto end;
85
0
  }
86
4.60k
  ERR_print_errors(bio);
87
88
4.60k
  length = BIO_pending(bio);
89
4.60k
  if (length <= 0) {
90
    /* no error? */
91
4.60k
    goto end;
92
4.60k
  }
93
  /* trailing null byte */
94
1
  buffer = malloc(length + 1);
95
1
  if (buffer == NULL) {
96
0
    sc_do_log(ctx, level, file, line, func, "No memory!");
97
0
    goto end;
98
0
  }
99
1
  rc = BIO_read(bio, buffer, length);
100
1
  buffer[length] = '\0';
101
1
  if (rc <= 0) {
102
0
    sc_do_log(ctx, level, file, line, func, "Cannot read OpenSSL error");
103
0
    goto end;
104
0
  }
105
106
1
  sc_do_log(ctx, level, file, line, func, "OpenSSL error\n%s", buffer);
107
4.60k
end:
108
4.60k
  free(buffer);
109
4.60k
  BIO_free(bio);
110
4.60k
}
111
#else
112
void sc_do_log_openssl(sc_context_t *ctx, int level, const char *file, int line, const char *func)
113
{
114
  sc_do_log(ctx, level, file, line, func, "OpenSSL not enabled");
115
}
116
#endif
117
118
void sc_do_log_noframe(sc_context_t *ctx, int level, const char *format, va_list args)
119
0
{
120
0
  sc_do_log_va(ctx, level, NULL, 0, NULL, 0, format, args);
121
0
}
122
123
static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int line, const char *func, int color, const char *format, va_list args)
124
18.4M
{
125
#ifdef _WIN32
126
  SYSTEMTIME st;
127
#else
128
18.4M
  struct tm *tm;
129
18.4M
  struct timeval tv;
130
18.4M
  char time_string[40];
131
18.4M
#endif
132
133
18.4M
  if (!ctx || ctx->debug < level)
134
18.4M
    return;
135
136
#ifdef _WIN32
137
  /* In Windows, file handles can not be shared between DLL-s, each DLL has a
138
   * separate file handle table. Make sure we always have a valid file
139
   * descriptor. */
140
  if (sc_ctx_log_to_file(ctx, ctx->debug_filename) < 0)
141
    return;
142
#endif
143
0
  if (ctx->debug_file == NULL)
144
0
    return;
145
146
#ifdef _WIN32
147
  GetLocalTime(&st);
148
  sc_color_fprintf(SC_COLOR_FG_GREEN|SC_COLOR_BOLD,
149
      ctx, ctx->debug_file,
150
      "P:%lu; T:%lu",
151
      (unsigned long)GetCurrentProcessId(),
152
      (unsigned long)GetCurrentThreadId());
153
  sc_color_fprintf(SC_COLOR_FG_GREEN,
154
      ctx, ctx->debug_file,
155
      " %i-%02i-%02i %02i:%02i:%02i.%03i",
156
      st.wYear, st.wMonth, st.wDay,
157
      st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
158
#else
159
0
  sc_color_fprintf(SC_COLOR_FG_GREEN|SC_COLOR_BOLD,
160
0
      ctx, ctx->debug_file,
161
0
      "P:%lu; T:0x%lu",
162
0
      (unsigned long)getpid(),
163
0
      (unsigned long)pthread_self());
164
0
  gettimeofday (&tv, NULL);
165
0
  tm = localtime (&tv.tv_sec);
166
0
  strftime (time_string, sizeof(time_string), "%H:%M:%S", tm);
167
0
  sc_color_fprintf(SC_COLOR_FG_GREEN,
168
0
      ctx, ctx->debug_file,
169
0
      " %s.%03ld",
170
0
      time_string,
171
0
      (long)tv.tv_usec / 1000);
172
0
#endif
173
174
0
  sc_color_fprintf(SC_COLOR_FG_YELLOW,
175
0
      ctx, ctx->debug_file,
176
0
      " [");
177
0
  sc_color_fprintf(SC_COLOR_FG_YELLOW|SC_COLOR_BOLD,
178
0
      ctx, ctx->debug_file,
179
0
      "%s",
180
0
      ctx->app_name);
181
0
  sc_color_fprintf(SC_COLOR_FG_YELLOW,
182
0
      ctx, ctx->debug_file,
183
0
      "] ");
184
185
0
  if (file != NULL) {
186
0
    sc_color_fprintf(SC_COLOR_FG_YELLOW,
187
0
        ctx, ctx->debug_file,
188
0
        "%s:%d:%s: ",
189
0
        file, line, func ? func : "");
190
0
  }
191
192
0
  sc_color_fprintf_va(color, ctx, ctx->debug_file, format, args);
193
0
  if (strlen(format) == 0 || format[strlen(format) - 1] != '\n')
194
0
    sc_color_fprintf(color, ctx, ctx->debug_file, "\n");
195
0
  fflush(ctx->debug_file);
196
197
#ifdef _WIN32
198
  if (ctx->debug_file && (ctx->debug_file != stderr && ctx->debug_file != stdout))
199
    fclose(ctx->debug_file);
200
  ctx->debug_file = NULL;
201
#endif
202
0
}
203
204
void _sc_debug(struct sc_context *ctx, int level, const char *format, ...)
205
0
{
206
0
  va_list ap;
207
208
0
  va_start(ap, format);
209
0
  sc_do_log_va(ctx, level, NULL, 0, NULL, 0, format, ap);
210
0
  va_end(ap);
211
0
}
212
213
void _sc_log(struct sc_context *ctx, const char *format, ...)
214
0
{
215
0
  va_list ap;
216
217
0
  va_start(ap, format);
218
0
  sc_do_log_va(ctx, SC_LOG_DEBUG_NORMAL, NULL, 0, NULL, 0, format, ap);
219
0
  va_end(ap);
220
0
}
221
222
void _sc_log_openssl(struct sc_context *ctx)
223
0
{
224
0
  sc_do_log_openssl(ctx, SC_LOG_DEBUG_DEPS, NULL, 0, NULL);
225
0
}
226
227
static int is_a_tty(FILE *fp)
228
0
{
229
0
  if (fp != NULL) {
230
0
    int fd = fileno(fp);
231
0
    if (fd >= 0) {
232
#ifdef _WIN32
233
      HANDLE h = (HANDLE)_get_osfhandle(fd);
234
      if (h != INVALID_HANDLE_VALUE) {
235
        return GetFileType(h) == FILE_TYPE_CHAR;
236
      }
237
#else
238
0
      return isatty(fd);
239
0
#endif
240
0
    }
241
0
  }
242
0
  return 0;
243
0
}
244
245
#ifdef _WIN32
246
#define set_color(sc_color, win_color, vt100_color) \
247
  do { if (colors & sc_color) { attr |= win_color; } } while (0)
248
#else
249
#define set_color(sc_color, win_color, vt100_color) \
250
0
  do { if (colors & sc_color) { fprintf(stream, vt100_color); } } while (0)
251
#endif
252
253
int sc_color_fprintf(int colors, struct sc_context *ctx, FILE * stream, const char * format, ...)
254
0
{
255
0
  int r;
256
0
  va_list ap;
257
258
0
  va_start(ap, format);
259
0
  r = sc_color_fprintf_va(colors, ctx, stream, format, ap);
260
0
  va_end(ap);
261
262
0
  return r;
263
0
}
264
265
int sc_color_fprintf_va(int colors, struct sc_context *ctx, FILE * stream, const char *format, va_list args)
266
0
{
267
0
  int r;
268
#ifdef _WIN32
269
  WORD old_attr = 0;
270
  int fd = stream ? fileno(stream) : -1;
271
  HANDLE handle = fd >= 0 ? (HANDLE) _get_osfhandle(fd) : INVALID_HANDLE_VALUE;
272
#endif
273
274
0
  if (!is_a_tty(stream))
275
0
    colors = 0;
276
277
0
  if (colors && (!ctx || (!(ctx->flags & SC_CTX_FLAG_DISABLE_COLORS)))) {
278
#ifdef _WIN32
279
    WORD attr = 0;
280
    CONSOLE_SCREEN_BUFFER_INFO csbi;
281
    GetConsoleScreenBufferInfo(handle, &csbi);
282
    old_attr = csbi.wAttributes;
283
#endif
284
0
    set_color(SC_COLOR_FG_RED,
285
0
        FOREGROUND_RED,
286
0
        "\x1b[31m");
287
0
    set_color(SC_COLOR_FG_GREEN,
288
0
        FOREGROUND_GREEN,
289
0
        "\x1b[32m");
290
0
    set_color(SC_COLOR_FG_YELLOW,
291
0
        FOREGROUND_GREEN|FOREGROUND_RED,
292
0
        "\x1b[33m");
293
0
    set_color(SC_COLOR_FG_BLUE,
294
0
        FOREGROUND_BLUE,
295
0
        "\x1b[34m");
296
0
    set_color(SC_COLOR_FG_MAGENTA,
297
0
        FOREGROUND_BLUE|FOREGROUND_RED,
298
0
        "\x1b[35m");
299
0
    set_color(SC_COLOR_FG_CYAN,
300
0
        FOREGROUND_BLUE|FOREGROUND_GREEN,
301
0
        "\x1b[36m");
302
0
    set_color(SC_COLOR_BG_RED,
303
0
        FOREGROUND_RED,
304
0
        "\x1b[41m");
305
0
    set_color(SC_COLOR_BG_GREEN,
306
0
        BACKGROUND_GREEN,
307
0
        "\x1b[42m");
308
0
    set_color(SC_COLOR_BG_YELLOW,
309
0
        BACKGROUND_GREEN|BACKGROUND_RED,
310
0
        "\x1b[43m");
311
0
    set_color(SC_COLOR_BG_BLUE,
312
0
        BACKGROUND_BLUE,
313
0
        "\x1b[44m");
314
0
    set_color(SC_COLOR_BG_MAGENTA,
315
0
        BACKGROUND_BLUE|BACKGROUND_RED,
316
0
        "\x1b[45m");
317
0
    set_color(SC_COLOR_BG_CYAN,
318
0
        BACKGROUND_BLUE|BACKGROUND_GREEN,
319
0
        "\x1b[46m");
320
0
    set_color(SC_COLOR_BOLD,
321
0
        FOREGROUND_INTENSITY,
322
0
        "\x1b[1m");
323
#ifdef _WIN32
324
    SetConsoleTextAttribute(handle, attr);
325
#endif
326
0
  }
327
328
0
  r = vfprintf(stream, format, args);
329
330
0
  if (colors && (!ctx || (!(ctx->flags & SC_CTX_FLAG_DISABLE_COLORS)))) {
331
#ifdef _WIN32
332
    SetConsoleTextAttribute(handle, old_attr);
333
#else
334
0
    fprintf(stream, "\x1b[0m");
335
0
#endif
336
0
  }
337
338
0
  return r;
339
0
}
340
341
void _sc_debug_hex(sc_context_t *ctx, int type, const char *file, int line,
342
    const char *func, const char *label, const u8 *data, size_t len)
343
422k
{
344
422k
  size_t blen = len * 5 + 128;
345
422k
  char *buf = malloc(blen);
346
422k
  if (buf == NULL)
347
0
    return;
348
349
422k
  sc_hex_dump(data, len, buf, blen);
350
351
422k
  if (label)
352
422k
    sc_do_log(ctx, type, file, line, func,
353
422k
      "\n%s (%"SC_FORMAT_LEN_SIZE_T"u byte%s):\n%s",
354
422k
      label, len, len==1?"":"s", buf);
355
0
  else
356
0
    sc_do_log(ctx, type, file, line, func,
357
0
      "%"SC_FORMAT_LEN_SIZE_T"u byte%s:\n%s",
358
0
      len, len==1?"":"s", buf);
359
360
422k
  free(buf);
361
422k
}
362
363
void sc_hex_dump(const u8 * in, size_t count, char *buf, size_t len)
364
422k
{
365
422k
  char *p = buf;
366
422k
  size_t p_len = len;
367
422k
  int lines = 0;
368
369
422k
  if (buf == NULL || (in == NULL && count != 0)) {
370
0
    return;
371
0
  }
372
422k
  buf[0] = 0;
373
422k
  if ((count * 5) > len)
374
0
    return;
375
2.50M
  while (count) {
376
2.07M
    char ascbuf[17];
377
2.07M
    size_t i;
378
379
32.8M
    for (i = 0; i < count && i < 16; i++) {
380
30.8M
      sprintf(p, "%02X ", *in);
381
30.8M
      if (isprint(*in))
382
14.0M
        ascbuf[i] = *in;
383
16.7M
      else
384
16.7M
        ascbuf[i] = '.';
385
30.8M
      p += 3;
386
30.8M
      p_len -= 3;
387
30.8M
      in++;
388
30.8M
    }
389
2.07M
    count -= i;
390
2.07M
    ascbuf[i] = 0;
391
2.54M
    for (; i < 16 && lines; i++) {
392
461k
      strlcat(p, "   ", p_len);
393
461k
      p += 3;
394
461k
      p_len -= 3;
395
461k
    }
396
2.07M
    snprintf(p, p_len, "%s\n", ascbuf);
397
2.07M
    p += strlen(ascbuf) + 1;
398
2.07M
    p_len -= strlen(ascbuf) - 1;
399
2.07M
    lines++;
400
2.07M
  }
401
422k
}
402
403
const char *
404
sc_dump_hex(const u8 * in, size_t count)
405
178k
{
406
178k
  static char dump_buf[0x1000];
407
178k
  size_t ii, size = sizeof(dump_buf) - 0x10;
408
178k
  size_t offs = 0;
409
410
178k
  memset(dump_buf, 0, sizeof(dump_buf));
411
178k
  if (in == NULL)
412
0
    return dump_buf;
413
414
959k
  for (ii=0; ii<count; ii++) {
415
780k
    if (ii && !(ii%16))   {
416
14.4k
      if (!(ii%48))
417
3.72k
        snprintf(dump_buf + offs, size - offs, "\n");
418
10.7k
      else
419
10.7k
        snprintf(dump_buf + offs, size - offs, " ");
420
14.4k
      offs = strlen(dump_buf);
421
14.4k
    }
422
423
780k
    snprintf(dump_buf + offs, size - offs, "%02X", *(in + ii));
424
780k
    offs += 2;
425
426
780k
    if (offs > size)
427
0
      break;
428
780k
  }
429
430
178k
  if (ii<count)
431
0
    snprintf(dump_buf + offs, sizeof(dump_buf) - offs, "....\n");
432
433
178k
  return dump_buf;
434
178k
}
435
436
const char *
437
sc_dump_oid(const struct sc_object_id *oid)
438
4.89k
{
439
4.89k
  static char dump_buf[SC_MAX_OBJECT_ID_OCTETS * 20];
440
4.89k
        size_t ii;
441
442
4.89k
  memset(dump_buf, 0, sizeof(dump_buf));
443
4.89k
  if (oid)
444
37.3k
    for (ii=0; ii<SC_MAX_OBJECT_ID_OCTETS && oid->value[ii] != -1; ii++)
445
32.4k
      snprintf(dump_buf + strlen(dump_buf), sizeof(dump_buf) - strlen(dump_buf), "%s%i", (ii ? "." : ""), oid->value[ii]);
446
447
4.89k
  return dump_buf;
448
4.89k
}