diff options
author | Christophe Ricard <christophe.ricard@gmail.com> | 2015-02-01 22:54:31 +0100 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2015-03-27 11:00:26 +0100 |
commit | 93b77c2299b25c4a2e8a908ae6035b6cdbb7b841 (patch) | |
tree | da8710ff820b8a2127b34dec44cd7dc91b04a55e | |
parent | f5a7b72d2927ba06a582dea28ea30b75203c72a9 (diff) | |
download | neard-93b77c2299b25c4a2e8a908ae6035b6cdbb7b841.tar.gz |
se: Release logical channel when AID selection fails
When a select AID response status word is not 0x9000, the logical
channel used to communicate with this application should be closed.
-rw-r--r-- | se/se.c | 35 |
1 files changed, 30 insertions, 5 deletions
@@ -122,7 +122,8 @@ static void io_cb(void *context, if (!err) err = __seel_apdu_resp_status(apdu, apdu_length); - req->cb(req->context, apdu, apdu_length, err); + if (req->cb) + req->cb(req->context, apdu, apdu_length, err); __seel_apdu_free(req->apdu); g_free(req); @@ -461,19 +462,39 @@ static void select_aid_cb(void *context, int err) { struct open_channel_context *ctx = context; + struct seel_apdu *close_channel; struct seel_channel *channel; char *path; DBusConnection *conn; + int ret; conn = near_dbus_get_connection(); - if (err != 0) - return open_channel_error(ctx, err); + if (err != 0) { + /* + * err != 0 means SW != 9000. + * In this case, we need to clean the previously + * allocated logical channel. + */ + close_channel = __seel_apdu_close_logical_channel(ctx->channel); + if (!close_channel) + goto err; + + ret = __seel_se_queue_io(ctx->se, close_channel, NULL, ctx); + if (ret < 0) { + near_error("close channel error %d", ret); + err = ret; + } + + goto err; + } channel = __seel_channel_add(ctx->se, ctx->channel, ctx->aid, ctx->aid_len, false); - if (!channel) - return open_channel_error(ctx, -ENOMEM); + if (!channel) { + err = -ENOMEM; + goto err; + } path = __seel_channel_get_path(channel); g_hash_table_replace(ctx->se->channel_hash, path, channel); @@ -485,6 +506,10 @@ static void select_aid_cb(void *context, dbus_message_unref(ctx->msg); ctx->msg = NULL; g_free(ctx); + return; + +err: + return open_channel_error(ctx, err); } static void open_channel_cb(void *context, |