bankd: Move all PC/SC specific code to bankd_pcsc

Change-Id: I435b42982b54d74447c435dcefa26d1e317d15e0
This commit is contained in:
Harald Welte 2019-03-28 18:42:35 +01:00
parent 1f699b405a
commit 297d72ef47
4 changed files with 114 additions and 69 deletions

View File

@ -17,6 +17,12 @@
#include "client.h"
#include "debug.h"
extern struct value_string worker_state_names[];
#define LOGW(w, fmt, args...) \
printf("[%03u %s] %s:%u " fmt, (w)->num, get_value_string(worker_state_names, (w)->state), \
__FILE__, __LINE__, ## args)
struct bankd;
enum bankd_worker_state {
@ -64,6 +70,8 @@ struct bankd_worker {
/* top talloc context for this worker/thread */
void *tall_ctx;
const struct bankd_driver_ops *ops;
/* File descriptor of the TCP connection to the remsim-client (modem) */
struct {
int fd;
@ -90,6 +98,15 @@ struct bankd_worker {
} card;
};
/* bankd card reader driver operations */
struct bankd_driver_ops {
/* open a given card/slot: called once client + mapping exists */
int (*open_card)(struct bankd_worker *worker);
int (*transceive)(struct bankd_worker *worker, const uint8_t *out, size_t out_len,
uint8_t *in, size_t *in_len);
/* called at cleanup time of a worker thread: clear any driver related state */
void (*cleanup)(struct bankd_worker *worker);
};
/* global bank deamon */
struct bankd {
@ -120,3 +137,5 @@ struct bankd {
int bankd_pcsc_read_slotnames(struct bankd *bankd, const char *csv_file);
const char *bankd_pcsc_get_slot_name(struct bankd *bankd, const struct bank_slot *slot);
extern const struct bankd_driver_ops pcsc_driver_ops;

View File

@ -31,10 +31,6 @@
#include <pthread.h>
#include <wintypes.h>
#include <winscard.h>
#include <pcsclite.h>
#include <sys/socket.h>
#include <netdb.h>
@ -113,6 +109,7 @@ static struct bankd_worker *bankd_create_worker(struct bankd *bankd, unsigned in
worker->bankd = bankd;
worker->num = i;
worker->ops = &pcsc_driver_ops;
/* in the initial state, the worker has no client.fd, bank_slot or pcsc handle yet */
@ -299,18 +296,6 @@ struct value_string worker_state_names[] = {
{ 0, NULL }
};
#define LOGW(w, fmt, args...) \
printf("[%03u %s] %s:%u " fmt, (w)->num, get_value_string(worker_state_names, (w)->state), \
__FILE__, __LINE__, ## args)
#define PCSC_ERROR(w, rv, text) \
if (rv != SCARD_S_SUCCESS) { \
LOGW((w), text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
goto end; \
} else { \
LOGW((w), ": OK\n"); \
}
static int worker_send_rspro(struct bankd_worker *worker, RsproPDU_t *pdu);
static void worker_set_state(struct bankd_worker *worker, enum bankd_worker_state new_state)
@ -372,10 +357,9 @@ static void worker_cleanup(void *arg)
pthread_mutex_unlock(&bankd->workers_mutex);
}
static int worker_open_card(struct bankd_worker *worker)
{
long rc;
int rc;
OSMO_ASSERT(worker->state == BW_ST_CONN_CLIENT_MAPPED);
@ -385,44 +369,19 @@ static int worker_open_card(struct bankd_worker *worker)
if (!worker->reader.name) {
LOGW(worker, "No PC/SC reader name configured for %u/%u, fix your config\n",
worker->slot.bank_id, worker->slot.slot_nr);
rc = -1;
goto end;
return -1;
}
}
OSMO_ASSERT(worker->reader.name);
if (!worker->reader.pcsc.hContext) {
LOGW(worker, "Attempting to open PC/SC context\n");
/* The PC/SC context must be created inside the thread where we'll later use it */
rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &worker->reader.pcsc.hContext);
PCSC_ERROR(worker, rc, "SCardEstablishContext")
}
if (!worker->reader.pcsc.hCard) {
LOGW(worker, "Attempting to open card/slot '%s'\n", worker->reader.name);
DWORD dwActiveProtocol;
rc = SCardConnect(worker->reader.pcsc.hContext, worker->reader.name, SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0, &worker->reader.pcsc.hCard, &dwActiveProtocol);
PCSC_ERROR(worker, rc, "SCardConnect")
}
/* use DWORD type as this is what the PC/SC API expects */
char pbReader[MAX_READERNAME];
DWORD dwReaderLen = sizeof(pbReader);
DWORD dwAtrLen = worker->card.atr_len = sizeof(worker->card.atr);
DWORD dwState, dwProt;
rc = SCardStatus(worker->reader.pcsc.hCard, pbReader, &dwReaderLen, &dwState, &dwProt,
worker->card.atr, &dwAtrLen);
PCSC_ERROR(worker, rc, "SCardStatus")
worker->card.atr_len = dwAtrLen;
LOGW(worker, "Card ATR: %s\n", osmo_hexdump_nospc(worker->card.atr, worker->card.atr_len));
rc = worker->ops->open_card(worker);
if (rc < 0)
return rc;
worker_set_state(worker, BW_ST_CONN_CLIENT_MAPPED_CARD);
/* FIXME: notify client about this state change */
return 0;
end:
return rc;
}
@ -588,14 +547,12 @@ respond_and_err:
static int worker_handle_tpduModemToCard(struct bankd_worker *worker, const RsproPDU_t *pdu)
{
const struct TpduModemToCard *mdm2sim = &pdu->msg.choice.tpduModemToCard;
const SCARD_IO_REQUEST *pioSendPci = SCARD_PCI_T0;
SCARD_IO_REQUEST pioRecvPci;
uint8_t rx_buf[1024];
DWORD rx_buf_len = sizeof(rx_buf);
RsproPDU_t *pdu_resp;
struct client_slot clslot;
struct bank_slot bslot;
long rc;
int rc;
LOGW(worker, "tpduModemToCard(%s)\n", osmo_hexdump_nospc(mdm2sim->data.buf, mdm2sim->data.size));
@ -618,10 +575,10 @@ static int worker_handle_tpduModemToCard(struct bankd_worker *worker, const Rspr
return -106;
}
rc = SCardTransmit(worker->reader.pcsc.hCard,
pioSendPci, mdm2sim->data.buf, mdm2sim->data.size,
&pioRecvPci, rx_buf, &rx_buf_len);
PCSC_ERROR(worker, rc, "SCardTransmit");
rc = worker->ops->transceive(worker, mdm2sim->data.buf, mdm2sim->data.size,
rx_buf, &rx_buf_len);
if (rc < 0)
return rc;
/* encode response PDU and send it */
pdu_resp = rspro_gen_TpduCard2Modem(&mdm2sim->toBankSlot, &mdm2sim->fromClientSlot,
@ -629,8 +586,6 @@ static int worker_handle_tpduModemToCard(struct bankd_worker *worker, const Rspr
worker_send_rspro(worker, pdu_resp);
return 0;
end:
return rc;
}
/* handle one incoming RSPRO message from a client inside a worker thread */
@ -828,14 +783,7 @@ static void *worker_main(void *arg)
/* clean-up: reset to sane state */
memset(&g_worker->card, 0, sizeof(g_worker->card));
if (g_worker->reader.pcsc.hCard) {
SCardDisconnect(g_worker->reader.pcsc.hCard, SCARD_UNPOWER_CARD);
g_worker->reader.pcsc.hCard = 0;
}
if (g_worker->reader.pcsc.hContext) {
SCardReleaseContext(g_worker->reader.pcsc.hContext);
g_worker->reader.pcsc.hContext = 0;
}
g_worker->ops->cleanup(g_worker);
if (g_worker->reader.name)
g_worker->reader.name = NULL;
if (g_worker->client.fd >= 0)

View File

@ -138,3 +138,81 @@ const char *bankd_pcsc_get_slot_name(struct bankd *bankd, const struct bank_slot
}
return NULL;
}
#include <wintypes.h>
#include <winscard.h>
#include <pcsclite.h>
#define PCSC_ERROR(w, rv, text) \
if (rv != SCARD_S_SUCCESS) { \
LOGW((w), text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
goto end; \
} else { \
LOGW((w), ": OK\n"); \
}
static int pcsc_open_card(struct bankd_worker *worker)
{
long rc;
if (!worker->reader.pcsc.hContext) {
LOGW(worker, "Attempting to open PC/SC context\n");
/* The PC/SC context must be created inside the thread where we'll later use it */
rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &worker->reader.pcsc.hContext);
PCSC_ERROR(worker, rc, "SCardEstablishContext")
}
if (!worker->reader.pcsc.hCard) {
LOGW(worker, "Attempting to open card/slot '%s'\n", worker->reader.name);
DWORD dwActiveProtocol;
rc = SCardConnect(worker->reader.pcsc.hContext, worker->reader.name, SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0, &worker->reader.pcsc.hCard, &dwActiveProtocol);
PCSC_ERROR(worker, rc, "SCardConnect")
}
/* use DWORD type as this is what the PC/SC API expects */
char pbReader[MAX_READERNAME];
DWORD dwReaderLen = sizeof(pbReader);
DWORD dwAtrLen = worker->card.atr_len = sizeof(worker->card.atr);
DWORD dwState, dwProt;
rc = SCardStatus(worker->reader.pcsc.hCard, pbReader, &dwReaderLen, &dwState, &dwProt,
worker->card.atr, &dwAtrLen);
PCSC_ERROR(worker, rc, "SCardStatus")
worker->card.atr_len = dwAtrLen;
LOGW(worker, "Card ATR: %s\n", osmo_hexdump_nospc(worker->card.atr, worker->card.atr_len));
end:
return rc;
}
static int pcsc_transceive(struct bankd_worker *worker, const uint8_t *out, size_t out_len,
uint8_t *in, size_t *in_len)
{
const SCARD_IO_REQUEST *pioSendPci = SCARD_PCI_T0;
SCARD_IO_REQUEST pioRecvPci;
long rc;
rc = SCardTransmit(worker->reader.pcsc.hCard, pioSendPci, out, out_len, &pioRecvPci, in, in_len);
PCSC_ERROR(worker, rc, "SCardTransmit");
end:
return rc;
}
static void pcsc_cleanup(struct bankd_worker *worker)
{
if (worker->reader.pcsc.hCard) {
SCardDisconnect(worker->reader.pcsc.hCard, SCARD_UNPOWER_CARD);
worker->reader.pcsc.hCard = 0;
}
if (worker->reader.pcsc.hContext) {
SCardReleaseContext(worker->reader.pcsc.hContext);
worker->reader.pcsc.hContext = 0;
}
}
const struct bankd_driver_ops pcsc_driver_ops = {
.open_card = pcsc_open_card,
.transceive = pcsc_transceive,
.cleanup = pcsc_cleanup,
};

View File

@ -1,6 +1,6 @@
"1","0","ACS ACR33 ICC Reader 01 00"
"1","1","ACS ACR33 ICC Reader 01 01"
"1","2","ACS ACR33 ICC Reader 01 02"
"1","3","ACS ACR33 ICC Reader 01 03"
"1","4","ACS ACR33 ICC Reader 01 04"
"1","0","ACS ACR33 ICC Reader 00 00"
"1","1","ACS ACR33 ICC Reader 00 01"
"1","2","ACS ACR33 ICC Reader 00 02"
"1","3","ACS ACR33 ICC Reader 00 03"
"1","4","ACS ACR33 ICC Reader 00 04"
"1","23","Alcor Micro AU9560 00 00"

1 1 0 ACS ACR33 ICC Reader 01 00 ACS ACR33 ICC Reader 00 00
2 1 1 ACS ACR33 ICC Reader 01 01 ACS ACR33 ICC Reader 00 01
3 1 2 ACS ACR33 ICC Reader 01 02 ACS ACR33 ICC Reader 00 02
4 1 3 ACS ACR33 ICC Reader 01 03 ACS ACR33 ICC Reader 00 03
5 1 4 ACS ACR33 ICC Reader 01 04 ACS ACR33 ICC Reader 00 04
6 1 23 Alcor Micro AU9560 00 00 Alcor Micro AU9560 00 00