bankd: Open PC/SC by default in EXCLUSIVE mode

Let's open the cards in EXCLUSIVE mode, we don't want other applications
tinkering with the card state while we have a bankd worker running on
it.  This change also means that no two bankd workers can trip on
each other accidentially anymore.

Related: OS#5527
Change-Id: I43a1c8c7bd1c0124ee5f605e2e5b04ed8f7836ab
This commit is contained in:
Harald Welte 2022-07-13 15:20:13 +02:00
parent 1f51279887
commit 628672bc72
4 changed files with 31 additions and 3 deletions

View File

@ -89,6 +89,15 @@ approach seems to make more sense.
*-P, --bind-port <1-65535>*::
Specify the local TCP port to which the socket for incoming connections
from `osmo-remsim-client`s is bound to.
*-s, --permit-shared-pcsc*::
Specify whether the PC/SC readers should be accessed in SCARD_SHARE_SHARED
mode, instead of the default (SCARD_SHARE_EXCLUSIVE). Shared mode would
permit multiple application programs to access a single reader/slot/card
concurrently. This is potentially dangerous as the two programs operate
without knowledge of each other, and either of them might modify the card
state (such as the currently selected file, validated PIN, etc.) in a
way not expected by the other application.
==== Examples
.remsim-server is on 10.2.3.4, cardreader has 5 slots:

View File

@ -130,6 +130,10 @@ struct bankd {
pthread_mutex_t workers_mutex;
struct llist_head pcsc_slot_names;
struct {
bool permit_shared_pcsc;
} cfg;
};
int bankd_pcsc_read_slotnames(struct bankd *bankd, const char *csv_file);

View File

@ -98,6 +98,8 @@ static void bankd_init(struct bankd *bankd)
/* FIXME: other members of app_comp_id */
INIT_LLIST_HEAD(&bankd->pcsc_slot_names);
bankd->cfg.permit_shared_pcsc = false;
}
/* create + start a new bankd_worker thread */
@ -291,6 +293,7 @@ static void printf_help()
" connections (default: INADDR_ANY)\n"
" -P --bind-port <1-65535> Local TCP port to bind for incoming client\n"
" connectionss (default: 9999)\n"
" -s --permit-shared-pcsc Permit SHARED access to PC/SC readers (default: exclusive)\n"
);
}
@ -312,10 +315,11 @@ static void handle_options(int argc, char **argv)
{ "component-name", 1, 0, 'N' },
{ "bind-ip", 1, 0, 'I' },
{ "bind-port", 1, 0, 'P' },
{ "permit-shared-pcsc", 0, 0, 's' },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "hVd:i:o:b:n:N:I:P:", long_options, &option_index);
c = getopt_long(argc, argv, "hVd:i:o:b:n:N:I:P:s", long_options, &option_index);
if (c == -1)
break;
@ -352,6 +356,9 @@ static void handle_options(int argc, char **argv)
case 'P':
g_bind_port = atoi(optarg);
break;
case 's':
g_bankd->cfg.permit_shared_pcsc = true;
break;
}
}
}

View File

@ -184,6 +184,14 @@ if (rv != SCARD_S_SUCCESS) { \
LOGW((w), text ": OK\n"); \
}
static DWORD bankd_share_mode(struct bankd *bankd)
{
if (bankd->cfg.permit_shared_pcsc)
return SCARD_SHARE_SHARED;
else
return SCARD_SHARE_EXCLUSIVE;
}
static int pcsc_get_atr(struct bankd_worker *worker)
{
long rc;
@ -232,7 +240,7 @@ static int pcsc_connect_slot_regex(struct bankd_worker *worker)
int r = regexec(&compiled_name, p, 0, NULL, 0);
if (r == 0) {
LOGW(worker, "Attempting to open card/slot '%s'\n", p);
rc = SCardConnect(worker->reader.pcsc.hContext, p, SCARD_SHARE_SHARED,
rc = SCardConnect(worker->reader.pcsc.hContext, p, bankd_share_mode(worker->bankd),
SCARD_PROTOCOL_T0, &worker->reader.pcsc.hCard,
&dwActiveProtocol);
if (rc == SCARD_S_SUCCESS)
@ -289,7 +297,7 @@ static int pcsc_reset_card(struct bankd_worker *worker, bool cold_reset)
LOGW(worker, "Resetting card in '%s' (%s)\n", worker->reader.name,
cold_reset ? "cold reset" : "warm reset");
rc = SCardReconnect(worker->reader.pcsc.hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0,
rc = SCardReconnect(worker->reader.pcsc.hCard, bankd_share_mode(worker->bankd), SCARD_PROTOCOL_T0,
cold_reset ? SCARD_UNPOWER_CARD : SCARD_RESET_CARD, &dwActiveProtocol);
PCSC_ERROR(worker, rc, "SCardReconnect");