Coverage Report

Created: 2026-08-31 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/ctx.c
Line
Count
Source
1
/*
2
 * ctx.c: Context related functions
3
 *
4
 * Copyright (C) 2002  Juha Yrjölä <juha.yrjola@iki.fi>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#ifdef HAVE_CONFIG_H
22
#include "config.h"
23
#endif
24
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <assert.h>
29
#include <errno.h>
30
#include <sys/stat.h>
31
#include <limits.h>
32
33
#ifdef _WIN32
34
#include <windows.h>
35
#include <winreg.h>
36
#include <direct.h>
37
#include <io.h>
38
#endif
39
40
#ifdef __APPLE__
41
#include <libproc.h>
42
#endif
43
44
#include "common/libscdl.h"
45
#include "common/compat_strlcpy.h"
46
#include "internal.h"
47
#ifdef ENABLE_OPENSSL
48
#include <openssl/crypto.h>
49
#include "sc-ossl-compat.h"
50
#endif
51
52
53
static int ignored_reader(sc_context_t *ctx, sc_reader_t *reader)
54
0
{
55
0
  if (ctx != NULL && reader != NULL && reader->name != NULL) {
56
0
    size_t i;
57
0
    const scconf_list *list;
58
59
0
    for (i = 0; ctx->conf_blocks[i]; i++) {
60
0
      list = scconf_find_list(ctx->conf_blocks[i], "ignored_readers");
61
0
      while (list != NULL) {
62
0
        if (strstr(reader->name, list->data) != NULL) {
63
0
          sc_log(ctx, "Ignoring reader \'%s\' because of \'%s\'\n",
64
0
              reader->name, list->data);
65
0
          return 1;
66
0
        }
67
0
        list = list->next;
68
0
      }
69
0
    }
70
0
  }
71
72
0
  return 0;
73
0
}
74
75
int _sc_add_reader(sc_context_t *ctx, sc_reader_t *reader)
76
0
{
77
0
  if (reader == NULL || ignored_reader(ctx, reader)) {
78
0
    return SC_ERROR_INVALID_ARGUMENTS;
79
0
  }
80
0
  reader->ctx = ctx;
81
0
  list_append(&ctx->readers, reader);
82
0
  return SC_SUCCESS;
83
0
}
84
85
int _sc_delete_reader(sc_context_t *ctx, sc_reader_t *reader)
86
3.42k
{
87
3.42k
  if (reader == NULL) {
88
0
    return SC_ERROR_INVALID_ARGUMENTS;
89
0
  }
90
3.42k
  if (reader->ops->release)
91
3.42k
      reader->ops->release(reader);
92
3.42k
  free(reader->name);
93
3.42k
  free(reader->vendor);
94
3.42k
  list_delete(&ctx->readers, reader);
95
3.42k
  free(reader);
96
3.42k
  return SC_SUCCESS;
97
3.42k
}
98
99
struct _sc_driver_entry {
100
  const char *name;
101
  void *(*func)(void);
102
};
103
104
// clang-format off
105
static const struct _sc_driver_entry internal_card_drivers[] = {
106
  /* The card handled by skeid shares the ATR with other cards running CardOS 5.4.
107
   * In order to prevent the cardos driver from matching skeid cards, skeid driver
108
   * precedes cardos and matches no other CardOS 5.4 card. */
109
  { "skeid",  (void *(*)(void)) sc_get_skeid_driver },
110
  /* The card handled by dtrust shares the ATR with other cards running CardOS 5.4.
111
   * In order to prevent the cardos driver from matching dtrust cards, dtrust driver
112
   * precedes cardos and matches no other CardOS 5.4 card. */
113
  { "dtrust", (void *(*)(void)) sc_get_dtrust_driver },
114
  { "cardos", (void *(*)(void)) sc_get_cardos_driver },
115
  { "gemsafeV1",  (void *(*)(void)) sc_get_gemsafeV1_driver },
116
  { "starcos",  (void *(*)(void)) sc_get_starcos_driver },
117
  { "tcos", (void *(*)(void)) sc_get_tcos_driver },
118
#ifdef ENABLE_OPENSSL
119
  { "oberthur", (void *(*)(void)) sc_get_oberthur_driver },
120
  { "authentic",  (void *(*)(void)) sc_get_authentic_driver },
121
  { "iasecc", (void *(*)(void)) sc_get_iasecc_driver },
122
#endif
123
  { "belpic", (void *(*)(void)) sc_get_belpic_driver },
124
#ifdef ENABLE_OPENSSL
125
  { "entersafe",(void *(*)(void)) sc_get_entersafe_driver },
126
#ifdef ENABLE_SM
127
  { "epass2003",(void *(*)(void)) sc_get_epass2003_driver },
128
#endif
129
#endif
130
  { "rutoken",  (void *(*)(void)) sc_get_rutoken_driver },
131
  { "rutoken_ecp",(void *(*)(void)) sc_get_rtecp_driver },
132
  { "myeid",      (void *(*)(void)) sc_get_myeid_driver },
133
#if defined(ENABLE_OPENSSL) && defined(ENABLE_SM)
134
  { "dnie",       (void *(*)(void)) sc_get_dnie_driver },
135
#endif
136
  { "masktech", (void *(*)(void)) sc_get_masktech_driver },
137
  { "idprime",  (void *(*)(void)) sc_get_idprime_driver },
138
  { "cedulauy", (void *(*)(void)) sc_get_cedulauy_driver },
139
#if defined(ENABLE_SM) && defined(ENABLE_OPENPACE)
140
  { "edo",        (void *(*)(void)) sc_get_edo_driver },
141
  { "lteid", (void *(*)(void)) sc_get_lteid_driver },
142
#endif
143
144
/* Here should be placed drivers that need some APDU transactions in the
145
 * driver's `match_card()` function. */
146
  { "esteid2018", (void *(*)(void)) sc_get_esteid2018_driver },
147
  { "esteid2025", (void *(*)(void)) sc_get_esteid2025_driver },
148
  /* srbeid: Serbian cards with CardEdge PKI applet (eID, health, PKS).
149
   * Uses AID selection in match_card() for cards without a distinct ATR. */
150
  { "srbeid", (void *(*)(void)) sc_get_srbeid_driver },
151
  { "coolkey",  (void *(*)(void)) sc_get_coolkey_driver },
152
  /* MUSCLE card applet returns 9000 on whatever AID is selected, see
153
   * https://github.com/JavaCardOS/MuscleCard-Applet/blob/master/musclecard/src/com/musclecard/CardEdge/CardEdge.java#L326
154
   * put the muscle driver first to cope with this bug. */
155
  { "muscle", (void *(*)(void)) sc_get_muscle_driver },
156
  { "sc-hsm", (void *(*)(void)) sc_get_sc_hsm_driver },
157
  { "setcos", (void *(*)(void)) sc_get_setcos_driver },
158
  { "PIV-II", (void *(*)(void)) sc_get_piv_driver },
