From b953803ae59ea3e66e3ed799b90dbb66a9002fce Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Tue, 6 May 2014 12:24:10 +0300 Subject: [PATCH] silc-client: handle prompt abort better When verfying public key abort any previously ungoing prompt so that we can get the public key verification prompt up. It's important to not loose the public key verification prompts so we now allow new prompt to come up after previous one has aborted. It leaks Irssi memory, but handles things correctly towards silcclient library. Irssi's prompt handling is broken because it stores the data in a global variable allowing only one prompt at a time. --- apps/irssi/src/silc/core/client_ops.c | 8 +++++- apps/irssi/src/silc/core/clientutil.c | 8 ++++++ lib/silcclient/client_prvmsg.c | 35 ++++++++++++--------------- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index 25db9eae..b3b6cdbc 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -2487,8 +2487,8 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, "server" : "client"); int i; + server = (SILC_SERVER_REC*)conn->context; if (conn_type != SILC_CONN_CLIENT) { - server = (SILC_SERVER_REC*)conn->context; SILC_VERIFY(server); if (!server) { if (completion) @@ -2497,6 +2497,12 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, } } + /* If we have pending public key prompt already up */ + if (server && server->prompt_op) { + silc_async_abort(server->prompt_op, NULL, NULL); + server->prompt_op = NULL; + } + if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC) { printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_UNSUPPORTED, diff --git a/apps/irssi/src/silc/core/clientutil.c b/apps/irssi/src/silc/core/clientutil.c index a8a1b5b7..0daceeff 100644 --- a/apps/irssi/src/silc/core/clientutil.c +++ b/apps/irssi/src/silc/core/clientutil.c @@ -411,6 +411,14 @@ static void silc_keyboard_entry_redirect_abort(SilcAsyncOperation op, * the operation has been aborted. */ ctx->user_prompt_proc(NULL, ctx->user_context, KeyboardCompletionAborted); + + /* + * Allow new prompt after we've abored despite us leaking Irssi prompt + * data. It's more important to get new prompt up and this abort + * guarantees we handle things correctly towards silcclient library by + * calling the callback above. + */ + silc_keyboard_prompt_pending = FALSE; } static void silc_keyboard_entry_redirect_completion(const char *line, diff --git a/lib/silcclient/client_prvmsg.c b/lib/silcclient/client_prvmsg.c index 4abccb49..8116a9ff 100644 --- a/lib/silcclient/client_prvmsg.c +++ b/lib/silcclient/client_prvmsg.c @@ -808,25 +808,22 @@ silc_client_autoneg_key_recv_ske(SilcPacketEngine engine, /* Responder is started here if correct packet comes in */ if (!ake->ske_op) { - if (packet->type == SILC_PACKET_KEY_EXCHANGE) - { - /* Ignore pre-set proposal */ - if (ake->params.prop) { - silc_ske_group_free(ake->params.prop->group); - silc_cipher_free(ake->params.prop->cipher); - silc_hash_free(ake->params.prop->hash); - silc_hmac_free(ake->params.prop->hmac); - silc_pkcs_public_key_free(ake->params.prop->public_key); - silc_free(ake->params.prop); - ake->params.prop = NULL; - } - } - else if (packet->type != SILC_PACKET_KEY_EXCHANGE_1) - { - SILC_LOG_DEBUG(("Invalid SKE packet for responder")); - silc_async_abort(client_entry->internal.op, NULL, NULL); - goto drop; + if (packet->type == SILC_PACKET_KEY_EXCHANGE) { + /* Ignore pre-set proposal */ + if (ake->params.prop) { + silc_ske_group_free(ake->params.prop->group); + silc_cipher_free(ake->params.prop->cipher); + silc_hash_free(ake->params.prop->hash); + silc_hmac_free(ake->params.prop->hmac); + silc_pkcs_public_key_free(ake->params.prop->public_key); + silc_free(ake->params.prop); + ake->params.prop = NULL; } + } else if (packet->type != SILC_PACKET_KEY_EXCHANGE_1) { + SILC_LOG_DEBUG(("Invalid SKE packet for responder")); + silc_async_abort(client_entry->internal.op, NULL, NULL); + goto drop; + } ake->ske_op = silc_ske_responder(ake->ske, ake->ske_stream, &ake->params); if (!ake->ske_op) { @@ -940,7 +937,7 @@ silc_client_autoneg_key_verify_pubkey_cb(SilcBool success, void *context) SilcVerifyKeyContext verify = context; SilcClientAutonegMessageKey ake = verify->context; - SILC_LOG_DEBUG(("Start")); + SILC_LOG_DEBUG(("Start, verify %p, ake %p", context, ake)); /* Call the completion callback back to the SKE */ if (!verify->aborted) { -- 2.24.0