Merge branch 'master' of https://github.com/OpenSC/OpenSC into ecc-fixes
This commit is contained in:
commit
27ea7cc6ac
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,6 +4,7 @@ core
|
|||||||
archive
|
archive
|
||||||
acinclude.m4
|
acinclude.m4
|
||||||
aclocal.m4
|
aclocal.m4
|
||||||
|
aminclude_static.am
|
||||||
autom4te.cache
|
autom4te.cache
|
||||||
compile
|
compile
|
||||||
confdefs.h
|
confdefs.h
|
||||||
@ -22,6 +23,7 @@ mkinstalldirs
|
|||||||
so_locations
|
so_locations
|
||||||
stamp-h*
|
stamp-h*
|
||||||
tags
|
tags
|
||||||
|
test-driver
|
||||||
.deps
|
.deps
|
||||||
.libs
|
.libs
|
||||||
.#*#
|
.#*#
|
||||||
|
63
appveyor.yml
63
appveyor.yml
@ -1,13 +1,5 @@
|
|||||||
version: 0.20.0.{build}
|
version: 0.20.0.{build}
|
||||||
|
|
||||||
image:
|
|
||||||
# not compatible with OpenSSL 1.1.1:
|
|
||||||
# - Visual Studio 2013
|
|
||||||
# not compatible with WiX 3.11.2:
|
|
||||||
# - Visual Studio 2019
|
|
||||||
- Visual Studio 2015
|
|
||||||
- Visual Studio 2017
|
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
- x86
|
- x86
|
||||||
- x64
|
- x64
|
||||||
@ -19,6 +11,21 @@ configuration:
|
|||||||
environment:
|
environment:
|
||||||
GH_TOKEN:
|
GH_TOKEN:
|
||||||
secure: aLu3tFc7lRJbotnmnHLx/QruIHc5rLaGm1RttoEdy4QILlPXzVkCZ6loYMz0sfrY
|
secure: aLu3tFc7lRJbotnmnHLx/QruIHc5rLaGm1RttoEdy4QILlPXzVkCZ6loYMz0sfrY
|
||||||
|
PATH: C:\cygwin\bin;%PATH%
|
||||||
|
OPENPACE_VER: 1.1.0
|
||||||
|
ZLIB_VER_DOT: 1.2.11
|
||||||
|
matrix:
|
||||||
|
# not compatible with OpenSSL 1.1.1:
|
||||||
|
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||||
|
# VCVARSALL: "%VS120COMNTOOLS%/../../VC/vcvarsall.bat"
|
||||||
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
|
VCVARSALL: "%VS140COMNTOOLS%/../../VC/vcvarsall.bat"
|
||||||
|
DO_PUSH_ARTIFACT: yes
|
||||||
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
|
VCVARSALL: "%ProgramFiles(x86)%/Microsoft Visual Studio/2017/Community/VC/Auxiliary/Build/vcvarsall.bat"
|
||||||
|
# not compatible with WiX 3.11.2:
|
||||||
|
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
|
# VCVARSALL: "%ProgramFiles(x86)%/Microsoft Visual Studio/2019/Community/VC/Auxiliary/Build/vcvarsall.bat"
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
|
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
|
||||||
@ -26,26 +33,21 @@ install:
|
|||||||
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
|
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
|
||||||
throw "There are newer queued builds for this pull request, failing early." }
|
throw "There are newer queued builds for this pull request, failing early." }
|
||||||
- date /T & time /T
|
- date /T & time /T
|
||||||
- set PATH=C:\cygwin\bin;%PATH%
|
|
||||||
- set OPENPACE_VER=1.1.0
|
|
||||||
- set ZLIB_VER_DOT=1.2.11
|
|
||||||
- ps: $env:PACKAGE_NAME=(git describe --tags --abbrev=0)
|
- ps: $env:PACKAGE_NAME=(git describe --tags --abbrev=0)
|
||||||
- ps: >-
|
- ps: >-
|
||||||
If ($env:Platform -Match "x86") {
|
If ($env:Platform -Match "x86") {
|
||||||
$env:VCVARS_PLATFORM="x86"
|
|
||||||
$env:OPENSSL_PF="Win32"
|
$env:OPENSSL_PF="Win32"
|
||||||
$env:ARTIFACT="OpenSC-${env:PACKAGE_NAME}_win32"
|
$env:ARTIFACT="OpenSC-${env:PACKAGE_NAME}_win32"
|
||||||
} Else {
|
} Else {
|
||||||
$env:VCVARS_PLATFORM="amd64"
|
|
||||||
$env:OPENSSL_PF="Win64"
|
$env:OPENSSL_PF="Win64"
|
||||||
$env:ARTIFACT="OpenSC-${env:PACKAGE_NAME}_win64"
|
$env:ARTIFACT="OpenSC-${env:PACKAGE_NAME}_win64"
|
||||||
}
|
}
|
||||||
- ps: >-
|
- ps: >-
|
||||||
If ($env:Configuration -Like "*Light*") {
|
If ($env:Configuration -Like "*Light*") {
|
||||||
$env:ARTIFACT="${env:ARTIFACT}-Light"
|
$env:ARTIFACT+="-Light"
|
||||||
} Else {
|
} Else {
|
||||||
$env:NMAKE_EXTRA="OPENSSL_DEF=/DENABLE_OPENSSL OPENSSL_DIR=C:\OpenSSL-v111-${env:OPENSSL_PF} ${env:NMAKE_EXTRA}"
|
$env:NMAKE_EXTRA+=" OPENSSL_DEF=/DENABLE_OPENSSL OPENSSL_DIR=C:\OpenSSL-v111-${env:OPENSSL_PF}"
|
||||||
$env:NMAKE_EXTRA="OPENSSL_EXTRA_CFLAGS=/DOPENSSL_SECURE_MALLOC_SIZE=65536 ${env:NMAKE_EXTRA}"
|
$env:NMAKE_EXTRA+=" OPENSSL_EXTRA_CFLAGS=/DOPENSSL_SECURE_MALLOC_SIZE=65536"
|
||||||
If (!(Test-Path C:\zlib )) {
|
If (!(Test-Path C:\zlib )) {
|
||||||
appveyor DownloadFile "https://github.com/madler/zlib/archive/v${env:ZLIB_VER_DOT}.zip" -FileName zlib.zip
|
appveyor DownloadFile "https://github.com/madler/zlib/archive/v${env:ZLIB_VER_DOT}.zip" -FileName zlib.zip
|
||||||
7z x zlib.zip -oC:\
|
7z x zlib.zip -oC:\
|
||||||
@ -60,19 +62,8 @@ install:
|
|||||||
If (!(Test-Path cngsdk.msi )) {
|
If (!(Test-Path cngsdk.msi )) {
|
||||||
appveyor DownloadFile "http://download.microsoft.com/download/2/C/9/2C93059C-0532-42DF-8C24-9AEAFF00768E/cngsdk.msi"
|
appveyor DownloadFile "http://download.microsoft.com/download/2/C/9/2C93059C-0532-42DF-8C24-9AEAFF00768E/cngsdk.msi"
|
||||||
}
|
}
|
||||||
- ps: >-
|
|
||||||
If ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019") {
|
|
||||||
$env:VCVARSALL="${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat"
|
|
||||||
} ElseIf ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2017") {
|
|
||||||
$env:VCVARSALL="${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat"
|
|
||||||
} ElseIf ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") {
|
|
||||||
$env:VCVARSALL="${env:VS140COMNTOOLS}\..\..\VC\vcvarsall.bat"
|
|
||||||
$env:DO_PUSH_ARTIFACT="yes"
|
|
||||||
} ElseIf ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2013") {
|
|
||||||
$env:VCVARSALL="${env:VS120COMNTOOLS}\..\..\VC\vcvarsall.bat"
|
|
||||||
}
|
|
||||||
- echo "Using %APPVEYOR_BUILD_WORKER_IMAGE% with %VCVARSALL%"
|
- echo "Using %APPVEYOR_BUILD_WORKER_IMAGE% with %VCVARSALL%"
|
||||||
- call "%VCVARSALL%" %VCVARS_PLATFORM%
|
- call "%VCVARSALL%" %Platform%
|
||||||
- cngsdk.msi /quiet
|
- cngsdk.msi /quiet
|
||||||
- uname -a
|
- uname -a
|
||||||
- set
|
- set
|
||||||
@ -85,23 +76,23 @@ build_script:
|
|||||||
xcopy C:\zlib C:\zlib-${env:OPENSSL_PF} /e /i /y /s
|
xcopy C:\zlib C:\zlib-${env:OPENSSL_PF} /e /i /y /s
|
||||||
cd C:\zlib-${env:OPENSSL_PF}
|
cd C:\zlib-${env:OPENSSL_PF}
|
||||||
(Get-Content win32/Makefile.msc).replace('-MD', '-MT') | Set-Content win32/Makefile.msc
|
(Get-Content win32/Makefile.msc).replace('-MD', '-MT') | Set-Content win32/Makefile.msc
|
||||||
nmake -f win32/Makefile.msc zlib.lib
|
nmake /nologo -f win32/Makefile.msc zlib.lib
|
||||||
}
|
}
|
||||||
$env:NMAKE_EXTRA="ZLIBSTATIC_DEF=/DENABLE_ZLIB_STATIC ZLIB_INCL_DIR=/IC:\zlib-${env:OPENSSL_PF} ZLIB_LIB=C:\zlib-${env:OPENSSL_PF}\zlib.lib ${env:NMAKE_EXTRA}"
|
$env:NMAKE_EXTRA+=" ZLIBSTATIC_DEF=/DENABLE_ZLIB_STATIC ZLIB_INCL_DIR=/IC:\zlib-${env:OPENSSL_PF} ZLIB_LIB=C:\zlib-${env:OPENSSL_PF}\zlib.lib"
|
||||||
If (!(Test-Path -Path "C:\openpace-${env:OPENSSL_PF}" )) {
|
If (!(Test-Path -Path "C:\openpace-${env:OPENSSL_PF}" )) {
|
||||||
# build libeac.lib as a static library
|
# build libeac.lib as a static library
|
||||||
xcopy C:\openpace C:\openpace-${env:OPENSSL_PF} /e /i /y /s
|
xcopy C:\openpace C:\openpace-${env:OPENSSL_PF} /e /i /y /s
|
||||||
cd C:\openpace-${env:OPENSSL_PF}\src
|
cd C:\openpace-${env:OPENSSL_PF}\src
|
||||||
# OpenSSL 1.1.0
|
# OpenSSL 1.1.0
|
||||||
#cl /IC:\OpenSSL-v111-${env:OPENSSL_PF}\include /I. /DX509DIR=\`"/\`" /DCVCDIR=\`"/\`" /W3 /D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN /GS /MT /DHAVE_ASN1_STRING_GET0_DATA=1 /DHAVE_DECL_OPENSSL_ZALLOC=1 /DHAVE_DH_GET0_KEY=1 /DHAVE_DH_GET0_PQG=1 /DHAVE_DH_SET0_KEY=1 /DHAVE_DH_SET0_PQG=1 /DHAVE_ECDSA_SIG_GET0=1 /DHAVE_ECDSA_SIG_SET0=1 /DHAVE_EC_KEY_METHOD=1 /DHAVE_RSA_GET0_KEY=1 /DHAVE_RSA_SET0_KEY=1 /c ca_lib.c cv_cert.c cvc_lookup.c x509_lookup.c eac_asn1.c eac.c eac_ca.c eac_dh.c eac_ecdh.c eac_kdf.c eac_lib.c eac_print.c eac_util.c misc.c pace.c pace_lib.c pace_mappings.c ri.c ri_lib.c ta.c ta_lib.c objects.c ssl_compat.c
|
#cl /nologo /IC:\OpenSSL-v110-${env:OPENSSL_PF}\include /I. /DX509DIR=\`"/\`" /DCVCDIR=\`"/\`" /W3 /D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN /GS /MT /DHAVE_ASN1_STRING_GET0_DATA=1 /DHAVE_DECL_OPENSSL_ZALLOC=1 /DHAVE_DH_GET0_KEY=1 /DHAVE_DH_GET0_PQG=1 /DHAVE_DH_SET0_KEY=1 /DHAVE_DH_SET0_PQG=1 /DHAVE_ECDSA_SIG_GET0=1 /DHAVE_ECDSA_SIG_SET0=1 /DHAVE_EC_KEY_METHOD=1 /DHAVE_RSA_GET0_KEY=1 /DHAVE_RSA_SET0_KEY=1 /c ca_lib.c cv_cert.c cvc_lookup.c x509_lookup.c eac_asn1.c eac.c eac_ca.c eac_dh.c eac_ecdh.c eac_kdf.c eac_lib.c eac_print.c eac_util.c misc.c pace.c pace_lib.c pace_mappings.c ri.c ri_lib.c ta.c ta_lib.c objects.c ssl_compat.c
|
||||||
# OpenSSL 1.1.1
|
# OpenSSL 1.1.1
|
||||||
cl /IC:\OpenSSL-v111-${env:OPENSSL_PF}\include /I. /DX509DIR=\`"/\`" /DCVCDIR=\`"/\`" /W3 /D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN /GS /MT /DHAVE_ASN1_STRING_GET0_DATA=1 /DHAVE_DECL_OPENSSL_ZALLOC=1 /DHAVE_DH_GET0_KEY=1 /DHAVE_DH_GET0_PQG=1 /DHAVE_DH_SET0_KEY=1 /DHAVE_DH_SET0_PQG=1 /DHAVE_ECDSA_SIG_GET0=1 /DHAVE_ECDSA_SIG_SET0=1 /DHAVE_EC_KEY_METHOD=1 /DHAVE_RSA_GET0_KEY=1 /DHAVE_RSA_SET0_KEY=1 /DHAVE_EC_POINT_GET_AFFINE_COORDINATES=1 /DHAVE_EC_POINT_SET_AFFINE_COORDINATES=1 /c ca_lib.c cv_cert.c cvc_lookup.c x509_lookup.c eac_asn1.c eac.c eac_ca.c eac_dh.c eac_ecdh.c eac_kdf.c eac_lib.c eac_print.c eac_util.c misc.c pace.c pace_lib.c pace_mappings.c ri.c ri_lib.c ta.c ta_lib.c objects.c ssl_compat.c
|
cl /nologo /IC:\OpenSSL-v111-${env:OPENSSL_PF}\include /I. /DX509DIR=\`"/\`" /DCVCDIR=\`"/\`" /W3 /D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN /GS /MT /DHAVE_ASN1_STRING_GET0_DATA=1 /DHAVE_DECL_OPENSSL_ZALLOC=1 /DHAVE_DH_GET0_KEY=1 /DHAVE_DH_GET0_PQG=1 /DHAVE_DH_SET0_KEY=1 /DHAVE_DH_SET0_PQG=1 /DHAVE_ECDSA_SIG_GET0=1 /DHAVE_ECDSA_SIG_SET0=1 /DHAVE_EC_KEY_METHOD=1 /DHAVE_RSA_GET0_KEY=1 /DHAVE_RSA_SET0_KEY=1 /DHAVE_EC_POINT_GET_AFFINE_COORDINATES=1 /DHAVE_EC_POINT_SET_AFFINE_COORDINATES=1 /c ca_lib.c cv_cert.c cvc_lookup.c x509_lookup.c eac_asn1.c eac.c eac_ca.c eac_dh.c eac_ecdh.c eac_kdf.c eac_lib.c eac_print.c eac_util.c misc.c pace.c pace_lib.c pace_mappings.c ri.c ri_lib.c ta.c ta_lib.c objects.c ssl_compat.c
|
||||||
# OpenSSL 1.0.2
|
# OpenSSL 1.0.2
|
||||||
#cl /IC:\OpenSSL-v111-${env:OPENSSL_PF}\include /I. /DX509DIR=\`"/\`" /DCVCDIR=\`"/\`" /W3 /D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN /GS /MT /c ca_lib.c cv_cert.c cvc_lookup.c x509_lookup.c eac_asn1.c eac.c eac_ca.c eac_dh.c eac_ecdh.c eac_kdf.c eac_lib.c eac_print.c eac_util.c misc.c pace.c pace_lib.c pace_mappings.c ri.c ri_lib.c ta.c ta_lib.c objects.c ssl_compat.c
|
#cl /nologo /IC:\OpenSSL-${env:OPENSSL_PF}\include /I. /DX509DIR=\`"/\`" /DCVCDIR=\`"/\`" /W3 /D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN /GS /MT /c ca_lib.c cv_cert.c cvc_lookup.c x509_lookup.c eac_asn1.c eac.c eac_ca.c eac_dh.c eac_ecdh.c eac_kdf.c eac_lib.c eac_print.c eac_util.c misc.c pace.c pace_lib.c pace_mappings.c ri.c ri_lib.c ta.c ta_lib.c objects.c ssl_compat.c
|
||||||
lib /out:libeac.lib ca_lib.obj cv_cert.obj cvc_lookup.obj x509_lookup.obj eac_asn1.obj eac.obj eac_ca.obj eac_dh.obj eac_ecdh.obj eac_kdf.obj eac_lib.obj eac_print.obj eac_util.obj misc.obj pace.obj pace_lib.obj pace_mappings.obj ri.obj ri_lib.obj ta.obj ta_lib.obj objects.obj ssl_compat.obj
|
lib /nologo /out:libeac.lib ca_lib.obj cv_cert.obj cvc_lookup.obj x509_lookup.obj eac_asn1.obj eac.obj eac_ca.obj eac_dh.obj eac_ecdh.obj eac_kdf.obj eac_lib.obj eac_print.obj eac_util.obj misc.obj pace.obj pace_lib.obj pace_mappings.obj ri.obj ri_lib.obj ta.obj ta_lib.obj objects.obj ssl_compat.obj
|
||||||
cd C:\projects\OpenSC
|
cd C:\projects\OpenSC
|
||||||
}
|
}
|
||||||
$env:NMAKE_EXTRA="OPENPACE_DEF=/DENABLE_OPENPACE OPENPACE_DIR=C:\openpace-${env:OPENSSL_PF} ${env:NMAKE_EXTRA}"
|
$env:NMAKE_EXTRA+=" OPENPACE_DEF=/DENABLE_OPENPACE OPENPACE_DIR=C:\openpace-${env:OPENSSL_PF}"
|
||||||
}
|
}
|
||||||
- bash -c "exec 0</dev/null && if [ \"$APPVEYOR_REPO_BRANCH\" == \"master\" -a -z \"$APPVEYOR_PULL_REQUEST_NUMBER\" ]; then ./bootstrap; fi"
|
- bash -c "exec 0</dev/null && if [ \"$APPVEYOR_REPO_BRANCH\" == \"master\" -a -z \"$APPVEYOR_PULL_REQUEST_NUMBER\" ]; then ./bootstrap; fi"
|
||||||
- bash -c "exec 0</dev/null && if [ \"$APPVEYOR_REPO_BRANCH\" == \"master\" -a -n \"$APPVEYOR_PULL_REQUEST_NUMBER\" ]; then ./bootstrap.ci -s \"-pr$APPVEYOR_PULL_REQUEST_NUMBER\"; fi"
|
- bash -c "exec 0</dev/null && if [ \"$APPVEYOR_REPO_BRANCH\" == \"master\" -a -n \"$APPVEYOR_PULL_REQUEST_NUMBER\" ]; then ./bootstrap.ci -s \"-pr$APPVEYOR_PULL_REQUEST_NUMBER\"; fi"
|
||||||
@ -111,7 +102,7 @@ build_script:
|
|||||||
- bash -c "exec 0</dev/null && ./configure --with-cygwin-native --disable-openssl --disable-readline --disable-zlib || cat config.log"
|
- bash -c "exec 0</dev/null && ./configure --with-cygwin-native --disable-openssl --disable-readline --disable-zlib || cat config.log"
|
||||||
- bash -c "exec 0</dev/null && rm src/getopt.h"
|
- bash -c "exec 0</dev/null && rm src/getopt.h"
|
||||||
- nmake /f Makefile.mak %NMAKE_EXTRA%
|
- nmake /f Makefile.mak %NMAKE_EXTRA%
|
||||||
- cd win32 && nmake /f Makefile.mak %NMAKE_EXTRA% OpenSC.msi && cd ..
|
- cd win32 && nmake /nologo /f Makefile.mak %NMAKE_EXTRA% OpenSC.msi && cd ..
|
||||||
- move win32\OpenSC.msi %ARTIFACT%.msi
|
- move win32\OpenSC.msi %ARTIFACT%.msi
|
||||||
# put all pdb files for dump analysis, but this consumes approx 100 MB per build
|
# put all pdb files for dump analysis, but this consumes approx 100 MB per build
|
||||||
- md %ARTIFACT%-Debug
|
- md %ARTIFACT%-Debug
|
||||||
|
@ -400,7 +400,8 @@ AC_HEADER_ASSERT
|
|||||||
AC_CHECK_HEADERS([ \
|
AC_CHECK_HEADERS([ \
|
||||||
errno.h fcntl.h stdlib.h \
|
errno.h fcntl.h stdlib.h \
|
||||||
inttypes.h string.h strings.h \
|
inttypes.h string.h strings.h \
|
||||||
sys/time.h unistd.h sys/mman.h
|
sys/time.h unistd.h sys/mman.h \
|
||||||
|
sys/endian.h endian.h
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
@ -1036,6 +1036,7 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||||||
|
|
||||||
rv = iasecc_process_fci(card, file, apdu.resp, apdu.resplen);
|
rv = iasecc_process_fci(card, file, apdu.resp, apdu.resplen);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
|
sc_file_free(file);
|
||||||
if (file_out) {
|
if (file_out) {
|
||||||
sc_file_free(*file_out);
|
sc_file_free(*file_out);
|
||||||
*file_out = NULL;
|
*file_out = NULL;
|
||||||
|
@ -150,7 +150,7 @@ static int idprime_select_index(sc_card_t *card)
|
|||||||
}
|
}
|
||||||
sc_file_free(file);
|
sc_file_free(file);
|
||||||
/* Ignore too large files */
|
/* Ignore too large files */
|
||||||
if (r > MAX_FILE_SIZE) {
|
if (r <= 0 || r > MAX_FILE_SIZE) {
|
||||||
r = SC_ERROR_INVALID_DATA;
|
r = SC_ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -148,7 +148,7 @@ int sc_parse_ef_atr(struct sc_card *card)
|
|||||||
|
|
||||||
sc_format_path("3F002F01", &path);
|
sc_format_path("3F002F01", &path);
|
||||||
rv = sc_select_file(card, &path, &file);
|
rv = sc_select_file(card, &path, &file);
|
||||||
LOG_TEST_RET(ctx, rv, "Cannot select EF(ATR) file");
|
LOG_TEST_GOTO_ERR(ctx, rv, "Cannot select EF(ATR) file");
|
||||||
|
|
||||||
if (file->size) {
|
if (file->size) {
|
||||||
size = file->size;
|
size = file->size;
|
||||||
@ -156,8 +156,10 @@ int sc_parse_ef_atr(struct sc_card *card)
|
|||||||
size = 1024;
|
size = 1024;
|
||||||
}
|
}
|
||||||
buf = malloc(size);
|
buf = malloc(size);
|
||||||
if (!buf)
|
if (!buf) {
|
||||||
LOG_TEST_GOTO_ERR(ctx, SC_ERROR_OUT_OF_MEMORY, "Memory allocation error");
|
rv = SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
LOG_TEST_GOTO_ERR(ctx, rv, "Memory allocation error");
|
||||||
|
}
|
||||||
rv = sc_read_binary(card, 0, buf, size, 0);
|
rv = sc_read_binary(card, 0, buf, size, 0);
|
||||||
LOG_TEST_GOTO_ERR(ctx, rv, "Cannot read EF(ATR) file");
|
LOG_TEST_GOTO_ERR(ctx, rv, "Cannot read EF(ATR) file");
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ const char *sc_strerror(int error)
|
|||||||
"Message too long (keypad)",
|
"Message too long (keypad)",
|
||||||
"Timeout while waiting for event from card reader",
|
"Timeout while waiting for event from card reader",
|
||||||
"Unresponsive card (correctly inserted?)",
|
"Unresponsive card (correctly inserted?)",
|
||||||
"Reader detached (hotplug device?)",
|
"Reader detached",
|
||||||
"Reader reattached (hotplug device?)",
|
"Reader reattached",
|
||||||
"Reader in use by another application"
|
"Reader in use by another application"
|
||||||
};
|
};
|
||||||
const int rdr_base = -SC_ERROR_READER;
|
const int rdr_base = -SC_ERROR_READER;
|
||||||
|
@ -100,6 +100,7 @@ typedef unsigned __int8 uint8_t;
|
|||||||
#define SCARD_E_NOT_TRANSACTED 0x80100016 /**< An attempt was made to end a non-existent transaction. */
|
#define SCARD_E_NOT_TRANSACTED 0x80100016 /**< An attempt was made to end a non-existent transaction. */
|
||||||
#define SCARD_E_READER_UNAVAILABLE 0x80100017 /**< The specified reader is not currently available for use. */
|
#define SCARD_E_READER_UNAVAILABLE 0x80100017 /**< The specified reader is not currently available for use. */
|
||||||
#define SCARD_E_NO_SERVICE 0x8010001D /**< The Smart card resource manager is not running. */
|
#define SCARD_E_NO_SERVICE 0x8010001D /**< The Smart card resource manager is not running. */
|
||||||
|
#define SCARD_E_SERVICE_STOPPED 0x8010001E /**< The smart card resource manager has shut down. */
|
||||||
#define SCARD_E_NO_READERS_AVAILABLE 0x8010002E /**< Cannot find a smart card reader. */
|
#define SCARD_E_NO_READERS_AVAILABLE 0x8010002E /**< Cannot find a smart card reader. */
|
||||||
#define SCARD_W_UNRESPONSIVE_CARD 0x80100066 /**< The smart card is not responding to a reset. */
|
#define SCARD_W_UNRESPONSIVE_CARD 0x80100066 /**< The smart card is not responding to a reset. */
|
||||||
#define SCARD_W_UNPOWERED_CARD 0x80100067 /**< Power has been removed from the smart card, so that further communication is not possible. */
|
#define SCARD_W_UNPOWERED_CARD 0x80100067 /**< Power has been removed from the smart card, so that further communication is not possible. */
|
||||||
|
@ -213,10 +213,10 @@ extern "C" {
|
|||||||
/* Event masks for sc_wait_for_event() */
|
/* Event masks for sc_wait_for_event() */
|
||||||
#define SC_EVENT_CARD_INSERTED 0x0001
|
#define SC_EVENT_CARD_INSERTED 0x0001
|
||||||
#define SC_EVENT_CARD_REMOVED 0x0002
|
#define SC_EVENT_CARD_REMOVED 0x0002
|
||||||
#define SC_EVENT_CARD_EVENTS SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED
|
#define SC_EVENT_CARD_EVENTS (SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED)
|
||||||
#define SC_EVENT_READER_ATTACHED 0x0004
|
#define SC_EVENT_READER_ATTACHED 0x0004
|
||||||
#define SC_EVENT_READER_DETACHED 0x0008
|
#define SC_EVENT_READER_DETACHED 0x0008
|
||||||
#define SC_EVENT_READER_EVENTS SC_EVENT_READER_ATTACHED|SC_EVENT_READER_DETACHED
|
#define SC_EVENT_READER_EVENTS (SC_EVENT_READER_ATTACHED|SC_EVENT_READER_DETACHED)
|
||||||
|
|
||||||
#define MAX_FILE_SIZE 65535
|
#define MAX_FILE_SIZE 65535
|
||||||
|
|
||||||
@ -1024,18 +1024,25 @@ int sc_disconnect_card(struct sc_card *card);
|
|||||||
int sc_detect_card_presence(sc_reader_t *reader);
|
int sc_detect_card_presence(sc_reader_t *reader);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for an event on readers. Note: only the event is detected,
|
* Waits for an event on readers.
|
||||||
* there is no update of any card or other info.
|
*
|
||||||
* NOTE: Only PC/SC backend implements this.
|
* In case of a reader event (attached/detached), the list of reader is
|
||||||
* @param ctx pointer to a Context structure
|
* adjusted accordingly. This means that a subsequent call to
|
||||||
* @param event_mask The types of events to wait for; this should
|
* `sc_ctx_detect_readers()` is not needed.
|
||||||
* be ORed from one of the following
|
*
|
||||||
* SC_EVENT_CARD_REMOVED
|
* @note Only PC/SC backend implements this. An infinite timeout on macOS does
|
||||||
* SC_EVENT_CARD_INSERTED
|
* not detect reader events (use a limited timeout instead if needed).
|
||||||
* SC_EVENT_READER_ATTACHED
|
*
|
||||||
* @param event_reader (OUT) the reader on which the event was detected, or NULL if new reader
|
* @param ctx (IN) pointer to a Context structure
|
||||||
|
* @param event_mask (IN) The types of events to wait for; this should
|
||||||
|
* be ORed from one of the following:
|
||||||
|
* - SC_EVENT_CARD_REMOVED
|
||||||
|
* - SC_EVENT_CARD_INSERTED
|
||||||
|
* - SC_EVENT_READER_ATTACHED
|
||||||
|
* - SC_EVENT_READER_DETACHED
|
||||||
|
* @param event_reader (OUT) the reader on which the event was detected
|
||||||
* @param event (OUT) the events that occurred. This is also ORed
|
* @param event (OUT) the events that occurred. This is also ORed
|
||||||
* from the SC_EVENT_CARD_* constants listed above.
|
* from the constants listed above.
|
||||||
* @param timeout Amount of millisecs to wait; -1 means forever
|
* @param timeout Amount of millisecs to wait; -1 means forever
|
||||||
* @retval < 0 if an error occurred
|
* @retval < 0 if an error occurred
|
||||||
* @retval = 0 if a an event happened
|
* @retval = 0 if a an event happened
|
||||||
|
@ -127,6 +127,9 @@ struct pcsc_global_private_data {
|
|||||||
SCardTransmit_t SCardTransmit;
|
SCardTransmit_t SCardTransmit;
|
||||||
SCardListReaders_t SCardListReaders;
|
SCardListReaders_t SCardListReaders;
|
||||||
SCardGetAttrib_t SCardGetAttrib;
|
SCardGetAttrib_t SCardGetAttrib;
|
||||||
|
|
||||||
|
sc_reader_t *attached_reader;
|
||||||
|
sc_reader_t *removed_reader;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pcsc_private_data {
|
struct pcsc_private_data {
|
||||||
@ -185,6 +188,7 @@ static int pcsc_to_opensc_error(LONG rv)
|
|||||||
return SC_ERROR_READER_DETACHED;
|
return SC_ERROR_READER_DETACHED;
|
||||||
|
|
||||||
case SCARD_E_NO_SERVICE:
|
case SCARD_E_NO_SERVICE:
|
||||||
|
case SCARD_E_SERVICE_STOPPED:
|
||||||
/* If the service is (auto)started, there could be readers later */
|
/* If the service is (auto)started, there could be readers later */
|
||||||
return SC_ERROR_NO_READERS_FOUND;
|
return SC_ERROR_NO_READERS_FOUND;
|
||||||
case SCARD_E_NO_SMARTCARD:
|
case SCARD_E_NO_SMARTCARD:
|
||||||
@ -358,7 +362,7 @@ static int refresh_attributes(sc_reader_t *reader)
|
|||||||
if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE)
|
if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE)
|
||||||
return SC_ERROR_NOT_ALLOWED;
|
return SC_ERROR_NOT_ALLOWED;
|
||||||
|
|
||||||
if (priv->reader_state.szReader == NULL) {
|
if (priv->reader_state.szReader == NULL || reader->ctx->flags & SC_READER_REMOVED) {
|
||||||
priv->reader_state.szReader = reader->name;
|
priv->reader_state.szReader = reader->name;
|
||||||
priv->reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
|
priv->reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
|
||||||
priv->reader_state.dwEventState = SCARD_STATE_UNAWARE;
|
priv->reader_state.dwEventState = SCARD_STATE_UNAWARE;
|
||||||
@ -382,12 +386,11 @@ static int refresh_attributes(sc_reader_t *reader)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* the system could not detect the reader. It means, the prevoiusly attached reader is disconnected. */
|
/* the system could not detect the reader. It means, the prevoiusly attached reader is disconnected. */
|
||||||
if (
|
if (rv == (LONG)SCARD_E_UNKNOWN_READER
|
||||||
#ifdef SCARD_E_NO_READERS_AVAILABLE
|
#ifdef SCARD_E_NO_READERS_AVAILABLE
|
||||||
(rv == (LONG)SCARD_E_NO_READERS_AVAILABLE) ||
|
|| rv == (LONG)SCARD_E_NO_READERS_AVAILABLE
|
||||||
#endif
|
#endif
|
||||||
(rv == (LONG)SCARD_E_UNKNOWN_READER) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) {
|
|| rv == (LONG)SCARD_E_SERVICE_STOPPED) {
|
||||||
|
|
||||||
if (old_flags & SC_READER_CARD_PRESENT) {
|
if (old_flags & SC_READER_CARD_PRESENT) {
|
||||||
reader->flags |= SC_READER_CARD_CHANGED;
|
reader->flags |= SC_READER_CARD_CHANGED;
|
||||||
}
|
}
|
||||||
@ -1143,7 +1146,7 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
rv = gpriv->SCardControl(card_handle, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, feature_buf, sizeof(feature_buf), &feature_len);
|
rv = gpriv->SCardControl(card_handle, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, feature_buf, sizeof(feature_buf), &feature_len);
|
||||||
if (rv != (LONG)SCARD_S_SUCCESS) {
|
if (rv != SCARD_S_SUCCESS) {
|
||||||
PCSC_TRACE(reader, "SCardControl failed", rv);
|
PCSC_TRACE(reader, "SCardControl failed", rv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1382,6 +1385,8 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sc_log(ctx, "Probing PC/SC readers");
|
sc_log(ctx, "Probing PC/SC readers");
|
||||||
|
gpriv->attached_reader = NULL;
|
||||||
|
gpriv->removed_reader = NULL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (gpriv->pcsc_ctx == (SCARDCONTEXT)-1) {
|
if (gpriv->pcsc_ctx == (SCARDCONTEXT)-1) {
|
||||||
@ -1399,12 +1404,11 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
|||||||
* All readers have disappeared, so mark them as
|
* All readers have disappeared, so mark them as
|
||||||
* such so we don't keep polling them over and over.
|
* such so we don't keep polling them over and over.
|
||||||
*/
|
*/
|
||||||
if (
|
if (rv == (LONG)SCARD_E_NO_SERVICE
|
||||||
#ifdef SCARD_E_NO_READERS_AVAILABLE
|
#ifdef SCARD_E_NO_READERS_AVAILABLE
|
||||||
(rv == (LONG)SCARD_E_NO_READERS_AVAILABLE) ||
|
|| rv == (LONG)SCARD_E_NO_READERS_AVAILABLE
|
||||||
#endif
|
#endif
|
||||||
(rv == (LONG)SCARD_E_NO_SERVICE) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) {
|
|| rv == (LONG)SCARD_E_SERVICE_STOPPED) {
|
||||||
|
|
||||||
for (i = 0; i < sc_ctx_get_reader_count(ctx); i++) {
|
for (i = 0; i < sc_ctx_get_reader_count(ctx); i++) {
|
||||||
sc_reader_t *reader = sc_ctx_get_reader(ctx, i);
|
sc_reader_t *reader = sc_ctx_get_reader(ctx, i);
|
||||||
|
|
||||||
@ -1414,6 +1418,7 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
reader->flags |= SC_READER_REMOVED;
|
reader->flags |= SC_READER_REMOVED;
|
||||||
|
gpriv->removed_reader = reader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1473,6 +1478,7 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
|||||||
if (!strcmp(reader->name, reader_name)) {
|
if (!strcmp(reader->name, reader_name)) {
|
||||||
if (reader->flags & SC_READER_REMOVED) {
|
if (reader->flags & SC_READER_REMOVED) {
|
||||||
reader->flags &= ~SC_READER_REMOVED;
|
reader->flags &= ~SC_READER_REMOVED;
|
||||||
|
gpriv->attached_reader = reader;
|
||||||
refresh_attributes(reader);
|
refresh_attributes(reader);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1487,8 +1493,11 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
|||||||
(reader_buf + reader_buf_size) - next_reader_name);
|
(reader_buf + reader_buf_size) - next_reader_name);
|
||||||
reader_buf_size -= (next_reader_name - reader_name);
|
reader_buf_size -= (next_reader_name - reader_name);
|
||||||
} else {
|
} else {
|
||||||
/* existing reader not found */
|
if (!(reader->flags & SC_READER_REMOVED)) {
|
||||||
reader->flags |= SC_READER_REMOVED;
|
/* existing reader not found */
|
||||||
|
reader->flags |= SC_READER_REMOVED;
|
||||||
|
gpriv->removed_reader = reader;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1503,6 +1512,7 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
|||||||
_sc_delete_reader(ctx, reader);
|
_sc_delete_reader(ctx, reader);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
gpriv->attached_reader = reader;
|
||||||
|
|
||||||
/* check for pinpad support early, to allow opensc-tool -l display accurate information */
|
/* check for pinpad support early, to allow opensc-tool -l display accurate information */
|
||||||
priv = reader->drv_data;
|
priv = reader->drv_data;
|
||||||
@ -1555,7 +1565,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
|
|||||||
SCARD_READERSTATE *rgReaderStates;
|
SCARD_READERSTATE *rgReaderStates;
|
||||||
size_t i;
|
size_t i;
|
||||||
unsigned int num_watch, count;
|
unsigned int num_watch, count;
|
||||||
int r = SC_ERROR_INTERNAL;
|
int r = SC_ERROR_INTERNAL, detect_readers = 0, detected_hotplug = 0;
|
||||||
DWORD dwtimeout;
|
DWORD dwtimeout;
|
||||||
|
|
||||||
LOG_FUNC_CALLED(ctx);
|
LOG_FUNC_CALLED(ctx);
|
||||||
@ -1579,8 +1589,13 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
|
|||||||
sc_reader_t *reader = sc_ctx_get_reader(ctx, i);
|
sc_reader_t *reader = sc_ctx_get_reader(ctx, i);
|
||||||
if (reader->flags & SC_READER_REMOVED)
|
if (reader->flags & SC_READER_REMOVED)
|
||||||
continue;
|
continue;
|
||||||
|
struct pcsc_private_data *priv = reader->drv_data;
|
||||||
rgReaderStates[num_watch].szReader = reader->name;
|
rgReaderStates[num_watch].szReader = reader->name;
|
||||||
rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE;
|
if (priv->reader_state.szReader == NULL) {
|
||||||
|
rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE;
|
||||||
|
} else {
|
||||||
|
rgReaderStates[num_watch].dwCurrentState = priv->reader_state.dwEventState;
|
||||||
|
}
|
||||||
rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE;
|
rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE;
|
||||||
num_watch++;
|
num_watch++;
|
||||||
}
|
}
|
||||||
@ -1589,6 +1604,12 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
|
|||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
/* OS X 10.6.2 - 10.12.6 do not support PnP notification */
|
/* OS X 10.6.2 - 10.12.6 do not support PnP notification */
|
||||||
sc_log(ctx, "PnP notification not supported");
|
sc_log(ctx, "PnP notification not supported");
|
||||||
|
/* Always check on new readers as if a hotplug
|
||||||
|
* event was detected. This overwrites a
|
||||||
|
* SC_ERROR_EVENT_TIMEOUT if a new reader is
|
||||||
|
* detected with SC_SUCCESS. */
|
||||||
|
detect_readers = 1;
|
||||||
|
detected_hotplug = 1;
|
||||||
#else
|
#else
|
||||||
rgReaderStates[num_watch].szReader = "\\\\?PnP?\\Notification";
|
rgReaderStates[num_watch].szReader = "\\\\?PnP?\\Notification";
|
||||||
rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE;
|
rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE;
|
||||||
@ -1622,9 +1643,11 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*event_reader = NULL;
|
||||||
|
*event = 0;
|
||||||
|
|
||||||
if (num_watch == 0) {
|
if (num_watch == 0) {
|
||||||
sc_log(ctx, "No readers available to be watched");
|
sc_log(ctx, "No readers available to be watched");
|
||||||
*event_reader = NULL;
|
|
||||||
r = SC_ERROR_NO_READERS_FOUND;
|
r = SC_ERROR_NO_READERS_FOUND;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1646,7 +1669,6 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
|
|||||||
|
|
||||||
/* Scan the current state of all readers to see if they
|
/* Scan the current state of all readers to see if they
|
||||||
* match any of the events we're polling for */
|
* match any of the events we're polling for */
|
||||||
*event = 0;
|
|
||||||
for (i = 0, rsp = rgReaderStates; i < num_watch; i++, rsp++) {
|
for (i = 0, rsp = rgReaderStates; i < num_watch; i++, rsp++) {
|
||||||
DWORD state, prev_state;
|
DWORD state, prev_state;
|
||||||
sc_log(ctx, "'%s' before=0x%08X now=0x%08X",
|
sc_log(ctx, "'%s' before=0x%08X now=0x%08X",
|
||||||
@ -1657,51 +1679,72 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
|
|||||||
state = rsp->dwEventState;
|
state = rsp->dwEventState;
|
||||||
rsp->dwCurrentState = rsp->dwEventState;
|
rsp->dwCurrentState = rsp->dwEventState;
|
||||||
if (state & SCARD_STATE_CHANGED) {
|
if (state & SCARD_STATE_CHANGED) {
|
||||||
|
|
||||||
/* check for hotplug events */
|
/* check for hotplug events */
|
||||||
if (!strcmp(rgReaderStates[i].szReader, "\\\\?PnP?\\Notification")) {
|
if (!strcmp(rsp->szReader, "\\\\?PnP?\\Notification")) {
|
||||||
sc_log(ctx, "detected hotplug event");
|
sc_log(ctx, "detected hotplug event");
|
||||||
*event |= SC_EVENT_READER_ATTACHED;
|
/* Windows sends hotplug event on both, attaching and
|
||||||
*event_reader = NULL;
|
* detaching a reader. pcscd only sends it in case of
|
||||||
}
|
* attaching a reader. We'll detect later in which case we
|
||||||
|
* are. */
|
||||||
|
detect_readers = 1;
|
||||||
|
detected_hotplug = 1;
|
||||||
|
|
||||||
if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) {
|
/* Windows wants us to manually reset the changed state */
|
||||||
sc_log(ctx, "card inserted event");
|
rsp->dwEventState &= ~SCARD_STATE_CHANGED;
|
||||||
*event |= SC_EVENT_CARD_INSERTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((prev_state & SCARD_STATE_PRESENT) && !(state & SCARD_STATE_PRESENT)) {
|
/* By default, ignore a hotplug event as if a timout
|
||||||
sc_log(ctx, "card removed event");
|
* occurred, since it may be an unrequested removal or
|
||||||
*event |= SC_EVENT_CARD_REMOVED;
|
* false alarm. Just continue to loop and check at the end
|
||||||
}
|
* of this function whether we need to return the attached
|
||||||
|
* reader or not. */
|
||||||
|
r = SC_ERROR_EVENT_TIMEOUT;
|
||||||
|
} else {
|
||||||
|
sc_reader_t *reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader);
|
||||||
|
if (reader) {
|
||||||
|
/* copy the state so we know what to watch out for */
|
||||||
|
struct pcsc_private_data *priv = reader->drv_data;
|
||||||
|
priv->reader_state.dwEventState = state;
|
||||||
|
priv->reader_state.dwCurrentState = prev_state;
|
||||||
|
}
|
||||||
|
|
||||||
if ((state & SCARD_STATE_UNKNOWN) && !(prev_state & SCARD_STATE_UNKNOWN)) {
|
if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) {
|
||||||
sc_log(ctx, "reader detached event");
|
sc_log(ctx, "card inserted event");
|
||||||
*event |= SC_EVENT_READER_DETACHED;
|
*event |= SC_EVENT_CARD_INSERTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((prev_state & SCARD_STATE_UNKNOWN) && !(state & SCARD_STATE_UNKNOWN)) {
|
if ((prev_state & SCARD_STATE_PRESENT) && !(state & SCARD_STATE_PRESENT)) {
|
||||||
sc_log(ctx, "reader re-attached event");
|
sc_log(ctx, "card removed event");
|
||||||
*event |= SC_EVENT_READER_ATTACHED;
|
*event |= SC_EVENT_CARD_REMOVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*event & event_mask) {
|
if ((state & SCARD_STATE_UNKNOWN) && !(prev_state & SCARD_STATE_UNKNOWN)) {
|
||||||
sc_log(ctx, "Matching event 0x%02X in reader %s", *event, rsp->szReader);
|
sc_log(ctx, "reader detached event");
|
||||||
*event_reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader);
|
*event |= SC_EVENT_READER_DETACHED;
|
||||||
r = SC_SUCCESS;
|
detect_readers = 1;
|
||||||
goto out;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
if ((state & SCARD_STATE_IGNORE) && !(prev_state & SCARD_STATE_IGNORE)) {
|
||||||
|
sc_log(ctx, "reader detached event");
|
||||||
|
*event |= SC_EVENT_READER_DETACHED;
|
||||||
|
detect_readers = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((prev_state & SCARD_STATE_UNKNOWN) && !(state & SCARD_STATE_UNKNOWN)) {
|
||||||
|
sc_log(ctx, "reader re-attached event");
|
||||||
|
*event |= SC_EVENT_READER_ATTACHED;
|
||||||
|
detect_readers = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*event & event_mask) {
|
||||||
|
sc_log(ctx, "Matching event 0x%02X in reader %s", *event, rsp->szReader);
|
||||||
|
*event_reader = reader;
|
||||||
|
r = SC_SUCCESS;
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
|
*event = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No match - copy the state so pcscd knows
|
|
||||||
* what to watch out for */
|
|
||||||
/* rsp->dwCurrentState = rsp->dwEventState; */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeout == 0) {
|
|
||||||
r = SC_ERROR_EVENT_TIMEOUT;
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the timeout if caller wants to time out */
|
/* Set the timeout if caller wants to time out */
|
||||||
@ -1713,13 +1756,13 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
|
|||||||
|
|
||||||
rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, dwtimeout, rgReaderStates, num_watch);
|
rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, dwtimeout, rgReaderStates, num_watch);
|
||||||
|
|
||||||
if (rv == (LONG) SCARD_E_CANCELLED) {
|
if (rv == (LONG)SCARD_E_CANCELLED) {
|
||||||
/* C_Finalize was called, events don't matter */
|
/* C_Finalize was called, events don't matter */
|
||||||
r = SC_ERROR_EVENT_TIMEOUT;
|
r = SC_ERROR_EVENT_TIMEOUT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rv == (LONG) SCARD_E_TIMEOUT) {
|
if (rv == (LONG)SCARD_E_TIMEOUT) {
|
||||||
r = SC_ERROR_EVENT_TIMEOUT;
|
r = SC_ERROR_EVENT_TIMEOUT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1731,12 +1774,54 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (!reader_states) {
|
/* in case of an error re-detect all readers */
|
||||||
free(rgReaderStates);
|
if (r < 0 && r != SC_ERROR_EVENT_TIMEOUT)
|
||||||
|
detect_readers = 1;
|
||||||
|
|
||||||
|
if (detect_readers) {
|
||||||
|
pcsc_detect_readers(ctx);
|
||||||
}
|
}
|
||||||
else if (*reader_states == NULL) {
|
|
||||||
sc_log(ctx, "return allocated 'reader states'");
|
if (detected_hotplug) {
|
||||||
*reader_states = rgReaderStates;
|
if (gpriv->attached_reader) {
|
||||||
|
if (event_reader && event && !*event) {
|
||||||
|
/* no other event has been detected, yet */
|
||||||
|
*event_reader = gpriv->attached_reader;
|
||||||
|
*event = SC_EVENT_READER_ATTACHED;
|
||||||
|
r = SC_SUCCESS;
|
||||||
|
}
|
||||||
|
gpriv->attached_reader = NULL;
|
||||||
|
} else if (gpriv->removed_reader) {
|
||||||
|
/* Normally, we only check the hotplug event for attached readers.
|
||||||
|
* However, Windows also notifies on removal. Check, if the latter
|
||||||
|
* was requested by the caller. */
|
||||||
|
if (event_mask & SC_EVENT_READER_DETACHED
|
||||||
|
&& event_reader && event && !*event) {
|
||||||
|
/* no other event has been detected, yet */
|
||||||
|
*event_reader = gpriv->removed_reader;
|
||||||
|
*event = SC_EVENT_READER_DETACHED;
|
||||||
|
r = SC_SUCCESS;
|
||||||
|
}
|
||||||
|
gpriv->removed_reader = NULL;
|
||||||
|
} else {
|
||||||
|
/* false alarm, there was no reader attached or removed,
|
||||||
|
* avoid re-initialize the reader states by resetting detect_readers */
|
||||||
|
detect_readers = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detect_readers) {
|
||||||
|
free(rgReaderStates);
|
||||||
|
if (reader_states && *reader_states)
|
||||||
|
*reader_states = NULL;
|
||||||
|
} else {
|
||||||
|
if (!reader_states) {
|
||||||
|
free(rgReaderStates);
|
||||||
|
}
|
||||||
|
else if (*reader_states == NULL) {
|
||||||
|
sc_log(ctx, "return allocated reader states");
|
||||||
|
*reader_states = rgReaderStates;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_FUNC_RETURN(ctx, r);
|
LOG_FUNC_RETURN(ctx, r);
|
||||||
@ -2449,6 +2534,7 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c
|
|||||||
}
|
}
|
||||||
|
|
||||||
sc_log(ctx, "Probing PC/SC reader");
|
sc_log(ctx, "Probing PC/SC reader");
|
||||||
|
gpriv->attached_reader = NULL;
|
||||||
|
|
||||||
gpriv->pcsc_ctx = *(SCARDCONTEXT *)pcsc_context_handle;
|
gpriv->pcsc_ctx = *(SCARDCONTEXT *)pcsc_context_handle;
|
||||||
card_handle = *(SCARDHANDLE *)pcsc_card_handle;
|
card_handle = *(SCARDHANDLE *)pcsc_card_handle;
|
||||||
@ -2467,6 +2553,7 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c
|
|||||||
} else {
|
} else {
|
||||||
_sc_delete_reader(ctx, reader);
|
_sc_delete_reader(ctx, reader);
|
||||||
}
|
}
|
||||||
|
gpriv->attached_reader = reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -40,8 +40,13 @@
|
|||||||
#ifndef _BSD_SOURCE
|
#ifndef _BSD_SOURCE
|
||||||
#define _BSD_SOURCE /* See feature_test_macros(7) */
|
#define _BSD_SOURCE /* See feature_test_macros(7) */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SYS_ENDIAN_H
|
||||||
|
#include <sys/endian.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ENDIAN_H
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
int get_pace_capabilities(u8 *bitmap)
|
int get_pace_capabilities(u8 *bitmap)
|
||||||
{
|
{
|
||||||
|
@ -1668,22 +1668,6 @@ pkcs15_login(struct sc_pkcs11_slot *slot, CK_USER_TYPE userType,
|
|||||||
|
|
||||||
if (!p11card)
|
if (!p11card)
|
||||||
return CKR_TOKEN_NOT_RECOGNIZED;
|
return CKR_TOKEN_NOT_RECOGNIZED;
|
||||||
if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD
|
|
||||||
|| (p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) {
|
|
||||||
/* pPin should be NULL in case of a pin pad reader, but
|
|
||||||
* some apps (e.g. older Netscapes) don't know about it.
|
|
||||||
* So we don't require that pPin == NULL, but set it to
|
|
||||||
* NULL ourselves. This way, you can supply an empty (if
|
|
||||||
* possible) or fake PIN if an application asks a PIN).
|
|
||||||
*/
|
|
||||||
/* But we want to be able to specify a PIN on the command
|
|
||||||
* line (e.g. for the test scripts). So we don't do anything
|
|
||||||
* here - this gives the user the choice of entering
|
|
||||||
* an empty pin (which makes us use the pin pad) or
|
|
||||||
* a valid pin (which is processed normally). --okir */
|
|
||||||
if (ulPinLen == 0)
|
|
||||||
pPin = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* By default, we make the reader resource manager keep other
|
/* By default, we make the reader resource manager keep other
|
||||||
* processes from accessing the card while we're logged in.
|
* processes from accessing the card while we're logged in.
|
||||||
@ -1843,26 +1827,11 @@ pkcs15_change_pin(struct sc_pkcs11_slot *slot,
|
|||||||
return CKR_USER_PIN_NOT_INITIALIZED;
|
return CKR_USER_PIN_NOT_INITIALIZED;
|
||||||
|
|
||||||
sc_log(context, "Change '%.*s' (ref:%i,type:%i)", (int) sizeof pin_obj->label, pin_obj->label, auth_info->attrs.pin.reference, login_user);
|
sc_log(context, "Change '%.*s' (ref:%i,type:%i)", (int) sizeof pin_obj->label, pin_obj->label, auth_info->attrs.pin.reference, login_user);
|
||||||
if ((p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD)
|
if (pNewPin && (ulNewLen < auth_info->attrs.pin.min_length || ulNewLen > auth_info->attrs.pin.max_length)) {
|
||||||
|| (p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) {
|
|
||||||
/* pPin should be NULL in case of a pin pad reader, but
|
|
||||||
* some apps (e.g. older Netscapes) don't know about it.
|
|
||||||
* So we don't require that pPin == NULL, but set it to
|
|
||||||
* NULL ourselves. This way, you can supply an empty (if
|
|
||||||
* possible) or fake PIN if an application asks a PIN).
|
|
||||||
*/
|
|
||||||
pOldPin = pNewPin = NULL;
|
|
||||||
ulOldLen = ulNewLen = 0;
|
|
||||||
}
|
|
||||||
else if (ulNewLen < auth_info->attrs.pin.min_length || ulNewLen > auth_info->attrs.pin.max_length) {
|
|
||||||
return CKR_PIN_LEN_RANGE;
|
return CKR_PIN_LEN_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (login_user < 0) {
|
if (login_user < 0 && sc_pkcs11_conf.pin_unblock_style == SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN) {
|
||||||
if (sc_pkcs11_conf.pin_unblock_style != SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN) {
|
|
||||||
sc_log(context, "PIN unlock is not allowed in unlogged session");
|
|
||||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
||||||
}
|
}
|
||||||
else if (login_user == CKU_CONTEXT_SPECIFIC) {
|
else if (login_user == CKU_CONTEXT_SPECIFIC) {
|
||||||
@ -1872,7 +1841,7 @@ pkcs15_change_pin(struct sc_pkcs11_slot *slot,
|
|||||||
}
|
}
|
||||||
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
||||||
}
|
}
|
||||||
else if ((login_user == CKU_USER) || (login_user == CKU_SO)) {
|
else if (login_user < 0 || login_user == CKU_USER || login_user == CKU_SO) {
|
||||||
rc = sc_pkcs15_change_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
rc = sc_pkcs15_change_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -469,16 +469,17 @@ static int sm_encrypt(const struct iso_sm_ctx *ctx, sc_card_t *card,
|
|||||||
sm_apdu->datalen = sm_data_len;
|
sm_apdu->datalen = sm_data_len;
|
||||||
sm_apdu->lc = sm_data_len;
|
sm_apdu->lc = sm_data_len;
|
||||||
sm_apdu->le = 0;
|
sm_apdu->le = 0;
|
||||||
|
/* for encrypted APDUs we usually get authenticated status bytes (4B), a
|
||||||
|
* MAC (2B without data) and a cryptogram with padding indicator (2B tag
|
||||||
|
* and indicator, max. 2B/3B ASN.1 length, without data). The cryptogram is
|
||||||
|
* always padded to the block size. */
|
||||||
if (apdu->cse & SC_APDU_EXT) {
|
if (apdu->cse & SC_APDU_EXT) {
|
||||||
sm_apdu->cse = SC_APDU_CASE_4_EXT;
|
sm_apdu->cse = SC_APDU_CASE_4_EXT;
|
||||||
|
sm_apdu->resplen = 4 + 2 + mac_len + 2 + 3 + ((apdu->resplen+1)/ctx->block_length+1)*ctx->block_length;
|
||||||
} else {
|
} else {
|
||||||
sm_apdu->cse = SC_APDU_CASE_4_SHORT;
|
sm_apdu->cse = SC_APDU_CASE_4_SHORT;
|
||||||
|
sm_apdu->resplen = 4 + 2 + mac_len + 2 + 2 + ((apdu->resplen+1)/ctx->block_length+1)*ctx->block_length;
|
||||||
}
|
}
|
||||||
/* for encrypted APDUs we usually get authenticated status bytes
|
|
||||||
* (4B), a MAC (2B without data) and a cryptogram with padding
|
|
||||||
* indicator (3B without data). The cryptogram is always padded to
|
|
||||||
* the block size. */
|
|
||||||
sm_apdu->resplen = 4 + 2 + mac_len + 3 + ((apdu->resplen+1)/ctx->block_length+1)*ctx->block_length;
|
|
||||||
resp_data = calloc(sm_apdu->resplen, 1);
|
resp_data = calloc(sm_apdu->resplen, 1);
|
||||||
if (!resp_data) {
|
if (!resp_data) {
|
||||||
r = SC_ERROR_OUT_OF_MEMORY;
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
@ -1486,7 +1486,7 @@ static int do_update_binary(int argc, char **argv)
|
|||||||
|
|
||||||
r = parse_string_or_hexdata(argv[2], buf, &buflen);
|
r = parse_string_or_hexdata(argv[2], buf, &buflen);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "Unable to parse input data: %s\n", strerror(r));
|
fprintf(stderr, "Unable to parse input data: %s\n", sc_strerror(r));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1509,7 +1509,7 @@ static int do_update_binary(int argc, char **argv)
|
|||||||
r = sc_update_binary(card, offs, buf, buflen, 0);
|
r = sc_update_binary(card, offs, buf, buflen, 0);
|
||||||
sc_unlock(card);
|
sc_unlock(card);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "Cannot update %04X: %s\n", file->id, strerror(r));
|
fprintf(stderr, "Cannot update %04X: %s\n", file->id, sc_strerror(r));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1561,7 +1561,7 @@ static int do_update_record(int argc, char **argv)
|
|||||||
r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR);
|
r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "Cannot read record %"SC_FORMAT_LEN_SIZE_T"u of %04X: %s\n",
|
fprintf(stderr, "Cannot read record %"SC_FORMAT_LEN_SIZE_T"u of %04X: %s\n",
|
||||||
rec, file->id, strerror(r));
|
rec, file->id, sc_strerror(r));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1574,7 +1574,7 @@ static int do_update_record(int argc, char **argv)
|
|||||||
buflen = sizeof(buf) - offs;
|
buflen = sizeof(buf) - offs;
|
||||||
r = parse_string_or_hexdata(argv[3], buf + offs, &buflen);
|
r = parse_string_or_hexdata(argv[3], buf + offs, &buflen);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "Unable to parse input data: %s.\n", strerror(r));
|
fprintf(stderr, "Unable to parse input data: %s.\n", sc_strerror(r));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1584,7 +1584,7 @@ static int do_update_record(int argc, char **argv)
|
|||||||
sc_unlock(card);
|
sc_unlock(card);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "Cannot update record %"SC_FORMAT_LEN_SIZE_T"u of %04X: %s\n.",
|
fprintf(stderr, "Cannot update record %"SC_FORMAT_LEN_SIZE_T"u of %04X: %s\n.",
|
||||||
rec, file->id, strerror(r));
|
rec, file->id, sc_strerror(r));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1698,7 +1698,7 @@ static int do_erase(int argc, char **argv)
|
|||||||
r = sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL);
|
r = sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL);
|
||||||
sc_unlock(card);
|
sc_unlock(card);
|
||||||
if (r) {
|
if (r) {
|
||||||
fprintf(stderr, "Failed to erase card: %s\n", sc_strerror (r));
|
fprintf(stderr, "Failed to erase card: %s\n", sc_strerror(r));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -49,26 +49,21 @@ void Sleep(unsigned int Milliseconds)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void stop_daemon()
|
|
||||||
{
|
|
||||||
#ifdef PCSCLITE_GOOD
|
|
||||||
sc_cancel(ctx);
|
|
||||||
#endif
|
|
||||||
run_daemon = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void notify_daemon()
|
void notify_daemon()
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
const unsigned int event_mask = SC_EVENT_CARD_EVENTS;
|
const unsigned int event_mask = SC_EVENT_CARD_EVENTS|SC_EVENT_READER_EVENTS;
|
||||||
unsigned int event;
|
unsigned int event;
|
||||||
struct sc_reader *event_reader = NULL;
|
struct sc_reader *event_reader = NULL;
|
||||||
size_t error_count = 0;
|
void *reader_states = NULL;
|
||||||
|
#ifndef __APPLE__
|
||||||
/* timeout adjusted to the maximum response time for WM_CLOSE in case
|
/* timeout adjusted to the maximum response time for WM_CLOSE in case
|
||||||
* canceling doesn't work */
|
* canceling doesn't work */
|
||||||
const int timeout = 20000;
|
const int timeout = 20000;
|
||||||
struct sc_atr old_atr;
|
#else
|
||||||
void *reader_states = NULL;
|
/* lower timeout, because Apple doesn't support hotplug events */
|
||||||
|
const int timeout = 2000;
|
||||||
|
#endif
|
||||||
|
|
||||||
r = sc_establish_context(&ctx, "opensc-notify");
|
r = sc_establish_context(&ctx, "opensc-notify");
|
||||||
if (r < 0 || !ctx) {
|
if (r < 0 || !ctx) {
|
||||||
@ -76,50 +71,51 @@ void notify_daemon()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (run_daemon && error_count < 1000) {
|
while (run_daemon) {
|
||||||
|
|
||||||
r = sc_wait_for_event(ctx, event_mask,
|
r = sc_wait_for_event(ctx, event_mask,
|
||||||
&event_reader, &event, timeout, &reader_states);
|
&event_reader, &event, timeout, &reader_states);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (r == SC_ERROR_NO_READERS_FOUND) {
|
if (r == SC_ERROR_NO_READERS_FOUND) {
|
||||||
/* No readers available, PnP notification not supported */
|
Sleep(timeout);
|
||||||
Sleep(200);
|
continue;
|
||||||
} else {
|
|
||||||
error_count++;
|
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_count = 0;
|
if (event_reader) {
|
||||||
|
if (event & SC_EVENT_CARD_REMOVED
|
||||||
if (event & SC_EVENT_CARD_REMOVED) {
|
|| (event & SC_EVENT_READER_DETACHED
|
||||||
sc_notify_id(ctx, &old_atr, NULL, NOTIFY_CARD_REMOVED);
|
&& event_reader->flags & SC_READER_CARD_PRESENT)) {
|
||||||
}
|
/* sc_notify_id uses only the reader's name for displaying on
|
||||||
if (event & SC_EVENT_CARD_INSERTED) {
|
* removal, so use a dummy card here to get that information
|
||||||
if (event_reader) {
|
* into the notification */
|
||||||
/* FIXME `pcsc_wait_for_event` has all the information that's
|
struct sc_pkcs15_card p15card;
|
||||||
* requested again with `pcsc_detect_card_presence`, but it
|
sc_card_t card;
|
||||||
* doesn't use the ATR, for example, to refresh the reader's
|
memset(&card, 0, sizeof card);
|
||||||
* attributes. To get the ATR we need to call
|
card.reader = event_reader;
|
||||||
* sc_detect_card_presence. Eventually this should be fixed. */
|
memset(&p15card, 0, sizeof p15card);
|
||||||
sc_detect_card_presence(event_reader);
|
p15card.card = &card;
|
||||||
memcpy(old_atr.value, event_reader->atr.value,
|
sc_notify_id(ctx, &event_reader->atr, &p15card, NOTIFY_CARD_REMOVED);
|
||||||
event_reader->atr.len);
|
} else if (event & SC_EVENT_CARD_INSERTED
|
||||||
old_atr.len = event_reader->atr.len;
|
|| (event & SC_EVENT_READER_ATTACHED
|
||||||
} else {
|
&& event_reader->flags & SC_READER_CARD_PRESENT)) {
|
||||||
old_atr.len = 0;
|
/* sc_notify_id prevers the reader's name for displaying on
|
||||||
|
* insertion, so use a dummy card here to get that information
|
||||||
|
* into the notification */
|
||||||
|
struct sc_pkcs15_card p15card;
|
||||||
|
sc_card_t card;
|
||||||
|
memset(&card, 0, sizeof card);
|
||||||
|
card.reader = event_reader;
|
||||||
|
memset(&p15card, 0, sizeof p15card);
|
||||||
|
p15card.card = &card;
|
||||||
|
sc_notify_id(ctx, &event_reader->atr, &p15card, NOTIFY_CARD_INSERTED);
|
||||||
}
|
}
|
||||||
sc_notify_id(ctx, old_atr.len ? &old_atr : NULL, NULL,
|
|
||||||
NOTIFY_CARD_INSERTED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
if (error_count >= 1000) {
|
|
||||||
sc_log(ctx, "Too many errors; aborting.");
|
|
||||||
}
|
|
||||||
/* free `reader_states` */
|
/* free `reader_states` */
|
||||||
sc_wait_for_event(ctx, 0, NULL, NULL, 0, &reader_states);
|
sc_wait_for_event(ctx, 0, NULL, NULL, 0, &reader_states);
|
||||||
reader_states = NULL;
|
|
||||||
sc_release_context(ctx);
|
sc_release_context(ctx);
|
||||||
ctx = NULL;
|
ctx = NULL;
|
||||||
}
|
}
|
||||||
@ -132,7 +128,8 @@ void notify_daemon()
|
|||||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (message == WM_CLOSE || message == WM_QUIT) {
|
if (message == WM_CLOSE || message == WM_QUIT) {
|
||||||
stop_daemon();
|
run_daemon = 0;
|
||||||
|
sc_cancel(ctx);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,32 +179,54 @@ WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nShowC
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef HAVE_SIGACTION
|
#if defined(HAVE_SIGACTION) && defined(HAVE_PTHREAD)
|
||||||
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static int cancellation_fd[] = {-1, -1};
|
||||||
|
|
||||||
void sig_handler(int sig) {
|
void sig_handler(int sig) {
|
||||||
stop_daemon();
|
run_daemon = 0;
|
||||||
|
write(cancellation_fd[1], &sig, sizeof sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_sa_handler(void)
|
static void *cancellation_proc(void *arg)
|
||||||
{
|
{
|
||||||
struct sigaction new_sig, old_sig;
|
(void)arg;
|
||||||
|
while (run_daemon) {
|
||||||
|
int sig;
|
||||||
|
if (sizeof sig == read(cancellation_fd[0], &sig, sizeof sig)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sc_cancel(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Register signal handlers */
|
void setup_cancellation(void)
|
||||||
|
{
|
||||||
|
pthread_t cancellation_thread;
|
||||||
|
struct sigaction new_sig, old_sig;
|
||||||
new_sig.sa_handler = sig_handler;
|
new_sig.sa_handler = sig_handler;
|
||||||
sigemptyset(&new_sig.sa_mask);
|
sigemptyset(&new_sig.sa_mask);
|
||||||
new_sig.sa_flags = SA_RESTART;
|
new_sig.sa_flags = SA_RESTART;
|
||||||
if ((sigaction(SIGINT, &new_sig, &old_sig) < 0)
|
|
||||||
|| (sigaction(SIGTERM, &new_sig, &old_sig) < 0)) {
|
if (pipe(cancellation_fd) != 0
|
||||||
fprintf(stderr, "Failed to create signal handler: %s", strerror(errno));
|
|| (errno = pthread_create(&cancellation_thread, NULL, cancellation_proc, NULL)) != 0
|
||||||
|
|| sigaction(SIGINT, &new_sig, &old_sig) != 0
|
||||||
|
|| sigaction(SIGTERM, &new_sig, &old_sig) != 0) {
|
||||||
|
fprintf(stderr, "Failed to setup cancellation: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void set_sa_handler(void)
|
void setup_cancellation(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "opensc-notify-cmdline.h"
|
#include "opensc-notify-cmdline.h"
|
||||||
@ -244,8 +263,8 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
if ((!cmdline.customized_mode_counter && !cmdline.standard_mode_counter)
|
if ((!cmdline.customized_mode_counter && !cmdline.standard_mode_counter)
|
||||||
|| cmdline.daemon_mode_counter) {
|
|| cmdline.daemon_mode_counter) {
|
||||||
set_sa_handler();
|
|
||||||
run_daemon = 1;
|
run_daemon = 1;
|
||||||
|
setup_cancellation();
|
||||||
notify_daemon();
|
notify_daemon();
|
||||||
} else {
|
} else {
|
||||||
/* give the notification process some time to spawn */
|
/* give the notification process some time to spawn */
|
||||||
|
@ -1597,53 +1597,42 @@ static void init_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess)
|
|||||||
|
|
||||||
static int change_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess)
|
static int change_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess)
|
||||||
{
|
{
|
||||||
char old_buf[21], *old_pin = NULL;
|
char old_buf[21], *old_pin = opt_so_pin ? (char*)opt_so_pin : (char*)opt_pin;
|
||||||
char new_buf[21], *new_pin = NULL;
|
char new_buf[21], *new_pin = (char *)opt_new_pin;
|
||||||
CK_TOKEN_INFO info;
|
CK_TOKEN_INFO info;
|
||||||
CK_RV rv;
|
CK_RV rv;
|
||||||
int r;
|
int r;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
get_token_info(slot, &info);
|
get_token_info(slot, &info);
|
||||||
|
const CK_FLAGS hasReaderPinPad = info.flags & CKF_PROTECTED_AUTHENTICATION_PATH;
|
||||||
|
|
||||||
if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
|
if (!hasReaderPinPad && !old_pin) {
|
||||||
if (!opt_pin && !opt_so_pin) {
|
printf("Please enter the current PIN: ");
|
||||||
printf("Please enter the current PIN: ");
|
r = util_getpass(&old_pin, &len, stdin);
|
||||||
r = util_getpass(&old_pin, &len, stdin);
|
if (r < 0)
|
||||||
if (r < 0)
|
return 1;
|
||||||
return 1;
|
if (!old_pin || !*old_pin || strlen(old_pin) > 20)
|
||||||
if (!old_pin || !*old_pin || strlen(old_pin) > 20)
|
return 1;
|
||||||
return 1;
|
strcpy(old_buf, old_pin);
|
||||||
strcpy(old_buf, old_pin);
|
old_pin = old_buf;
|
||||||
old_pin = old_buf;
|
}
|
||||||
}
|
if (!hasReaderPinPad && !new_pin) {
|
||||||
else {
|
printf("Please enter the new PIN: ");
|
||||||
if (opt_so_pin)
|
r = util_getpass(&new_pin, &len, stdin);
|
||||||
old_pin = (char *) opt_so_pin;
|
if (r < 0)
|
||||||
else
|
return 1;
|
||||||
old_pin = (char *) opt_pin;
|
if (!new_pin || !*new_pin || strlen(new_pin) > 20)
|
||||||
}
|
return 1;
|
||||||
|
strcpy(new_buf, new_pin);
|
||||||
|
|
||||||
if (!opt_new_pin) {
|
printf("Please enter the new PIN again: ");
|
||||||
printf("Please enter the new PIN: ");
|
r = util_getpass(&new_pin, &len, stdin);
|
||||||
r = util_getpass(&new_pin, &len, stdin);
|
if (r < 0)
|
||||||
if (r < 0)
|
return 1;
|
||||||
return 1;
|
if (!new_pin || !*new_pin || strcmp(new_buf, new_pin) != 0) {
|
||||||
if (!new_pin || !*new_pin || strlen(new_pin) > 20)
|
free(new_pin);
|
||||||
return 1;
|
return 1;
|
||||||
strcpy(new_buf, new_pin);
|
|
||||||
|
|
||||||
printf("Please enter the new PIN again: ");
|
|
||||||
r = util_getpass(&new_pin, &len, stdin);
|
|
||||||
if (r < 0)
|
|
||||||
return 1;
|
|
||||||
if (!new_pin || !*new_pin || strcmp(new_buf, new_pin) != 0) {
|
|
||||||
free(new_pin);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
new_pin = (char *) opt_new_pin;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,8 +34,12 @@ static const char *get_inserted_text(struct sc_pkcs15_card *p15card, struct sc_a
|
|||||||
static char text[3*SC_MAX_ATR_SIZE] = {0};
|
static char text[3*SC_MAX_ATR_SIZE] = {0};
|
||||||
const char prefix[] = "ATR: ";
|
const char prefix[] = "ATR: ";
|
||||||
|
|
||||||
if (p15card && p15card->card && p15card->card->name) {
|
if (p15card && p15card->card
|
||||||
|
&& p15card->card->name) {
|
||||||
return p15card->card->name;
|
return p15card->card->name;
|
||||||
|
} else if (p15card && p15card->card
|
||||||
|
&& p15card->card->reader && p15card->card->reader->name) {
|
||||||
|
return p15card->card->reader->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!atr)
|
if (!atr)
|
||||||
@ -192,7 +196,7 @@ const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr,
|
|||||||
str = "Dieses Fenster wird automatisch geschlossen, wenn die PIN am PIN-Pad eingegeben wurde (Timeout typischerweise nach 30 Sekunden).";
|
str = "Dieses Fenster wird automatisch geschlossen, wenn die PIN am PIN-Pad eingegeben wurde (Timeout typischerweise nach 30 Sekunden).";
|
||||||
break;
|
break;
|
||||||
case NOTIFY_CARD_INSERTED:
|
case NOTIFY_CARD_INSERTED:
|
||||||
if (p15card) {
|
if (p15card && p15card->card && p15card->card->name) {
|
||||||
str = "Smartcard kann jetzt verwendet werden";
|
str = "Smartcard kann jetzt verwendet werden";
|
||||||
} else {
|
} else {
|
||||||
str = "Smartcard erkannt";
|
str = "Smartcard erkannt";
|
||||||
@ -260,7 +264,7 @@ const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr,
|
|||||||
str = "This window will be closed automatically after the PIN has been submitted on the PIN pad (timeout typically after 30 seconds).";
|
str = "This window will be closed automatically after the PIN has been submitted on the PIN pad (timeout typically after 30 seconds).";
|
||||||
break;
|
break;
|
||||||
case NOTIFY_CARD_INSERTED:
|
case NOTIFY_CARD_INSERTED:
|
||||||
if (p15card) {
|
if (p15card && p15card->card && p15card->card->name) {
|
||||||
str = "Smart card is ready to use";
|
str = "Smart card is ready to use";
|
||||||
} else {
|
} else {
|
||||||
str = "Smart card detected";
|
str = "Smart card detected";
|
||||||
|
Loading…
Reference in New Issue
Block a user