159
  { "cac",  (void *(*)(void)) sc_get_cac_driver },
160
  { "itacns", (void *(*)(void)) sc_get_itacns_driver },
161
  { "isoApplet",  (void *(*)(void)) sc_get_isoApplet_driver },
162
#ifdef ENABLE_ZLIB
163
  { "gids", (void *(*)(void)) sc_get_gids_driver },
164
#endif
165
  { "openpgp",  (void *(*)(void)) sc_get_openpgp_driver },
166
  { "jpki", (void *(*)(void)) sc_get_jpki_driver },
167
  { "npa",  (void *(*)(void)) sc_get_npa_driver },
168
  { "cac1", (void *(*)(void)) sc_get_cac1_driver },
169
  { "nqapplet", (void *(*)(void)) sc_get_nqApplet_driver },
170
#if defined(ENABLE_SM) && defined(ENABLE_OPENPACE)
171
  { "eOI",  (void *(*)(void)) sc_get_eoi_driver },
172
#endif
173
  /* The default driver should be last, as it handles all the
174
   * unrecognized cards. */
175
  { "default",  (void *(*)(void)) sc_get_default_driver },
176
  { NULL, NULL }
177
};
178
179
static const struct _sc_driver_entry old_card_drivers[] = {
180
  { "asepcos",    (void *(*)(void)) sc_get_asepcos_driver },
181
  { "atrust-acos",(void *(*)(void)) sc_get_atrust_acos_driver },
182
  { "cyberflex",  (void *(*)(void)) sc_get_cyberflex_driver },
183
  { "flex",       (void *(*)(void)) sc_get_cryptoflex_driver },
184
  { "mcrd",       (void *(*)(void)) sc_get_mcrd_driver },
185
  { NULL, NULL }
186
};
187
// clang-format on
188
189
struct _sc_ctx_options {
190
  struct _sc_driver_entry cdrv[SC_MAX_CARD_DRIVERS];
191
  int ccount;
192
};
193
194
195
int
196
sc_ctx_win32_get_config_value(const char *name_env,
197
      const char *name_reg, const char *name_key,
198
    void *out, size_t *out_len)
199
0
{
200
#ifdef _WIN32
201
  long rc;
202
  HKEY hKey;
203
204
  if (!out || !out_len)
205
    return SC_ERROR_INVALID_ARGUMENTS;
206
207
  if (name_env)   {
208
    char *value = getenv(name_env);
209
    if (value) {
210
      if (strlen(value) > *out_len)
211
        return SC_ERROR_NOT_ENOUGH_MEMORY;
212
      memcpy(out, value, strlen(value));
213
      *out_len = strlen(value);
214
      return SC_SUCCESS;
215
    }
216
  }
217
218
  if (!name_reg)
219
    return SC_ERROR_INVALID_ARGUMENTS;
220
221
  if (!name_key)
222
    name_key = "Software\\" OPENSC_VS_FF_COMPANY_NAME "\\OpenSC" OPENSC_ARCH_SUFFIX;
223
224
  rc = RegOpenKeyExA(HKEY_CURRENT_USER, name_key, 0, KEY_QUERY_VALUE, &hKey);
225
  if (rc == ERROR_SUCCESS) {
226
    DWORD len = *out_len;
227
    rc = RegQueryValueEx(hKey, name_reg, NULL, NULL, out, &len);
228
    RegCloseKey(hKey);
229
    if (rc == ERROR_SUCCESS) {
230
      *out_len = len;
231
      return SC_SUCCESS;
232
    }
233
  }
234
235
  rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE, name_key, 0, KEY_QUERY_VALUE, &hKey);
236
  if (rc == ERROR_SUCCESS) {
237
    DWORD len = *out_len;
238
    rc = RegQueryValueEx(hKey, name_reg, NULL, NULL, out, &len);
239
    RegCloseKey(hKey);
240
    if (rc == ERROR_SUCCESS) {
241
      *out_len = len;
242
      return SC_SUCCESS;
243
    }
244
  }
245
246
  return SC_ERROR_OBJECT_NOT_FOUND;
247
#else
248
0
  return SC_ERROR_NOT_SUPPORTED;
249
0
#endif
250
0
}
251
252
253
/* Simclist helper to locate readers by name */
254
0
static int reader_list_seeker(const void *el, const void *key) {
255
0
  const struct sc_reader *reader = (struct sc_reader *)el;
256
0
  if ((el == NULL) || (key == NULL))
257
0
    return 0;
258
0
  if (strcmp(reader->name, (char*)key) == 0)
259
0
    return 1;
260
0
  return 0;
261
0
}
262
263
static void del_drvs(struct _sc_ctx_options *opts)
264
6.85k
{
265
6.85k
  struct _sc_driver_entry *lst;
266
6.85k
  int *cp, i;
267
268
6.85k
  lst = opts->cdrv;
269
6.85k
  cp = &opts->ccount;
270
271
297k
  for (i = 0; i < *cp; i++) {
272
291k
    free((void *)lst[i].name);
273
291k
  }
274
6.85k
  *cp = 0;
275
6.85k
}
276
277
static void add_drv(struct _sc_ctx_options *opts, const char *name)
278
291k
{
279
291k
  struct _sc_driver_entry *lst;
280
291k
  int *cp, max, i;
281
282
291k
  lst = opts->cdrv;
283
291k
  cp = &opts->ccount;
284
291k
  max = SC_MAX_CARD_DRIVERS;
285
291k
  if (*cp == max) /* No space for more drivers... */
286
0
    return;
287
6.35M
  for (i = 0; i < *cp; i++)
288
6.06M
    if (strcmp(name, lst[i].name) == 0)
289
0
      return;
290
291k
  lst[*cp].name = strdup(name);
291
292
291k
  *cp = *cp + 1;
293
291k
}
294
295
static void add_internal_drvs(struct _sc_ctx_options *opts)
296
6.85k
{
297
6.85k
  const struct _sc_driver_entry *lst;
298
6.85k
  int i;
299
300
6.85k
  lst = internal_card_drivers;
301
6.85k
  i = 0;
302
280k
  while (lst[i].name != NULL) {
303
274k
    add_drv(opts, lst[i].name);
304
274k
    i++;
305
274k
  }
306
6.85k
}
307
308
static void add_old_drvs(struct _sc_ctx_options *opts)
309
3.42k
{
310
3.42k
  const struct _sc_driver_entry *lst;
311
3.42k
  int i;
312
313
3.42k
  lst = old_card_drivers;
314
3.42k
  i = 0;
315
20.5k
  while (lst[i].name != NULL) {
316
17.1k
    add_drv(opts, lst[i].name);
317
17.1k
    i++;
318
17.1k
  }
319
3.42k
}
320
321
static void set_defaults(sc_context_t *ctx, struct _sc_ctx_options *opts)
322
3.42k
{
323
3.42k
  ctx->debug = 0;
324
3.42k
  if (ctx->debug_file && (ctx->debug_file != stderr && ctx->debug_file != stdout))
325
0
    fclose(ctx->debug_file);
326
3.42k
  ctx->debug_file = stderr;
327
3.42k
  ctx->flags = 0;
328
3.42k
  ctx->forced_driver = NULL;
329
3.42k
  add_internal_drvs(opts);
330
3.42k
}
331
332
/* In Windows, file handles can not be shared between DLL-s,
333
 * each DLL has a separate file handle table. Thus tools and utilities
334
 * can not set the file handle themselves when -v is specified on command line.
335
 */
