This enables a passthru mode in the spice client, where we relay apdus from the client to the host, rather than passing through nss and emulating a card.
Signed-off-by: Jeremy White <jwh...@codeweavers.com> --- Makefile.objs | 5 + configure | 38 +++ libcacard/capcsc.c | 612 +++++++++++++++++++++++++++++++++++++++++++ libcacard/capcsc.h | 16 ++ libcacard/libcacard.syms | 1 + libcacard/vcard.c | 2 +- libcacard/vcard.h | 2 +- libcacard/vcard_emul_nss.c | 28 +- libcacard/vcard_emul_type.c | 3 +- libcacard/vscclient.c | 16 +- 10 files changed, 706 insertions(+), 17 deletions(-) create mode 100644 libcacard/capcsc.c create mode 100644 libcacard/capcsc.h diff --git a/Makefile.objs b/Makefile.objs index abeb902..bb9659e 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -32,6 +32,11 @@ libcacard-y += libcacard/card_7816.o libcacard-y += libcacard/vcardt.o libcacard/vcard_emul_nss.o-cflags := $(NSS_CFLAGS) libcacard/vcard_emul_nss.o-libs := $(NSS_LIBS) +ifeq ($(CONFIG_SMARTCARD_PCSC),y) +libcacard-y += libcacard/capcsc.o +libcacard/capcsc.o-cflags := $(PCSC_CFLAGS) +libcacard/capcsc.o-libs := $(PCSC_LIBS) +endif ###################################################################### # Target independent part of system emulation. The long term path is to diff --git a/configure b/configure index cae588c..f1dd05c 100755 --- a/configure +++ b/configure @@ -307,6 +307,7 @@ trace_file="trace" spice="" rbd="" smartcard_nss="" +smartcard_pcsc="" libusb="" usb_redir="" glx="" @@ -1042,6 +1043,10 @@ for opt do ;; --enable-smartcard-nss) smartcard_nss="yes" ;; + --disable-smartcard-pcsc) smartcard_pcsc="no" + ;; + --enable-smartcard-pcsc) smartcard_pcsc="yes" + ;; --disable-libusb) libusb="no" ;; --enable-libusb) libusb="yes" @@ -1368,6 +1373,8 @@ Advanced options (experts only): --enable-libnfs enable nfs support --disable-smartcard-nss disable smartcard nss support --enable-smartcard-nss enable smartcard nss support + --disable-smartcard-pcsc disable smartcard pcsc passthru support + --enable-smartcard-pcsc enable smartcard pcsc passthru support --disable-libusb disable libusb (for usb passthrough) --enable-libusb enable libusb (for usb passthrough) --disable-usb-redir disable usb network redirection support @@ -3648,6 +3655,30 @@ EOF fi fi +# check for pcsclite for smartcard passthru support +if test "$smartcard_pcsc" != "no"; then + cat > $TMPC << EOF +#include <winscard.h> +int main(void) { SCardEstablishContext(0, 0, 0, 0); return 0; } +EOF + # FIXME: do not include $glib_* in here + pcsc_libs="$($pkg_config --libs libpcsclite 2>/dev/null) $glib_libs" + pcsc_cflags="$($pkg_config --cflags libpcsclite 2>/dev/null) $glib_cflags" + test_cflags="$pcsc_cflags" + if test "$werror" = "yes"; then + test_cflags="-Werror $test_cflags" + fi + if test -n "$libtool" && + compile_prog "$test_cflags" "$pcsc_libs"; then + smartcard_pcsc="yes" + else + if test "$smartcard_pcsc" = "yes"; then + feature_not_found "pcsc" "Install libpcsclite" + fi + smartcard_pcsc="no" + fi +fi + # check for libusb if test "$libusb" != "no" ; then if $pkg_config --atleast-version=1.0.13 libusb-1.0; then @@ -4318,6 +4349,7 @@ fi echo "rbd support $rbd" echo "xfsctl support $xfs" echo "nss used $smartcard_nss" +echo "pcsc used $smartcard_pcsc" echo "libusb $libusb" echo "usb net redir $usb_redir" echo "GLX support $glx" @@ -4674,6 +4706,12 @@ if test "$smartcard_nss" = "yes" ; then echo "NSS_CFLAGS=$nss_cflags" >> $config_host_mak fi +if test "$smartcard_pcsc" = "yes" ; then + echo "CONFIG_SMARTCARD_PCSC=y" >> $config_host_mak + echo "PCSC_LIBS=$pcsc_libs" >> $config_host_mak + echo "PCSC_CFLAGS=$pcsc_cflags" >> $config_host_mak +fi + if test "$libusb" = "yes" ; then echo "CONFIG_USB_LIBUSB=y" >> $config_host_mak fi diff --git a/libcacard/capcsc.c b/libcacard/capcsc.c new file mode 100644 index 0000000..c7da458 --- /dev/null +++ b/libcacard/capcsc.c @@ -0,0 +1,612 @@ +/* + * Supply a vreader using the PC/SC interface. + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + */ + +/* avoid including prototypes.h that causes some qemu type conflicts */ +#define NO_NSPR_10_SUPPORT +#include <prthread.h> + +#include "qemu-common.h" + +#include "vcard.h" +#include "card_7816.h" +#include "capcsc.h" +#include "vreader.h" +#include "vevent.h" + +#include <PCSC/wintypes.h> +#include <PCSC/winscard.h> + + +typedef struct _PCSCContext PCSCContext; + +typedef struct _APDUMsg { + void *data; + int len; + pid_t sender; + LONG rc; + struct _APDUMsg *next; +} APDUMsg; + +typedef struct +{ + PCSCContext *context; + int index; + char *name; + DWORD protocol; + DWORD state; + SCARDHANDLE card; + BYTE atr[MAX_ATR_SIZE]; + DWORD atrlen; + int card_connected; + CompatGMutex request_lock; + APDUMsg *requests; + unsigned long request_count; + CompatGMutex response_lock; + APDUMsg *responses; +} SCardReader; + +typedef struct _PCSCContext +{ + SCARDCONTEXT context; + SCardReader readers[CAPCSC_MAX_READERS]; + int reader_count; + int readers_changed; + PRThread *thread; + CompatGMutex lock; +} PCSCContext; + + +static void push_request(SCardReader *r, void *data, int len) +{ + APDUMsg *a = malloc(sizeof(*a)); + APDUMsg **p; + + a->data = malloc(len); + a->len = len; + a->sender = getpid(); + a->next = NULL; + memcpy(a->data, data, len); + + g_mutex_lock(&r->request_lock); + for (p = &r->requests; *p; p = &(*p)->next) + ; + *p = a; + r->request_count++; + + g_mutex_unlock(&r->request_lock); +} + +static APDUMsg * get_request(SCardReader *r) +{ + APDUMsg *p; + g_mutex_lock(&r->request_lock); + p = r->requests; + if (r->requests) + r->requests = p->next; + g_mutex_unlock(&r->request_lock); + return p; +} + +static void push_response(SCardReader *r, void *data, int len, LONG rc, pid_t sender) +{ + APDUMsg *a = malloc(sizeof(*a)); + APDUMsg **p; + + a->data = malloc(len); + a->len = len; + a->sender = sender; + a->next = NULL; + a->rc = rc; + memcpy(a->data, data, len); + + g_mutex_lock(&r->response_lock); + for (p = &r->responses; *p; p = &(*p)->next) + ; + *p = a; + + g_mutex_unlock(&r->response_lock); +} + +static APDUMsg * get_response(SCardReader *r) +{ + APDUMsg **p; + APDUMsg *ret = NULL; + g_mutex_lock(&r->response_lock); + for (p = &r->responses; *p && (*p)->sender != getpid(); p = &((*p)->next)) + ; + if (*p) + { + ret = *p; + *p = ret->next; + } + g_mutex_unlock(&r->response_lock); + return ret; +} + +static void free_msg(APDUMsg *m) +{ + free(m->data); + free(m); +} + + +static void delete_reader(PCSCContext *pc, int i) +{ + SCardReader *r = &pc->readers[i]; + g_mutex_clear(&r->request_lock); + g_mutex_clear(&r->response_lock); + free(r->name); + r->name = NULL; + + if (i < (pc->reader_count - 1)) + { + int rem = pc->reader_count - i - 1; + memmove(&pc->readers[i], &pc->readers[i + 1], sizeof(SCardReader) * rem); + } + + pc->reader_count--; +} + +static void delete_reader_cb(VReaderEmul *ve) +{ + SCardReader *r = (SCardReader *) ve; + + g_mutex_lock(&r->context->lock); + delete_reader(r->context, r->index); + g_mutex_unlock(&r->context->lock); +} + +static int new_reader(PCSCContext *pc, const char *name, DWORD state) +{ + SCardReader *r; + VReader *vreader; + + if (pc->reader_count >= CAPCSC_MAX_READERS - 1) + return 1; + + r = &pc->readers[pc->reader_count]; + memset(r, 0, sizeof(*r)); + r->index = pc->reader_count++; + r->context = pc; + r->name = strdup(name); + g_mutex_init(&r->request_lock); + g_mutex_init(&r->response_lock); + + vreader = vreader_new(name, (VReaderEmul *) r, delete_reader_cb); + vreader_add_reader(vreader); + vreader_free(vreader); + + return 0; +} + +static int find_reader(PCSCContext *pc, const char *name) +{ + int i; + for (i = 0; i < pc->reader_count; i++) + if (strcmp(pc->readers[i].name, name) == 0) + return i; + + return -1; +} + + +static int scan_for_readers(PCSCContext *pc) +{ + LONG rc; + + int i; + char buf[8192]; + DWORD buflen = sizeof(buf); + + char *p; + int matches[CAPCSC_MAX_READERS]; + + g_mutex_lock(&pc->lock); + + for (i = 0; i < CAPCSC_MAX_READERS; i++) + matches[i] = 0; + + pc->readers_changed = 1; + memset(buf, 0, sizeof(buf)); + rc = SCardListReaders(pc->context, NULL, buf, &buflen); + if (rc == SCARD_E_NO_READERS_AVAILABLE) + { + rc = 0; + goto exit; + } + + if (rc != SCARD_S_SUCCESS) + { + fprintf(stderr, "SCardListReaders failed: %s (0x%lX)\n", + pcsc_stringify_error(rc), rc); + goto exit; + } + + for (p = buf; p && p < buf + sizeof(buf); p += (strlen(p) + 1)) + { + if (strlen(p) > 0) + { + i = find_reader(pc, p); + if (i >= 0) + matches[i]++; + else + { + if (! new_reader(pc, p, SCARD_STATE_UNAWARE)) + matches[pc->reader_count - 1]++; + } + } + } + + rc = 0; + +exit: + i = pc->reader_count - 1; + g_mutex_unlock(&pc->lock); + + for (; i >= 0; i--) + if (! matches[i]) + { + VReader *reader = vreader_get_reader_by_name(pc->readers[i].name); + if (reader) + { + vreader_free(reader); + vreader_remove_reader(reader); + } + } + + + return rc; +} + +static int init_pcsc(PCSCContext *pc) +{ + LONG rc; + + memset(pc, 0, sizeof(*pc)); + + rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &pc->context); + if (rc != SCARD_S_SUCCESS) + { + fprintf(stderr, "SCardEstablishContext: Cannot Connect to Resource Manager %lX\n", rc); + return rc; + } + + return 0; +} + + +static void prepare_reader_states(PCSCContext *pc, SCARD_READERSTATE **states, DWORD *reader_count) +{ + SCARD_READERSTATE *state; + int i; + + if (*states) + free(*states); + + *reader_count = pc->reader_count; + + (*reader_count)++; + *states = malloc((*reader_count) * sizeof(**states)); + memset(*states, 0, sizeof((*reader_count) * sizeof(**states))); + + for (i = 0, state = *states; i < pc->reader_count; i++, state++) + { + state->szReader = pc->readers[i].name; + state->dwCurrentState = pc->readers[i].state; + } + + /* Leave a space to be notified of new readers */ + state->szReader = "\\\\?PnP?\\Notification"; + state->dwCurrentState = SCARD_STATE_UNAWARE; +} + +static int connect_card(SCardReader *r) +{ + LONG rc; + + r->protocol = -1; + rc = SCardConnect(r->context->context, r->name, SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, + &r->card, &r->protocol); + if (rc != SCARD_S_SUCCESS) + { + fprintf(stderr, "Failed to connect to a card reader: %s (0x%lX)\n", + pcsc_stringify_error(rc), rc); + return rc; + } + + r->card_connected = 1; + r->request_count = 0; + + return 0; +} + +static LONG send_receive(SCardReader *r, BYTE *transmit, DWORD transmit_len, + BYTE *receive, DWORD *receive_len) +{ + const SCARD_IO_REQUEST *send_header; + SCARD_IO_REQUEST receive_header; + LONG rc; + + if (! r->card_connected) + { + rc = connect_card(r); + if (rc) + return rc; + } + + if (r->protocol == SCARD_PROTOCOL_T0) + send_header = SCARD_PCI_T0; + else if (r->protocol == SCARD_PROTOCOL_T1) + send_header = SCARD_PCI_T1; + else + { + fprintf(stderr, "Unknown protocol %lX\n", r->protocol); + return 1; + } + + rc = SCardTransmit(r->card, send_header, transmit, transmit_len, + &receive_header, receive, receive_len); + if (rc != SCARD_S_SUCCESS) + { + fprintf(stderr, "Failed to transmit %ld bytes: %s (0x%lX)\n", + transmit_len, pcsc_stringify_error(rc), rc); + return rc; + } + + return 0; +} + + +static VCardStatus apdu_cb(VCard *card, VCardAPDU *apdu, VCardResponse **response) +{ + VCardStatus ret = VCARD_DONE; + SCardReader *r = (SCardReader *) vcard_get_private(card); + APDUMsg *resp; + + + push_request(r, apdu->a_data, apdu->a_len); + while (1) + { + resp = get_response(r); + if (resp) + break; + + usleep(1); + } + + if (resp->rc || resp->len < 2) + ret = VCARD_FAIL; + else + *response = vcard_response_new_bytes(card, resp->data, resp->len - 2, apdu->a_Le, + ((BYTE *)resp->data)[resp->len - 2], + ((BYTE *)resp->data)[resp->len - 1]); + + free_msg(resp); + + return ret; +} + +static VCardStatus reset_cb(VCard *card, int channel) +{ + SCardReader *r = (SCardReader *) vcard_get_private(card); + LONG rc; + unsigned long count; + + while (get_request(r) || get_response(r)) + ; + + /* vreader_power_on is a bit too free with it's resets. + And a reconnect is expensive; as much as 10-20 seconds. + Hence, we discard any initial reconnect request. */ + g_mutex_lock(&r->request_lock); + count = r->request_count++; + g_mutex_unlock(&r->request_lock); + if (count == 0) + return VCARD_DONE; + + rc = SCardReconnect(r->card, SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &r->protocol); + if (rc != SCARD_S_SUCCESS) + { + fprintf(stderr, "Failed to reconnect to a card reader: %s (0x%lX)\n", + pcsc_stringify_error(rc), rc); + return VCARD_FAIL; + } + return VCARD_DONE; +} + +static void get_atr_cb (VCard *card, unsigned char *atr, int *atr_len) +{ + SCardReader *r = (SCardReader *) vcard_get_private(card); + *atr_len = r->atrlen; + if (atr) + memcpy(atr, r->atr, r->atrlen); +} + +static void delete_card_cb (VCardEmul *ve) +{ + fprintf(stderr, "TODO, got a delete_card_cb\n"); +} + +static void insert_card(SCardReader *r, SCARD_READERSTATE *s) +{ + memcpy(r->atr, s->rgbAtr, MIN(sizeof(r->atr), sizeof(s->rgbAtr))); + r->atrlen = s->cbAtr; + + VReader *reader = vreader_get_reader_by_name(r->name); + if (! reader) + return; + + if (connect_card(r)) + return; + + VCardApplet * applet = vcard_new_applet(apdu_cb, reset_cb, (const unsigned char *) CAPCSC_APPLET, strlen(CAPCSC_APPLET)); + if (! applet) + return; + + VCard * card = vcard_new((VCardEmul *) r, delete_card_cb); + if (! card) + { + vcard_delete_applet(applet); + vreader_free(reader); + return; + } + + vcard_set_type(card, VCARD_DIRECT); + vcard_set_atr_func(card, get_atr_cb); + vcard_add_applet(card, applet); + + vreader_insert_card(reader, card); + vreader_free(reader); +} + +static void remove_card(SCardReader *r) +{ + LONG rc; + memset(r->atr, 0, sizeof(r->atr)); + r->atrlen = 0; + + rc = SCardDisconnect(r->card, SCARD_LEAVE_CARD); + if (rc != SCARD_S_SUCCESS) + fprintf(stderr, "Non fatal info: failed to disconnect card reader: %s (0x%lX)\n", + pcsc_stringify_error(rc), rc); + r->card_connected = 0; + + VReader *reader = vreader_get_reader_by_name(r->name); + if (! reader) + return; + + vreader_insert_card(reader, NULL); + vreader_free(reader); +} + +static void process_reader_change(SCardReader *r, SCARD_READERSTATE *s) +{ + if (s->dwEventState & SCARD_STATE_PRESENT) + insert_card(r, s); + else if (s->dwEventState & SCARD_STATE_EMPTY) + remove_card(r); + else + fprintf(stderr, "Unexpected card state change from %lx to %lx:\n", r->state, s->dwEventState); + + r->state = s->dwEventState & ~SCARD_STATE_CHANGED; +} + +static void process_requests(SCardReader *r) +{ + BYTE outbuf[4096]; + DWORD outlen = sizeof(outbuf); + LONG rc; + APDUMsg *request = get_request(r); + + if (request) + { + rc = send_receive(r, request->data, request->len, outbuf, &outlen); + push_response(r, outbuf, outlen, rc, request->sender); + free_msg(request); + } +} + +/* + * This thread looks for card and reader insertions and puts events on the + * event queue. PCSC is also not thread safe, so we relay requests for + * the smart card stack through here as well. + */ +static void event_thread(void *arg) +{ + PCSCContext *pc = (PCSCContext *) arg; + DWORD reader_count = 0; + SCARD_READERSTATE *reader_states = NULL; + LONG rc; + + scan_for_readers(pc); + + do { + int i; + DWORD timeout = INFINITE; + + g_mutex_lock(&pc->lock); + if (pc->readers_changed) + { + prepare_reader_states(pc, &reader_states, &reader_count); + timeout = 0; + } + else if (reader_count > 1) + timeout = CAPCSC_POLL_TIME; + + pc->readers_changed = 0; + g_mutex_unlock(&pc->lock); + + rc = SCardGetStatusChange(pc->context, timeout, reader_states, reader_count); + + /* If we have a new reader, or an unknown reader, rescan and go back and do it again */ + if ( (rc == SCARD_S_SUCCESS && (reader_states[reader_count - 1].dwEventState & SCARD_STATE_CHANGED)) || + rc == SCARD_E_UNKNOWN_READER ) + { + scan_for_readers(pc); + continue; + } + + if (rc == SCARD_E_TIMEOUT) + { + g_mutex_lock(&pc->lock); + /* TODO - get an EINTR to speed this up? */ + for (i = 0; i < reader_count - 1; i++) + process_requests(&pc->readers[i]); + g_mutex_unlock(&pc->lock); + + continue; + } + + if (rc != SCARD_S_SUCCESS) + { + fprintf(stderr, "Unexpected SCardGetStatusChange ret %lx(%s)\n", rc, pcsc_stringify_error(rc)); + continue; + } + + g_mutex_lock(&pc->lock); + for (i = 0; i < reader_count; i++) + { + if (reader_states[i].dwEventState & SCARD_STATE_CHANGED) + { + process_reader_change(&pc->readers[i], &reader_states[i]); + pc->readers_changed++; + } + + } + g_mutex_unlock(&pc->lock); + + } while (1); +} + +/* + * We poll the PC/SC interface, looking for device changes + */ +static int new_event_thread(PCSCContext *pc) +{ + pc->thread = PR_CreateThread(PR_SYSTEM_THREAD, event_thread, + pc, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, + PR_UNJOINABLE_THREAD, 0); + return pc->thread == NULL; +} + + +static PCSCContext context; + +int capcsc_init(void) +{ + g_mutex_init(&context.lock); + + if (init_pcsc(&context)) + return -1; + + if (new_event_thread(&context)) + return -1; + + return 0; +} diff --git a/libcacard/capcsc.h b/libcacard/capcsc.h new file mode 100644 index 0000000..4e292cf --- /dev/null +++ b/libcacard/capcsc.h @@ -0,0 +1,16 @@ +/* + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + */ +#ifndef CAPCSC_H +#define CAPCSC_H 1 + +#define CAPCSC_POLL_TIME 50 /* ms - Time we will poll for card change when a reader is connected */ +#define CAPCSC_MAX_READERS 16 /* Technically, -1, as we leave a space to find new readers */ + +#define CAPCSC_APPLET "CAPCSC APPLET" + +int capcsc_init(void); + + +#endif diff --git a/libcacard/libcacard.syms b/libcacard/libcacard.syms index 1697515..0e44dc0 100644 --- a/libcacard/libcacard.syms +++ b/libcacard/libcacard.syms @@ -1,5 +1,6 @@ cac_card_init cac_is_cac_card +capcsc_init vcard_add_applet vcard_apdu_delete vcard_apdu_new diff --git a/libcacard/vcard.c b/libcacard/vcard.c index d140a8e..4a1d91e 100644 --- a/libcacard/vcard.c +++ b/libcacard/vcard.c @@ -95,7 +95,7 @@ vcard_reset(VCard *card, VCardPower power) VCardApplet * vcard_new_applet(VCardProcessAPDU applet_process_function, VCardResetApplet applet_reset_function, - unsigned char *aid, int aid_len) + const unsigned char *aid, int aid_len) { VCardApplet *applet; diff --git a/libcacard/vcard.h b/libcacard/vcard.h index 47dc703..c16b944 100644 --- a/libcacard/vcard.h +++ b/libcacard/vcard.h @@ -30,7 +30,7 @@ void vcard_reset(VCard *card, VCardPower power); */ VCardApplet *vcard_new_applet(VCardProcessAPDU applet_process_function, VCardResetApplet applet_reset_function, - unsigned char *aid, int aid_len); + const unsigned char *aid, int aid_len); /* * destructor for a VCardApplet diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c index 950edee..18e6871 100644 --- a/libcacard/vcard_emul_nss.c +++ b/libcacard/vcard_emul_nss.c @@ -25,6 +25,7 @@ #include <prthread.h> #include <secerr.h> +#include "config-host.h" #include "qemu-common.h" #include "vcard.h" @@ -34,6 +35,9 @@ #include "vevent.h" #include "libcacard/vcardt_internal.h" +#if defined(CONFIG_SMARTCARD_PCSC) +#include "capcsc.h" +#endif typedef enum { @@ -892,6 +896,22 @@ vcard_emul_init(const VCardEmulOptions *options) options = &default_options; } +#if defined(CONFIG_SMARTCARD_PCSC) + if (options->use_hw && options->hw_card_type == VCARD_EMUL_PASSTHRU) { + if (options->vreader_count > 0) { + fprintf(stderr, "Error: you cannot use a soft card and a passthru card simultaneously.\n"); + return VCARD_EMUL_FAIL; + } + + if (capcsc_init()) { + fprintf(stderr, "Error initializing PCSC interface.\n"); + return VCARD_EMUL_FAIL; + } + + return VCARD_EMUL_OK; + } +#endif + /* first initialize NSS */ if (options->nss_db) { rv = NSS_Init(options->nss_db); @@ -1270,5 +1290,11 @@ vcard_emul_usage(void) "hw_type, and parameters of hw_param.\n" "\n" "If more one or more soft= parameters are specified, these readers will be\n" -"presented to the guest\n"); +"presented to the guest\n" +#if defined(CONFIG_SMARTCARD_PCSC) +"\n" +"If a hw_type of PASSTHRU is given, a connection will be made to the hardware\n" +"using libpcscslite. Note that in that case, no soft cards are permitted.\n" +#endif +); } diff --git a/libcacard/vcard_emul_type.c b/libcacard/vcard_emul_type.c index 59a1458..e8f6a4c 100644 --- a/libcacard/vcard_emul_type.c +++ b/libcacard/vcard_emul_type.c @@ -9,6 +9,7 @@ */ #include <strings.h> +#include "config-host.h" #include "vcardt.h" #include "vcard_emul_type.h" #include "cac.h" @@ -48,7 +49,7 @@ VCardEmulType vcard_emul_type_from_string(const char *type_string) if (strcasecmp(type_string, "CAC") == 0) { return VCARD_EMUL_CAC; } -#ifdef USE_PASSTHRU +#ifdef CONFIG_SMARTCARD_PCSC if (strcasecmp(type_string, "PASSTHRU") == 0) { return VCARD_EMUL_PASSTHRU; } diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c index fa6041d..8573f50 100644 --- a/libcacard/vscclient.c +++ b/libcacard/vscclient.c @@ -41,14 +41,8 @@ print_byte_array( static void print_usage(void) { - printf("vscclient [-c <certname> .. -e <emul_args> -d <level>%s] " - "<host> <port>\n", -#ifdef USE_PASSTHRU - " -p"); - printf(" -p use passthrough mode\n"); -#else - ""); -#endif + printf("vscclient [-c <certname> .. -e <emul_args> -d <level>] " + "<host> <port>\n"); vcard_emul_usage(); } @@ -673,7 +667,7 @@ main( } #endif - while ((c = getopt(argc, argv, "c:e:pd:")) != -1) { + while ((c = getopt(argc, argv, "c:e:d:")) != -1) { switch (c) { case 'c': if (cert_count >= MAX_CERTS) { @@ -685,10 +679,6 @@ main( case 'e': emul_args = optarg; break; - case 'p': - print_usage(); - exit(4); - break; case 'd': verbose = get_id_from_string(optarg, 1); break; -- 1.7.10.4