diff --git a/ChangeLog b/ChangeLog index 520e794..a7f4d2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +1.9.9: Ludovic Rousseau +11 September 2022 +- SCardEstablishContext() may return SCARD_W_SECURITY_VIOLATION if refused by Polkit +- Fix SCardReleaseContext() failure on orphan handles +- Fix SCardDisconnect() on orphan handle +- pcsc-spy: log the pioSendPci & pioRecvPci SCardTransmit() parameters +- Improve the log from pcscd: log the return code in text instead of hex +- Some other minor improvements + + 1.9.8: Ludovic Rousseau 11 June 2022 - Install install_spy.sh & uninstall_spy.sh scripts in docdir diff --git a/ChangeLog.git b/ChangeLog.git index 699c733..5fc6a03 100644 --- a/ChangeLog.git +++ b/ChangeLog.git @@ -1,4 +1,290 @@ -commit 41dc5a51321bc3198af36574f73dc007cab72a7d (HEAD -> master, tag: 1.9.8) +commit 15c16c7796607b1c8a2ce253d3f536918ab26b4a (HEAD -> master, origin/master, origin/HEAD) +Author: Ludovic Rousseau +Date: Sun Sep 11 16:12:03 2022 +0200 + + Release 1.9.9 + + Signed-off-by: Ludovic Rousseau + + ChangeLog | 10 ++++++++++ + configure.ac | 2 +- + 2 files changed, 11 insertions(+), 1 deletion(-) + +commit d069c580b74273bfcf12523b73f71bb6be9378dd (zotac/master, github/master) +Author: Ludovic Rousseau +Date: Sun Sep 11 13:59:34 2022 +0200 + + c.sh: reformat + + c.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 241a993f954b00cbb5904ac5fc6e4425977fc319 +Author: Ludovic Rousseau +Date: Thu Sep 8 19:43:39 2022 +0200 + + UT control_get_firmware: support multi-readers + + Do not exit if the command fails with a reader but continue with the other + readers. + + UnitaryTests/control_get_firmware.py | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +commit 1935b6997b281f0d836b829b4cfeeab6c81c3ded +Author: Ludovic Rousseau +Date: Sat Aug 20 15:29:28 2022 +0200 + + SCardEstablishContext() may return SCARD_W_SECURITY_VIOLATION + + See the previous patch for details. + + src/winscard_clnt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 68f629ffecaec3886c717021e70ac62c22b38bd8 +Author: Ludovic Rousseau +Date: Sat Aug 20 15:13:00 2022 +0200 + + MessageReceive() may return SCARD_W_SECURITY_VIOLATION + + If the daemon kills/resets the connection because the user is not + authorized by Polkit then the client side now returns + SCARD_W_SECURITY_VIOLATION instead of the too generic + SCARD_F_COMM_ERROR. + Polkit is used in RedHat/Fedora. Users connected by ssh do not have + access to PC/SC by default. + + On the daemon side we have in the logs: + 00000003 [139737213696960] pcscdaemon.c:133:SVCServiceRunLoop() A new + context thread creation is requested: 10 + 00019807 [139737012623104] auth.c:139:IsClientAuthorized() Process + 41685 (user: 1000) is NOT authorized for action: access_pcsc + 00000107 [139737012623104] winscard_svc.c:335:ContextThread() Rejected + unauthorized PC/SC client + But this information was not available in the client side. + + pcsc_scan will now report: + $ pcsc_scan + SCardEstablishContext: Access denied. + + This has been discussed on the pcsclite-muscle mailing list at: + "[Pcsclite-muscle] Change the error code when PC/SC access is refused by + polkit?" + http://lists.infradead.org/pipermail/pcsclite-muscle/2022-July/001279.html + + src/winscard_msg.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +commit 34f27e766f413d8f37a95ad605dbe6f664c077bc +Author: Ludovic Rousseau +Date: Sat Aug 20 15:03:53 2022 +0200 + + pcsc_stringify_error(): add SCARD_W_SECURITY_VIOLATION + + src/error.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +commit 8eca1a54b252a84f5498ac5e5b84e81a47c9d231 +Author: Ludovic Rousseau +Date: Sat Aug 20 14:45:14 2022 +0200 + + Remove unsed #define + + SCARD_PROTOCOL_ANY_OLD is no more used on the client side. + + src/winscard_clnt.c | 3 --- + 1 file changed, 3 deletions(-) + +commit 6a6291eb8e7906d4f63c962360e5fdc5d6d745db +Author: Ludovic Rousseau +Date: Sat Aug 13 14:44:28 2022 +0200 + + Log the error in text and not just the hex code + + We now have: + 00000008 [139893430789696] winscard.c:1621:SCardTransmit() Card not transacted: rv=SCARD_E_NO_SMARTCARD + instead of: + 00000008 [139893430789696] winscard.c:1621:SCardTransmit() Card not transacted: rv=0x8010000C + + src/eventhandler.c | 2 +- + src/readerfactory.c | 2 +- + src/winscard.c | 14 +++++++------- + 3 files changed, 9 insertions(+), 9 deletions(-) + +commit fecbcac0e6a8cf43b691151fef2967600098b49b +Author: Ludovic Rousseau +Date: Sat Aug 13 14:52:42 2022 +0200 + + UnitaryTests: fix a deprecation warning + + UnitaryTests/ThreadSafeConnect.py:87: DeprecationWarning: getName() is deprecated, get the name attribute instead + print("joined:", thread.getName()) + + UnitaryTests/ThreadSafeConnect.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 13bd3dcc9fa1ae6894ac4f882c5a62b28a6adde5 +Author: Ludovic Rousseau +Date: Sat Aug 13 14:41:59 2022 +0200 + + export rv2txt() function + + convert from integer rv value to a string value + SCARD_S_SUCCESS -> "SCARD_S_SUCCESS" + + src/PCSC/debuglog.h | 2 ++ + src/debuglog.c | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +commit 002d1ffef359cfba1c45f24c78ac21e18925e670 +Author: Ludovic Rousseau +Date: Fri Aug 12 17:51:37 2022 +0200 + + Improve the log from pcscd + + - log the return code in text instead of hex + 00000002 [139848448452160] winscard_svc.c:523:ContextThread() CONNECT for client 12, rv=SCARD_E_UNKNOWN_READER + insted of: + 00000004 [140270933177920] winscard_svc.c:523:ContextThread() CONNECT rv=0x80100009 for client 12 + + - colorize the return value in red in case it is different from SCARD_S_SUCCESS + + The idea is to more easily spot an error code in the values returned by + pcscd. + + src/PCSC/debuglog.h | 5 +++ + src/debuglog.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++---- + src/winscard_svc.c | 2 +- + 3 files changed, 107 insertions(+), 9 deletions(-) + +commit e2de54e00f2ebeebf633adef32228d2af33a6483 +Author: Ludovic Rousseau +Date: Sat Jul 30 14:02:49 2022 +0200 + + pcsc-spy: log the pioSendPci & pioRecvPci SCardTransmit() parameters + + The pioSendPci contains the protocol to use and may be important to + diagnose a SCARD_E_PROTO_MISMATCH error. + + src/spy/libpcscspy.c | 4 ++++ + src/spy/pcsc-spy | 30 ++++++++++++++++++++++++++++++ + 2 files changed, 34 insertions(+) + +commit af1f32ca3762374dc66aac972c0c3fc50e9ae566 +Author: Ludovic Rousseau +Date: Sun Jul 17 17:57:26 2022 +0200 + + pcscd.8: remove reference to bundleTool + + bundleTool is no more provided with pcsc-lite since + 84448b0d2a7b5300837c40311f12d81a959a9f45 in 2006. + + doc/pcscd.8.in | 1 - + 1 file changed, 1 deletion(-) + +commit ff8f77d445ebf7f863ed4cf4951b7ab6e1d08426 +Author: Ludovic Rousseau +Date: Sun Jul 17 17:52:29 2022 +0200 + + pcscd.8: fix typo in manpage + + doc/pcscd.8.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit c35130f2215b75c6d54c4f0162d68548a6de4bab +Author: Ludovic Rousseau +Date: Sun Jun 19 21:32:20 2022 +0200 + + Improve SCardDisconnect fix + + Same justification as for the previous patch. RFReaderInfoById() may + return SCARD_E_READER_UNAVAILABLE. + + src/winscard.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit d7a08877c3f1d423f8fcfcb5b60f2cf6fefeceda +Author: Ludovic Rousseau +Date: Sun Jun 19 21:27:46 2022 +0200 + + Improve SCardReleaseContext fix + + From Maksim Ivanov: + SCARD_E_READER_UNAVAILABLE can be returned by RFReaderInfoById(): it's a + corner case when the reader context is still there, but has a zero + reference count. + + See RFReaderInfoById() using the REF_READER macro, which calls + _RefReader() (and returns its error code on error), which in turn has + this code: + + if (0 == sReader->reference) + return SCARD_E_READER_UNAVAILABLE; + + src/winscard_svc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit d0e594789096c7b99ace1ec6ab2cecb7961747cb +Author: Ludovic Rousseau +Date: Sun Jun 19 18:53:36 2022 +0200 + + Test orphan handles + + Check the return values of SCardDisconnect() and SCardReleaseContext() + after a reader removal. + + UnitaryTests/SCard_RemovedReader.py | 80 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 80 insertions(+) + +commit a4e5bf41ae652fd3837cc446a5a8cce0f4249845 +Author: Ludovic Rousseau +Date: Sun Jun 19 18:49:42 2022 +0200 + + Fix SCardDisconnect on orphan handle + + If the reader is removed between SCardConnect() and SCardDisconnect() + then SCardDisconnect() should not fail with SCARD_E_INVALID_VALUE. + + We now have the same behavior as on Windows 10. + + This patch is quiet similar to the previous one from Maksim Ivanov. + Thanks for the idea. + + src/winscard.c | 3 +++ + 1 file changed, 3 insertions(+) + +commit 2735a6d1b7ffa5ca81e602417516a9c0702c0fcd +Author: Maksim Ivanov +Date: Sat Jun 18 13:46:38 2022 +0200 + + Fix SCardReleaseContext failure on orphan handles + + Fix returning a spurious error from SCardReleaseContext() for a + correct SCARDCONTEXT, in case there was an orphan SCARDHANDLE left after + disconnecting a reader. + + The error was caused by the fact that SCardReleaseContext attempts to do + SCardDisconnect for all active SCARDHANDLEs stored in SCARDCONTEXT, + which fails when the handle was already deleted by the hotplug code from + READER_CONTEXT or the reader got zero reference count. + + src/winscard_svc.c | 59 ++++++++++++++++++++++++++++++------------------------ + 1 file changed, 33 insertions(+), 26 deletions(-) + +commit 2c3e9156bea6d658f5f7af801f5b92cdb9c83882 +Author: Ludovic Rousseau +Date: Mon Jun 13 17:11:50 2022 +0200 + + pcscd.h: remove unused PCSCLITE_STATUS_WAIT + + PCSCLITE_STATUS_WAIT is no more used since + c2a93242e445558ead8eea40223482ee8995954a in 2008. + + src/pcscd.h.in | 2 -- + 1 file changed, 2 deletions(-) + +commit 41dc5a51321bc3198af36574f73dc007cab72a7d (tag: 1.9.8) Author: Ludovic Rousseau Date: Sat Jun 11 10:49:34 2022 +0200 @@ -10,7 +296,7 @@ Date: Sat Jun 11 10:49:34 2022 +0200 configure.ac | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) -commit f7f80db5fae5f15c0d0ce2e6cd81a5c11c0a7510 (zotac/master, origin/master, origin/HEAD, github/master) +commit f7f80db5fae5f15c0d0ce2e6cd81a5c11c0a7510 Author: Ludovic Rousseau Date: Fri Jun 10 09:58:46 2022 +0200 diff --git a/Makefile.in b/Makefile.in index ebac14b..7be8054 100644 --- a/Makefile.in +++ b/Makefile.in @@ -160,7 +160,7 @@ DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/src/PCSC/pcsclite.h.in AUTHORS COPYING ChangeLog \ INSTALL NEWS README TODO ar-lib compile config.guess \ - config.sub install-sh ltmain.sh missing ylwrap + config.sub depcomp install-sh ltmain.sh missing ylwrap DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) diff --git a/configure b/configure index 78e41f3..db22796 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for pcsc-lite 1.9.8. +# Generated by GNU Autoconf 2.71 for pcsc-lite 1.9.9. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, @@ -618,8 +618,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='pcsc-lite' PACKAGE_TARNAME='pcsc-lite' -PACKAGE_VERSION='1.9.8' -PACKAGE_STRING='pcsc-lite 1.9.8' +PACKAGE_VERSION='1.9.9' +PACKAGE_STRING='pcsc-lite 1.9.9' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1424,7 +1424,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pcsc-lite 1.9.8 to adapt to many kinds of systems. +\`configure' configures pcsc-lite 1.9.9 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1495,7 +1495,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pcsc-lite 1.9.8:";; + short | recursive ) echo "Configuration of pcsc-lite 1.9.9:";; esac cat <<\_ACEOF @@ -1649,7 +1649,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pcsc-lite configure 1.9.8 +pcsc-lite configure 1.9.9 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2065,7 +2065,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pcsc-lite $as_me 1.9.8, which was +It was created by pcsc-lite $as_me 1.9.9, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3336,7 +3336,7 @@ fi # Define the identity of the package. PACKAGE='pcsc-lite' - VERSION='1.9.8' + VERSION='1.9.9' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -17242,7 +17242,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pcsc-lite $as_me 1.9.8, which was +This file was extended by pcsc-lite $as_me 1.9.9, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17310,7 +17310,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -pcsc-lite config.status 1.9.8 +pcsc-lite config.status 1.9.9 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 55d3c6d..467c1ee 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.69]) -AC_INIT([pcsc-lite],[1.9.8]) +AC_INIT([pcsc-lite],[1.9.9]) AC_CONFIG_SRCDIR(src/pcscdaemon.c) AM_INIT_AUTOMAKE(1.8 dist-bzip2 no-dist-gzip) AC_CONFIG_HEADERS([config.h]) diff --git a/doc/pcscd.8.in b/doc/pcscd.8.in index 16cb514..f9c4cfd 100644 --- a/doc/pcscd.8.in +++ b/doc/pcscd.8.in @@ -77,7 +77,7 @@ files to detect added or removed non-USB readers (serial or PCMCIA). .BR \-x ", " \-\-auto\-exit pcscd will quit after 60 seconds of inactivity after the release of the last PC/SC context. This is used when pcscd -os started on demand by systemd. +is started on demand by systemd. .TP .BR \-S ", " \-\-reader\-name\-no\-serial Do not include the USB serial number in the reader name. @@ -90,7 +90,7 @@ coordinates communications with smart card readers and smart cards and cryptographic tokens that are connected to the system. .PP It allows applications to access smart cards and readers using the -winscard API but without knowing details of the card or reader. +WinSCard API but without knowing details of the card or reader. .PP pcscd coordinates the loading of drivers for card readers. . @@ -125,7 +125,6 @@ file. : directory containing bundles for USB drivers . .SH "SEE ALSO" -.BR bundleTool (8), .BR reader.conf (5), .BR syslog (3) . diff --git a/src/PCSC/debuglog.h b/src/PCSC/debuglog.h index 856350d..64883e2 100644 --- a/src/PCSC/debuglog.h +++ b/src/PCSC/debuglog.h @@ -92,9 +92,11 @@ enum { #define Log2(priority, fmt, data) do {(void)priority; } while(0) #define Log3(priority, fmt, data1, data2) do {int p = priority; (void)p; } while(0) #define Log4(priority, fmt, data1, data2, data3) do { } while(0) +#define LogRv4(priority, rv, fmt, data1, data2) 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 rv2text(rv) "" #define DebugLogA(a) #define DebugLogB(a, b) @@ -107,9 +109,11 @@ enum { #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 LogRv4(priority, rv, fmt, data1, data2) log_msg_rv(priority, rv, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2) #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) +const char * rv2text(unsigned int rv); #define DebugLogA(a) Log1(PCSC_LOG_INFO, a) #define DebugLogB(a, b) Log2(PCSC_LOG_INFO, a, b) @@ -117,6 +121,9 @@ enum { #endif /* NO_LOG */ +PCSC_API void log_msg_rv(const int priority, unsigned int rv, const char *fmt, ...) + __attribute__((format(printf, 3, 4))); + PCSC_API void log_msg(const int priority, const char *fmt, ...) __attribute__((format(printf, 2, 3))); diff --git a/src/debuglog.c b/src/debuglog.c index a6bcd31..ac87676 100644 --- a/src/debuglog.c +++ b/src/debuglog.c @@ -110,7 +110,27 @@ static char LogLevel = PCSC_LOG_ERROR; static signed char LogDoColor = 0; /**< no color by default */ -static void log_line(const int priority, const char *DebugBuffer); +static void log_line(const int priority, const char *DebugBuffer, + unsigned int rv); + +/* + * log a message with the RV value returned by the daemon + */ +void log_msg_rv(const int priority, unsigned int rv, const char *fmt, ...) +{ + char DebugBuffer[DEBUG_BUF_SIZE]; + va_list argptr; + + if ((priority < LogLevel) /* log priority lower than threshold? */ + || (DEBUGLOG_NO_DEBUG == LogMsgType)) + return; + + va_start(argptr, fmt); + vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr); + va_end(argptr); + + log_line(priority, DebugBuffer, rv); +} void log_msg(const int priority, const char *fmt, ...) { @@ -125,10 +145,62 @@ void log_msg(const int priority, const char *fmt, ...) vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr); va_end(argptr); - log_line(priority, DebugBuffer); + log_line(priority, DebugBuffer, -1); } /* log_msg */ -static void log_line(const int priority, const char *DebugBuffer) +/* convert from integer rv value to a string value + * SCARD_S_SUCCESS -> "SCARD_S_SUCCESS" + */ +const char * rv2text(unsigned int rv) +{ + const char *rv_text = NULL; + static __thread char strError[30]; + +#define CASE(x) \ + case x: \ + rv_text = "rv=" #x; \ + break + + if (rv != (unsigned int)-1) + { + switch (rv) + { + CASE(SCARD_S_SUCCESS); + CASE(SCARD_E_CANCELLED); + CASE(SCARD_E_INSUFFICIENT_BUFFER); + CASE(SCARD_E_INVALID_HANDLE); + CASE(SCARD_E_INVALID_PARAMETER); + CASE(SCARD_E_INVALID_VALUE); + CASE(SCARD_E_NO_MEMORY); + CASE(SCARD_E_NO_SERVICE); + CASE(SCARD_E_NO_SMARTCARD); + CASE(SCARD_E_NOT_TRANSACTED); + CASE(SCARD_E_PROTO_MISMATCH); + CASE(SCARD_E_READER_UNAVAILABLE); + CASE(SCARD_E_SHARING_VIOLATION); + CASE(SCARD_E_TIMEOUT); + CASE(SCARD_E_UNKNOWN_READER); + CASE(SCARD_E_UNSUPPORTED_FEATURE); + CASE(SCARD_F_COMM_ERROR); + CASE(SCARD_F_INTERNAL_ERROR); + CASE(SCARD_W_REMOVED_CARD); + CASE(SCARD_W_RESET_CARD); + CASE(SCARD_W_UNPOWERED_CARD); + CASE(SCARD_W_UNRESPONSIVE_CARD); + CASE(SCARD_E_NO_READERS_AVAILABLE); + + default: + (void)snprintf(strError, sizeof(strError)-1, + "Unknown error: 0x%08X", rv); + rv_text = strError; + } + } + + return rv_text; +} + +static void log_line(const int priority, const char *DebugBuffer, + unsigned int rv) { if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType) syslog(LOG_INFO, "%s", DebugBuffer); @@ -139,6 +211,7 @@ static void log_line(const int priority, const char *DebugBuffer) struct timeval tmp; int delta; pthread_t thread_id; + const char *rv_text = NULL; gettimeofday(&new_time, NULL); if (0 == last_time.tv_sec) @@ -160,6 +233,8 @@ static void log_line(const int priority, const char *DebugBuffer) thread_id = pthread_self(); + rv_text = rv2text(rv); + if (LogDoColor) { const char *color_pfx = "", *color_sfx = "\33[0m"; @@ -190,13 +265,31 @@ static void log_line(const int priority, const char *DebugBuffer) #else #define THREAD_FORMAT "%lu" #endif - printf("%s%.8d%s [" THREAD_FORMAT "] %s%s%s\n", - time_pfx, delta, time_sfx, thread_id, - color_pfx, DebugBuffer, color_sfx); + if (rv_text) + { + const char * rv_pfx = "", * rv_sfx = ""; + if (rv != SCARD_S_SUCCESS) + { + rv_pfx = "\33[31m"; /* Red */ + rv_sfx = "\33[0m"; + } + + printf("%s%.8d%s [" THREAD_FORMAT "] %s%s%s, %s%s%s\n", + time_pfx, delta, time_sfx, thread_id, + color_pfx, DebugBuffer, color_sfx, + rv_pfx, rv_text, rv_sfx); + } + else + printf("%s%.8d%s [" THREAD_FORMAT "] %s%s%s\n", + time_pfx, delta, time_sfx, thread_id, + color_pfx, DebugBuffer, color_sfx); } else { - printf("%.8d %s\n", delta, DebugBuffer); + if (rv_text) + printf("%.8d %s, %s\n", delta, DebugBuffer, rv_text); + else + printf("%.8d %s\n", delta, DebugBuffer); } fflush(stdout); } @@ -220,7 +313,7 @@ static void log_xxd_always(const int priority, const char *msg, c += 3; } - log_line(priority, DebugBuffer); + log_line(priority, DebugBuffer, -1); } /* log_xxd_always */ void log_xxd(const int priority, const char *msg, const unsigned char *buffer, diff --git a/src/error.c b/src/error.c index 2a0523f..498445b 100644 --- a/src/error.c +++ b/src/error.c @@ -213,7 +213,9 @@ PCSC_API const char* pcsc_stringify_error(const LONG pcscError) case SCARD_W_REMOVED_CARD: msg = "Card was removed."; break; - /* case SCARD_W_SECURITY_VIOLATION: */ + case SCARD_W_SECURITY_VIOLATION: + msg = "Access denied."; + break; /* case SCARD_W_WRONG_CHV: */ /* case SCARD_W_CHV_BLOCKED: */ /* case SCARD_W_EOF: */ diff --git a/src/eventhandler.c b/src/eventhandler.c index 179ea11..e64b1d5 100644 --- a/src/eventhandler.c +++ b/src/eventhandler.c @@ -302,7 +302,7 @@ static void * EHStatusHandlerThread(READER_CONTEXT * rContext) readerState = SCARD_PRESENT | SCARD_SWALLOWED; RFSetPowerState(rContext, POWER_STATE_UNPOWERED); Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED"); - Log3(PCSC_LOG_ERROR, "Error powering up card: %ld 0x%04lX", rv, rv); + Log2(PCSC_LOG_ERROR, "Error powering up card: %s", rv2text(rv)); } #endif diff --git a/src/pcscd.h.in b/src/pcscd.h.in index 86ec1b0..81c2988 100644 --- a/src/pcscd.h.in +++ b/src/pcscd.h.in @@ -57,8 +57,6 @@ #define PCSC_MAX_CONTEXT_CARD_HANDLES 200 #define PCSC_MAX_READER_HANDLES 200 -#define PCSCLITE_STATUS_WAIT 200000 /**< Status Change Sleep */ - /** Different values for struct ReaderContext powerState field */ enum { diff --git a/src/readerfactory.c b/src/readerfactory.c index a3af9d5..1cb4197 100644 --- a/src/readerfactory.c +++ b/src/readerfactory.c @@ -1395,7 +1395,7 @@ void RFCleanupReaders(void) REMOVE_READER_NO_FLAG); if (rv != SCARD_S_SUCCESS) - Log2(PCSC_LOG_ERROR, "RFRemoveReader error: 0x%08lX", rv); + Log2(PCSC_LOG_ERROR, "RFRemoveReader error: %s", rv2text(rv)); } free(sReadersContexts[i]); diff --git a/src/spy/libpcscspy.c b/src/spy/libpcscspy.c index db1663c..69296e2 100644 --- a/src/spy/libpcscspy.c +++ b/src/spy/libpcscspy.c @@ -590,9 +590,13 @@ PCSC_API p_SCardTransmit(SCardTransmit) Enter(); spy_long(hCard); + spy_long(pioSendPci->dwProtocol); + spy_long(pioSendPci->cbPciLength); spy_buffer(pbSendBuffer, cbSendLength); rv = spy.SCardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength, pioRecvPci, pbRecvBuffer, pcbRecvLength); + spy_long(pioRecvPci->dwProtocol); + spy_long(pioRecvPci->cbPciLength); if (pcbRecvLength) spy_buffer(pbRecvBuffer, *pcbRecvLength); else diff --git a/src/spy/pcsc-spy b/src/spy/pcsc-spy index 9b2da79..886e0f3 100755 --- a/src/spy/pcsc-spy +++ b/src/spy/pcsc-spy @@ -219,6 +219,20 @@ class PCSCspy(object): else: self.log_in("hCard: %s" % hCard) + def log_in_scard_io_request(self): + """ log SCARD_IO_REQUEST IN parameter """ + dwProtocol = self.get_line() + if self.diffable: + self.log_in("pioSendPci.dwProtocol: 0x????") + else: + self.log_in("pioSendPci.dwProtocol: %s" % dwProtocol) + + cbPciLength = self.get_line() + if self.diffable: + self.log_in("pioSendPci.cbPciLength: 0x????") + else: + self.log_in("pioSendPci.cbPciLength: %s" % cbPciLength) + def log_in_hContext(self): """ log hContext IN parameter """ hContext = self.get_line() @@ -289,6 +303,20 @@ class PCSCspy(object): self.log_in("dwPreferredProtocols: %s (%s)" % (dwPreferredProtocols, ", ".join(PreferredProtocols))) + def log_out_scard_io_request(self): + """ log SCARD_IO_REQUEST OUT parameter """ + dwProtocol = self.get_line() + if self.diffable: + self.log_out("pioRecvPci.dwProtocol: 0x????") + else: + self.log_out("pioRecvPci.dwProtocol: %s" % dwProtocol) + + cbPciLength = self.get_line() + if self.diffable: + self.log_out("pioRecvPci.cbPciLength: 0x????") + else: + self.log_out("pioRecvPci.cbPciLength: %s" % cbPciLength) + def log_out_dwActiveProtocol(self): """ log dwActiveProtocol OUT parameter """ dwActiveProtocol = self.get_line() @@ -510,8 +538,10 @@ class PCSCspy(object): """ SCardTransmit """ self.log_name("SCardTransmit") self.log_in_hCard() + self.log_in_scard_io_request() self.log_in2("bSendLength") self.log_buffer("bSendBuffer", "in") + self.log_out_scard_io_request() self.log_out2("bRecvLength") self.log_buffer("bRecvBuffer", "out") self._log_rv() diff --git a/src/winscard.c b/src/winscard.c index e6f4c67..030d136 100644 --- a/src/winscard.c +++ b/src/winscard.c @@ -335,8 +335,8 @@ LONG SCardConnect(/*@unused@*/ SCARDCONTEXT hContext, LPCSTR szReader, rContext->readerState->cardAtrLength); } else - Log3(PCSC_LOG_ERROR, "Error powering up card: %ld 0x%04lX", - rv, rv); + Log2(PCSC_LOG_ERROR, "Error powering up card: %s", + rv2text(rv)); } if (! (rContext->readerState->readerState & SCARD_POWERED)) @@ -840,6 +840,9 @@ LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) /* get rContext corresponding to hCard */ rv = RFReaderInfoById(hCard, &rContext); + /* ignore reader removal */ + if (SCARD_E_INVALID_VALUE == rv || SCARD_E_READER_UNAVAILABLE == rv) + return SCARD_S_SUCCESS; if (rv != SCARD_S_SUCCESS) return rv; @@ -924,8 +927,8 @@ LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) else { if (SCARD_UNPOWER_CARD == dwDisposition) - Log3(PCSC_LOG_ERROR, "Error powering down card: %ld 0x%04lX", - rv, rv); + Log2(PCSC_LOG_ERROR, "Error powering down card: %s", + rv2text(rv)); else { rContext->readerState->cardAtrLength = 0; @@ -1077,7 +1080,7 @@ LONG SCardBeginTransaction(SCARDHANDLE hCard) if (SCARD_E_SHARING_VIOLATION == rv) (void)SYS_USleep(PCSCLITE_LOCK_POLL_RATE); - Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv); + Log2(PCSC_LOG_DEBUG, "Status: %s", rv2text(rv)); exit: UNREF_READER(rContext) @@ -1229,7 +1232,7 @@ LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) if (rv == SCARD_S_SUCCESS) rv = rv2; - Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv); + Log2(PCSC_LOG_DEBUG, "Status: %s", rv2text(rv)); exit: UNREF_READER(rContext) @@ -1615,7 +1618,7 @@ LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, if (rv != SCARD_S_SUCCESS) { *pcbRecvLength = 0; - Log2(PCSC_LOG_ERROR, "Card not transacted: 0x%08lX", rv); + Log2(PCSC_LOG_ERROR, "Card not transacted: %s", rv2text(rv)); if (SCARD_E_NO_SMARTCARD == rv) { diff --git a/src/winscard_clnt.c b/src/winscard_clnt.c index 5eef776..78a651d 100644 --- a/src/winscard_clnt.c +++ b/src/winscard_clnt.c @@ -134,9 +134,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //#define DO_PROFILE -/** used for backward compatibility */ -#define SCARD_PROTOCOL_ANY_OLD 0x1000 - #ifndef TRUE #define TRUE 1 #define FALSE 0 @@ -530,6 +527,7 @@ DESTRUCTOR static void destructor(void) * @retval SCARD_E_NO_SERVICE The server is not running (\ref SCARD_E_NO_SERVICE) * @retval SCARD_F_COMM_ERROR An internal communications error has been detected (\ref SCARD_F_COMM_ERROR) * @retval SCARD_F_INTERNAL_ERROR An internal consistency check failed (\ref SCARD_F_INTERNAL_ERROR) + * @retval SCARD_W_SECURITY_VIOLATION Access was denied by the daemon (Polkit issue?). (\ref SCARD_W_SECURITY_VIOLATION) */ static LONG SCardEstablishContextTH(DWORD dwScope, /*@unused@*/ LPCVOID pvReserved1, @@ -609,7 +607,6 @@ static LONG SCardEstablishContextTH(DWORD dwScope, { Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION"); - rv = SCARD_F_COMM_ERROR; goto cleanup; } diff --git a/src/winscard_msg.c b/src/winscard_msg.c index 8efa52e..c5216ef 100644 --- a/src/winscard_msg.c +++ b/src/winscard_msg.c @@ -506,7 +506,11 @@ INTERNAL LONG MessageReceive(void *buffer_void, uint64_t buffer_size, * other errors are fatal */ if (errno != EINTR && errno != EAGAIN) { - retval = SCARD_F_COMM_ERROR; + /* connection reseted by pcscd? */ + if (ECONNRESET == errno) + retval = SCARD_W_SECURITY_VIOLATION; + else + retval = SCARD_F_COMM_ERROR; break; } } diff --git a/src/winscard_svc.c b/src/winscard_svc.c index 0140832..6149f4e 100644 --- a/src/winscard_svc.c +++ b/src/winscard_svc.c @@ -321,7 +321,7 @@ static const char *CommandsText[] = { WRITE_BODY_WITH_COMMAND(CommandsText[header.command], v) #define WRITE_BODY_WITH_COMMAND(command, v) \ do { \ - Log4(PCSC_LOG_DEBUG, "%s rv=0x%X for client %d", command, v.rv, filedes); \ + LogRv4(PCSC_LOG_DEBUG, v.rv, "%s for client %d", command, filedes); \ ret = MessageSend(&v, sizeof(v), filedes); \ } while (0) @@ -886,47 +886,53 @@ static LONG MSGRemoveContext(SCARDCONTEXT hContext, SCONTEXT * threadContext) hCard = *(int32_t *)ptr; /* - * Unlock the sharing + * Unlock the sharing. If the reader or handle already + * disappeared, skip the disconnection part and just delete the + * orphan handle. */ rv = RFReaderInfoById(hCard, &rContext); - if (rv != SCARD_S_SUCCESS) + if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INVALID_VALUE + && rv != SCARD_E_READER_UNAVAILABLE) { (void)pthread_mutex_unlock(&threadContext->cardsList_lock); return rv; } - if (0 == rContext->hLockId) + if (rContext) { - /* no lock. Just leave the card */ - (void)SCardDisconnect(hCard, SCARD_LEAVE_CARD); - } - else - { - if (hCard != rContext->hLockId) + if (0 == rContext->hLockId) { - /* - * if the card is locked by someone else we do not reset it - */ - - /* decrement card use */ + /* no lock. Just leave the card */ (void)SCardDisconnect(hCard, SCARD_LEAVE_CARD); } else { - /* release the lock */ - rContext->hLockId = 0; + if (hCard != rContext->hLockId) + { + /* + * if the card is locked by someone else we do not reset it + */ - /* - * We will use SCardStatus to see if the card has been - * reset there is no need to reset each time - * Disconnect is called - */ - rv = SCardStatus(hCard, NULL, NULL, NULL, NULL, NULL, NULL); - - if (rv == SCARD_W_RESET_CARD || rv == SCARD_W_REMOVED_CARD) + /* decrement card use */ (void)SCardDisconnect(hCard, SCARD_LEAVE_CARD); + } else - (void)SCardDisconnect(hCard, SCARD_RESET_CARD); + { + /* release the lock */ + rContext->hLockId = 0; + + /* + * We will use SCardStatus to see if the card has been + * reset there is no need to reset each time + * Disconnect is called + */ + rv = SCardStatus(hCard, NULL, NULL, NULL, NULL, NULL, NULL); + + if (rv == SCARD_W_RESET_CARD || rv == SCARD_W_REMOVED_CARD) + (void)SCardDisconnect(hCard, SCARD_LEAVE_CARD); + else + (void)SCardDisconnect(hCard, SCARD_RESET_CARD); + } } } @@ -936,7 +942,9 @@ static LONG MSGRemoveContext(SCARDCONTEXT hContext, SCONTEXT * threadContext) Log2(PCSC_LOG_CRITICAL, "list_delete_at failed with return value: %d", lrv); - UNREF_READER(rContext) + if (rContext) { + UNREF_READER(rContext) + } } (void)pthread_mutex_unlock(&threadContext->cardsList_lock);