336
int sc_ctx_log_to_file(sc_context_t *ctx, const char* filename)
337
0
{
338
  /* Close any existing handles */
339
0
  if (ctx->debug_file && (ctx->debug_file != stderr && ctx->debug_file != stdout))   {
340
0
    fclose(ctx->debug_file);
341
0
    ctx->debug_file = NULL;
342
0
  }
343
344
0
  if (!ctx->debug_filename)   {
345
0
    if (!filename)
346
0
      filename = "stderr";
347
0
    ctx->debug_filename = strdup(filename);
348
0
  }
349
350
0
  if (!filename)
351
0
    return SC_SUCCESS;
352
353
  /* Handle special names */
354
0
  if (!strcmp(filename, "stdout"))
355
0
    ctx->debug_file = stdout;
356
0
  else if (!strcmp(filename, "stderr"))
357
0
    ctx->debug_file = stderr;
358
0
  else {
359
0
    ctx->debug_file = fopen(filename, "a");
360
0
    if (ctx->debug_file == NULL)
361
0
      return SC_ERROR_INTERNAL;
362
0
  }
363
0
  return SC_SUCCESS;
364
0
}
365
366
static void
367
set_drivers(struct _sc_ctx_options *opts, const scconf_list *list)
368
3.42k
{
369
3.42k
  const char *s_internal = "internal", *s_old = "old";
370
3.42k
  if (list != NULL)
371
3.42k
    del_drvs(opts);
372
10.2k
  while (list != NULL) {
373
6.85k
    if (strcmp(list->data, s_internal) == 0)
374
3.42k
      add_internal_drvs(opts);
375
3.42k
    else if (strcmp(list->data, s_old) == 0)
376
3.42k
      add_old_drvs(opts);
377
0
    else
378
0
      add_drv(opts, list->data);
379
6.85k
    list = list->next;
380
6.85k
  }
381
3.42k
}
382
383
static int
384
load_parameters(sc_context_t *ctx, scconf_block *block, struct _sc_ctx_options *opts)
385
3.42k
{
386
3.42k
  int err = 0;
387
3.42k
  const scconf_list *list;
388
3.42k
  const char *val;
389
3.42k
  int debug;
390
3.42k
  const char *disable_hw_pkcs1_padding;
391
#ifdef _WIN32
392
  char expanded_val[PATH_MAX];
393
  DWORD expanded_len;
394
#endif
395
396
3.42k
  debug = scconf_get_int(block, "debug", ctx->debug);
397
3.42k
  if (debug > ctx->debug)
398
0
    ctx->debug = debug;
399
400
3.42k
  val = scconf_get_str(block, "debug_file", NULL);
401
3.42k
  if (val)   {
402
#ifdef _WIN32
403
    expanded_len = PATH_MAX;
404
    expanded_len = ExpandEnvironmentStringsA(val, expanded_val, expanded_len);
405
    if (0 < expanded_len && expanded_len < sizeof expanded_val)
406
      val = expanded_val;
407
#endif
408
0
    sc_ctx_log_to_file(ctx, val);
409
0
  }
410
3.42k
  else if (ctx->debug)   {
411
0
    sc_ctx_log_to_file(ctx, NULL);
412
0
  }
413
414
3.42k
  if (scconf_get_bool (block, "disable_popups",
415
3.42k
        ctx->flags & SC_CTX_FLAG_DISABLE_POPUPS))
416
0
    ctx->flags |= SC_CTX_FLAG_DISABLE_POPUPS;
417
418
3.42k
  if (scconf_get_bool (block, "disable_colors",
419
3.42k
        ctx->flags & SC_CTX_FLAG_DISABLE_COLORS))
420
0
    ctx->flags |= SC_CTX_FLAG_DISABLE_COLORS;
421
422
3.42k
  if (scconf_get_bool (block, "enable_default_driver",
423
3.42k
        ctx->flags & SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER))
424
0
    ctx->flags |= SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER;
425
426
3.42k
  list = scconf_find_list(block, "card_drivers");
427
3.42k
  set_drivers(opts, list);
428
429
  /* Disable PKCS#1 v1.5 type 2 (for decryption) depadding on card by default */
430
3.42k
  disable_hw_pkcs1_padding = "decipher";
431
3.42k
  ctx->disable_hw_pkcs1_padding = SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_02;
432
3.42k
  disable_hw_pkcs1_padding = scconf_get_str(block, "disable_hw_pkcs1_padding", disable_hw_pkcs1_padding);
433
3.42k
  if (0 == strcmp(disable_hw_pkcs1_padding, "no")) {
434
0
    ctx->disable_hw_pkcs1_padding = 0;
435
3.42k
  } else if (0 == strcmp(disable_hw_pkcs1_padding, "sign")) {
436
0
    ctx->disable_hw_pkcs1_padding = SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01;
437
3.42k
  } else if (0 == strcmp(disable_hw_pkcs1_padding, "decipher")) {
438
3.42k
    ctx->disable_hw_pkcs1_padding = SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_02;
439
3.42k
  } else if (0 == strcmp(disable_hw_pkcs1_padding, "both")) {
440
0
    ctx->disable_hw_pkcs1_padding = SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01 | SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_02;
441
0
  }
442
443
#ifdef USE_OPENSSL3_LIBCTX
444
  val = scconf_get_str(block, "openssl_config", NULL);
445
  if (val != NULL) {
446
    ctx->openssl_config = strdup(val);
447
  }
448
#endif
449
450
3.42k
  return err;
451
3.42k
}
452
453
454
/**
455
 * find library module for provided driver in configuration file
456
 * if not found assume library name equals to module name
457
 */
458
static const char *find_library(sc_context_t *ctx, const char *name)
459
0
{
460
0
  int i, log_warning;
461
0
  const char *libname = NULL;
462
0
  scconf_block **blocks, *blk;
463
464
0
  for (i = 0; ctx->conf_blocks[i]; i++) {
465
0
    blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "card_driver", name);
466
0
    if (!blocks)
467
0
      continue;
468
0
    blk = blocks[0];
469
0
    free(blocks);
470
0
    if (blk == NULL)
471
0
      continue;
472
0
    libname = scconf_get_str(blk, "module", name);
473
#ifdef _WIN32
474
    log_warning = libname && libname[0] != '\\';
475
#else
476
0
    log_warning = libname && libname[0] != '/';
477
0
#endif
478
0
    if (log_warning)
479
0
      sc_log(ctx, "warning: relative path to driver '%s' used", libname);
480
0
    break;
481
0
  }
