root/trunk/src/libopensc/ctx.c

Revision 3556, 23.6 kB (checked in by aj, 3 months ago)

Add new entersafe driver for ePass 3000 tokens.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#include "internal.h"
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <assert.h>
26#include <errno.h>
27#include <sys/stat.h>
28#include <limits.h>
29#include <ltdl.h>
30
31#ifdef _WIN32
32#include <winreg.h>
33#endif
34
35int _sc_add_reader(sc_context_t *ctx, sc_reader_t *reader)
36{
37        assert(reader != NULL);
38        reader->ctx = ctx;
39        if (ctx->reader_count == SC_MAX_READERS)
40                return SC_ERROR_TOO_MANY_OBJECTS;
41        ctx->reader[ctx->reader_count] = reader;
42        ctx->reader_count++;
43
44        return SC_SUCCESS;
45}
46
47struct _sc_driver_entry {
48        char *name;
49        void *(*func)(void);
50};
51
52static const struct _sc_driver_entry internal_card_drivers[] = {
53        /* legacy, the old name was "etoken", so we keep that for a while */
54        { "rutoken",    (void *(*)(void)) sc_get_rutoken_driver },
55        { "cardos",     (void *(*)(void)) sc_get_cardos_driver },
56        { "etoken",     (void *(*)(void)) sc_get_cardos_driver },
57        { "flex",       (void *(*)(void)) sc_get_cryptoflex_driver },
58        { "cyberflex",  (void *(*)(void)) sc_get_cyberflex_driver },
59#ifdef ENABLE_OPENSSL
60        { "gpk",        (void *(*)(void)) sc_get_gpk_driver },
61#endif
62        { "gemsafeV1",  (void *(*)(void)) sc_get_gemsafeV1_driver },
63        { "miocos",     (void *(*)(void)) sc_get_miocos_driver },
64        { "mcrd",       (void *(*)(void)) sc_get_mcrd_driver },
65        { "asepcos",    (void *(*)(void)) sc_get_asepcos_driver },
66        { "setcos",     (void *(*)(void)) sc_get_setcos_driver },
67        { "starcos",    (void *(*)(void)) sc_get_starcos_driver },
68        { "tcos",       (void *(*)(void)) sc_get_tcos_driver },
69        { "opengpg",    (void *(*)(void)) sc_get_openpgp_driver },
70        { "jcop",       (void *(*)(void)) sc_get_jcop_driver },
71#ifdef ENABLE_OPENSSL
72        { "oberthur",   (void *(*)(void)) sc_get_oberthur_driver },
73#endif
74        { "belpic",     (void *(*)(void)) sc_get_belpic_driver },
75        { "atrust-acos",(void *(*)(void)) sc_get_atrust_acos_driver },
76        { "muscle", (void *(*)(void)) sc_get_muscle_driver },   /* Above EMV because the detection gets caught there first */
77        { "emv",        (void *(*)(void)) sc_get_emv_driver },
78        { "incrypto34", (void *(*)(void)) sc_get_incrypto34_driver },
79#ifdef ENABLE_OPENSSL
80        { "PIV-II",     (void *(*)(void)) sc_get_piv_driver },
81#endif
82        { "acos5",      (void *(*)(void)) sc_get_acos5_driver },
83        { "akis",       (void *(*)(void)) sc_get_akis_driver },
84#ifdef ENABLE_OPENSSL
85        { "entersafe",(void *(*)(void)) sc_get_entersafe_driver },
86#endif
87        /* The default driver should be last, as it handles all the
88         * unrecognized cards. */
89        { "default",    (void *(*)(void)) sc_get_default_driver },
90        { NULL, NULL }
91};
92
93static const struct _sc_driver_entry internal_reader_drivers[] = {
94#if defined(ENABLE_PCSC)
95        { "pcsc",       (void *(*)(void)) sc_get_pcsc_driver },
96#endif
97        { "ctapi",      (void *(*)(void)) sc_get_ctapi_driver },
98#ifndef _WIN32
99#ifdef ENABLE_OPENCT
100        { "openct",     (void *(*)(void)) sc_get_openct_driver },
101#endif
102#endif
103        { NULL, NULL }
104};
105
106struct _sc_ctx_options {
107        struct _sc_driver_entry rdrv[SC_MAX_READER_DRIVERS];
108        int rcount;
109        struct _sc_driver_entry cdrv[SC_MAX_CARD_DRIVERS];
110        int ccount;
111        char *forced_card_driver;
112};
113
114static void del_drvs(struct _sc_ctx_options *opts, int type)
115{
116        struct _sc_driver_entry *lst;
117        int *cp, i;
118
119        if (type == 0) {
120                lst = opts->rdrv;
121                cp = &opts->rcount;
122        } else {
123                lst = opts->cdrv;
124                cp = &opts->ccount;
125        }
126        for (i = 0; i < *cp; i++) {
127                free(lst[i].name);
128        }
129        *cp = 0;
130}
131
132static void add_drv(struct _sc_ctx_options *opts, int type, const char *name)
133{
134        struct _sc_driver_entry *lst;
135        int *cp, max, i;
136
137        if (type == 0) {
138                lst = opts->rdrv;
139                cp = &opts->rcount;
140                max = SC_MAX_READER_DRIVERS;
141        } else {
142                lst = opts->cdrv;
143                cp = &opts->ccount;
144                max = SC_MAX_CARD_DRIVERS;
145        }
146        if (*cp == max) /* No space for more drivers... */
147                return;
148        for (i = 0; i < *cp; i++)
149                if (strcmp(name, lst[i].name) == 0)
150                        return;
151        lst[*cp].name = strdup(name);
152
153        *cp = *cp + 1;
154}
155
156static void add_internal_drvs(struct _sc_ctx_options *opts, int type)
157{
158        const struct _sc_driver_entry *lst;
159        int i;
160
161        if (type == 0)
162                lst = internal_reader_drivers;
163        else
164                lst = internal_card_drivers;
165        i = 0;
166        while (lst[i].name != NULL) {
167                add_drv(opts, type, lst[i].name);
168                i++;
169        }
170}
171
172static void set_defaults(sc_context_t *ctx, struct _sc_ctx_options *opts)
173{
174        ctx->debug = 0;
175        if (ctx->debug_file && ctx->debug_file != stdout)
176                fclose(ctx->debug_file);
177        ctx->debug_file = stdout;
178        ctx->suppress_errors = 0;
179        if (ctx->error_file && ctx->error_file != stderr)
180                fclose(ctx->error_file);
181        ctx->error_file = stderr;
182        ctx->forced_driver = NULL;
183        add_internal_drvs(opts, 0);
184        add_internal_drvs(opts, 1);
185}
186
187static int load_parameters(sc_context_t *ctx, scconf_block *block,
188                           struct _sc_ctx_options *opts)
189{
190        int err = 0;
191        const scconf_list *list;
192        const char *val, *s_internal = "internal";
193    const char *debug = NULL;
194
195        ctx->debug = scconf_get_int(block, "debug", ctx->debug);
196        debug = getenv("OPENSC_DEBUG");
197        if (debug)
198                ctx->debug = atoi(debug);
199
200        val = scconf_get_str(block, "debug_file", NULL);
201        if (val) {
202                if (ctx->debug_file && ctx->debug_file != stdout)
203                        fclose(ctx->debug_file);
204                if (strcmp(val, "stdout") != 0)
205                        ctx->debug_file = fopen(val, "a");
206                else
207                        ctx->debug_file = stdout;
208        }
209        val = scconf_get_str(block, "error_file", NULL);
210        if (val) {
211                if (ctx->error_file && ctx->error_file != stderr)
212                        fclose(ctx->error_file);
213                if (strcmp(val, "stderr") != 0)
214                        ctx->error_file = fopen(val, "a");
215                else
216                        ctx->error_file = stderr;
217        }
218        val = scconf_get_str(block, "force_card_driver", NULL);
219        if (val) {
220                if (opts->forced_card_driver)
221                        free(opts->forced_card_driver);
222                opts->forced_card_driver = strdup(val);
223        }
224        list = scconf_find_list(block, "reader_drivers");
225        if (list != NULL)
226                del_drvs(opts, 0);
227        while (list != NULL) {
228                if (strcmp(list->data, s_internal) == 0)
229                        add_internal_drvs(opts, 0);
230                else
231                        add_drv(opts, 0, list->data);
232                list = list->next;
233        }
234
235        list = scconf_find_list(block, "card_drivers");
236        if (list != NULL)
237                del_drvs(opts, 1);
238        while (list != NULL) {
239                if (strcmp(list->data, s_internal) == 0)
240                        add_internal_drvs(opts, 1);
241                else
242                        add_drv(opts, 1, list->data);
243                list = list->next;
244        }
245
246        val = scconf_get_str(block, "preferred_language", "en");
247        if (val)
248                sc_ui_set_language(ctx, val);
249
250        return err;
251}
252
253static void load_reader_driver_options(sc_context_t *ctx,
254                        struct sc_reader_driver *driver)
255{
256        const char      *name = driver->short_name;
257        scconf_block    *conf_block = NULL;
258        int             i;
259
260        for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
261                scconf_block **blocks;
262
263                blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
264                                            "reader_driver", name);
265                if (blocks) {
266                        conf_block = blocks[0];
267                        free(blocks);
268                }
269                if (conf_block != NULL)
270                        break;
271        }
272
273        driver->max_send_size = SC_DEFAULT_MAX_SEND_SIZE;
274        driver->max_recv_size = SC_DEFAULT_MAX_RECV_SIZE;
275        if (conf_block != NULL) {
276                driver->max_send_size = scconf_get_int(conf_block,
277                        "max_send_size", SC_DEFAULT_MAX_SEND_SIZE);
278                driver->max_recv_size = scconf_get_int(conf_block,
279                        "max_recv_size", SC_DEFAULT_MAX_RECV_SIZE);
280        }
281}
282
283/**
284 * find library module for provided driver in configuration file
285 * if not found assume library name equals to module name
286 */
287static const char *find_library(sc_context_t *ctx, const char *name, int type)
288{
289        int          i;
290        const char   *libname = NULL;
291        scconf_block **blocks, *blk;
292
293        for (i = 0; ctx->conf_blocks[i]; i++) {
294                blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
295                        (type==0) ? "reader_driver" : "card_driver", name);
296                if (!blocks)
297                        continue;
298                blk = blocks[0];
299                free(blocks);
300                if (blk == NULL)
301                        continue;
302                libname = scconf_get_str(blk, "module", name);
303#ifdef _WIN32
304                if (libname && libname[0] != '\\' ) {
305#else
306                if (libname && libname[0] != '/' ) {
307#endif
308                        sc_debug(ctx, "warning: relative path to driver '%s' used\n",
309                                 libname);
310                }
311                break;
312        }
313
314        return libname;
315}
316
317/**
318 * load card/reader driver modules
319 * Every module should contain a function " void * sc_module_init(char *) "
320 * that returns a pointer to the function _sc_get_xxxx_driver()
321 * used to initialize static modules
322 * Also, an exported "char *sc_module_version" variable should exist in module
323 *
324 * type == 0 -> reader driver
325 * type == 1 -> card driver
326 */
327static void *load_dynamic_driver(sc_context_t *ctx, void **dll,
328        const char *name, int type)
329{
330        const char *version, *libname;
331        lt_dlhandle handle;
332        void *(*modinit)(const char *) = NULL;
333        void *(**tmodi)(const char *) = &modinit;
334        const char *(*modversion)(void) = NULL;
335        const char *(**tmodv)(void) = &modversion;
336
337        if (name == NULL) { /* should not occurr, but... */
338                sc_error(ctx,"No module specified\n",name);
339                return NULL;
340        }
341        libname = find_library(ctx, name, type);
342        if (libname == NULL)
343                return NULL;
344        handle = lt_dlopen(libname);
345        if (handle == NULL) {
346                sc_error(ctx, "Module %s: cannot load %s library: %s\n", name, libname, lt_dlerror());
347                return NULL;
348        }
349
350        /* verify correctness of module */
351        *(void **)tmodi = lt_dlsym(handle, "sc_module_init");
352        *(void **)tmodv = lt_dlsym(handle, "sc_driver_version");
353        if (modinit == NULL || modversion == NULL) {
354                sc_error(ctx, "dynamic library '%s' is not a OpenSC module\n",libname);
355                lt_dlclose(handle);
356                return NULL;
357        }
358        /* verify module version */
359        version = modversion();
360        /* XXX: We really need to have ABI version for each interface */
361        if (version == NULL || strncmp(version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)) != 0) {
362                sc_error(ctx,"dynamic library '%s': invalid module version\n",libname);
363                lt_dlclose(handle);
364                return NULL;
365        }
366        *dll = handle;
367        sc_debug(ctx, "successfully loaded %s driver '%s'\n",
368                type ? "card" : "reader", name);
369        return modinit(name);
370}
371
372static int load_reader_drivers(sc_context_t *ctx,
373                               struct _sc_ctx_options *opts)
374{
375        const struct _sc_driver_entry *ent;
376        int drv_count;
377        int i;
378
379        for (drv_count = 0; ctx->reader_drivers[drv_count] != NULL; drv_count++);
380
381        for (i = 0; i < opts->rcount; i++) {
382                struct sc_reader_driver *driver;
383                struct sc_reader_driver *(*func)(void) = NULL;
384                struct sc_reader_driver *(**tfunc)(void) = &func;
385                int  j;
386                void *dll = NULL;
387
388                ent = &opts->rdrv[i];
389                for (j = 0; internal_reader_drivers[j].name != NULL; j++)
390                        if (strcmp(ent->name, internal_reader_drivers[j].name) == 0) {
391                                func = (struct sc_reader_driver *(*)(void)) internal_reader_drivers[j].func;
392                                break;
393                        }
394                /* if not initialized assume external module */
395                if (func == NULL)
396                        *(void**)(tfunc) = load_dynamic_driver(ctx, &dll, ent->name, 0);
397                /* if still null, assume driver not found */
398                if (func == NULL) {
399                        sc_error(ctx, "Unable to load '%s'.\n", ent->name);
400                        continue;
401                }
402                driver = func();
403                driver->dll = dll;
404                load_reader_driver_options(ctx, driver);
405                driver->ops->init(ctx, &ctx->reader_drv_data[i]);
406
407                ctx->reader_drivers[drv_count] = driver;
408                drv_count++;
409        }
410        return SC_SUCCESS;
411}
412
413static int load_card_driver_options(sc_context_t *ctx,
414                                    struct sc_card_driver *driver)
415{
416        scconf_block **blocks, *blk;
417        int i;
418
419        for (i = 0; ctx->conf_blocks[i]; i++) {
420                blocks = scconf_find_blocks(ctx->conf,
421                                        ctx->conf_blocks[i],
422                                        "card_driver", driver->short_name);
423                if (!blocks)
424                        continue;
425                blk = blocks[0];
426                free(blocks);
427
428                if (blk == NULL)
429                        continue;
430
431                /* no options at the moment */
432        }
433        return SC_SUCCESS;
434}
435
436static int load_card_drivers(sc_context_t *ctx,
437                             struct _sc_ctx_options *opts)
438{
439        const struct _sc_driver_entry *ent;
440        int drv_count;
441        int i;
442
443        for (drv_count = 0; ctx->card_drivers[drv_count] != NULL; drv_count++);
444
445        for (i = 0; i < opts->ccount; i++) {
446                struct sc_card_driver *(*func)(void) = NULL;
447                struct sc_card_driver *(**tfunc)(void) = &func;
448                void *dll = NULL;
449                int  j;
450
451                ent = &opts->cdrv[i];
452                for (j = 0; internal_card_drivers[j].name != NULL; j++)
453                        if (strcmp(ent->name, internal_card_drivers[j].name) == 0) {
454                                func = (struct sc_card_driver *(*)(void)) internal_card_drivers[j].func;
455                                break;
456                        }
457                /* if not initialized assume external module */
458                if (func == NULL)
459                        *(void **)(tfunc) = load_dynamic_driver(ctx, &dll, ent->name, 1);
460                /* if still null, assume driver not found */
461                if (func == NULL) {
462                        sc_error(ctx, "Unable to load '%s'.\n", ent->name);
463                        continue;
464                }
465
466                ctx->card_drivers[drv_count] = func();
467                ctx->card_drivers[drv_count]->dll = dll;
468
469                ctx->card_drivers[drv_count]->atr_map = NULL;
470                ctx->card_drivers[drv_count]->natrs = 0;
471
472                load_card_driver_options(ctx, ctx->card_drivers[drv_count]);
473                drv_count++;
474        }
475        return SC_SUCCESS;
476}
477
478static int load_card_atrs(sc_context_t *ctx,
479                          struct _sc_ctx_options *opts)
480{
481        struct sc_card_driver *driver;
482        scconf_block **blocks;
483        int i, j, k;
484
485        for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
486                blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "card_atr", NULL);
487                if (!blocks)
488                        continue;
489                for (j = 0; blocks[j] != NULL; j++) {
490                        scconf_block *b = blocks[j];
491                        char *atr = b->name->data;
492                        const scconf_list *list;
493                        struct sc_atr_table t;
494                        const char *dname;
495
496                        driver = NULL;
497
498                        if (strlen(atr) < 4)
499                                continue;
500
501                        /* The interesting part. If there's no card
502                         * driver assigned for the ATR, add it to
503                         * the default driver. This will reduce the
504                         * amount of code required to process things
505                         * related to card_atr blocks in situations,
506                         * where the code is not exactly related to
507                         * card driver settings, but for example
508                         * forcing a protocol at the reader driver.
509                         */
510                        dname = scconf_get_str(b, "driver", "default");
511
512                        /* Find the card driver structure according to dname */
513                        for (k = 0; ctx->card_drivers[k] != NULL; k++) {
514                                driver = ctx->card_drivers[k];
515                                if (!strcmp(dname, driver->short_name))
516                                        break;
517                                driver = NULL;
518                        }
519
520                        if (!driver)
521                                continue;
522
523                        memset(&t, 0, sizeof(struct sc_atr_table));
524                        t.atr = atr;
525                        t.atrmask = (char *) scconf_get_str(b, "atrmask", NULL);
526                        t.name = (char *) scconf_get_str(b, "name", NULL);
527                        t.type = scconf_get_int(b, "type", -1);
528                        list = scconf_find_list(b, "flags");
529                        while (list != NULL) {
530                                unsigned int flags;
531
532                                if (!list->data) {
533                                        list = list->next;
534                                        continue;
535                                }
536                                flags = 0;
537                                if (!strcmp(list->data, "keygen")) {
538                                        flags = SC_CARD_FLAG_ONBOARD_KEY_GEN;
539                                } else if (!strcmp(list->data, "rng")) {
540                                        flags = SC_CARD_FLAG_RNG;
541                                } else {
542                                        if (sscanf(list->data, "%x", &flags) != 1)
543                                                flags = 0;
544                                }
545                                t.flags |= flags;
546                                list = list->next;
547                        }
548                        t.card_atr = b;
549                        _sc_add_atr(ctx, driver, &t);
550                }
551                free(blocks);
552        }
553        return SC_SUCCESS;
554}
555
556static void process_config_file(sc_context_t *ctx, struct _sc_ctx_options *opts)
557{
558        int i, r, count = 0;
559        scconf_block **blocks;
560        const char *conf_path = NULL;
561#ifdef _WIN32
562        char temp_path[PATH_MAX];
563        DWORD temp_len;
564        long rc;
565        HKEY hKey;
566#endif
567
568        memset(ctx->conf_blocks, 0, sizeof(ctx->conf_blocks));
569#ifdef _WIN32
570        conf_path = getenv("OPENSC_CONF");
571        if (!conf_path) {
572                rc = RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\OpenSC",
573                        0, KEY_QUERY_VALUE, &hKey );
574                if( rc == ERROR_SUCCESS ) {
575                        temp_len = PATH_MAX;
576                        rc = RegQueryValueEx( hKey, "ConfigFile", NULL, NULL,
577                                (LPBYTE) temp_path, &temp_len);
578                        if( (rc == ERROR_SUCCESS) && (temp_len < PATH_MAX) )
579                                conf_path = temp_path;
580                        RegCloseKey( hKey );
581                }
582        }
583
584        if (! conf_path) {
585                rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\OpenSC",
586                        0, KEY_QUERY_VALUE, &hKey );
587                if( rc == ERROR_SUCCESS ) {
588                        temp_len = PATH_MAX;
589                        rc = RegQueryValueEx( hKey, "ConfigFile", NULL, NULL,
590                                (LPBYTE) temp_path, &temp_len);
591                        if( (rc == ERROR_SUCCESS) && (temp_len < PATH_MAX) )
592                                conf_path = temp_path;
593                        RegCloseKey( hKey );
594                }
595        }
596
597        if (! conf_path) {
598                sc_debug(ctx, "process_config_file doesn't find opensc config file. Please set the registry key.");
599                return;
600        }
601
602#else
603        conf_path = getenv("OPENSC_CONF");
604        if (!conf_path)
605                conf_path = OPENSC_CONF_PATH;
606#endif
607        ctx->conf = scconf_new(conf_path);
608        if (ctx->conf == NULL)
609                return;
610        r = scconf_parse(ctx->conf);
611#ifdef OPENSC_CONFIG_STRING
612        /* Parse the string if config file didn't exist */
613        if (r < 0)
614                r = scconf_parse_string(ctx->conf, OPENSC_CONFIG_STRING);
615#endif
616        if (r < 1) {
617                /* A negative return value means the config file isn't
618                 * there, which is not an error. Nevertheless log this
619                 * fact. */
620                if (r < 0)
621                        sc_debug(ctx, "scconf_parse failed: %s", ctx->conf->errmsg);
622                else
623                        sc_error(ctx, "scconf_parse failed: %s", ctx->conf->errmsg);
624                scconf_free(ctx->conf);
625                ctx->conf = NULL;
626                return;
627        }
628        blocks = scconf_find_blocks(ctx->conf, NULL, "app", ctx->app_name);
629        if (blocks[0])
630                ctx->conf_blocks[count++] = blocks[0];
631        free(blocks);
632        if (strcmp(ctx->app_name, "default") != 0) {
633                blocks = scconf_find_blocks(ctx->conf, NULL, "app", "default");
634                if (blocks[0])
635                        ctx->conf_blocks[count++] = blocks[0];
636                free(blocks);
637        }
638        /* Above we add 2 blocks at most, but conf_blocks has 3 elements,
639         * so at least one is NULL */
640        for (i = 0; ctx->conf_blocks[i]; i++)
641                load_parameters(ctx, ctx->conf_blocks[i], opts);
642}
643
644int sc_ctx_detect_readers(sc_context_t *ctx)
645{
646        int i;
647
648        sc_mutex_lock(ctx, ctx->mutex);
649
650        for (i = 0; ctx->reader_drivers[i] != NULL; i++) {
651                const struct sc_reader_driver *drv = ctx->reader_drivers[i];
652
653                if (drv->ops->detect_readers != NULL)
654                        drv->ops->detect_readers(ctx, ctx->reader_drv_data[i]);
655        }
656
657        sc_mutex_unlock(ctx, ctx->mutex);
658
659        /* XXX: Do not ignore erros? */
660        return SC_SUCCESS;
661}
662
663sc_reader_t *sc_ctx_get_reader(sc_context_t *ctx, unsigned int i)
664{
665        if (i >= (unsigned int)ctx->reader_count || i >= SC_MAX_READERS)
666                return NULL;
667        return ctx->reader[i];
668}
669
670unsigned int sc_ctx_get_reader_count(sc_context_t *ctx)
671{
672        return (unsigned int)ctx->reader_count;
673}
674
675void sc_ctx_suppress_errors_on(sc_context_t *ctx)
676{
677        ctx->suppress_errors++;
678}
679
680void sc_ctx_suppress_errors_off(sc_context_t *ctx)
681{
682        ctx->suppress_errors--;
683}
684
685int sc_establish_context(sc_context_t **ctx_out, const char *app_name)
686{
687        sc_context_param_t ctx_param;
688
689        memset(&ctx_param, 0, sizeof(sc_context_param_t));
690        ctx_param.ver      = 0;
691        ctx_param.app_name = app_name;
692        return sc_context_create(ctx_out, &ctx_param);
693}
694
695int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
696{
697        sc_context_t            *ctx;
698        struct _sc_ctx_options  opts;
699        int                     r;
700
701        if (ctx_out == NULL)
702                return SC_ERROR_INVALID_ARGUMENTS;
703
704        ctx = calloc(1, sizeof(sc_context_t));
705        if (ctx == NULL)
706                return SC_ERROR_OUT_OF_MEMORY;
707        memset(&opts, 0, sizeof(opts));
708        set_defaults(ctx, &opts);
709
710        /* set the application name if set in the parameter options */
711        if (parm != NULL && parm->app_name != NULL)
712                ctx->app_name = strdup(parm->app_name);
713        else
714                ctx->app_name = strdup("default");
715        if (ctx->app_name == NULL) {
716                sc_release_context(ctx);
717                return SC_ERROR_OUT_OF_MEMORY;
718        }
719
720        /* set thread context and create mutex object (if specified) */
721        if (parm != NULL && parm->thread_ctx != NULL)
722                ctx->thread_ctx = parm->thread_ctx;
723        r = sc_mutex_create(ctx, &ctx->mutex);
724        if (r != SC_SUCCESS) {
725                sc_release_context(ctx);
726                return r;
727        }
728
729        process_config_file(ctx, &opts);
730        sc_debug(ctx, "===================================\n"); /* first thing in the log */
731        sc_debug(ctx, "opensc version: %s\n", sc_get_version());
732
733        /* initialize ltdl */
734        if (lt_dlinit() != 0) {
735                sc_debug(ctx, "lt_dlinit failed\n");
736                sc_release_context(ctx);
737                return SC_ERROR_OUT_OF_MEMORY;
738        }
739
740        load_reader_drivers(ctx, &opts);
741        load_card_drivers(ctx, &opts);
742        load_card_atrs(ctx, &opts);
743        if (opts.forced_card_driver) {
744                /* FIXME: check return value? */
745                sc_set_card_driver(ctx, opts.forced_card_driver);
746                free(opts.forced_card_driver);
747        }
748        del_drvs(&opts, 0);
749        del_drvs(&opts, 1);
750        sc_ctx_detect_readers(ctx);
751        *ctx_out = ctx;
752        return SC_SUCCESS;
753}
754
755int sc_release_context(sc_context_t *ctx)
756{
757        int i;
758
759        assert(ctx != NULL);
760        SC_FUNC_CALLED(ctx, 1);
761        for (i = 0; i < ctx->reader_count; i++) {
762                sc_reader_t *rdr = ctx->reader[i];
763
764                if (rdr->ops->release != NULL)
765                        rdr->ops->release(rdr);
766                free(rdr->name);
767                free(rdr);
768        }
769        for (i = 0; ctx->reader_drivers[i] != NULL; i++) {
770                const struct sc_reader_driver *drv = ctx->reader_drivers[i];
771
772                if (drv->ops->finish != NULL)
773                        drv->ops->finish(ctx, ctx->reader_drv_data[i]);
774                if (drv->dll)
775                        lt_dlclose(drv->dll);
776        }
777        for (i = 0; ctx->card_drivers[i]; i++) {
778                struct sc_card_driver *drv = ctx->card_drivers[i];
779
780                if (drv->atr_map)
781                        _sc_free_atr(ctx, drv);
782                if (drv->dll)
783                        lt_dlclose(drv->dll);
784        }
785        if (ctx->preferred_language != NULL)
786                free(ctx->preferred_language);
787        if (ctx->mutex != NULL) {
788                int r = sc_mutex_destroy(ctx, ctx->mutex);
789                if (r != SC_SUCCESS) {
790                        sc_error(ctx, "unable to destroy mutex\n");
791                        return r;
792                }
793        }
794        if (ctx->conf != NULL)
795                scconf_free(ctx->conf);
796        if (ctx->debug_file && ctx->debug_file != stdout)
797                fclose(ctx->debug_file);
798        if (ctx->error_file && ctx->error_file != stderr)
799                fclose(ctx->error_file);
800        if (ctx->app_name != NULL)
801                free(ctx->app_name);
802        sc_mem_clear(ctx, sizeof(*ctx));
803        free(ctx);
804        return SC_SUCCESS;
805}
806
807int sc_set_card_driver(sc_context_t *ctx, const char *short_name)
808{
809        int i = 0, match = 0;
810
811        sc_mutex_lock(ctx, ctx->mutex);
812        if (short_name == NULL) {
813                ctx->forced_driver = NULL;
814                match = 1;
815        } else while (ctx->card_drivers[i] != NULL && i < SC_MAX_CARD_DRIVERS) {
816                struct sc_card_driver *drv = ctx->card_drivers[i];
817
818                if (strcmp(short_name, drv->short_name) == 0) {
819                        ctx->forced_driver = drv;
820                        match = 1;
821                        break;
822                }
823                i++;
824        }
825        sc_mutex_unlock(ctx, ctx->mutex);
826        if (match == 0)
827                return SC_ERROR_OBJECT_NOT_FOUND; /* FIXME: invent error */
828        return SC_SUCCESS;
829}
830
831int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize)
832{
833        char *homedir;
834        const char *cache_dir;
835#ifdef _WIN32
836        char temp_path[PATH_MAX];
837#endif
838
839#ifndef _WIN32
840        cache_dir = ".eid/cache";
841        homedir = getenv("HOME");
842#else
843        cache_dir = "eid-cache";
844        homedir = getenv("USERPROFILE");
845        /* If USERPROFILE isn't defined, assume it's a single-user OS
846         * and put the cache dir in the Windows dir (usually C:\\WINDOWS) */
847        if (homedir == NULL || homedir[0] == '\0') {
848                GetWindowsDirectory(temp_path, sizeof(temp_path));
849                homedir = temp_path;
850        }
851#endif
852        if (homedir == NULL)
853                return SC_ERROR_INTERNAL;
854        if (snprintf(buf, bufsize, "%s/%s", homedir, cache_dir) < 0)
855                return SC_ERROR_BUFFER_TOO_SMALL;
856        return SC_SUCCESS;
857}
858
859int sc_make_cache_dir(sc_context_t *ctx)
860{
861        char dirname[PATH_MAX], *sp;
862        int    r;
863        size_t j, namelen;
864
865        if ((r = sc_get_cache_dir(ctx, dirname, sizeof(dirname))) < 0)
866                return r;
867        namelen = strlen(dirname);
868
869        while (1) {
870#ifdef _WIN32
871                if (mkdir(dirname) >= 0)
872#else
873                if (mkdir(dirname, 0700) >= 0)
874#endif
875                        break;
876                if (errno != ENOENT
877                 || (sp = strrchr(dirname, '/')) == NULL
878                 || sp == dirname)
879                        goto failed;
880                *sp = '\0';
881        }
882
883        /* We may have stripped one or more path components from
884         * the directory name. Restore them */
885        while (1) {
886                j = strlen(dirname);
887                if (j >= namelen)
888                        break;
889                dirname[j] = '/';
890#ifdef _WIN32
891                if (mkdir(dirname) < 0)
892#else
893                if (mkdir(dirname, 0700) < 0)
894#endif
895                        goto failed;
896        }
897        return SC_SUCCESS;
898
899        /* for lack of a better return code */
900failed: sc_error(ctx, "failed to create cache directory\n");
901        return SC_ERROR_INTERNAL;
902}
Note: See TracBrowser for help on using the browser.