restrict access to card handles after fork

fixes #333
closes #493
This commit is contained in:
Frank Morgner 2015-07-22 01:28:48 +02:00
parent b48fa70308
commit edc839e072
5 changed files with 72 additions and 9 deletions

View File

@ -639,6 +639,16 @@ typedef struct {
unsigned long (*thread_id)(void);
} sc_thread_context_t;
/** Stop modifing or using external resources
*
* Currently this is used to avoid freeing duplicated external resources for a
* process that has been forked. For example, a child process may want to leave
* the duplicated card handles for the parent process. With this flag the child
* process indicates that shall the reader shall ignore those resources when
* calling sc_disconnect_card.
*/
#define SC_TERMINATE 0x00000001
typedef struct sc_context {
scconf_context *conf;
scconf_block *conf_blocks[3];

View File

@ -116,6 +116,9 @@ static int refresh_attributes(sc_reader_t *reader)
u8 cmd[5], rbuf[256], sad, dad;
unsigned short lr;
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
cmd[0] = CTBCS_CLA;
cmd[1] = CTBCS_INS_STATUS;
cmd[2] = CTBCS_P1_CT_KERNEL;
@ -158,6 +161,9 @@ static int ctapi_internal_transmit(sc_reader_t *reader,
u8 dad, sad;
unsigned short lr;
char rv;
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
if (control)
dad = 1;
@ -235,6 +241,9 @@ static int ctapi_connect(sc_reader_t *reader)
unsigned short lr;
int r;
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
cmd[0] = CTBCS_CLA;
cmd[1] = CTBCS_INS_REQUEST;
cmd[2] = CTBCS_P1_INTERFACE1;
@ -280,7 +289,9 @@ static int ctapi_release(sc_reader_t *reader)
{
struct ctapi_private_data *priv = GET_PRIV_DATA(reader);
priv->funcs.CT_close(priv->ctn);
if (!(reader->ctx->magic & SC_TERMINATE))
priv->funcs.CT_close(priv->ctn);
free(priv);
return 0;

View File

@ -154,7 +154,7 @@ static int openct_reader_release(sc_reader_t *reader)
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE);
if (data) {
if (data->h)
if (data->h && !(reader->ctx->magic & SC_TERMINATE))
ct_reader_disconnect(data->h);
sc_mem_clear(data, sizeof(*data));
reader->drv_data = NULL;
@ -174,6 +174,9 @@ static int openct_reader_detect_card_presence(sc_reader_t *reader)
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE);
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
reader->flags = 0;
if (!data->h && !(data->h = ct_reader_connect(data->num)))
return 0;
@ -197,6 +200,9 @@ openct_reader_connect(sc_reader_t *reader)
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE);
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
if (data->h)
ct_reader_disconnect(data->h);
@ -242,7 +248,7 @@ static int openct_reader_disconnect(sc_reader_t *reader)
struct driver_data *data = (struct driver_data *) reader->drv_data;
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE);
if (data->h)
if (data->h && !(reader->flags & SC_TERMINATE))
ct_reader_disconnect(data->h);
data->h = NULL;
return SC_SUCCESS;
@ -256,6 +262,9 @@ openct_reader_internal_transmit(sc_reader_t *reader,
struct driver_data *data = (struct driver_data *) reader->drv_data;
int rc;
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
/* Hotplug check */
if ((rc = openct_reader_reconnect(reader)) < 0)
return rc;
@ -324,6 +333,9 @@ static int openct_reader_perform_verify(sc_reader_t *reader, struct sc_pin_cmd_d
u8 buf[254];
int rc;
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
/* Hotplug check */
if ((rc = openct_reader_reconnect(reader)) < 0)
return rc;
@ -382,6 +394,9 @@ static int openct_reader_lock(sc_reader_t *reader)
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE);
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
/* Hotplug check */
if ((rc = openct_reader_reconnect(reader)) < 0)
return rc;
@ -408,6 +423,9 @@ static int openct_reader_unlock(sc_reader_t *reader)
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE);
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
/* Not connected */
if (data->h == NULL)
return 0;

View File