482
483
0
  return libname;
484
0
}
485
486
/**
487
 * load card/reader driver modules
488
 * Every module should contain a function " void * sc_module_init(char *) "
489
 * that returns a pointer to the function _sc_get_xxxx_driver()
490
 * used to initialize static modules
491
 * Also, an exported "char *sc_module_version" variable should exist in module
492
 */
493
static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name)
494
0
{
495
0
  const char *version, *libname;
496
0
  void *handle;
497
0
  void *(*modinit)(const char *) = NULL;
498
0
  void *(**tmodi)(const char *) = &modinit;
499
0
  const char *(*modversion)(void) = NULL;
500
0
  const char *(**tmodv)(void) = &modversion;
501
502
0
  if (dll == NULL) {
503
0
    sc_log(ctx, "No dll parameter specified");
504
0
    return NULL;
505
0
  }
506
0
  if (name == NULL) { /* should not occur, but... */
507
0
    sc_log(ctx, "No module specified");
508
0
    return NULL;
509
0
  }
510
0
  libname = find_library(ctx, name);
511
0
  if (libname == NULL)
512
0
    return NULL;
513
0
  handle = sc_dlopen(libname);
514
0
  if (handle == NULL) {
515
0
    sc_log(ctx, "Module %s: cannot load %s library: %s", name, libname, sc_dlerror());
516
0
    return NULL;
517
0
  }
518
519
  /* verify correctness of module */
520
0
  *(void **)tmodi = sc_dlsym(handle, "sc_module_init");
521
0
  *(void **)tmodv = sc_dlsym(handle, "sc_driver_version");
522
0
  if (modinit == NULL || modversion == NULL) {
523
0
    sc_log(ctx, "dynamic library '%s' is not a OpenSC module",libname);
524
0
    sc_dlclose(handle);
525
0
    return NULL;
526
0
  }
527
  /* verify module version */
528
0
  version = modversion();
529
  /* XXX: We really need to have ABI version for each interface */
530
0
  if (version == NULL || strncmp(version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)) != 0) {
531
0
    sc_log(ctx, "dynamic library '%s': invalid module version", libname);
532
0
    sc_dlclose(handle);
533
0
    return NULL;
534
0
  }
535
536
0
  *dll = handle;
537
0
  sc_log(ctx, "successfully loaded card driver '%s'", name);
538
0
  return modinit(name);
539
0
}
540
541
static int load_card_driver_options(sc_context_t *ctx,
542
    struct sc_card_driver *driver)
543
154k
{
544
154k
  scconf_block **blocks, *blk;
545
154k
  int i;
546
547
308k
  for (i = 0; ctx->conf_blocks[i]; i++) {
548
154k
    blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
549
154k
        "card_driver", driver->short_name);
550
154k
    if (!blocks)
551
0
      continue;
552
154k
    blk = blocks[0];
553
154k
    free(blocks);
554
555
154k
    if (blk == NULL)
556
154k
      continue;
557
558
    /* no options at the moment */
559
154k
  }
560
154k
  return SC_SUCCESS;
561
154k
}
562
563
static int load_card_drivers(sc_context_t *ctx, struct _sc_ctx_options *opts)
564
3.42k
{
565
3.42k
  const struct _sc_driver_entry *ent;
566
3.42k
  int drv_count;
567
3.42k
  int i;
568
569
3.42k
  for (drv_count = 0; ctx->card_drivers[drv_count] != NULL; drv_count++)
570
0
    ;
571
572
157k
  for (i = 0; i < opts->ccount; i++) {
573
154k
    struct sc_card_driver *(*func)(void) = NULL;
574
154k
    struct sc_card_driver *(**tfunc)(void) = &func;
575
154k
    void *dll = NULL;
576
154k
    int  j;
577
578
154k
    if (drv_count >= SC_MAX_CARD_DRIVERS - 1)   {
579
0
      sc_log(ctx, "Not more then %i card drivers allowed.", SC_MAX_CARD_DRIVERS);
580
0
      break;
581
0
    }
582
583
154k
    ent = &opts->cdrv[i];
584
3.51M
    for (j = 0; internal_card_drivers[j].name != NULL; j++) {
585
3.49M
      if (strcmp(ent->name, internal_card_drivers[j].name) == 0) {
586
137k
        func = (struct sc_card_driver *(*)(void)) internal_card_drivers[j].func;
587
137k
        break;
588
137k
      }
589
3.49M
    }
590
154k
    if (func == NULL) {
591
51.3k
      for (j = 0; old_card_drivers[j].name != NULL; j++) {
592
51.3k
        if (strcmp(ent->name, old_card_drivers[j].name) == 0) {
593
17.1k
          func = (struct sc_card_driver *(*)(void)) old_card_drivers[j].func;
594
17.1k
          break;
595
17.1k
        }
596
51.3k
      }
597
17.1k
    }
598
    /* if not initialized assume external module */
599
154k
    if (func == NULL)
600
0
      *(void **)(tfunc) = load_dynamic_driver(ctx, &dll, ent->name);
601
    /* if still null, assume driver not found */
602
154k
    if (func == NULL) {
603
0
      sc_log(ctx, "Unable to load '%s'.", ent->name);
604
0
      if (dll)
605
0
        sc_dlclose(dll);
606
0
      continue;
607
0
    }
608
609
154k
    ctx->card_drivers[drv_count] = func();
610
154k
    if (ctx->card_drivers[drv_count] == NULL) {
611
0
      sc_log(ctx, "Driver '%s' not available.", ent->name);
612
0
      continue;
613
0
    }
614
615
154k
    ctx->card_drivers[drv_count]->dll = dll;
616
154k
    ctx->card_drivers[drv_count]->atr_map = NULL;
617
154k
    ctx->card_drivers[drv_count]->natrs = 0;
618
619
154k
    load_card_driver_options(ctx, ctx->card_drivers[drv_count]);
620
621
    /* Ensure that the list is always terminated by NULL */
622
154k
    ctx->card_drivers[drv_count + 1] = NULL;
623
624
154k
    drv_count++;
625
154k
  }
626
3.42k
  return SC_SUCCESS;
627
3.42k
}
628
629
static int load_card_atrs(sc_context_t *ctx)
630
3.42k
{
631
3.42k
  struct sc_card_driver *driver;
632
3.42k
  scconf_block **blocks;
633
3.42k
  int i, j, k;
634
635
6.85k
  for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
636
3.42k
    blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "card_atr", NULL);
637
3.42k
    if (!blocks)
638
0
      continue;
