PC/SC: make (dis)connect actions configurable, SCardDisconnect, SCardEndTransaction and SCardReconnect
actions can now be configured via opensc.conf in better detail. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4891 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
77c8cfc37d
commit
c1c3aa1d55
@ -55,17 +55,26 @@ app default {
|
|||||||
# max_send_size = 255;
|
# max_send_size = 255;
|
||||||
# max_recv_size = 256;
|
# max_recv_size = 256;
|
||||||
|
|
||||||
# Connect to reader in exclusive mode.
|
# Connect to reader in exclusive mode?
|
||||||
# Default: false
|
# Default: false
|
||||||
# connect_exclusive = true;
|
# connect_exclusive = true;
|
||||||
#
|
#
|
||||||
# Reset the card after disconnect.
|
# What to do when disconnecting from a card (SCardDisconnect)
|
||||||
# Default: true
|
# Valid values: leave, reset, unpower.
|
||||||
# connect_reset = false;
|
# Default: reset
|
||||||
|
# disconnect_action = unpower;
|
||||||
#
|
#
|
||||||
# Reset the card after each transaction.
|
# What to do at the end of a transaction (SCardEndTransaction)
|
||||||
# Default: false
|
# Valid values: leave, reset, unpower.
|
||||||
# transaction_reset = true;
|
# Default: leave
|
||||||
|
# transaction_end_action = reset;
|
||||||
|
#
|
||||||
|
# What to do when reconnection to a card (SCardReconnect)
|
||||||
|
# Valid values: leave, reset, unpower.
|
||||||
|
# Note that this affects only the internal reconnect (after a SCARD_W_RESET_CARD).
|
||||||
|
# A forced reset via sc_reset() always does a full powerup.
|
||||||
|
# Default: leave
|
||||||
|
# reconnect_action = reset;
|
||||||
#
|
#
|
||||||
# Enable pinpad if detected (PC/SC v2.0.2 Part 10)
|
# Enable pinpad if detected (PC/SC v2.0.2 Part 10)
|
||||||
# Default: true
|
# Default: true
|
||||||
|
@ -51,8 +51,9 @@ struct pcsc_global_private_data {
|
|||||||
SCARDCONTEXT pcsc_wait_ctx;
|
SCARDCONTEXT pcsc_wait_ctx;
|
||||||
int enable_pinpad;
|
int enable_pinpad;
|
||||||
int connect_exclusive;
|
int connect_exclusive;
|
||||||
int connect_reset;
|
DWORD disconnect_action;
|
||||||
int transaction_reset;
|
DWORD transaction_end_action;
|
||||||
|
DWORD reconnect_action;
|
||||||
const char *provider_library;
|
const char *provider_library;
|
||||||
lt_dlhandle dlhandle;
|
lt_dlhandle dlhandle;
|
||||||
SCardEstablishContext_t SCardEstablishContext;
|
SCardEstablishContext_t SCardEstablishContext;
|
||||||
@ -91,6 +92,16 @@ struct pcsc_private_data {
|
|||||||
|
|
||||||
static int pcsc_detect_card_presence(sc_reader_t *reader);
|
static int pcsc_detect_card_presence(sc_reader_t *reader);
|
||||||
|
|
||||||
|
static DWORD pcsc_reset_action(const char *str)
|
||||||
|
{
|
||||||
|
if (!strcmp(str, "reset"))
|
||||||
|
return SCARD_RESET_CARD;
|
||||||
|
else if (!strcmp(str, "unpower"))
|
||||||
|
return SCARD_UNPOWER_CARD;
|
||||||
|
else
|
||||||
|
return SCARD_LEAVE_CARD;
|
||||||
|
}
|
||||||
|
|
||||||
static int pcsc_to_opensc_error(LONG rv)
|
static int pcsc_to_opensc_error(LONG rv)
|
||||||
{
|
{
|
||||||
switch (rv) {
|
switch (rv) {
|
||||||
@ -254,7 +265,7 @@ out:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calls SCardGetStatusChange on the reader to set ATR and associated flags (card present/changed) */
|
||||||
static int refresh_attributes(sc_reader_t *reader)
|
static int refresh_attributes(sc_reader_t *reader)
|
||||||
{
|
{
|
||||||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||||
@ -378,7 +389,7 @@ static int check_forced_protocol(sc_context_t *ctx, u8 *atr, size_t atr_len, DWO
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int pcsc_reconnect(sc_reader_t * reader, int reset)
|
static int pcsc_reconnect(sc_reader_t * reader, DWORD action)
|
||||||
{
|
{
|
||||||
DWORD active_proto, tmp, protocol = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
|
DWORD active_proto, tmp, protocol = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
|
||||||
LONG rv;
|
LONG rv;
|
||||||
@ -403,7 +414,7 @@ static int pcsc_reconnect(sc_reader_t * reader, int reset)
|
|||||||
|
|
||||||
rv = priv->gpriv->SCardReconnect(priv->pcsc_card,
|
rv = priv->gpriv->SCardReconnect(priv->pcsc_card,
|
||||||
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
|
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
|
||||||
protocol, reset ? SCARD_UNPOWER_CARD : SCARD_LEAVE_CARD, &active_proto);
|
protocol, action, &active_proto);
|
||||||
|
|
||||||
if (rv != SCARD_S_SUCCESS) {
|
if (rv != SCARD_S_SUCCESS) {
|
||||||
PCSC_TRACE(reader, "SCardReconnect failed", rv);
|
PCSC_TRACE(reader, "SCardReconnect failed", rv);
|
||||||
@ -466,8 +477,7 @@ static int pcsc_disconnect(sc_reader_t * reader)
|
|||||||
|
|
||||||
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL);
|
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL);
|
||||||
|
|
||||||
priv->gpriv->SCardDisconnect(priv->pcsc_card, priv->gpriv->connect_reset ?
|
priv->gpriv->SCardDisconnect(priv->pcsc_card, priv->gpriv->disconnect_action);
|
||||||
SCARD_RESET_CARD : SCARD_LEAVE_CARD);
|
|
||||||
reader->flags = 0;
|
reader->flags = 0;
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -494,7 +504,7 @@ static int pcsc_lock(sc_reader_t *reader)
|
|||||||
return SC_ERROR_READER_REATTACHED;
|
return SC_ERROR_READER_REATTACHED;
|
||||||
case SCARD_W_RESET_CARD:
|
case SCARD_W_RESET_CARD:
|
||||||
/* try to reconnect if the card was reset by some other application */
|
/* try to reconnect if the card was reset by some other application */
|
||||||
r = pcsc_reconnect(reader, 0);
|
r = pcsc_reconnect(reader, SCARD_LEAVE_CARD);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "pcsc_reconnect failed", r);
|
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "pcsc_reconnect failed", r);
|
||||||
return r;
|
return r;
|
||||||
@ -517,8 +527,7 @@ static int pcsc_unlock(sc_reader_t *reader)
|
|||||||
|
|
||||||
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL);
|
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL);
|
||||||
|
|
||||||
rv = priv->gpriv->SCardEndTransaction(priv->pcsc_card, priv->gpriv->transaction_reset ?
|
rv = priv->gpriv->SCardEndTransaction(priv->pcsc_card, priv->gpriv->transaction_end_action);
|
||||||
SCARD_RESET_CARD : SCARD_LEAVE_CARD);
|
|
||||||
|
|
||||||
priv->locked = 0;
|
priv->locked = 0;
|
||||||
if (rv != SCARD_S_SUCCESS) {
|
if (rv != SCARD_S_SUCCESS) {
|
||||||
@ -542,7 +551,7 @@ static int pcsc_reset(sc_reader_t *reader)
|
|||||||
int r;
|
int r;
|
||||||
int old_locked = priv->locked;
|
int old_locked = priv->locked;
|
||||||
|
|
||||||
r = pcsc_reconnect(reader, 1);
|
r = pcsc_reconnect(reader, SCARD_UNPOWER_CARD);
|
||||||
if(r != SC_SUCCESS)
|
if(r != SC_SUCCESS)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -600,9 +609,10 @@ static int pcsc_init(sc_context_t *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Defaults */
|
/* Defaults */
|
||||||
gpriv->connect_reset = 1;
|
|
||||||
gpriv->connect_exclusive = 0;
|
gpriv->connect_exclusive = 0;
|
||||||
gpriv->transaction_reset = 0;
|
gpriv->disconnect_action = SCARD_RESET_CARD;
|
||||||
|
gpriv->transaction_end_action = SCARD_LEAVE_CARD;
|
||||||
|
gpriv->reconnect_action = SCARD_LEAVE_CARD;
|
||||||
gpriv->enable_pinpad = 1;
|
gpriv->enable_pinpad = 1;
|
||||||
gpriv->provider_library = DEFAULT_PCSC_PROVIDER;
|
gpriv->provider_library = DEFAULT_PCSC_PROVIDER;
|
||||||
gpriv->pcsc_ctx = -1;
|
gpriv->pcsc_ctx = -1;
|
||||||
@ -610,19 +620,21 @@ static int pcsc_init(sc_context_t *ctx)
|
|||||||
|
|
||||||
conf_block = sc_get_conf_block(ctx, "reader_driver", "pcsc", 1);
|
conf_block = sc_get_conf_block(ctx, "reader_driver", "pcsc", 1);
|
||||||
if (conf_block) {
|
if (conf_block) {
|
||||||
gpriv->connect_reset =
|
|
||||||
scconf_get_bool(conf_block, "connect_reset", gpriv->connect_reset);
|
|
||||||
gpriv->connect_exclusive =
|
gpriv->connect_exclusive =
|
||||||
scconf_get_bool(conf_block, "connect_exclusive", gpriv->connect_exclusive);
|
scconf_get_bool(conf_block, "connect_exclusive", gpriv->connect_exclusive);
|
||||||
gpriv->transaction_reset =
|
gpriv->disconnect_action =
|
||||||
scconf_get_bool(conf_block, "transaction_reset", gpriv->transaction_reset);
|
pcsc_reset_action(scconf_get_str(conf_block, "disconnect_action", "reset"));
|
||||||
|
gpriv->transaction_end_action =
|
||||||
|
pcsc_reset_action(scconf_get_str(conf_block, "transaction_end_action", "leave"));
|
||||||
|
gpriv->reconnect_action =
|
||||||
|
pcsc_reset_action(scconf_get_str(conf_block, "reconnect_action", "leave"));
|
||||||
gpriv->enable_pinpad =
|
gpriv->enable_pinpad =
|
||||||
scconf_get_bool(conf_block, "enable_pinpad", gpriv->enable_pinpad);
|
scconf_get_bool(conf_block, "enable_pinpad", gpriv->enable_pinpad);
|
||||||
gpriv->provider_library =
|
gpriv->provider_library =
|
||||||
scconf_get_str(conf_block, "provider_library", gpriv->provider_library);
|
scconf_get_str(conf_block, "provider_library", gpriv->provider_library);
|
||||||
}
|
}
|
||||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PC/SC options: connect_reset=%d connect_exclusive=%d transaction_reset=%d enable_pinpad=%d",
|
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PC/SC options: connect_exclusive=%d disconnect_action=%d transaction_end_action=%d reconnect_action=%d enable_pinpad=%d",
|
||||||
gpriv->connect_reset, gpriv->connect_exclusive, gpriv->transaction_reset, gpriv->enable_pinpad);
|
gpriv->connect_exclusive, gpriv->disconnect_action, gpriv->transaction_end_action, gpriv->reconnect_action, gpriv->enable_pinpad);
|
||||||
|
|
||||||
gpriv->dlhandle = lt_dlopen(gpriv->provider_library);
|
gpriv->dlhandle = lt_dlopen(gpriv->provider_library);
|
||||||
if (gpriv->dlhandle == NULL) {
|
if (gpriv->dlhandle == NULL) {
|
||||||
|
Loading…
Reference in New Issue
Block a user