@ -184,6 +184,9 @@ static int pcsc_internal_transmit(sc_reader_t *reader,
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL);
card = priv->pcsc_card;
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
sSendPci.dwProtocol = opensc_proto_to_pcsc(reader->active_protocol);
sSendPci.cbPciLength = sizeof(sSendPci);
sRecvPci.dwProtocol = opensc_proto_to_pcsc(reader->active_protocol);
@ -284,6 +287,9 @@ static int refresh_attributes(sc_reader_t *reader)
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "%s check", reader->name);
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
if (priv->reader_state.szReader == NULL) {
priv->reader_state.szReader = reader->name;
priv->reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
@ -505,7 +511,8 @@ static int pcsc_disconnect(sc_reader_t * reader)
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL);
priv->gpriv->SCardDisconnect(priv->pcsc_card, priv->gpriv->disconnect_action);
if (!(reader->ctx->magic & SC_TERMINATE))
priv->gpriv->SCardDisconnect(priv->pcsc_card, priv->gpriv->disconnect_action);
reader->flags = 0;
return SC_SUCCESS;
}
@ -518,6 +525,9 @@ static int pcsc_lock(sc_reader_t *reader)
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL);
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
rv = priv->gpriv->SCardBeginTransaction(priv->pcsc_card);
switch (rv) {
@ -555,6 +565,9 @@ static int pcsc_unlock(sc_reader_t *reader)
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL);
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
rv = priv->gpriv->SCardEndTransaction(priv->pcsc_card, priv->gpriv->transaction_end_action);
priv->locked = 0;
@ -597,12 +610,18 @@ static int pcsc_cancel(sc_context_t *ctx)
struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *)ctx->reader_drv_data;
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
if (ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
#ifndef _WIN32
if (gpriv->pcsc_wait_ctx != -1) {
rv = gpriv->SCardCancel(gpriv->pcsc_wait_ctx);
if (rv == SCARD_S_SUCCESS)
if (rv == SCARD_S_SUCCESS) {
/* Also close and clear the waiting context */
rv = gpriv->SCardReleaseContext(gpriv->pcsc_wait_ctx);
gpriv->pcsc_wait_ctx = -1;
}
}
#else
rv = gpriv->SCardCancel(gpriv->pcsc_ctx);
@ -747,7 +766,7 @@ static int pcsc_finish(sc_context_t *ctx)
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
if (gpriv) {
if (gpriv->pcsc_ctx != -1)
if (gpriv->pcsc_ctx != -1 && !(ctx->magic & SC_TERMINATE))
gpriv->SCardReleaseContext(gpriv->pcsc_ctx);
if (gpriv->dlhandle != NULL)
sc_dlclose(gpriv->dlhandle);
@ -1643,6 +1662,9 @@ pcsc_pin_cmd(sc_reader_t *reader, struct sc_pin_cmd_data *data)
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL);
if (reader->ctx->magic & SC_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
if (priv->gpriv->SCardControl == NULL)
return SC_ERROR_NOT_SUPPORTED;
@ -1932,8 +1954,8 @@ static int transform_pace_output(u8 *rbuf, size_t rbuflen,
static int
pcsc_perform_pace(struct sc_reader *reader, void *input_pace, void *output_pace)
{
struct establish_pace_channel_input *pace_input = (struct establish_pace_channel_input *) input_pace;
struct establish_pace_channel_output *pace_output = (struct establish_pace_channel_output *) output_pace;
struct establish_pace_channel_input *pace_input = (struct establish_pace_channel_input *) input_pace;
struct establish_pace_channel_output *pace_output = (struct establish_pace_channel_output *) output_pace;
struct pcsc_private_data *priv;
u8 rbuf[SC_MAX_EXT_APDU_BUFFER_SIZE], sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE];
size_t rcount = sizeof rbuf, scount = sizeof sbuf;

View File

@ -202,9 +202,11 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
unsigned int i;
sc_context_param_t ctx_opts;
/* Handle fork() exception */
#if !defined(_WIN32)
/* Handle fork() exception */
if (current_pid != initialized_pid) {
if (context)
context->magic |= SC_TERMINATE;
C_Finalize(NULL_PTR);
}
initialized_pid = current_pid;