639
3.42k
    for (j = 0; blocks[j] != NULL; j++) {
640
0
      scconf_block *b = blocks[j];
641
0
      char *atr = b->name->data;
642
0
      const scconf_list *list;
643
0
      struct sc_atr_table t;
644
0
      const char *dname;
645
646
0
      driver = NULL;
647
648
0
      if (strlen(atr) < 4)
649
0
        continue;
650
651
      /* The interesting part. If there's no card
652
       * driver assigned for the ATR, add it to
653
       * the default driver. This will reduce the
654
       * amount of code required to process things
655
       * related to card_atr blocks in situations,
656
       * where the code is not exactly related to
657
       * card driver settings, but for example
658
       * forcing a protocol at the reader driver.
659
       */
660
0
      dname = scconf_get_str(b, "driver", "default");
661
662
      /* Find the card driver structure according to dname */
663
0
      for (k = 0; ctx->card_drivers[k] != NULL; k++) {
664
0
        driver = ctx->card_drivers[k];
665
0
        if (!strcmp(dname, driver->short_name))
666
0
          break;
667
0
        driver = NULL;
668
0
      }
669
670
0
      if (!driver)
671
0
        continue;
672
673
0
      memset(&t, 0, sizeof(struct sc_atr_table));
674
0
      t.atr = atr;
675
0
      t.atrmask = (char *) scconf_get_str(b, "atrmask", NULL);
676
0
      t.name = (char *) scconf_get_str(b, "name", NULL);
677
0
      t.type = scconf_get_int(b, "type", SC_CARD_TYPE_UNKNOWN);
678
0
      list = scconf_find_list(b, "flags");
679
0
      while (list != NULL) {
680
0
        unsigned int flags = 0;
681
682
0
        if (!list->data) {
683
0
          list = list->next;
684
0
          continue;
685
0
        }
686
687
0
        if (!strcmp(list->data, "rng"))
688
0
          flags = SC_CARD_FLAG_RNG;
689
0
        else if (!strcmp(list->data, "keep_alive"))
690
0
          flags = SC_CARD_FLAG_KEEP_ALIVE;
691
0
        else if (sscanf(list->data, "%x", &flags) != 1)
692
0
          flags = 0;
693
694
0
        t.flags |= flags;
695
0
        list = list->next;
696
0
      }
697
0
      t.card_atr = b;
698
0
      _sc_add_atr(ctx, driver, &t);
699
0
    }
700
3.42k
    free(blocks);
701
3.42k
  }
702
3.42k
  return SC_SUCCESS;
