diff --git a/virtualsmartcard/configure.ac b/virtualsmartcard/configure.ac index 7786a47..d098a47 100644 --- a/virtualsmartcard/configure.ac +++ b/virtualsmartcard/configure.ac @@ -43,54 +43,83 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) # Checks for libraries. -PKG_CHECK_EXISTS([libpcsclite], - [PKG_CHECK_MODULES([PCSC], [libpcsclite])], - [AC_MSG_WARN([libpcsclite not found by pkg-config])]) -saved_CPPFLAGS="$CPPFLAGS" -CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS" -AC_CHECK_HEADERS(ifdhandler.h,, - [ AC_MSG_ERROR([ifdhandler.h not found, install libpcsclite or use ./configure PCSC_CFLAGS=...]) ]) -CPPFLAGS="$saved_CPPFLAGS" +# --enable-libpcsclite +AC_ARG_ENABLE(libpcsclite, + AC_HELP_STRING([--enable-libpcsclite=DIR],[Build a lightweight version of + libpcsclite, conflicts with PCSC-Lite @<:@default=no@:>@]), + [libpcsclite="${enableval}"], [libpcsclite=no]) +if test "${libpcsclite}" = no ; then + PKG_CHECK_EXISTS([libpcsclite], + [PKG_CHECK_MODULES([PCSC], [libpcsclite])], + [AC_MSG_WARN([libpcsclite not found by pkg-config])]) + + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS" + AC_CHECK_HEADERS(ifdhandler.h,, + [ AC_MSG_ERROR([ifdhandler.h not found, install libpcsclite or use ./configure PCSC_CFLAGS=...]) ]) + CPPFLAGS="$saved_CPPFLAGS" -# --enable-serialdropdir=DIR -AC_ARG_ENABLE(serialdropdir, - AC_HELP_STRING([--enable-serialdropdir=DIR],[directory to install the - serial wrapper driver (default to pcscd config or $(prefix)/pcsc/drivers/serial)]), - [serialdropdir="${enableval}"], [serialdropdir=false]) -if test "${serialdropdir}" = false ; then - if test "${prefix}" = NONE ; then - serialdropdir="`$PKG_CONFIG libpcsclite --variable=usbdropdir`/serial" - if test "${serialdropdir}" = "/serial" ; then - AC_MSG_ERROR([use --enable-serialdropdir=DIR]) - fi - else - serialdropdir="${prefix}`$PKG_CONFIG libpcsclite --variable=usbdropdir`/serial" - if test "${serialdropdir}" = "${prefix}/serial" ; then - AC_MSG_ERROR([use --enable-serialdropdir=DIR]) + # --enable-serialdropdir=DIR + AC_ARG_ENABLE(serialdropdir, + AC_HELP_STRING([--enable-serialdropdir=DIR],[directory to install the + serial wrapper driver (default to pcscd config or $(prefix)/pcsc/drivers/serial)]), + [serialdropdir="${enableval}"], [serialdropdir=no]) + if test "${serialdropdir}" = no ; then + if test "${prefix}" = NONE ; then + serialdropdir="`$PKG_CONFIG libpcsclite --variable=usbdropdir`/serial" + if test "${serialdropdir}" = "/serial" ; then + AC_MSG_ERROR([use --enable-serialdropdir=DIR]) + fi + else + serialdropdir="${prefix}`$PKG_CONFIG libpcsclite --variable=usbdropdir`/serial" + if test "${serialdropdir}" = "${prefix}/serial" ; then + AC_MSG_ERROR([use --enable-serialdropdir=DIR]) + fi fi fi + + + # --enable-serialconfdir=DIR + AC_ARG_ENABLE(serialconfdir, + AC_HELP_STRING([--enable-serialconfdir=DIR],[directory to install the + serial wrapper driver (default to pcscd config or /etc/reader.conf.d)]), + [serialconfdir="${enableval}"], [serialconfdir=no]) + if test "${serialconfdir}" = no ; then + if test "${prefix}" = NONE ; then + serialconfdir="`$PKG_CONFIG libpcsclite --variable=serialconfdir`" + if test "${serialconfdir}" = "" ; then + serialconfdir="/etc/reader.conf.d" + fi + else + serialconfdir="${prefix}`$PKG_CONFIG libpcsclite --variable=serialconfdir`" + if test "${serialconfdir}" = "${prefix}" ; then + serialconfdir="${prefix}/etc/reader.conf.d" + fi + fi + fi +else + builddir="`pwd`" + PCSC_CFLAGS="-DNO_LOG -I${builddir}/${srcdir}/src/libpcsclite/PCSC -I${builddir}/${srcdir}/src/libpcsclite" + PCSC_LIBS="$builddir/src/libpcsclite/libpcsclite.la" + AC_SUBST(PCSC_CFLAGS) + AC_SUBST(PCSC_LIBS) fi -# --enable-serialconfdir=DIR -AC_ARG_ENABLE(serialconfdir, - AC_HELP_STRING([--enable-serialconfdir=DIR],[directory to install the - serial wrapper driver (default to pcscd config or /etc/reader.conf.d)]), - [serialconfdir="${enableval}"], [serialconfdir=false]) -if test "${serialconfdir}" = false ; then - if test "${prefix}" = NONE ; then - serialconfdir="`$PKG_CONFIG libpcsclite --variable=serialconfdir`" - if test "${serialconfdir}" = "" ; then - serialconfdir="/etc/reader.conf.d" - fi - else - serialconfdir="${prefix}`$PKG_CONFIG libpcsclite --variable=serialconfdir`" - if test "${serialconfdir}" = "${prefix}" ; then - serialconfdir="${prefix}/etc/reader.conf.d" - fi - fi +# --enable-vpcdhost +AC_ARG_ENABLE(vpcdhost, + AC_HELP_STRING([--enable-vpcdhost=ADRESS],[Default address to connect to when + communicating with vicc. Use "/dev/null" if vpcd shall open + the socket and wait for an incoming connection. + @<:@default=/dev/null@:>@]), + [vpcdhost="${enableval}"], [vpcdhost=/dev/null]) +AC_SUBST(vpcdhost) +if test "${vpcdhost}" = "/dev/null"; then + AC_DEFINE_UNQUOTED(VPCDHOST, NULL, [OpenPICC character device]) +else + AC_DEFINE_UNQUOTED(VPCDHOST, "${vpcdhost}", [OpenPICC character device]) fi @@ -104,12 +133,15 @@ AC_CHECK_HEADERS([arpa/inet.h stdint.h stdlib.h string.h sys/socket.h sys/time.h # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T AC_TYPE_UINT16_T - +AC_CHECK_DECLS([SO_NOSIGPIPE], [], [], [#include ]) +AC_CHECK_DECLS([MSG_NOSIGNAL], [], [], [#include ]) + # Checks for library functions. AC_FUNC_MALLOC AC_CHECK_FUNCS([memset select socket]) # Select OS specific versions of source files. +AM_CONDITIONAL([BUILD_LIBPCSCLITE], [test "${libpcsclite}" = "yes"]) AC_SUBST(BUNDLE_HOST) AC_SUBST(DYN_LIB_EXT) AC_SUBST(LIB_PREFIX) @@ -159,8 +191,11 @@ ${PACKAGE} has been configured with following options: Version: ${PACKAGE_VERSION} User binaries: $(eval eval eval echo "${bindir}") PC/SC configuration: ${serialconfdir} -Python site-packages: $(eval eval eval echo "${pythondir}") Driver directory: ${serialdropdir} +Python site-packages: $(eval eval eval echo "${pythondir}") + +Build libpcsclite: ${libpcsclite} +VPCD hostname: ${vpcdhost} Host: ${host} @@ -188,6 +223,7 @@ AC_CONFIG_FILES([Makefile npa-example-data/dh/Makefile npa-example-data/ecdh/Makefile src/Makefile + src/libpcsclite/Makefile src/vpcd/Makefile src/vpicc/Makefile ]) diff --git a/virtualsmartcard/src/Makefile.am b/virtualsmartcard/src/Makefile.am index 0eb85ab..ea92d1f 100644 --- a/virtualsmartcard/src/Makefile.am +++ b/virtualsmartcard/src/Makefile.am @@ -1 +1,5 @@ +if BUILD_LIBPCSCLITE +SUBDIRS = libpcsclite vpcd vpicc +else SUBDIRS = vpcd vpicc +endif diff --git a/virtualsmartcard/src/libpcsclite/Makefile.am b/virtualsmartcard/src/libpcsclite/Makefile.am new file mode 100644 index 0000000..6b40e9b --- /dev/null +++ b/virtualsmartcard/src/libpcsclite/Makefile.am @@ -0,0 +1,42 @@ +EXTRA_DIST = PCSC/pcsclite.h.in libpcsclite.pc.in + +lib_LTLIBRARIES = libpcsclite.la + +libpcsclite_la_CPPFLAGS = $(PCSC_CFLAGS) -I$(srcdir)/../vpcd +libpcsclite_la_LDFLAGS = -no-undefined +libpcsclite_la_SOURCES = winscard.c $(top_builddir)/src/vpcd/libvpcd.la + +noinst_HEADERS = pcsclite.h + +nobase_include_HEADERS = \ + PCSC/pcsclite.h \ + PCSC/winscard.h \ + PCSC/wintypes.h + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libpcsclite.pc +libpcsclite.pc: libpcsclite.pc.in + $(do_subst) < $(srcdir)/libpcsclite.pc.in > libpcsclite.pc + +winscard.c: $(builddir)/pcsclite.h + +do_subst = $(SED) \ + -e 's,[@]PACKAGE_NAME[@],$(PACKAGE_NAME),g' \ + -e 's,[@]VERSION[@],$(PCSCVERSION),g' \ + -e 's,[@]exec_prefix[@],$(exec_prefix),g' \ + -e 's,[@]includedir[@],$(includedir),g' \ + -e 's,[@]libdir[@],$(libdir),g' \ + -e 's,[@]prefix[@],$(prefix),g' + +pcsclite.h: PCSC/pcsclite.h.in + $(do_subst) < $(srcdir)/PCSC/pcsclite.h.in > $(builddir)/pcsclite.h + +install-data-local: + $(INSTALL) -d $(DESTDIR)$(includedir)/PCSC + $(INSTALL_DATA) $(builddir)/pcsclite.h $(DESTDIR)$(includedir)/PCSC/pcsclite.h + +uninstall-local: + rm -f $(DESTDIR)$(includedir)/PCSC/pcsclite.h + +clean-local: + rm -f libpcsclite.pc pcsclite.h diff --git a/virtualsmartcard/src/libpcsclite/PCSC/debuglog.h b/virtualsmartcard/src/libpcsclite/PCSC/debuglog.h new file mode 100644 index 0000000..c434cf2 --- /dev/null +++ b/virtualsmartcard/src/libpcsclite/PCSC/debuglog.h @@ -0,0 +1,112 @@ +/* + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 1999-2004 + * David Corcoran + * Copyright (C) 1999-2011 + * Ludovic Rousseau + * + * $Id: debuglog.h 5854 2011-07-09 11:10:32Z rousseau $ + */ + +/** + * @file + * @brief This handles debugging. + * + * @note log message is sent to syslog or stderr depending on --foreground + * command line argument + * + * @code + * Log1(priority, "text"); + * log "text" with priority level priority + * Log2(priority, "text: %d", 1234); + * log "text: 1234" + * the format string can be anything printf() can understand + * Log3(priority, "text: %d %d", 1234, 5678); + * log "text: 1234 5678" + * the format string can be anything printf() can understand + * LogXxd(priority, msg, buffer, size); + * log "msg" + a hex dump of size bytes of buffer[] + * @endcode + */ + +#ifndef __debuglog_h__ +#define __debuglog_h__ + +#ifndef PCSC_API +#define PCSC_API +#endif + +enum { + DEBUGLOG_NO_DEBUG = 0, + DEBUGLOG_SYSLOG_DEBUG, + DEBUGLOG_STDOUT_DEBUG, + DEBUGLOG_STDOUT_COLOR_DEBUG +}; + +#define DEBUG_CATEGORY_NOTHING 0 +#define DEBUG_CATEGORY_APDU 1 +#define DEBUG_CATEGORY_SW 2 + +enum { + PCSC_LOG_DEBUG = 0, + PCSC_LOG_INFO, + PCSC_LOG_ERROR, + PCSC_LOG_CRITICAL +}; + +/* You can't do #ifndef __FUNCTION__ */ +#if !defined(__GNUC__) && !defined(__IBMC__) +#define __FUNCTION__ "" +#endif + +#ifndef __GNUC__ +#define __attribute__(x) /*nothing*/ +#endif + +#ifdef NO_LOG + +#define Log0(priority) do { } while(0) +#define Log1(priority, fmt) do { } while(0) +#define Log2(priority, fmt, data) do { } while(0) +#define Log3(priority, fmt, data1, data2) do { } while(0) +#define Log4(priority, fmt, data1, data2, data3) do { } while(0) +#define Log5(priority, fmt, data1, data2, data3, data4) do { } while(0) +#define Log9(priority, fmt, data1, data2, data3, data4, data5, data6, data7, data8) do { } while(0) +#define LogXxd(priority, msg, buffer, size) do { } while(0) + +#define DebugLogA(a) +#define DebugLogB(a, b) +#define DebugLogC(a, b,c) + +#else + +#define Log0(priority) log_msg(priority, "%s:%d:%s()", __FILE__, __LINE__, __FUNCTION__) +#define Log1(priority, fmt) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__) +#define Log2(priority, fmt, data) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data) +#define Log3(priority, fmt, data1, data2) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2) +#define Log4(priority, fmt, data1, data2, data3) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3) +#define Log5(priority, fmt, data1, data2, data3, data4) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3, data4) +#define Log9(priority, fmt, data1, data2, data3, data4, data5, data6, data7, data8) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3, data4, data5, data6, data7, data8) +#define LogXxd(priority, msg, buffer, size) log_xxd(priority, msg, buffer, size) + +#define DebugLogA(a) Log1(PCSC_LOG_INFO, a) +#define DebugLogB(a, b) Log2(PCSC_LOG_INFO, a, b) +#define DebugLogC(a, b,c) Log3(PCSC_LOG_INFO, a, b, c) + +#endif /* NO_LOG */ + +PCSC_API void log_msg(const int priority, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); + +PCSC_API void log_xxd(const int priority, const char *msg, + const unsigned char *buffer, const int size); + +void DebugLogSuppress(const int); +void DebugLogSetLogType(const int); +int DebugLogSetCategory(const int); +void DebugLogCategory(const int, const unsigned char *, const int); +PCSC_API void DebugLogSetLevel(const int level); + +#endif /* __debuglog_h__ */ + diff --git a/virtualsmartcard/src/libpcsclite/PCSC/ifdhandler.h b/virtualsmartcard/src/libpcsclite/PCSC/ifdhandler.h new file mode 100644 index 0000000..280d0b6 --- /dev/null +++ b/virtualsmartcard/src/libpcsclite/PCSC/ifdhandler.h @@ -0,0 +1,797 @@ +/* + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 1999-2004 + * David Corcoran + * Copyright (C) 2003-2004 + * Damien Sauveron + * Copyright (C) 2002-2011 + * Ludovic Rousseau + * + * $Id: ifdhandler.h 6413 2012-08-08 09:35:18Z rousseau $ + */ + +/** + * @file + * @defgroup IFDHandler IFDHandler + * @brief This provides reader specific low-level calls. + +The routines specified hereafter will allow you to write an IFD handler +for the PC/SC Lite resource manager. Please use the complement +developer's kit complete with headers and Makefile at: +http://www.musclecard.com/drivers.html + +This gives a common API for communication to most readers in a +homogeneous fashion. This document assumes that the driver developer is +experienced with standards such as ISO-7816-(1, 2, 3, 4), EMV and MCT +specifications. For listings of these specifications please access the +above web site. + +@section UsbReaders USB readers + +USB readers use the bundle approach so that the reader can be loaded +and unloaded upon automatic detection of the device. The bundle +approach is simple: the actual library is just embedded in a +directory so additional information can be gathered about the device. + +A bundle looks like the following: + +@verbatim +GenericReader.bundle/ + Contents/ + Info.plist - XML file describing the reader + MacOS/ - Driver directory for OS X + Solaris/ - Driver directory for Solaris + Linux/ - Driver directory for Linux + HPUX/ - Driver directory for HPUX +@endverbatim + +The @c Info.plist file describes the driver and gives the loader +all the necessary information. The following must be contained in the +@c Info.plist file: + +@subsection ifdVendorID + +The vendor ID of the USB device. + +Example: + +@verbatim + ifdVendorID + 0x04E6 +@endverbatim + +You may have an OEM of this reader in which an additional @c +can be used like in the below example: + +@verbatim + ifdVendorID + + 0x04E6 + 0x0973 + +@endverbatim + +If multiples exist all the other parameters must have a second value +also. You may chose not to support this feature but it is useful when +reader vendors OEM products so you only distribute one driver. + + +The CCID driver from Ludovic Rousseau +http://pcsclite.alioth.debian.org/ccid.html uses this feature since the +same driver supports many different readers. + +@subsection ifdProductID + + The product id of the USB device. + +@verbatim + ifdProductID + 0x3437 +@endverbatim + +@subsection ifdFriendlyName + + Example: + +@verbatim + ifdFriendlyName + SCM Microsystems USB Reader +@endverbatim + +@subsection CFBundleExecutable + + The executable name which exists in the particular platform's directory. + + Example: + +@verbatim + CFBundleExecutable + libccid.so.0.4.2 +@endverbatim + +@subsection ifdCapabilities + + List of capabilities supported by the driver. This is a bit field. Possible values are: + +- 0 + No special capabilities +- 1 IFD_GENERATE_HOTPLUG + The driver supports the hot plug feature. + +Complete sample file: + +@verbatim + + + + + CFBundleDevelopmentRegion + English + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 0.0.1d1 + ifdCapabilities + 0x00000000 + ifdProtocolSupport + 0x00000001 + ifdVersionNumber + 0x00000001 + + CFBundleExecutable + libfoobar.so.x.y + + ifdManufacturerString + Foo bar inc. + + ifdProductString + Driver for Foobar reader, version x.y + + ifdVendorID + 0x1234 + + ifdProductID + 0x5678 + + ifdFriendlyName + Foobar USB reader + + +@endverbatim + +As indicated in the XML file the DTD is available at +http://www.apple.com/DTDs/PropertyList-1.0.dtd. + +@section SerialReaders Serial readers + +Serial drivers must be configured to operate on a particular port and +respond to a particular name. The @c reader.conf file is used for this +purpose. + +It has the following syntax: + +@verbatim +# Configuration file for pcsc-lite +# David Corcoran + +FRIENDLYNAME Generic Reader +DEVICENAME /dev/ttyS0 +LIBPATH /usr/lib/pcsc/drivers/libgen_ifd.so +CHANNELID 1 +@endverbatim + +The pound sign # denotes a comment. + +@subsection FRIENDLYNAME +The FRIENDLYNAME field is an arbitrary text used to identify the reader. +This text is displayed by commands like @c pcsc_scan +http://ludovic.rousseau.free.fr/softwares/pcsc-tools/ that prints the +names of all the connected and detected readers. + +@subsection DEVICENAME +The DEVICENAME field was not used for old drivers (using the IFD handler +version 2.0 or previous). It is now (IFD handler version 3.0) used to +identify the physical port on which the reader is connected. This is +the device name of this port. It is dependent of the OS kernel. For +example the first serial port device is called @c /dev/ttyS0 under Linux +and @c /dev/cuaa0 under FreeBSD. + +If you want to use IFDHCreateChannel() instead of +IFDHCreateChannelByName() then do not use any DEVICENAME line in the +configuration file. IFDHCreateChannel() will then be called with the +CHANNELID parameter. + +@subsection LIBPATH +The LIBPATH field is the filename of the driver code. The driver is a +dynamically loaded piece of code (generally a @c drivername.so* file). + +@subsection CHANNELID +The CHANNELID is no more used for recent drivers (IFD handler 3.0) and +has been superseded by DEVICENAME. + +If you have an old driver this field is used to indicate the port to +use. You should read your driver documentation to know what information +is needed here. It should be the serial port number for a serial reader. + +CHANNELID was the numeric version of the port in which the reader will +be located. This may be done by a symbolic link where @c /dev/pcsc/1 is +the first device which may be a symbolic link to @c /dev/ttyS0 or +whichever location your reader resides. + + */ + +#ifndef _ifd_handler_h_ +#define _ifd_handler_h_ + +#include + + /* + * List of data structures available to ifdhandler + */ + typedef struct _DEVICE_CAPABILITIES + { + LPSTR Vendor_Name; /**< Tag 0x0100 */ + LPSTR IFD_Type; /**< Tag 0x0101 */ + DWORD IFD_Version; /**< Tag 0x0102 */ + LPSTR IFD_Serial; /**< Tag 0x0103 */ + DWORD IFD_Channel_ID; /**< Tag 0x0110 */ + + DWORD Asynch_Supported; /**< Tag 0x0120 */ + DWORD Default_Clock; /**< Tag 0x0121 */ + DWORD Max_Clock; /**< Tag 0x0122 */ + DWORD Default_Data_Rate; /**< Tag 0x0123 */ + DWORD Max_Data_Rate; /**< Tag 0x0124 */ + DWORD Max_IFSD; /**< Tag 0x0125 */ + DWORD Synch_Supported; /**< Tag 0x0126 */ + DWORD Power_Mgmt; /**< Tag 0x0131 */ + DWORD Card_Auth_Devices; /**< Tag 0x0140 */ + DWORD User_Auth_Device; /**< Tag 0x0142 */ + DWORD Mechanics_Supported; /**< Tag 0x0150 */ + DWORD Vendor_Features; /**< Tag 0x0180 - 0x01F0 User Defined. */ + } + DEVICE_CAPABILITIES, *PDEVICE_CAPABILITIES; + + typedef struct _ICC_STATE + { + UCHAR ICC_Presence; /**< Tag 0x0300 */ + UCHAR ICC_Interface_Status; /**< Tag 0x0301 */ + UCHAR ATR[MAX_ATR_SIZE]; /**< Tag 0x0303 */ + UCHAR ICC_Type; /**< Tag 0x0304 */ + } + ICC_STATE, *PICC_STATE; + + typedef struct _PROTOCOL_OPTIONS + { + DWORD Protocol_Type; /**< Tag 0x0201 */ + DWORD Current_Clock; /**< Tag 0x0202 */ + DWORD Current_F; /**< Tag 0x0203 */ + DWORD Current_D; /**< Tag 0x0204 */ + DWORD Current_N; /**< Tag 0x0205 */ + DWORD Current_W; /**< Tag 0x0206 */ + DWORD Current_IFSC; /**< Tag 0x0207 */ + DWORD Current_IFSD; /**< Tag 0x0208 */ + DWORD Current_BWT; /**< Tag 0x0209 */ + DWORD Current_CWT; /**< Tag 0x020A */ + DWORD Current_EBC; /**< Tag 0x020B */ + } + PROTOCOL_OPTIONS, *PPROTOCOL_OPTIONS; + + /** + * Use by SCardTransmit() + */ + typedef struct _SCARD_IO_HEADER + { + DWORD Protocol; + DWORD Length; + } + SCARD_IO_HEADER, *PSCARD_IO_HEADER; + + /* + * The list of tags should be alot more but this is all I use in the + * meantime + */ +#define TAG_IFD_ATR 0x0303 /**< ATR */ +#define TAG_IFD_SLOTNUM 0x0180 /**< select a slot */ +#define TAG_IFD_SLOT_THREAD_SAFE 0x0FAC /**< support access to different slots of the reader */ +#define TAG_IFD_THREAD_SAFE 0x0FAD /**< driver is thread safe */ +#define TAG_IFD_SLOTS_NUMBER 0x0FAE /**< number of slots of the reader */ +#define TAG_IFD_SIMULTANEOUS_ACCESS 0x0FAF /**< number of reader the driver can manage */ +#define TAG_IFD_POLLING_THREAD 0x0FB0 /**< not used. See TAG_IFD_POLLING_THREAD_WITH_TIMEOUT */ +#define TAG_IFD_POLLING_THREAD_KILLABLE 0x0FB1 /**< the polling thread can be killed */ +#define TAG_IFD_STOP_POLLING_THREAD 0x0FB2 /**< method used to stop the polling thread (instead of just pthread_kill()) */ +#define TAG_IFD_POLLING_THREAD_WITH_TIMEOUT 0x0FB3 /**< driver uses a polling thread with a timeout parameter */ + + /* + * IFD Handler version number enummerations + */ +#define IFD_HVERSION_1_0 0x00010000 +#define IFD_HVERSION_2_0 0x00020000 +#define IFD_HVERSION_3_0 0x00030000 + + /* + * List of defines available to ifdhandler + */ +#define IFD_POWER_UP 500 /**< power up the card */ +#define IFD_POWER_DOWN 501 /**< power down the card */ +#define IFD_RESET 502 /**< warm reset */ + +#define IFD_NEGOTIATE_PTS1 1 /**< negotiate PTS1 */ +#define IFD_NEGOTIATE_PTS2 2 /**< negotiate PTS2 */ +#define IFD_NEGOTIATE_PTS3 4 /**< negotiate PTS3 */ + +#define IFD_SUCCESS 0 /**< no error */ +#define IFD_ERROR_TAG 600 /**< tag unknown */ +#define IFD_ERROR_SET_FAILURE 601 /**< set failed */ +#define IFD_ERROR_VALUE_READ_ONLY 602 /**< value is read only */ +#define IFD_ERROR_PTS_FAILURE 605 /**< failed to negotiate PTS */ +#define IFD_ERROR_NOT_SUPPORTED 606 +#define IFD_PROTOCOL_NOT_SUPPORTED 607 /**< requested protocol not supported */ +#define IFD_ERROR_POWER_ACTION 608 /**< power up failed */ +#define IFD_ERROR_SWALLOW 609 +#define IFD_ERROR_EJECT 610 +#define IFD_ERROR_CONFISCATE 611 +#define IFD_COMMUNICATION_ERROR 612 /**< generic error */ +#define IFD_RESPONSE_TIMEOUT 613 /**< timeout */ +#define IFD_NOT_SUPPORTED 614 /**< request is not supported */ +#define IFD_ICC_PRESENT 615 /**< card is present */ +#define IFD_ICC_NOT_PRESENT 616 /**< card is absent */ +/** + * The \ref IFD_NO_SUCH_DEVICE error must be returned by the driver when + * it detects the reader is no more present. This will tell pcscd to + * remove the reader from the list of available readers. + */ +#define IFD_NO_SUCH_DEVICE 617 +#define IFD_ERROR_INSUFFICIENT_BUFFER 618 /**< buffer is too small */ + +#ifndef RESPONSECODE_DEFINED_IN_WINTYPES_H + typedef long RESPONSECODE; +#endif + + /* + * If you want to compile a V2.0 IFDHandler, define IFDHANDLERv2 + * before you include this file. + * + * By default it is setup for for most recent version of the API (V3.0) + */ + +#ifndef IFDHANDLERv2 + + /* + * List of Defined Functions Available to IFD_Handler 3.0 + * + * All the functions of IFD_Handler 2.0 are available + * IFDHCreateChannelByName() is new + * IFDHControl() API changed + */ + +/** +This function is required to open a communications channel to the port +listed by @p DeviceName. + +Once the channel is opened the reader must be in a state in which it is +possible to query IFDHICCPresence() for card status. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number\n + Use this for multiple card slots or multiple readers. 0xXXXXYYYY - + XXXX multiple readers, YYYY multiple slots. The resource manager will + set these automatically. By default the resource manager loads a new + instance of the driver so if your reader does not have more than one + smart card slot then ignore the Lun in all the functions.\n + \n + PC/SC supports the loading of multiple readers through one instance of + the driver in which XXXX is important. XXXX identifies the unique + reader in which the driver communicates to. The driver should set up + an array of structures that asociate this XXXX with the underlying + details of the particular reader. + +@param[in] DeviceName Filename to use by the driver.\n + For drivers configured by @p /etc/reader.conf this is the value of the + field \ref DEVICENAME. + \n + For USB drivers the @p DeviceName must start with @p usb:VID/PID. VID + is the Vendor ID and PID is the Product ID. Both are a 4-digits hex + number. + +Typically the string is generated by: + +@code +printf("usb:%04x/%04x", idVendor, idProduct); +@endcode + +The @p DeviceName string may also contain a more specialised +identification string. This additional information is used to +differentiate between two identical readers connected at the same time. +In this case the driver can't differentiate the two readers using VID +and PID and must use some additional information identifying the USB +port used by each reader. + +- libusb + + For USB drivers using libusb-1.0 http://libusb.sourceforge.net/ for USB + abstraction the @p DeviceName the string may be generated by: + + @code + printf("usb:%04x/%04x:libusb-1.0:%d:%d:%d", + idVendor, idProduct, bus_number, device_address, interface) + @endcode + + So it is something like: usb:08e6/3437:libusb-1.0:7:99:0 under + GNU/Linux. + +- libudev + + If pcscd is compiled with libudev support instead of libusb (default + since pcsc-lite 1.6.8) the string will look like: + + @code + printf("usb:%04x/%04x:libudev:%d:%s", idVendor, idProduct, + bInterfaceNumber, devpath); + @endcode + + bInterfaceNumber is the number of the interface on the device. It is + only usefull for devices with more than one CCID interface. + + devpath is the filename of the device on the file system. + + So it is something like: + usb:08e6/3437:libudev:0:/dev/bus/usb/008/047 + under GNU/Linux. + +- other + + If the driver does not understand the :libusb: or + :libudev: scheme or if a new scheme is used, the driver should + ignore the part it does not understand instead of failing. + + The driver shall recognize the usb:VID/PID part and, only if + possible, the remaining of the DeviceName field. + + It is the responsibility of the driver to correctly identify the reader. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPSTR DeviceName); + +/** +This function performs a data exchange with the reader (not the card) +specified by Lun. It is responsible for abstracting functionality such +as PIN pads, biometrics, LCD panels, etc. You should follow the MCT and +CTBCS specifications for a list of accepted commands to implement. This +function is fully voluntary and does not have to be implemented unless +you want extended functionality. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] dwControlCode Control code for the operation\n + This value identifies the specific operation to be performed. This + value is driver specific. +@param[in] TxBuffer Transmit data +@param[in] TxLength Length of this buffer +@param[out] RxBuffer Receive data +@param[in] RxLength Length of the response buffer +@param[out] pdwBytesReturned Length of response\n + This function will be passed the length of the buffer RxBuffer in + RxLength and it must set the length of the received data in + pdwBytesReturned. + +@note + @p *pdwBytesReturned should be set to zero on error. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_RESPONSE_TIMEOUT The response timed out (\ref IFD_RESPONSE_TIMEOUT) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, PUCHAR + TxBuffer, DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength, + LPDWORD pdwBytesReturned); + +#else + +/** + * Available in IFD_Handler 2.0 + * + * @deprecated + * You should use the new form of IFDHControl() + */ +RESPONSECODE IFDHControl(DWORD Lun, PUCHAR TxBuffer, DWORD TxLength, + PUCHAR RxBuffer, PDWORD RxLength); + +#endif + + /* + * common functions in IFD_Handler 2.0 and 3.0 + */ +/** +This function is required to open a communications channel to the port +listed by Channel. For example, the first serial reader on COM1 would +link to @p /dev/pcsc/1 which would be a symbolic link to @p /dev/ttyS0 +on some machines This is used to help with inter-machine independence. + +On machines with no /dev directory the driver writer may choose to map +their Channel to whatever they feel is appropriate. + +Once the channel is opened the reader must be in a state in which it is +possible to query IFDHICCPresence() for card status. + +USB readers can ignore the @p Channel parameter and query the USB bus +for the particular reader by manufacturer and product id. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number\n + Use this for multiple card slots or multiple readers. 0xXXXXYYYY - + XXXX multiple readers, YYYY multiple slots. The resource manager will + set these automatically. By default the resource manager loads a new + instance of the driver so if your reader does not have more than one + smart card slot then ignore the Lun in all the functions.\n + \n + PC/SC supports the loading of multiple readers through one instance of + the driver in which XXXX is important. XXXX identifies the unique + reader in which the driver communicates to. The driver should set up + an array of structures that associate this XXXX with the underlying + details of the particular reader. +@param[in] Channel Channel ID + This is denoted by the following: + - 0x000001 @p /dev/pcsc/1 + - 0x000002 @p /dev/pcsc/2 + - 0x000003 @p /dev/pcsc/3 + - 0x000004 @p /dev/pcsc/4 + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + + */ +RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel); + +/** +This function should close the reader communication channel for the +particular reader. Prior to closing the communication channel the reader +should make sure the card is powered down and the terminal is also +powered down. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHCloseChannel(DWORD Lun); + +/** +This function should get the slot/card capabilities for a particular +slot/card specified by Lun. Again, if you have only 1 card slot and +don't mind loading a new driver for each reader then ignore Lun. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] Tag Tag of the desired data value +- \ref TAG_IFD_ATR + Return the ATR and its size (implementation is mandatory). +- \ref TAG_IFD_SLOTNUM + Unused/deprecated +- \ref SCARD_ATTR_ATR_STRING + Same as \ref TAG_IFD_ATR but this one is not mandatory. It is defined + in Microsoft PC/SC SCardGetAttrib(). +- \ref TAG_IFD_SIMULTANEOUS_ACCESS + Return the number of sessions (readers) the driver can handle in + Value[0]. + This is used for multiple readers sharing the same driver. +- \ref TAG_IFD_THREAD_SAFE + If the driver supports more than one reader (see + \ref TAG_IFD_SIMULTANEOUS_ACCESS above) this tag indicates if the + driver supports access to multiple readers at the same time.\n + Value[0] = 1 indicates the driver supports simultaneous accesses. +- \ref TAG_IFD_SLOTS_NUMBER + Return the number of slots in this reader in Value[0]. +- \ref TAG_IFD_SLOT_THREAD_SAFE + If the reader has more than one slot (see \ref TAG_IFD_SLOTS_NUMBER + above) this tag indicates if the driver supports access to multiple + slots of the same reader at the same time.\n + Value[0] = 1 indicates the driver supports simultaneous slot + accesses. +- \ref TAG_IFD_POLLING_THREAD + Unused/deprecated +- \ref TAG_IFD_POLLING_THREAD_WITH_TIMEOUT + If the driver provides a polling thread then @p Value is a pointer to + this function. The function prototype is: +@verbatim + RESPONSECODE foo(DWORD Lun, int timeout); +@endverbatim +- \ref TAG_IFD_POLLING_THREAD_KILLABLE + Tell if the polling thread can be killed (pthread_kill()) by pcscd +- \ref TAG_IFD_STOP_POLLING_THREAD + Returns a pointer in @p Value to the function used to stop the polling + thread returned by \ref TAG_IFD_POLLING_THREAD_WITH_TIMEOUT. The + function prototype is: +@verbatim + RESPONSECODE foo(DWORD Lun); +@endverbatim +@param[in,out] Length Length of the desired data value +@param[out] Value Value of the desired data + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_ERROR_TAG Invalid tag given (\ref IFD_ERROR_TAG) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag, PDWORD Length, + PUCHAR Value); + +/** +This function should set the slot/card capabilities for a particular +slot/card specified by @p Lun. Again, if you have only 1 card slot and +don't mind loading a new driver for each reader then ignore @p Lun. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] Tag Tag of the desired data value +@param[in,out] Length Length of the desired data value +@param[out] Value Value of the desired data + +This function is also called when the application uses the PC/SC +SCardGetAttrib() function. The list of supported tags is not limited. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_ERROR_TAG Invalid tag given (\ref IFD_ERROR_TAG) +@retval IFD_ERROR_SET_FAILURE Could not set value (\ref IFD_ERROR_SET_FAILURE) +@retval IFD_ERROR_VALUE_READ_ONLY Trying to set read only value (\ref IFD_ERROR_VALUE_READ_ONLY) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag, DWORD Length, PUCHAR Value); + +/** +This function should set the Protocol Type Selection (PTS) of a +particular card/slot using the three PTS parameters sent + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] Protocol Desired protocol +- \ref SCARD_PROTOCOL_T0 + T=0 protocol +- \ref SCARD_PROTOCOL_T1 + T=1 protocol +@param[in] Flags Logical OR of possible values to determine which PTS values +to negotiate +- \ref IFD_NEGOTIATE_PTS1 +- \ref IFD_NEGOTIATE_PTS2 +- \ref IFD_NEGOTIATE_PTS3 +@param[in] PTS1 1st PTS Value +@param[in] PTS2 2nd PTS Value +@param[in] PTS3 3rd PTS Value\n + See ISO 7816/EMV documentation. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_ERROR_PTS_FAILURE Could not set PTS value (\ref IFD_ERROR_PTS_FAILURE) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_PROTOCOL_NOT_SUPPORTED Protocol is not supported (\ref IFD_PROTOCOL_NOT_SUPPORTED) +@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol, UCHAR Flags, + UCHAR PTS1, UCHAR PTS2, UCHAR PTS3); +/** +This function controls the power and reset signals of the smart card +reader at the particular reader/slot specified by @p Lun. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] Action Action to be taken on the card +- \ref IFD_POWER_UP + Power up the card (store and return Atr and AtrLength) +- \ref IFD_POWER_DOWN + Power down the card (Atr and AtrLength should be zeroed) +- \ref IFD_RESET + Perform a warm reset of the card (no power down). If the card is not powered then power up the card (store and return Atr and AtrLength) +@param[out] Atr Answer to Reset (ATR) of the card\n + The driver is responsible for caching this value in case + IFDHGetCapabilities() is called requesting the ATR and its length. The + ATR length should not exceed \ref MAX_ATR_SIZE. +@param[in,out] AtrLength Length of the ATR\n + This should not exceed \ref MAX_ATR_SIZE. + +@note +Memory cards without an ATR should return \ref IFD_SUCCESS on reset but the +Atr should be zeroed and the length should be zero Reset errors should +return zero for the AtrLength and return \ref IFD_ERROR_POWER_ACTION. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_ERROR_POWER_ACTION Error powering/resetting card (\ref IFD_ERROR_POWER_ACTION) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action, PUCHAR Atr, PDWORD + AtrLength); + +/** +This function performs an APDU exchange with the card/slot specified by +Lun. The driver is responsible for performing any protocol specific +exchanges such as T=0, 1, etc. differences. Calling this function will +abstract all protocol differences. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] SendPci contains two structure members +- Protocol 0, 1, ... 14\n + T=0 ... T=14 +- Length\n + Not used. +@param[in] TxBuffer Transmit APDU\n + Example: "\x00\xA4\x00\x00\x02\x3F\x00" +@param[in] TxLength Length of this buffer +@param[out] RxBuffer Receive APDU\n + Example: "\x61\x14" +@param[in,out] RxLength Length of the received APDU\n + This function will be passed the size of the buffer of RxBuffer and + this function is responsible for setting this to the length of the + received APDU response. This should be ZERO on all errors. The + resource manager will take responsibility of zeroing out any temporary + APDU buffers for security reasons. +@param[out] RecvPci contains two structure members +- Protocol - 0, 1, ... 14\n + T=0 ... T=14 +- Length\n + Not used. + +@note +The driver is responsible for knowing what type of card it has. If the +current slot/card contains a memory card then this command should ignore +the Protocol and use the MCT style commands for support for these style +cards and transmit them appropriately. If your reader does not support +memory cards or you don't want to implement this functionality, then +ignore this. +@par +RxLength should be set to zero on error. +@par +The driver is not responsible for doing an automatic Get Response +command for received buffers containing 61 XX. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_RESPONSE_TIMEOUT The response timed out (\ref IFD_RESPONSE_TIMEOUT) +@retval IFD_ICC_NOT_PRESENT ICC is not present (\ref IFD_ICC_NOT_PRESENT) +@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci, + PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, PDWORD + RxLength, PSCARD_IO_HEADER RecvPci); + +/** +This function returns the status of the card inserted in the reader/slot +specified by @p Lun. In cases where the device supports asynchronous +card insertion/removal detection, it is advised that the driver manages +this through a thread so the driver does not have to send and receive a +command each time this function is called. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_ICC_NOT_PRESENT ICC is not present (\ref IFD_ICC_NOT_PRESENT) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHICCPresence(DWORD Lun); + +#endif diff --git a/virtualsmartcard/src/libpcsclite/PCSC/pcsclite.h b/virtualsmartcard/src/libpcsclite/PCSC/pcsclite.h new file mode 120000 index 0000000..4d8e309 --- /dev/null +++ b/virtualsmartcard/src/libpcsclite/PCSC/pcsclite.h @@ -0,0 +1 @@ +../pcsclite.h \ No newline at end of file diff --git a/virtualsmartcard/src/libpcsclite/PCSC/pcsclite.h.in b/virtualsmartcard/src/libpcsclite/PCSC/pcsclite.h.in new file mode 100644 index 0000000..d554938 --- /dev/null +++ b/virtualsmartcard/src/libpcsclite/PCSC/pcsclite.h.in @@ -0,0 +1,220 @@ +/* + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 1999-2004 + * David Corcoran + * Copyright (C) 2002-2011 + * Ludovic Rousseau + * Copyright (C) 2005 + * Martin Paljak + * + * $Id: pcsclite.h.in 6355 2012-06-25 13:22:27Z rousseau $ + */ + +/** + * @file + * @brief This keeps a list of defines for pcsc-lite. + * + * Error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx + */ + +#ifndef __pcsclite_h__ +#define __pcsclite_h__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef LONG SCARDCONTEXT; /**< \p hContext returned by SCardEstablishContext() */ +typedef SCARDCONTEXT *PSCARDCONTEXT; +typedef SCARDCONTEXT *LPSCARDCONTEXT; +typedef LONG SCARDHANDLE; /**< \p hCard returned by SCardConnect() */ +typedef SCARDHANDLE *PSCARDHANDLE; +typedef SCARDHANDLE *LPSCARDHANDLE; + +#define MAX_ATR_SIZE 33 /**< Maximum ATR size */ + +/* Set structure elements aligment on bytes + * http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */ +#ifdef __APPLE__ +#pragma pack(1) +#endif + +typedef struct +{ + const char *szReader; + void *pvUserData; + DWORD dwCurrentState; + DWORD dwEventState; + DWORD cbAtr; + unsigned char rgbAtr[MAX_ATR_SIZE]; +} +SCARD_READERSTATE, *LPSCARD_READERSTATE; + +/** Protocol Control Information (PCI) */ +typedef struct +{ + unsigned long dwProtocol; /**< Protocol identifier */ + unsigned long cbPciLength; /**< Protocol Control Inf Length */ +} +SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST; + +typedef const SCARD_IO_REQUEST *LPCSCARD_IO_REQUEST; + +extern const SCARD_IO_REQUEST g_rgSCardT0Pci, g_rgSCardT1Pci, g_rgSCardRawPci; + +/* restore default structure elements alignment */ +#ifdef __APPLE__ +#pragma pack() +#endif + +#define SCARD_PCI_T0 (&g_rgSCardT0Pci) /**< protocol control information (PCI) for T=0 */ +#define SCARD_PCI_T1 (&g_rgSCardT1Pci) /**< protocol control information (PCI) for T=1 */ +#define SCARD_PCI_RAW (&g_rgSCardRawPci) /**< protocol control information (PCI) for RAW protocol */ + +/** error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx + */ +#define SCARD_S_SUCCESS ((LONG)0x00000000) /**< No error was encountered. */ +#define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001) /**< An internal consistency check failed. */ +#define SCARD_E_CANCELLED ((LONG)0x80100002) /**< The action was cancelled by an SCardCancel request. */ +#define SCARD_E_INVALID_HANDLE ((LONG)0x80100003) /**< The supplied handle was invalid. */ +#define SCARD_E_INVALID_PARAMETER ((LONG)0x80100004) /**< One or more of the supplied parameters could not be properly interpreted. */ +#define SCARD_E_INVALID_TARGET ((LONG)0x80100005) /**< Registry startup information is missing or invalid. */ +#define SCARD_E_NO_MEMORY ((LONG)0x80100006) /**< Not enough memory available to complete this command. */ +#define SCARD_F_WAITED_TOO_LONG ((LONG)0x80100007) /**< An internal consistency timer has expired. */ +#define SCARD_E_INSUFFICIENT_BUFFER ((LONG)0x80100008) /**< The data buffer to receive returned data is too small for the returned data. */ +#define SCARD_E_UNKNOWN_READER ((LONG)0x80100009) /**< The specified reader name is not recognized. */ +#define SCARD_E_TIMEOUT ((LONG)0x8010000A) /**< The user-specified timeout value has expired. */ +#define SCARD_E_SHARING_VIOLATION ((LONG)0x8010000B) /**< The smart card cannot be accessed because of other connections outstanding. */ +#define SCARD_E_NO_SMARTCARD ((LONG)0x8010000C) /**< The operation requires a Smart Card, but no Smart Card is currently in the device. */ +#define SCARD_E_UNKNOWN_CARD ((LONG)0x8010000D) /**< The specified smart card name is not recognized. */ +#define SCARD_E_CANT_DISPOSE ((LONG)0x8010000E) /**< The system could not dispose of the media in the requested manner. */ +#define SCARD_E_PROTO_MISMATCH ((LONG)0x8010000F) /**< The requested protocols are incompatible with the protocol currently in use with the smart card. */ +#define SCARD_E_NOT_READY ((LONG)0x80100010) /**< The reader or smart card is not ready to accept commands. */ +#define SCARD_E_INVALID_VALUE ((LONG)0x80100011) /**< One or more of the supplied parameters values could not be properly interpreted. */ +#define SCARD_E_SYSTEM_CANCELLED ((LONG)0x80100012) /**< The action was cancelled by the system, presumably to log off or shut down. */ +#define SCARD_F_COMM_ERROR ((LONG)0x80100013) /**< An internal communications error has been detected. */ +#define SCARD_F_UNKNOWN_ERROR ((LONG)0x80100014) /**< An internal error has been detected, but the source is unknown. */ +#define SCARD_E_INVALID_ATR ((LONG)0x80100015) /**< An ATR obtained from the registry is not a valid ATR string. */ +#define SCARD_E_NOT_TRANSACTED ((LONG)0x80100016) /**< An attempt was made to end a non-existent transaction. */ +#define SCARD_E_READER_UNAVAILABLE ((LONG)0x80100017) /**< The specified reader is not currently available for use. */ +#define SCARD_P_SHUTDOWN ((LONG)0x80100018) /**< The operation has been aborted to allow the server application to exit. */ +#define SCARD_E_PCI_TOO_SMALL ((LONG)0x80100019) /**< The PCI Receive buffer was too small. */ +#define SCARD_E_READER_UNSUPPORTED ((LONG)0x8010001A) /**< The reader driver does not meet minimal requirements for support. */ +#define SCARD_E_DUPLICATE_READER ((LONG)0x8010001B) /**< The reader driver did not produce a unique reader name. */ +#define SCARD_E_CARD_UNSUPPORTED ((LONG)0x8010001C) /**< The smart card does not meet minimal requirements for support. */ +#define SCARD_E_NO_SERVICE ((LONG)0x8010001D) /**< The Smart card resource manager is not running. */ +#define SCARD_E_SERVICE_STOPPED ((LONG)0x8010001E) /**< The Smart card resource manager has shut down. */ +#define SCARD_E_UNEXPECTED ((LONG)0x8010001F) /**< An unexpected card error has occurred. */ +#define SCARD_E_UNSUPPORTED_FEATURE ((LONG)0x8010001F) /**< This smart card does not support the requested feature. */ +#define SCARD_E_ICC_INSTALLATION ((LONG)0x80100020) /**< No primary provider can be found for the smart card. */ +#define SCARD_E_ICC_CREATEORDER ((LONG)0x80100021) /**< The requested order of object creation is not supported. */ +/* #define SCARD_E_UNSUPPORTED_FEATURE ((LONG)0x80100022) / **< This smart card does not support the requested feature. */ +#define SCARD_E_DIR_NOT_FOUND ((LONG)0x80100023) /**< The identified directory does not exist in the smart card. */ +#define SCARD_E_FILE_NOT_FOUND ((LONG)0x80100024) /**< The identified file does not exist in the smart card. */ +#define SCARD_E_NO_DIR ((LONG)0x80100025) /**< The supplied path does not represent a smart card directory. */ +#define SCARD_E_NO_FILE ((LONG)0x80100026) /**< The supplied path does not represent a smart card file. */ +#define SCARD_E_NO_ACCESS ((LONG)0x80100027) /**< Access is denied to this file. */ +#define SCARD_E_WRITE_TOO_MANY ((LONG)0x80100028) /**< The smart card does not have enough memory to store the information. */ +#define SCARD_E_BAD_SEEK ((LONG)0x80100029) /**< There was an error trying to set the smart card file object pointer. */ +#define SCARD_E_INVALID_CHV ((LONG)0x8010002A) /**< The supplied PIN is incorrect. */ +#define SCARD_E_UNKNOWN_RES_MNG ((LONG)0x8010002B) /**< An unrecognized error code was returned from a layered component. */ +#define SCARD_E_NO_SUCH_CERTIFICATE ((LONG)0x8010002C) /**< The requested certificate does not exist. */ +#define SCARD_E_CERTIFICATE_UNAVAILABLE ((LONG)0x8010002D) /**< The requested certificate could not be obtained. */ +#define SCARD_E_NO_READERS_AVAILABLE ((LONG)0x8010002E) /**< Cannot find a smart card reader. */ +#define SCARD_E_COMM_DATA_LOST ((LONG)0x8010002F) /**< A communications error with the smart card has been detected. Retry the operation. */ +#define SCARD_E_NO_KEY_CONTAINER ((LONG)0x80100030) /**< The requested key container does not exist on the smart card. */ +#define SCARD_E_SERVER_TOO_BUSY ((LONG)0x80100031) /**< The Smart Card Resource Manager is too busy to complete this operation. */ + +#define SCARD_W_UNSUPPORTED_CARD ((LONG)0x80100065) /**< The reader cannot communicate with the card, due to ATR string configuration conflicts. */ +#define SCARD_W_UNRESPONSIVE_CARD ((LONG)0x80100066) /**< The smart card is not responding to a reset. */ +#define SCARD_W_UNPOWERED_CARD ((LONG)0x80100067) /**< Power has been removed from the smart card, so that further communication is not possible. */ +#define SCARD_W_RESET_CARD ((LONG)0x80100068) /**< The smart card has been reset, so any shared state information is invalid. */ +#define SCARD_W_REMOVED_CARD ((LONG)0x80100069) /**< The smart card has been removed, so further communication is not possible. */ + +#define SCARD_W_SECURITY_VIOLATION ((LONG)0x8010006A) /**< Access was denied because of a security violation. */ +#define SCARD_W_WRONG_CHV ((LONG)0x8010006B) /**< The card cannot be accessed because the wrong PIN was presented. */ +#define SCARD_W_CHV_BLOCKED ((LONG)0x8010006C) /**< The card cannot be accessed because the maximum number of PIN entry attempts has been reached. */ +#define SCARD_W_EOF ((LONG)0x8010006D) /**< The end of the smart card file has been reached. */ +#define SCARD_W_CANCELLED_BY_USER ((LONG)0x8010006E) /**< The user pressed "Cancel" on a Smart Card Selection Dialog. */ +#define SCARD_W_CARD_NOT_AUTHENTICATED ((LONG)0x8010006F) /**< No PIN was presented to the smart card. */ + +#define SCARD_AUTOALLOCATE (DWORD)(-1) /**< see SCardFreeMemory() */ +#define SCARD_SCOPE_USER 0x0000 /**< Scope in user space */ +#define SCARD_SCOPE_TERMINAL 0x0001 /**< Scope in terminal */ +#define SCARD_SCOPE_SYSTEM 0x0002 /**< Scope in system */ + +#define SCARD_PROTOCOL_UNDEFINED 0x0000 /**< protocol not set */ +#define SCARD_PROTOCOL_UNSET SCARD_PROTOCOL_UNDEFINED /* backward compat */ +#define SCARD_PROTOCOL_T0 0x0001 /**< T=0 active protocol. */ +#define SCARD_PROTOCOL_T1 0x0002 /**< T=1 active protocol. */ +#define SCARD_PROTOCOL_RAW 0x0004 /**< Raw active protocol. */ +#define SCARD_PROTOCOL_T15 0x0008 /**< T=15 protocol. */ + +#define SCARD_PROTOCOL_ANY (SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1) /**< IFD determines prot. */ + +#define SCARD_SHARE_EXCLUSIVE 0x0001 /**< Exclusive mode only */ +#define SCARD_SHARE_SHARED 0x0002 /**< Shared mode only */ +#define SCARD_SHARE_DIRECT 0x0003 /**< Raw mode only */ + +#define SCARD_LEAVE_CARD 0x0000 /**< Do nothing on close */ +#define SCARD_RESET_CARD 0x0001 /**< Reset on close */ +#define SCARD_UNPOWER_CARD 0x0002 /**< Power down on close */ +#define SCARD_EJECT_CARD 0x0003 /**< Eject on close */ + +#define SCARD_UNKNOWN 0x0001 /**< Unknown state */ +#define SCARD_ABSENT 0x0002 /**< Card is absent */ +#define SCARD_PRESENT 0x0004 /**< Card is present */ +#define SCARD_SWALLOWED 0x0008 /**< Card not powered */ +#define SCARD_POWERED 0x0010 /**< Card is powered */ +#define SCARD_NEGOTIABLE 0x0020 /**< Ready for PTS */ +#define SCARD_SPECIFIC 0x0040 /**< PTS has been set */ + +#define SCARD_STATE_UNAWARE 0x0000 /**< App wants status */ +#define SCARD_STATE_IGNORE 0x0001 /**< Ignore this reader */ +#define SCARD_STATE_CHANGED 0x0002 /**< State has changed */ +#define SCARD_STATE_UNKNOWN 0x0004 /**< Reader unknown */ +#define SCARD_STATE_UNAVAILABLE 0x0008 /**< Status unavailable */ +#define SCARD_STATE_EMPTY 0x0010 /**< Card removed */ +#define SCARD_STATE_PRESENT 0x0020 /**< Card inserted */ +#define SCARD_STATE_ATRMATCH 0x0040 /**< ATR matches card */ +#define SCARD_STATE_EXCLUSIVE 0x0080 /**< Exclusive Mode */ +#define SCARD_STATE_INUSE 0x0100 /**< Shared Mode */ +#define SCARD_STATE_MUTE 0x0200 /**< Unresponsive card */ +#define SCARD_STATE_UNPOWERED 0x0400 /**< Unpowered card */ + +#ifndef INFINITE +#define INFINITE 0xFFFFFFFF /**< Infinite timeout */ +#endif + +#define PCSCLITE_VERSION_NUMBER "@VERSION@" /**< Current version */ +/** Maximum readers context (a slot is count as a reader) */ +#define PCSCLITE_MAX_READERS_CONTEXTS 16 + +#define MAX_READERNAME 128 + +#ifndef SCARD_ATR_LENGTH +#define SCARD_ATR_LENGTH MAX_ATR_SIZE /**< Maximum ATR size */ +#endif + +/* + * The message and buffer sizes must be multiples of 16. + * The max message size must be at least large enough + * to accomodate the transmit_struct + */ +#define MAX_BUFFER_SIZE 264 /**< Maximum Tx/Rx Buffer for short APDU */ +#define MAX_BUFFER_SIZE_EXTENDED (4 + 3 + (1<<16) + 3 + 2) /**< enhanced (64K + APDU + Lc + Le + SW) Tx/Rx Buffer */ + +/* + * Gets a stringified error response + */ +char *pcsc_stringify_error(const LONG); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/virtualsmartcard/src/libpcsclite/PCSC/winscard.h b/virtualsmartcard/src/libpcsclite/PCSC/winscard.h new file mode 100644 index 0000000..5b2f7b7 --- /dev/null +++ b/virtualsmartcard/src/libpcsclite/PCSC/winscard.h @@ -0,0 +1,102 @@ +/* + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 1999-2003 + * David Corcoran + * Copyright (C) 2002-2009 + * Ludovic Rousseau + * + * $Id: winscard.h 5962 2011-09-24 08:24:34Z rousseau $ + */ + +/** + * @file + * @brief This handles smart card reader communications. + */ + +#ifndef __winscard_h__ +#define __winscard_h__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef PCSC_API +#define PCSC_API +#endif + + PCSC_API LONG SCardEstablishContext(DWORD dwScope, + /*@null@*/ LPCVOID pvReserved1, /*@null@*/ LPCVOID pvReserved2, + /*@out@*/ LPSCARDCONTEXT phContext); + + PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext); + + PCSC_API LONG SCardIsValidContext(SCARDCONTEXT hContext); + + PCSC_API LONG SCardConnect(SCARDCONTEXT hContext, + LPCSTR szReader, + DWORD dwShareMode, + DWORD dwPreferredProtocols, + /*@out@*/ LPSCARDHANDLE phCard, /*@out@*/ LPDWORD pdwActiveProtocol); + + PCSC_API LONG SCardReconnect(SCARDHANDLE hCard, + DWORD dwShareMode, + DWORD dwPreferredProtocols, + DWORD dwInitialization, /*@out@*/ LPDWORD pdwActiveProtocol); + + PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition); + + PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard); + + PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition); + + PCSC_API LONG SCardStatus(SCARDHANDLE hCard, + /*@null@*/ /*@out@*/ LPSTR mszReaderName, + /*@null@*/ /*@out@*/ LPDWORD pcchReaderLen, + /*@null@*/ /*@out@*/ LPDWORD pdwState, + /*@null@*/ /*@out@*/ LPDWORD pdwProtocol, + /*@null@*/ /*@out@*/ LPBYTE pbAtr, + /*@null@*/ /*@out@*/ LPDWORD pcbAtrLen); + + PCSC_API LONG SCardGetStatusChange(SCARDCONTEXT hContext, + DWORD dwTimeout, + LPSCARD_READERSTATE rgReaderStates, DWORD cReaders); + + PCSC_API LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, + LPCVOID pbSendBuffer, DWORD cbSendLength, + /*@out@*/ LPVOID pbRecvBuffer, DWORD cbRecvLength, + LPDWORD lpBytesReturned); + + PCSC_API LONG SCardTransmit(SCARDHANDLE hCard, + const SCARD_IO_REQUEST *pioSendPci, + LPCBYTE pbSendBuffer, DWORD cbSendLength, + /*@out@*/ SCARD_IO_REQUEST *pioRecvPci, + /*@out@*/ LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength); + + PCSC_API LONG SCardListReaderGroups(SCARDCONTEXT hContext, + /*@out@*/ LPSTR mszGroups, LPDWORD pcchGroups); + + PCSC_API LONG SCardListReaders(SCARDCONTEXT hContext, + /*@null@*/ /*@out@*/ LPCSTR mszGroups, + /*@null@*/ /*@out@*/ LPSTR mszReaders, + /*@out@*/ LPDWORD pcchReaders); + + PCSC_API LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem); + + PCSC_API LONG SCardCancel(SCARDCONTEXT hContext); + + PCSC_API LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, + /*@out@*/ LPBYTE pbAttr, LPDWORD pcbAttrLen); + + PCSC_API LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, + LPCBYTE pbAttr, DWORD cbAttrLen); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/virtualsmartcard/src/libpcsclite/PCSC/wintypes.h b/virtualsmartcard/src/libpcsclite/PCSC/wintypes.h new file mode 100644 index 0000000..8697383 --- /dev/null +++ b/virtualsmartcard/src/libpcsclite/PCSC/wintypes.h @@ -0,0 +1,94 @@ +/* + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 1999 + * David Corcoran + * Copyright (C) 2002-2011 + * Ludovic Rousseau + * + * $Id: wintypes.h 5869 2011-07-09 12:04:18Z rousseau $ + */ + +/** + * @file + * @brief This keeps a list of Windows(R) types. + */ + +#ifndef __wintypes_h__ +#define __wintypes_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef __APPLE__ + +#include + +#ifndef BYTE + typedef uint8_t BYTE; +#endif + typedef uint8_t UCHAR; + typedef UCHAR *PUCHAR; + typedef uint16_t USHORT; + +#ifndef __COREFOUNDATION_CFPLUGINCOM__ + typedef uint32_t ULONG; + typedef void *LPVOID; + typedef int16_t BOOL; +#endif + + typedef ULONG *PULONG; + typedef const void *LPCVOID; + typedef uint32_t DWORD; + typedef DWORD *PDWORD; + typedef uint16_t WORD; + typedef int32_t LONG; + typedef const char *LPCSTR; + typedef const BYTE *LPCBYTE; + typedef BYTE *LPBYTE; + typedef DWORD *LPDWORD; + typedef char *LPSTR; + +#else + +#ifndef BYTE + typedef unsigned char BYTE; +#endif + typedef unsigned char UCHAR; + typedef UCHAR *PUCHAR; + typedef unsigned short USHORT; + +#ifndef __COREFOUNDATION_CFPLUGINCOM__ + typedef unsigned long ULONG; + typedef void *LPVOID; +#endif + + typedef const void *LPCVOID; + typedef unsigned long DWORD; + typedef DWORD *PDWORD; + typedef long LONG; + typedef const char *LPCSTR; + typedef const BYTE *LPCBYTE; + typedef BYTE *LPBYTE; + typedef DWORD *LPDWORD; + typedef char *LPSTR; + + /* these types were deprecated but still used by old drivers and + * applications. So just declare and use them. */ + typedef LPSTR LPTSTR; + typedef LPCSTR LPCTSTR; + + /* types unused by pcsc-lite */ + typedef short BOOL; + typedef unsigned short WORD; + typedef ULONG *PULONG; + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/virtualsmartcard/src/libpcsclite/libpcsclite.pc.in b/virtualsmartcard/src/libpcsclite/libpcsclite.pc.in new file mode 100644 index 0000000..6fe9ca4 --- /dev/null +++ b/virtualsmartcard/src/libpcsclite/libpcsclite.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/PCSC + +Name: @PACKAGE_NAME@ +Description: PC/SC smart card interface +Version: @VERSION@ +Libs: -L${libdir} -lpcsclite -lvpcd +Cflags: -DNO_LOG -I${includedir} diff --git a/virtualsmartcard/src/libpcsclite/winscard.c b/virtualsmartcard/src/libpcsclite/winscard.c new file mode 100644 index 0000000..e60e135 --- /dev/null +++ b/virtualsmartcard/src/libpcsclite/winscard.c @@ -0,0 +1,729 @@ +/* + * Copyright (C) 2013 Frank Morgner + * + * This file is part of virtualsmartcard. + * + * virtualsmartcard is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * virtualsmartcard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * virtualsmartcard. If not, see . + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "ifd-vpcd.h" +#include "vpcd.h" +#include +#include +#include +#include +#include +#include + +struct card { + DWORD dwShareMode; + size_t usage_counter; +}; + +#define SET_R_TEST(value) { r = value; if (r != SCARD_S_SUCCESS) { goto err; } } + +static struct card cards[PCSCLITE_MAX_READERS_CONTEXTS]; +static int cancel_status = 0; +static size_t context_count = 0; + +static const char reader_format_str[] = "Virtual PCD %02"SCNu32; +static const SCARDHANDLE validhandle = 1; + +/* part of libvpcd, but not exported */ +extern const unsigned char VICC_MAX_SLOTS; +extern const char *hostname; + +static LONG autoallocate(void *buf, LPDWORD len, DWORD max, void **rbuf) +{ + LPSTR *p; + + if (!len || !rbuf) + return SCARD_E_INVALID_PARAMETER; + + if (buf && (*len == SCARD_AUTOALLOCATE)) { + p = malloc(max); + if (!p) + return SCARD_E_NO_MEMORY; + + /* copy the pointer */ + memcpy(buf, &p, sizeof p); + + *len = max; + *rbuf = p; + } else { + /* we don't have anything to do. + * Simply tell the caller to use buf with unchanged length */ + *rbuf = buf; + } + + return SCARD_S_SUCCESS; +} + +static void initialize_globals(void) +{ + DWORD Lun, Channel = VPCDPORT; + const char *hostname_old = hostname; + + hostname = VPCDHOST; + for (Lun = 0; + Lun < PCSCLITE_MAX_READERS_CONTEXTS && Lun < VICC_MAX_SLOTS; + Lun++) { + IFDHCreateChannel (Lun, Channel); + } + hostname = hostname_old; +} + +static void release_globals(void) +{ + DWORD Lun; + for (Lun = 0; + Lun < PCSCLITE_MAX_READERS_CONTEXTS && Lun < VICC_MAX_SLOTS; + Lun++) { + IFDHCloseChannel (Lun); + } + memset(cards, 0, sizeof cards); +} + +static LONG handle2card(SCARDHANDLE hCard, struct card **card) +{ + DWORD index = hCard; + + if (!card) + return SCARD_F_INTERNAL_ERROR; + + if (index >= PCSCLITE_MAX_READERS_CONTEXTS) + return SCARD_E_INVALID_HANDLE; + + *card = &cards[index]; + + return SCARD_S_SUCCESS; +} + +LONG handle2reader(DWORD index, LPSTR mszReaderName, LPDWORD pcchReaderLen) +{ + LONG r; + char *reader; + int length; + + if (!pcchReaderLen) { + r = SCARD_E_INVALID_PARAMETER; + goto err; + } + + SET_R_TEST( autoallocate(mszReaderName, pcchReaderLen, MAX_READERNAME, (void **) &reader)); + + if (reader) { + /* caller wants to have the string */ + length = snprintf(reader, *pcchReaderLen, reader_format_str, (uint32_t) index); + if (length > *pcchReaderLen) { + r = SCARD_E_INSUFFICIENT_BUFFER; + goto err; + } + } else { + /* caller wants to have the length */ + length = snprintf(reader, 0, reader_format_str, (uint32_t) index); + } + + if (length < 0) { + r = SCARD_F_INTERNAL_ERROR; + goto err; + } + + *pcchReaderLen = length; + /* r has already been set to SCARD_S_SUCCESS */ + +err: + return r; +} + +static LONG reader2card(LPCSTR szReader, struct card **card, LPSCARDHANDLE phCard) +{ + DWORD index; + + if (!card) + return SCARD_F_INTERNAL_ERROR; + + if (1 != sscanf(szReader, reader_format_str, &index) + || index >= PCSCLITE_MAX_READERS_CONTEXTS) + return SCARD_E_READER_UNAVAILABLE; + + *card = &cards[index]; + if (phCard) + *phCard = index; + + return SCARD_S_SUCCESS; +} + +static LONG responsecode2long(RESPONSECODE r) +{ + switch (r) { + case IFD_ICC_PRESENT: + case IFD_SUCCESS: + return SCARD_S_SUCCESS; + case IFD_ERROR_INSUFFICIENT_BUFFER: + return SCARD_E_INSUFFICIENT_BUFFER; + case IFD_ERROR_NOT_SUPPORTED: + case IFD_NOT_SUPPORTED: + case IFD_PROTOCOL_NOT_SUPPORTED: + return SCARD_E_UNSUPPORTED_FEATURE; + case IFD_ERROR_CONFISCATE: + case IFD_ERROR_EJECT: + case IFD_ERROR_POWER_ACTION: + return SCARD_E_CANT_DISPOSE; + case IFD_RESPONSE_TIMEOUT: + return SCARD_E_TIMEOUT; + case IFD_ICC_NOT_PRESENT: + return SCARD_E_NO_SMARTCARD; + case IFD_COMMUNICATION_ERROR: + return SCARD_F_COMM_ERROR; + case IFD_NO_SUCH_DEVICE: + return SCARD_E_READER_UNAVAILABLE; + case IFD_ERROR_TAG: + case IFD_ERROR_SET_FAILURE: + case IFD_ERROR_VALUE_READ_ONLY: + case IFD_ERROR_PTS_FAILURE: + case IFD_ERROR_SWALLOW: + default: + return SCARD_F_INTERNAL_ERROR; + } +} + +static LONG handle2atr(DWORD Lun, LPBYTE pbAtr, LPDWORD pcbAtrLen) +{ + LONG r; + void *atr; + unsigned char _atr[MAX_ATR_SIZE]; + + SET_R_TEST( responsecode2long( + IFDHICCPresence(Lun))); + + SET_R_TEST( autoallocate(pbAtr, pcbAtrLen, MAX_ATR_SIZE, (void **) &atr)); + + if (!atr) { + /* caller wants to have the length */ + *pcbAtrLen = sizeof _atr; + atr = _atr; + } + + SET_R_TEST( responsecode2long( + IFDHGetCapabilities (Lun, TAG_IFD_ATR, pcbAtrLen, atr))); + +err: + return r; +} + +PCSC_API LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext) +{ + if (!phContext) + return SCARD_E_INVALID_PARAMETER; + + if (!context_count) + initialize_globals(); + context_count++; + + *phContext = validhandle; + + return SCARD_S_SUCCESS; +} + +PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext) +{ + if (context_count) { + context_count--; + } + + if (!context_count) { + release_globals(); + } + + return SCARD_S_SUCCESS; +} + +PCSC_API LONG SCardIsValidContext(SCARDCONTEXT hContext) +{ + if (context_count && hContext == validhandle) + return SCARD_S_SUCCESS; + else + return SCARD_E_INVALID_HANDLE; +} + +PCSC_API LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout) +{ + /* XXX better return an error here? */ + return SCARD_S_SUCCESS; +} + +PCSC_API LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) +{ + struct card *card; + LONG r; + + SET_R_TEST( reader2card(szReader, &card, phCard)); + + if (card->usage_counter) { + /* card/reader already in use */ + if (card->dwShareMode == SCARD_SHARE_EXCLUSIVE + || card->dwShareMode != dwShareMode) { + /* cannot use the provided mode */ + return SCARD_E_SHARING_VIOLATION; + } + } + + card->usage_counter++; + card->dwShareMode = dwShareMode; + +err: + return r; +} + +PCSC_API LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol) +{ + struct card *card; + LONG r; + + SET_R_TEST( handle2card(hCard, &card)); + + if (card->usage_counter > 1 + && card->dwShareMode != dwShareMode) { + /* cannot use the provided mode */ + r = SCARD_E_SHARING_VIOLATION; + goto err; + } + + card->dwShareMode = dwShareMode; + +err: + return r; +} + +PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) +{ + DWORD Lun = hCard; + LONG r; + UCHAR Atr[MAX_ATR_SIZE]; + DWORD AtrLength = sizeof Atr; + struct card *card; + + SET_R_TEST( handle2card(hCard, &card)); + + if (!card->usage_counter) { + r = SCARD_E_INVALID_HANDLE; + goto err; + } + card->usage_counter--; + + switch (dwDisposition) { + case SCARD_LEAVE_CARD: + r = SCARD_S_SUCCESS; + break; + + case SCARD_RESET_CARD: + if (card->usage_counter) { + r = SCARD_E_CANT_DISPOSE; + goto err; + } + SET_R_TEST( responsecode2long( + IFDHPowerICC (Lun, IFD_RESET, Atr, &AtrLength))); + break; + + case SCARD_EJECT_CARD: + /* fall through */ + case SCARD_UNPOWER_CARD: + if (card->usage_counter) { + r = SCARD_E_CANT_DISPOSE; + goto err; + } + SET_R_TEST( responsecode2long( + IFDHPowerICC (Lun, IFD_POWER_DOWN, Atr, &AtrLength))); + break; + + default: + r = SCARD_E_INVALID_PARAMETER; + break; + } + +err: + return r; +} + +PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard) +{ + struct card *card; + LONG r; + + SET_R_TEST( handle2card(hCard, &card)); + + /* we don't have a strategy if an other card handle is active */ + if (card->usage_counter != 1) + return SCARD_E_SHARING_VIOLATION; + + card->dwShareMode = SCARD_SHARE_EXCLUSIVE; + +err: + return r; +} + +PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) +{ + struct card *card; + LONG r; + + SET_R_TEST( handle2card(hCard, &card)); + + card->dwShareMode = dwDisposition; + +err: + return r; +} + +PCSC_API LONG SCardCancelTransaction(SCARDHANDLE hCard) +{ + return SCARD_S_SUCCESS; +} + +PCSC_API LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) +{ + LONG r; + + SET_R_TEST( handle2reader(hCard, mszReaderName, pcchReaderLen)); + SET_R_TEST( handle2atr(hCard, pbAtr, pcbAtrLen)); + +err: + return r; +} + +PCSC_API LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders) +{ + SCARDHANDLE hCard; + size_t i, seconds, event_count = 0; + struct card *card; + + cancel_status = 0; + + if (dwTimeout == INFINITE) { + /* "infinite" timeout */ + seconds = 60; + } else { + seconds = dwTimeout/1000; + } + + do { + for (i = 0; i < cReaders; i++) { + if (rgReaderStates[i].dwCurrentState & SCARD_STATE_IGNORE) + /* this reader should be ignored */ + continue; + + if (strcmp(rgReaderStates[i].szReader, "\\\\?PnP?\\Notification") == 0) + /* we don't allow readers to be added or removed */ + continue; + + rgReaderStates[i].dwEventState = 0; + + if (SCARD_S_SUCCESS != reader2card(rgReaderStates[i].szReader, + &card, &hCard)) { + /* given reader not recognized */ + rgReaderStates[i].dwEventState |= SCARD_STATE_UNKNOWN + | SCARD_STATE_CHANGED |SCARD_STATE_IGNORE; + event_count++; + continue; + } + + if (card->usage_counter) { + rgReaderStates[i].dwEventState |= SCARD_STATE_INUSE; + if (card->dwShareMode == SCARD_SHARE_EXCLUSIVE) + rgReaderStates[i].dwEventState |= SCARD_STATE_EXCLUSIVE; + } + + /* normally the application should set cbAtr appropriately. + * Some application don't mind to do that (e.g., pcsc_scan) */ + rgReaderStates[i].cbAtr = sizeof rgReaderStates[i].rgbAtr; + + if (SCARD_S_SUCCESS != handle2atr(hCard, rgReaderStates[i].rgbAtr, + &rgReaderStates[i].cbAtr)) { + rgReaderStates[i].dwEventState |= SCARD_STATE_EMPTY; + rgReaderStates[i].cbAtr = 0; + } else { + rgReaderStates[i].dwEventState |= SCARD_STATE_PRESENT; + } + + /* if current and event state differ in the flags SCARD_STATE_EMPTY + * or SCARD_STATE_PRESENT a state change has occurred */ + if (((rgReaderStates[i].dwCurrentState & SCARD_STATE_EMPTY) + != (rgReaderStates[i].dwEventState & SCARD_STATE_EMPTY)) + || ((rgReaderStates[i].dwCurrentState & SCARD_STATE_PRESENT) + != (rgReaderStates[i].dwEventState & SCARD_STATE_PRESENT))) { + rgReaderStates[i].dwEventState |= SCARD_STATE_CHANGED; + event_count++; + } + } + + if (!seconds || event_count) + break; + + sleep(1); + seconds--; + + } while (!cancel_status); + + if (!event_count) + return SCARD_E_TIMEOUT; + + return SCARD_S_SUCCESS; +} + +PCSC_API LONG SCardCancel(SCARDHANDLE hCard) +{ + cancel_status = 1; + return SCARD_S_SUCCESS; +} + +PCSC_API LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned) +{ + return responsecode2long( + IFDHControl (hCard, dwControlCode, (PUCHAR) pbSendBuffer, + cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned)); +} + +PCSC_API LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength) +{ + DWORD Lun = hCard; + LONG r; + /* ignored */ + SCARD_IO_HEADER SendPci, RecvPci; + + /* transceive data */ + SET_R_TEST( responsecode2long( + IFDHTransmitToICC (Lun, SendPci, (PUCHAR) pbSendBuffer, + cbSendLength, pbRecvBuffer, pcbRecvLength, &RecvPci))); + +err: + return r; +} + +PCSC_API LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen) +{ + return SCARD_F_INTERNAL_ERROR; +} + +PCSC_API LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen) +{ + return SCARD_F_INTERNAL_ERROR; +} + +PCSC_API LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders) +{ + DWORD Lun; + DWORD readerslen = 0, readerlen; + LONG r; + char *readers; + + if (!pcchReaders) { + r = SCARD_E_INVALID_PARAMETER; + goto err; + } + + + SET_R_TEST( autoallocate(mszReaders, pcchReaders, + (MAX_READERNAME+1)*PCSCLITE_MAX_READERS_CONTEXTS, + (void **) &readers)); + + + /* write reader names */ + for (Lun = 0; Lun < PCSCLITE_MAX_READERS_CONTEXTS; Lun++) { + /* what memory we have left */ + readerlen = *pcchReaders - readerslen; + + /* get the current readername */ + SET_R_TEST( handle2reader(Lun, readers ? readers+readerslen : NULL, + &readerlen)); + + /* readerlen has been set to the correct value */ + readerslen += readerlen; + /* copy null character */ + readerslen++; + } + + *pcchReaders = readerslen; + + if (!readerslen) { + r = SCARD_E_NO_READERS_AVAILABLE; + } else { + r = SCARD_S_SUCCESS; + } + +err: + return r; +} + +PCSC_API LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups) +{ + LONG r; + unsigned char *groups; + + SET_R_TEST( autoallocate(mszGroups, pcchGroups, 1, (void **) &groups)); + + if (groups) { + /* caller wants to have the string */ + *groups = '\0'; + } else { + /* caller wants to have the length */ + } + + *pcchGroups = 1; + + +err: + return r; +} + +PCSC_API LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem) +{ + free((void *) pvMem); + + return SCARD_S_SUCCESS; +} + +/* copied from error.c of pcsc-lite-1.5.5 */ +char *pcsc_stringify_error(const long pcscError) +{ + static char strError[75]; + + switch (pcscError) { + case SCARD_S_SUCCESS: + (void)strncpy(strError, "Command successful.", sizeof(strError)); + break; + case SCARD_E_CANCELLED: + (void)strncpy(strError, "Command cancelled.", sizeof(strError)); + break; + case SCARD_E_CANT_DISPOSE: + (void)strncpy(strError, "Cannot dispose handle.", sizeof(strError)); + break; + case SCARD_E_INSUFFICIENT_BUFFER: + (void)strncpy(strError, "Insufficient buffer.", sizeof(strError)); + break; + case SCARD_E_INVALID_ATR: + (void)strncpy(strError, "Invalid ATR.", sizeof(strError)); + break; + case SCARD_E_INVALID_HANDLE: + (void)strncpy(strError, "Invalid handle.", sizeof(strError)); + break; + case SCARD_E_INVALID_PARAMETER: + (void)strncpy(strError, "Invalid parameter given.", sizeof(strError)); + break; + case SCARD_E_INVALID_TARGET: + (void)strncpy(strError, "Invalid target given.", sizeof(strError)); + break; + case SCARD_E_INVALID_VALUE: + (void)strncpy(strError, "Invalid value given.", sizeof(strError)); + break; + case SCARD_E_NO_MEMORY: + (void)strncpy(strError, "Not enough memory.", sizeof(strError)); + break; + case SCARD_F_COMM_ERROR: + (void)strncpy(strError, "RPC transport error.", sizeof(strError)); + break; + case SCARD_F_INTERNAL_ERROR: + (void)strncpy(strError, "Internal error.", sizeof(strError)); + break; + case SCARD_F_UNKNOWN_ERROR: + (void)strncpy(strError, "Unknown error.", sizeof(strError)); + break; + case SCARD_F_WAITED_TOO_LONG: + (void)strncpy(strError, "Waited too long.", sizeof(strError)); + break; + case SCARD_E_UNKNOWN_READER: + (void)strncpy(strError, "Unknown reader specified.", sizeof(strError)); + break; + case SCARD_E_TIMEOUT: + (void)strncpy(strError, "Command timeout.", sizeof(strError)); + break; + case SCARD_E_SHARING_VIOLATION: + (void)strncpy(strError, "Sharing violation.", sizeof(strError)); + break; + case SCARD_E_NO_SMARTCARD: + (void)strncpy(strError, "No smart card inserted.", sizeof(strError)); + break; + case SCARD_E_UNKNOWN_CARD: + (void)strncpy(strError, "Unknown card.", sizeof(strError)); + break; + case SCARD_E_PROTO_MISMATCH: + (void)strncpy(strError, "Card protocol mismatch.", sizeof(strError)); + break; + case SCARD_E_NOT_READY: + (void)strncpy(strError, "Subsystem not ready.", sizeof(strError)); + break; + case SCARD_E_SYSTEM_CANCELLED: + (void)strncpy(strError, "System cancelled.", sizeof(strError)); + break; + case SCARD_E_NOT_TRANSACTED: + (void)strncpy(strError, "Transaction failed.", sizeof(strError)); + break; + case SCARD_E_READER_UNAVAILABLE: + (void)strncpy(strError, "Reader is unavailable.", sizeof(strError)); + break; + case SCARD_W_UNSUPPORTED_CARD: + (void)strncpy(strError, "Card is not supported.", sizeof(strError)); + break; + case SCARD_W_UNRESPONSIVE_CARD: + (void)strncpy(strError, "Card is unresponsive.", sizeof(strError)); + break; + case SCARD_W_UNPOWERED_CARD: + (void)strncpy(strError, "Card is unpowered.", sizeof(strError)); + break; + case SCARD_W_RESET_CARD: + (void)strncpy(strError, "Card was reset.", sizeof(strError)); + break; + case SCARD_W_REMOVED_CARD: + (void)strncpy(strError, "Card was removed.", sizeof(strError)); + break; + case SCARD_STATE_PRESENT: + (void)strncpy(strError, "Card was inserted.", sizeof(strError)); + break; + case SCARD_E_UNSUPPORTED_FEATURE: + (void)strncpy(strError, "Feature not supported.", sizeof(strError)); + break; + case SCARD_E_PCI_TOO_SMALL: + (void)strncpy(strError, "PCI struct too small.", sizeof(strError)); + break; + case SCARD_E_READER_UNSUPPORTED: + (void)strncpy(strError, "Reader is unsupported.", sizeof(strError)); + break; + case SCARD_E_DUPLICATE_READER: + (void)strncpy(strError, "Reader already exists.", sizeof(strError)); + break; + case SCARD_E_CARD_UNSUPPORTED: + (void)strncpy(strError, "Card is unsupported.", sizeof(strError)); + break; + case SCARD_E_NO_SERVICE: + (void)strncpy(strError, "Service not available.", sizeof(strError)); + break; + case SCARD_E_SERVICE_STOPPED: + (void)strncpy(strError, "Service was stopped.", sizeof(strError)); + break; + case SCARD_E_NO_READERS_AVAILABLE: + (void)strncpy(strError, "Cannot find a smart card reader.", sizeof(strError)); + break; + default: + (void)snprintf(strError, sizeof(strError)-1, "Unkown error: 0x%08lX", + pcscError); + }; + + /* add a null byte */ + strError[sizeof(strError)-1] = '\0'; + + return strError; +} diff --git a/virtualsmartcard/src/vpcd/Makefile.am b/virtualsmartcard/src/vpcd/Makefile.am index d8d862c..76becb1 100644 --- a/virtualsmartcard/src/vpcd/Makefile.am +++ b/virtualsmartcard/src/vpcd/Makefile.am @@ -1,19 +1,24 @@ VPCD_LIB = $(LIB_PREFIX)vpcd.$(DYN_LIB_EXT) -lib_LTLIBRARIES = libvpcd.la libvpcd_la_SOURCES = ifd-vpcd.c vpcd.c libvpcd_la_LIBADD = $(PCSC_LIBS) libvpcd_la_LDFLAGS = -no-undefined libvpcd_la_CFLAGS = $(PCSC_CFLAGS) +lib_LTLIBRARIES = libvpcd.la + noinst_HEADERS = vpcd.h EXTRA_DIST = reader.conf.in -do_subst = $(SED) -e 's,[@]TARGET[@],$(serialdropdir)/$(VPCD_LIB),g' +do_subst = $(SED) \ + -e 's,[@]TARGET[@],$(serialdropdir)/$(VPCD_LIB),g' \ + -e 's,[@]VPCDHOST[@],$(vpcdhost),g' +if BUILD_LIBPCSCLITE +else install: install_libvpcd install_libvpcd: libvpcd.la reader.conf.in @@ -31,3 +36,5 @@ uninstall_libvpcd: rm -f $(DESTDIR)$(serialdropdir)/$(VPCD_LIB).$(VERSION) \ $(DESTDIR)$(serialdropdir)/$(VPCD_LIB) \ $(DESTDIR)$(serialconfdir)/vpcd + +endif diff --git a/virtualsmartcard/src/vpcd/ifd-vpcd.c b/virtualsmartcard/src/vpcd/ifd-vpcd.c index ca48a07..5ec28fc 100644 --- a/virtualsmartcard/src/vpcd/ifd-vpcd.c +++ b/virtualsmartcard/src/vpcd/ifd-vpcd.c @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2010-2013 Frank Morgner + * + * This file is part of virtualsmartcard. + * + * virtualsmartcard is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * virtualsmartcard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * virtualsmartcard. If not, see . + */ +#include "ifd-vpcd.h" #include "vpcd.h" #include #include @@ -8,13 +27,12 @@ /* pcscd allows at most 16 readers. We will use 10. * See PCSCLITE_MAX_READERS_CONTEXTS in pcsclite.h */ -#define VICC_MAX_SLOTS \ - (PCSCLITE_MAX_READERS_CONTEXTS > 6 ? \ - PCSCLITE_MAX_READERS_CONTEXTS-6 : \ - 1) +const unsigned char VICC_MAX_SLOTS = + PCSCLITE_MAX_READERS_CONTEXTS > 6 ? + PCSCLITE_MAX_READERS_CONTEXTS-6 : 1; static struct vicc_ctx *ctx[VICC_MAX_SLOTS]; -static char *hostname = NULL; +const char *hostname = NULL; static const char openport[] = "/dev/null"; RESPONSECODE diff --git a/virtualsmartcard/src/vpcd/ifd-vpcd.h b/virtualsmartcard/src/vpcd/ifd-vpcd.h new file mode 100644 index 0000000..daf0503 --- /dev/null +++ b/virtualsmartcard/src/vpcd/ifd-vpcd.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 Frank Morgner + * + * This file is part of virtualsmartcard. + * + * virtualsmartcard is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * virtualsmartcard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * virtualsmartcard. If not, see . + */ +#ifndef _IFD_VPCD_H_ +#define _IFD_VPCD_H_ + +extern const unsigned char VICC_MAX_SLOTS; +extern const char *hostname; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/virtualsmartcard/src/vpcd/reader.conf.in b/virtualsmartcard/src/vpcd/reader.conf.in index e92228f..416a2b7 100644 --- a/virtualsmartcard/src/vpcd/reader.conf.in +++ b/virtualsmartcard/src/vpcd/reader.conf.in @@ -1,4 +1,4 @@ FRIENDLYNAME "Virtual PCD" -DEVICENAME /dev/null:0x8C7B +DEVICENAME @VPCDHOST@:0x8C7B LIBPATH @TARGET@ CHANNELID 0x8C7B diff --git a/virtualsmartcard/src/vpcd/vpcd.c b/virtualsmartcard/src/vpcd/vpcd.c index e12c605..cf6b20d 100644 --- a/virtualsmartcard/src/vpcd/vpcd.c +++ b/virtualsmartcard/src/vpcd/vpcd.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Frank Morgner + * Copyright (C) 2009-2013 Frank Morgner * * This file is part of virtualsmartcard. * @@ -18,6 +18,14 @@ */ #include "vpcd.h" +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined HAVE_DECL_MSG_NOSIGNAL && !HAVE_DECL_MSG_NOSIGNAL +#define MSG_NOSIGNAL +#endif + #ifdef _WIN32 #include #include @@ -64,7 +72,7 @@ ssize_t sendall(int sock, const void *buffer, size_t size) ssize_t r; for (sent = 0; sent < size; sent += r) { - r = send(sock, (void *) (buffer+sent), size-sent, 0); + r = send(sock, (void *) (buffer+sent), size-sent, MSG_NOSIGNAL); if (r < 0) return r; @@ -74,7 +82,7 @@ ssize_t sendall(int sock, const void *buffer, size_t size) } ssize_t recvall(int sock, void *buffer, size_t size) { - return recv(sock, buffer, size, MSG_WAITALL); + return recv(sock, buffer, size, MSG_WAITALL|MSG_NOSIGNAL); } static int opensock(unsigned short port) @@ -90,6 +98,11 @@ static int opensock(unsigned short port) if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &yes, sizeof yes) != 0) return -1; +#if HAVE_DECL_SO_NOSIGPIPE + if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *) &yes, sizeof yes) != 0) + return -1; +#endif + memset(&server_sockaddr, 0, sizeof server_sockaddr); server_sockaddr.sin_family = PF_INET; server_sockaddr.sin_port = htons(port); @@ -302,6 +315,9 @@ ssize_t vicc_transmit(struct vicc_ctx *ctx, int vicc_present(struct vicc_ctx *ctx) { unsigned char *atr = NULL; + if (!ctx) + return 0; + if (ctx->client_sock < 0) { if (ctx->server_sock) { /* server mode, try to accept a client */ diff --git a/virtualsmartcard/src/vpcd/vpcd.h b/virtualsmartcard/src/vpcd/vpcd.h index ce5aa86..f124133 100644 --- a/virtualsmartcard/src/vpcd/vpcd.h +++ b/virtualsmartcard/src/vpcd/vpcd.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Frank Morgner + * Copyright (C) 2009-2013 Frank Morgner * * This file is part of virtualsmartcard. *