703
3.42k
}
704
705
static void process_config_file(sc_context_t *ctx, struct _sc_ctx_options *opts)
706
3.42k
{
707
3.42k
  int i, r, count = 0;
708
3.42k
  scconf_block **blocks;
709
3.42k
  const char *conf_path = NULL;
710
3.42k
  const char *debug = NULL;
711
#ifdef _WIN32
712
  char temp_path[PATH_MAX];
713
  size_t temp_len;
714
#endif
715
716
  /* Takes effect even when no config around */
717
3.42k
  debug = getenv("OPENSC_DEBUG");
718
3.42k
  if (debug)
719
0
    ctx->debug = atoi(debug);
720
721
3.42k
  memset(ctx->conf_blocks, 0, sizeof(ctx->conf_blocks));
722
#ifdef _WIN32
723
  temp_len = PATH_MAX-1;
724
  r = sc_ctx_win32_get_config_value("OPENSC_CONF", "ConfigFile", "Software\\" OPENSC_VS_FF_COMPANY_NAME "\\OpenSC" OPENSC_ARCH_SUFFIX,
725
      temp_path, &temp_len);
726
  if (r)   {
727
    sc_log(ctx, "process_config_file doesn't find opensc config file. Please set the registry key.");
728
    return;
729
  }
730
  temp_path[temp_len] = '\0';
731
  conf_path = temp_path;
732
#else
733
3.42k
  conf_path = getenv("OPENSC_CONF");
734
3.42k
  if (!conf_path)
735
3.42k
    conf_path = OPENSC_CONF_PATH;
736
3.42k
#endif
737
3.42k
  ctx->conf = scconf_new(conf_path);
738
3.42k
  if (ctx->conf == NULL)
739
0
    return;
740
3.42k
  r = scconf_parse(ctx->conf);
741
3.42k
#define OPENSC_CONFIG_STRING "app default { card_drivers = old, internal; }"
742
3.42k
#ifdef OPENSC_CONFIG_STRING
743
  /* Parse the string if config file didn't exist */
744
3.42k
  if (r < 0)
745
3.42k
    r = scconf_parse_string(ctx->conf, OPENSC_CONFIG_STRING);
746
3.42k
#endif
747
3.42k
  if (r < 1) {
748
    /* A negative return value means the config file isn't
749
     * there, which is not an error. Nevertheless log this
750
     * fact. */
751
0
    if (r < 0)
752
0
      sc_log(ctx, "scconf_parse failed: %s", ctx->conf->errmsg);
753
0
    else
754
0
      sc_log(ctx, "scconf_parse failed: %s", ctx->conf->errmsg);
755
0
    scconf_free(ctx->conf);
756
0
    ctx->conf = NULL;
757
0
    return;
758
0
  }
759
  /* needs to be after the log file is known */
760
3.42k
  sc_log(ctx, "Used configuration file '%s'", conf_path);
761
3.42k
  blocks = scconf_find_blocks(ctx->conf, NULL, "app", ctx->exe_path);
762
3.42k
  if (blocks && blocks[0])
763
0
    ctx->conf_blocks[count++] = blocks[0];
764
3.42k
  free(blocks);
765
3.42k
  blocks = scconf_find_blocks(ctx->conf, NULL, "app", ctx->app_name);
766
3.42k
  if (blocks && blocks[0])
767
0
    ctx->conf_blocks[count++] = blocks[0];
768
3.42k
  free(blocks);
769
3.42k
  if (strcmp(ctx->app_name, "default") != 0) {
770
3.42k
    blocks = scconf_find_blocks(ctx->conf, NULL, "app", "default");
771
3.42k
    if (blocks && blocks[0])
772
3.42k
      ctx->conf_blocks[count] = blocks[0];
773
3.42k
    free(blocks);
774
3.42k
  }
775
  /* Above we add 3 blocks at most, but conf_blocks has 4 elements,
776
   * so at least one is NULL */
777
6.85k
  for (i = 0; ctx->conf_blocks[i]; i++)
778
3.42k
    load_parameters(ctx, ctx->conf_blocks[i], opts);
779
3.42k
}
780
781
int sc_ctx_detect_readers(sc_context_t *ctx)
782
3.42k
{
783
3.42k
  int r = 0;
784
3.42k
  const struct sc_reader_driver *drv = ctx->reader_driver;
785
786
3.42k
  sc_mutex_lock(ctx, ctx->mutex);
787
788
3.42k
  if (drv->ops->detect_readers != NULL)
789
0
    r = drv->ops->detect_readers(ctx);
790
791
3.42k
  sc_mutex_unlock(ctx, ctx->mutex);
792
793
3.42k
  return r;
794
3.42k
}
795
796
sc_reader_t *sc_ctx_get_reader(sc_context_t *ctx, unsigned int i)
797
3.42k
{
798
3.42k
  return list_get_at(&ctx->readers, i);
799
3.42k
}
800
801
sc_reader_t *sc_ctx_get_reader_by_id(sc_context_t *ctx, unsigned int id)
802
0
{
803
0
  return list_get_at(&ctx->readers, id);
804
0
}
805
806
sc_reader_t *sc_ctx_get_reader_by_name(sc_context_t *ctx, const char * name)
807
0
{
808
0
  return list_seek(&ctx->readers, name);
809
0
}
810
811
unsigned int sc_ctx_get_reader_count(sc_context_t *ctx)
812
0
{
813
0
  return list_size(&ctx->readers);
814
0
}
815
816
int sc_establish_context(sc_context_t **ctx_out, const char *app_name)
817
0
{
818
0
  sc_context_param_t ctx_param;
819
820
0
  memset(&ctx_param, 0, sizeof(sc_context_param_t));
821
0
  ctx_param.ver      = 0;
822
0
  ctx_param.app_name = app_name;
823
0
  return sc_context_create(ctx_out, &ctx_param);
824
0
}
825
826
/* For multithreaded issues */
827
int sc_context_repair(sc_context_t **ctx_out)
828
0
{
829
  /* Must already exist */
830
0
  if ((ctx_out == NULL) || (*ctx_out == NULL) ||
831
0
      ((*ctx_out)->app_name == NULL))
832
0
    return SC_ERROR_INVALID_ARGUMENTS;
833
834
  /* The only thing that should be shared across different contexts are the
835
   * card drivers - so rebuild the ATR's
836
   */
837
0
  load_card_atrs(*ctx_out);
838
839
  /* TODO: May need to re-open any card driver DLL's */
840
841
0
  return SC_SUCCESS;
842
0
}
843
844
#ifdef USE_OPENSSL3_LIBCTX
845
static int sc_openssl3_init(sc_context_t *ctx)
846
{
847
  ctx->ossl3ctx = calloc(1, sizeof(ossl3ctx_t));
848
  if (ctx->ossl3ctx == NULL) {
849
    return SC_ERROR_OUT_OF_MEMORY;
850
  }
851
852
  ctx->ossl3ctx->libctx = OSSL_LIB_CTX_new();
853
  if (ctx->ossl3ctx->libctx == NULL) {
854
    return SC_ERROR_INTERNAL;
855
  }
856
857
  if (ctx->openssl_config != NULL) {
858
    if (access(ctx->openssl_config, R_OK) != 0) {
859
      sc_log(ctx, "Warning: provided OpenSSL configuration file '%s' is not readable",
860
          ctx->openssl_config);
861
    } else {
862
      /*
863
       * Load OpenSC specific openssl config file to configure FIPS module
864
       * (or whatever else the user needs).
865
       * We assume that this config file will automatically activate the FIPS
866
       * and base providers so we don't need to explicitly load them here.
867
       */
868
      if (!OSSL_LIB_CTX_load_config(ctx->ossl3ctx->libctx, ctx->openssl_config)) {
869
        return SC_ERROR_INTERNAL;
870
      }
871
    }
872
  } else {
873
    /* We do not have configuration file specified: load the default
874
     * and legacy providers */
875
    const char *defprov_name = "default";
876
    if (FIPS_mode()) {
877
      defprov_name = "fips";
878
    }
879
    ctx->ossl3ctx->defprov = OSSL_PROVIDER_load(ctx->ossl3ctx->libctx, defprov_name);
880
    if (ctx->ossl3ctx->defprov == NULL) {
881
      OSSL_LIB_CTX_free(ctx->ossl3ctx->libctx);
882
      free(ctx->ossl3ctx);
883
      ctx->ossl3ctx = NULL;
884
      return SC_ERROR_INTERNAL;
885
    }
886
    /* yes, legacy -- smart cards depend on several legacy algorithms */
887
    ctx->ossl3ctx->legacyprov = OSSL_PROVIDER_load(ctx->ossl3ctx->libctx, "legacy");
888
    if (ctx->ossl3ctx->legacyprov == NULL) {
889
      sc_log(ctx, "Failed to load OpenSSL Legacy provider");
890
    }
891
  }
892
  return SC_SUCCESS;
893
}
894
895
static void sc_openssl3_deinit(sc_context_t *ctx)
896
{
897
  if (ctx->ossl3ctx == NULL)
898
    return;
899
  if (ctx->ossl3ctx->legacyprov)
900
    OSSL_PROVIDER_unload(ctx->ossl3ctx->legacyprov);
901
  if (ctx->ossl3ctx->defprov)
902
    OSSL_PROVIDER_unload(ctx->ossl3ctx->defprov);
903
  if (ctx->ossl3ctx->libctx)
904
    OSSL_LIB_CTX_free(ctx->ossl3ctx->libctx);
905
  free(ctx->ossl3ctx);
906
  ctx->ossl3ctx = NULL;
907
}
908
#endif
909
910
static char *get_exe_path()
911
3.42k
{
912
  /* Find the executable's path which runs this code.
913
   * See https://github.com/gpakosz/whereami/ for
914
   * potentially more platforms */
915
3.42k
  char exe_path[PATH_MAX] = "unknown executable path";
916
3.42k
  int path_found = 0;
917
918
#if   defined(_WIN32)
919
  if (0 < GetModuleFileNameA(NULL, exe_path, sizeof exe_path))
920
    path_found = 1;
921
#elif defined(__APPLE__)
922
  if (0 < proc_pidpath(getpid(), exe_path, sizeof exe_path))
923
    path_found = 1;
924
#elif defined(__linux__) || defined(__CYGWIN__)
925
3.42k
  if (NULL != realpath("/proc/self/exe", exe_path))
926
3.42k
    path_found = 1;
927
3.42k
#endif
928
929
#if defined(HAVE_GETPROGNAME)
930
  if (!path_found) {
931
    /* getprogname is unreliable and typically only returns the basename.
932
     * However, this should be enough for our purposes */
933
    const char *prog = getprogname();
934
    if (prog)
935
      strlcpy(exe_path, prog, sizeof exe_path);
936
  }
937
#else
938
  /* avoid warning "set but not used" */
939
3.42k
  (void) path_found;
940
3.42k
#endif
941
942
3.42k
  return strdup(exe_path);
943
3.42k
}
944
945
int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
946
3.42k
{
947
3.42k
  sc_context_t    *ctx;
948
3.42k
  struct _sc_ctx_options  opts;
949
3.42k
  int     r;
950
3.42k
  char      *driver;
951
952
3.42k
  if (ctx_out == NULL || parm == NULL)
953
0
    return SC_ERROR_INVALID_ARGUMENTS;
954
955
3.42k
  ctx = calloc(1, sizeof(sc_context_t));
956
3.42k
  if (ctx == NULL)
957
0
    return SC_ERROR_OUT_OF_MEMORY;
958
3.42k
  memset(&opts, 0, sizeof(opts));
959
960
  /* set the application name if set in the parameter options */
961
3.42k
  if (parm->app_name != NULL)
962
3.42k
    ctx->app_name = strdup(parm->app_name);
963
0
  else
964
0
    ctx->app_name = strdup("default");
965
3.42k
  if (ctx->app_name == NULL) {
966
0
    sc_release_context(ctx);
967
0
    return SC_ERROR_OUT_OF_MEMORY;
968
0
  }
969
970
3.42k
  ctx->exe_path = get_exe_path();
971
3.42k
  if (ctx->exe_path == NULL) {
972
0
    sc_release_context(ctx);
973
0
    return SC_ERROR_OUT_OF_MEMORY;
974
0
  }
975
976
3.42k
  ctx->flags = parm->flags;
977
3.42k
  set_defaults(ctx, &opts);
978
979
3.42k
  if (0 != list_init(&ctx->readers)) {
980
0
    del_drvs(&opts);
981
0
    sc_release_context(ctx);
982
0
    return SC_ERROR_OUT_OF_MEMORY;
983
0
  }
984
3.42k
  list_attributes_seeker(&ctx->readers, reader_list_seeker);
985
  /* set thread context and create mutex object (if specified) */
986
3.42k
  if (parm->thread_ctx != NULL)
987
0
    ctx->thread_ctx = parm->thread_ctx;
988
3.42k
  r = sc_mutex_create(ctx, &ctx->mutex);
989
3.42k
  if (r != SC_SUCCESS) {
990
0
    del_drvs(&opts);
991
0
    sc_release_context(ctx);
992
0
    return r;
993
0
  }
994
995
#if defined(ENABLE_OPENSSL) && defined(OPENSSL_SECURE_MALLOC_SIZE) && !defined(LIBRESSL_VERSION_NUMBER)
996
  if (!CRYPTO_secure_malloc_initialized()) {
997
    CRYPTO_secure_malloc_init(OPENSSL_SECURE_MALLOC_SIZE, OPENSSL_SECURE_MALLOC_SIZE/8);
998
  }
999
#endif
1000
1001
3.42k
  process_config_file(ctx, &opts);
1002
1003
  /* overwrite with caller's parameters if explicitly given */
1004
3.42k
  if (parm->debug) {
1005
111
    ctx->debug = parm->debug;
1006
111
  }
1007
3.42k
  if (parm->debug_file) {
1008
111
    if (ctx->debug_file && (ctx->debug_file != stderr && ctx->debug_file != stdout))
1009
0
      fclose(ctx->debug_file);
1010
111
    ctx->debug_file = parm->debug_file;
1011
111
  }
1012
1013
3.42k
  sc_log(ctx, "==================================="); /* first thing in the log */
1014
3.42k
  sc_log(ctx, "OpenSC version: %s", sc_get_version());
1015
3.42k
  sc_log(ctx, "Configured for %s (%s)", ctx->app_name, ctx->exe_path);
1016
1017
#ifdef USE_OPENSSL3_LIBCTX
1018
  r = sc_openssl3_init(ctx);
1019
  if (r != SC_SUCCESS) {
1020
    del_drvs(&opts);
1021
    sc_release_context(ctx);
1022
    return r;
1023
  }
1024
#endif
1025
1026
#ifdef ENABLE_PCSC
1027
  ctx->reader_driver = sc_get_pcsc_driver();
1028
#elif defined(ENABLE_CRYPTOTOKENKIT)
1029
  ctx->reader_driver = sc_get_cryptotokenkit_driver();
1030
#elif defined(ENABLE_CTAPI)
1031
  ctx->reader_driver = sc_get_ctapi_driver();
1032
#elif defined(ENABLE_OPENCT)
1033
  ctx->reader_driver = sc_get_openct_driver();
1034
#else
1035
  ctx->reader_driver = sc_get_empty_driver();
1036
#endif
1037
1038
3.42k
  r = ctx->reader_driver->ops->init(ctx);
1039
3.42k
  if (r != SC_SUCCESS)   {
1040
0
    del_drvs(&opts);
1041
0
    sc_release_context(ctx);
1042
0
    return r;
1043
0
  }
1044
1045
3.42k
  driver = getenv("OPENSC_DRIVER");
1046
3.42k
  if (driver) {
1047
0
    scconf_list *list = NULL;
1048
0
    scconf_list_add(&list, driver);
1049
0
    set_drivers(&opts, list);
1050
0
    scconf_list_destroy(list);
1051
0
  }
1052
1053
3.42k
  load_card_drivers(ctx, &opts);
1054
3.42k
  load_card_atrs(ctx);
1055
1056
3.42k
  del_drvs(&opts);
1057
3.42k
  sc_ctx_detect_readers(ctx);
1058
3.42k
  *ctx_out = ctx;
1059
1060
3.42k
  return SC_SUCCESS;
1061
3.42k
}
1062
1063
/* Used by minidriver to pass in provided handles to reader-pcsc */
1064
int sc_ctx_use_reader(sc_context_t *ctx, void *pcsc_context_handle, void *pcsc_card_handle)
1065
0
{
1066
0
  LOG_FUNC_CALLED(ctx);
1067
0
  if (ctx->reader_driver->ops->use_reader != NULL)
1068
0
    return ctx->reader_driver->ops->use_reader(ctx, pcsc_context_handle, pcsc_card_handle);
1069
1070
0
  return SC_ERROR_NOT_SUPPORTED;
1071
0
}
1072
1073
/* Following two are only implemented with internal PC/SC and don't consume a reader object */
1074
int sc_cancel(sc_context_t *ctx)
1075
0
{
1076
0
  LOG_FUNC_CALLED(ctx);
1077
0
  if (ctx->reader_driver->ops->cancel != NULL)
1078
0
    return ctx->reader_driver->ops->cancel(ctx);
1079
1080
0
  return SC_ERROR_NOT_SUPPORTED;
1081
0
}
1082
1083
1084
int sc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_reader_t **event_reader, unsigned int *event, int timeout, void **reader_states)
1085
0
{
1086
0
  LOG_FUNC_CALLED(ctx);
1087
0
  if (ctx->reader_driver->ops->wait_for_event != NULL)
1088
0
    return ctx->reader_driver->ops->wait_for_event(ctx, event_mask, event_reader, event, timeout, reader_states);
1089
1090
0
  return SC_ERROR_NOT_SUPPORTED;
1091
0
}
1092
1093
int sc_release_context(sc_context_t *ctx)
1094
3.42k
{
1095
3.42k
  unsigned int i;
1096
1097
3.42k
  if (ctx == NULL) {
1098
4
    return SC_ERROR_INVALID_ARGUMENTS;
1099
4
  }
1100
3.42k
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
1101
6.85k
  while (list_size(&ctx->readers)) {
1102
3.42k
    sc_reader_t *rdr = (sc_reader_t *) list_get_at(&ctx->readers, 0);
1103
3.42k
    _sc_delete_reader(ctx, rdr);
1104
3.42k
  }
1105
1106
3.42k
  if (ctx->reader_driver != NULL && ctx->reader_driver->ops->finish != NULL)
1107
0
    ctx->reader_driver->ops->finish(ctx);
1108
1109
157k
  for (i = 0; ctx->card_drivers[i]; i++) {
1110
154k
    struct sc_card_driver *drv = ctx->card_drivers[i];
1111
1112
154k
    if (drv->atr_map)
1113
0
      _sc_free_atr(ctx, drv);
1114
154k
    if (drv->dll)
1115
0
      sc_dlclose(drv->dll);
1116
154k
  }
1117
#ifdef USE_OPENSSL3_LIBCTX
1118
  sc_openssl3_deinit(ctx);
1119
#endif
1120
3.42k
  if (ctx->preferred_language != NULL)
1121
0
    free(ctx->preferred_language);
1122
3.42k
  if (ctx->mutex != NULL) {
1123
0
    int r = sc_mutex_destroy(ctx, ctx->mutex);
1124
0
    if (r != SC_SUCCESS) {
1125
0
      sc_log(ctx, "unable to destroy mutex");
1126
0
      return r;
1127
0
    }
1128
0
  }
1129
3.42k
  if (ctx->conf != NULL)
1130
3.42k
    scconf_free(ctx->conf);
1131
3.42k
  if (ctx->debug_file && (ctx->debug_file != stdout && ctx->debug_file != stderr))
1132
0
    fclose(ctx->debug_file);
1133
3.42k
  free(ctx->debug_filename);
1134
3.42k
  free(ctx->app_name);
1135
3.42k
  free(ctx->exe_path);
1136
3.42k
  list_destroy(&ctx->readers);
1137
3.42k
  sc_mem_clear(ctx, sizeof(*ctx));
1138
3.42k
  free(ctx);
1139
3.42k
  return SC_SUCCESS;
1140
3.42k
}
1141
1142
int sc_set_card_driver(sc_context_t *ctx, const char *short_name)
1143
3.42k
{
1144
3.42k
  int i = 0, match = 0;
1145
1146
3.42k
  sc_mutex_lock(ctx, ctx->mutex);
1147
3.42k
  if (short_name == NULL) {
1148
0
    ctx->forced_driver = NULL;
1149
0
    match = 1;
1150
116k
  } else while (i < SC_MAX_CARD_DRIVERS && ctx->card_drivers[i] != NULL) {
1151
116k
    struct sc_card_driver *drv = ctx->card_drivers[i];
1152
1153
116k
    if (strcmp(short_name, drv->short_name) == 0) {
1154
3.42k
      ctx->forced_driver = drv;
1155
3.42k
      match = 1;
1156
3.42k
      break;
1157
3.42k
    }
1158
113k
    i++;
1159
113k
  }
1160
3.42k
  sc_mutex_unlock(ctx, ctx->mutex);
1161
3.42k
  if (match == 0)
1162
0
    return SC_ERROR_OBJECT_NOT_FOUND; /* FIXME: invent error */
1163
3.42k
  return SC_SUCCESS;
1164
3.42k
}
1165
1166
int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize)
1167
1
{
1168
1
  char *homedir;
1169
1
  const char *cache_dir;
1170
1
        scconf_block *conf_block = NULL;
1171
#ifdef _WIN32
1172
  char temp_path[PATH_MAX];
1173
#endif
1174
1
  conf_block = sc_get_conf_block(ctx, "framework", "pkcs15", 1);
1175
1
  cache_dir = scconf_get_str(conf_block, "file_cache_dir", NULL);
1176
1
  if (cache_dir != NULL) {
1177
0
    strlcpy(buf, cache_dir, bufsize);
1178
0
    return SC_SUCCESS;
1179
0
  }
1180
1181
1
#ifndef _WIN32
1182
#ifdef __APPLE__
1183
  cache_dir = getenv("Caches");
1184
#else
1185
1
  cache_dir = getenv("XDG_CACHE_HOME");
1186
1
#endif
1187
1
  if (cache_dir != NULL && cache_dir[0] != '\0') {
1188
0
    snprintf(buf, bufsize, "%s/%s", cache_dir, "opensc");
1189
0
    return SC_SUCCESS;
1190
0
  }
1191
1
  cache_dir = ".cache/opensc";
1192
1
  homedir = getenv("HOME");
1193
#else
1194
  cache_dir = "eid-cache";
1195
  homedir = getenv("USERPROFILE");
1196
  /* If USERPROFILE isn't defined, assume it's a single-user OS
1197
   * and put the cache dir in the Windows dir (usually C:\\WINDOWS) */
1198
  if (homedir == NULL || homedir[0] == '\0') {
1199
    GetWindowsDirectoryA(temp_path, sizeof(temp_path));
1200
    homedir = temp_path;
1201
  }
1202
#endif
1203
1
  if (homedir == NULL || homedir[0] == '\0')
1204
0
    return SC_ERROR_INTERNAL;
1205
1
  if (snprintf(buf, bufsize, "%s/%s", homedir, cache_dir) < 0)
1206
0
    return SC_ERROR_BUFFER_TOO_SMALL;
1207
1
  return SC_SUCCESS;
1208
1
}
1209
1210
int sc_make_cache_dir(sc_context_t *ctx)
1211
0
{
1212
0
  char dirname[PATH_MAX], *sp;
1213
0
  int    r, mkdir_checker;
1214
0
  size_t j, namelen;
1215
1216
0
  if ((r = sc_get_cache_dir(ctx, dirname, sizeof(dirname))) < 0)
1217
0
    return r;
1218
0
  namelen = strlen(dirname);
1219
1220
0
  while (1) {
1221
#ifdef _WIN32
1222
    mkdir_checker = mkdir(dirname) >= 0;
1223
#else
1224
0
    mkdir_checker = mkdir(dirname, 0700) >= 0;
1225
0
#endif
1226
0
    if (mkdir_checker)
1227
0
      break;
1228
1229
0
    if (errno != ENOENT || (sp = strrchr(dirname, '/')) == NULL
1230
0
        || sp == dirname)
1231
0
      goto failed;
1232
0
    *sp = '\0';
1233
0
  }
1234
1235
  /* We may have stripped one or more path components from
1236
   * the directory name. Restore them */
1237
0
  while (1) {
1238
0
    j = strlen(dirname);
1239
0
    if (j >= namelen)
1240
0
      break;
1241
0
    dirname[j] = '/';
1242
#ifdef _WIN32
1243
    mkdir_checker = mkdir(dirname) < 0;
1244
#else
1245
0
    mkdir_checker = mkdir(dirname, 0700) < 0;
1246
0
#endif
1247
0
    if (mkdir_checker)
1248
0
      goto failed;
1249
0
  }
1250
0
  return SC_SUCCESS;
1251
1252
  /* for lack of a better return code */
1253
0
failed:
1254
0
  sc_log(ctx, "failed to create cache directory");
1255
0
  return SC_ERROR_INTERNAL;
1256
0
}