From 26c4ca7fbbc1e3afaa28d561f4b873a06879797e Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Tue, 23 Jan 2007 14:49:31 +0000 Subject: [PATCH] Fixed SKE session abortion of deletion. Added session timeout support. SILC_FSM_* macro API changes. --- lib/silcske/silcconnauth.c | 58 +++++----- lib/silcske/silcske.c | 217 ++++++++++++++++++++++--------------- lib/silcske/silcske.h | 7 +- lib/silcske/silcske_i.h | 4 +- 4 files changed, 166 insertions(+), 120 deletions(-) diff --git a/lib/silcske/silcconnauth.c b/lib/silcske/silcconnauth.c index 0f417d33..6947095b 100644 --- a/lib/silcske/silcconnauth.c +++ b/lib/silcske/silcconnauth.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2005 Pekka Riikonen + Copyright (C) 2005 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -116,7 +116,7 @@ static SilcBool silc_connauth_get_signature(SilcConnAuth connauth, /* Compute signature */ if (!silc_pkcs_sign(private_key, auth->data, silc_buffer_len(auth), - *auth_data, len, auth_data_len, ske->prop->hash)) { + *auth_data, len, auth_data_len, TRUE, ske->prop->hash)) { silc_free(*auth_data); silc_buffer_free(auth); return FALSE; @@ -267,7 +267,7 @@ SILC_FSM_STATE(silc_connauth_st_initiator_start) if (connauth->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_connauth_st_initiator_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Start timeout */ @@ -286,7 +286,7 @@ SILC_FSM_STATE(silc_connauth_st_initiator_start) if (!auth_data) { /** Out of memory */ silc_fsm_next(fsm, silc_connauth_st_initiator_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } auth_data_len = connauth->auth_data_len; flags = SILC_PACKET_FLAG_LONG_PAD; @@ -296,7 +296,7 @@ SILC_FSM_STATE(silc_connauth_st_initiator_start) if (!silc_connauth_get_signature(connauth, &auth_data, &auth_data_len)) { /** Error computing signature */ silc_fsm_next(fsm, silc_connauth_st_initiator_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } break; } @@ -306,7 +306,7 @@ SILC_FSM_STATE(silc_connauth_st_initiator_start) if (!packet) { /** Out of memory */ silc_fsm_next(fsm, silc_connauth_st_initiator_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } silc_buffer_format(packet, @@ -320,7 +320,7 @@ SILC_FSM_STATE(silc_connauth_st_initiator_start) flags, packet->data, silc_buffer_len(packet))) { /** Error sending packet */ silc_fsm_next(fsm, silc_connauth_st_initiator_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } if (auth_data) { @@ -331,7 +331,7 @@ SILC_FSM_STATE(silc_connauth_st_initiator_start) /** Wait for responder */ silc_fsm_next(fsm, silc_connauth_st_initiator_result); - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } SILC_FSM_STATE(silc_connauth_st_initiator_result) @@ -343,7 +343,7 @@ SILC_FSM_STATE(silc_connauth_st_initiator_result) if (connauth->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_connauth_st_initiator_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Check the status of authentication */ @@ -363,7 +363,7 @@ SILC_FSM_STATE(silc_connauth_st_initiator_result) /* Call completion callback */ connauth->completion(connauth, connauth->success, connauth->context); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } SILC_FSM_STATE(silc_connauth_st_initiator_failure) @@ -384,7 +384,7 @@ SILC_FSM_STATE(silc_connauth_st_initiator_failure) &silc_connauth_stream_cbs, connauth); silc_schedule_task_del_by_context(silc_fsm_get_schedule(fsm), connauth); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } SilcAsyncOperation @@ -447,7 +447,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_start) if (connauth->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Start timeout */ @@ -458,7 +458,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_start) /** Wait for initiator */ silc_fsm_next(fsm, silc_connauth_st_responder_authenticate); - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } SILC_FSM_STATE(silc_connauth_st_responder_authenticate) @@ -477,14 +477,14 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate) /** Aborted */ silc_packet_free(connauth->packet); silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } if (connauth->packet->type != SILC_PACKET_CONNECTION_AUTH) { /** Protocol failure */ silc_packet_free(connauth->packet); silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Parse the received authentication data packet. The received @@ -498,7 +498,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate) SILC_LOG_ERROR(("Bad payload in authentication packet")); silc_packet_free(connauth->packet); silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } if (payload_len != silc_buffer_len(&connauth->packet->buffer)) { @@ -506,7 +506,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate) SILC_LOG_ERROR(("Bad payload length in authentication packet")); silc_packet_free(connauth->packet); silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } payload_len -= 4; @@ -517,7 +517,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate) conn_type)); silc_packet_free(connauth->packet); silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } if (payload_len > 0) { @@ -532,7 +532,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate) SILC_LOG_DEBUG(("Bad payload in authentication payload")); silc_packet_free(connauth->packet); silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } } silc_packet_free(connauth->packet); @@ -546,7 +546,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate) /** Connection not configured */ SILC_LOG_ERROR(("Remote connection not configured")); silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Verify */ @@ -557,7 +557,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate) if (!memcmp(auth_data, passphrase, passphrase_len)) { /** Authentication failed */ silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } } else if (repository) { /* Digital signature */ @@ -574,7 +574,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate) if (!find || !connauth->auth_data) { /** Out of memory */ silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } silc_skr_find_set_pkcs_type(find, connauth->ske->pk_type); @@ -593,7 +593,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate) /** Authentication successful */ silc_fsm_next(fsm, silc_connauth_st_responder_success); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } SILC_FSM_STATE(silc_connauth_st_responder_authenticate_pk) @@ -604,14 +604,14 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate_pk) if (connauth->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } if (connauth->skr_status != SILC_SKR_OK) { /** Public key not found */ SILC_LOG_DEBUG(("Public key not found, error %d", connauth->skr_status)); silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } SILC_LOG_DEBUG(("Found %d public keys", @@ -626,14 +626,14 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate_pk) SILC_LOG_DEBUG(("Invalid signature")); silc_free(connauth->auth_data); silc_fsm_next(fsm, silc_connauth_st_responder_failure); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } silc_free(connauth->auth_data); /** Authentication successful */ silc_fsm_next(fsm, silc_connauth_st_responder_success); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } SILC_FSM_STATE(silc_connauth_st_responder_success) @@ -654,7 +654,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_success) &silc_connauth_stream_cbs, connauth); silc_schedule_task_del_by_context(silc_fsm_get_schedule(fsm), connauth); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } SILC_FSM_STATE(silc_connauth_st_responder_failure) @@ -675,7 +675,7 @@ SILC_FSM_STATE(silc_connauth_st_responder_failure) &silc_connauth_stream_cbs, connauth); silc_schedule_task_del_by_context(silc_fsm_get_schedule(fsm), connauth); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } SilcAsyncOperation diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index d49d9ccb..a6ec2754 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2000 - 2006 Pekka Riikonen + Copyright (C) 2000 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -55,6 +55,7 @@ SILC_FSM_STATE(silc_ske_st_responder_error); SILC_FSM_STATE(silc_ske_st_rekey_initiator_start); SILC_FSM_STATE(silc_ske_st_rekey_initiator_done); SILC_FSM_STATE(silc_ske_st_rekey_initiator_end); +SILC_TASK_CALLBACK(silc_ske_packet_send_retry); SilcSKEKeyMaterial silc_ske_process_key_material(SilcSKE ske, @@ -81,7 +82,8 @@ static SilcBool silc_ske_packet_receive(SilcPacketEngine engine, /* Clear retransmission */ ske->retry_timer = SILC_SKE_RETRY_MIN; ske->retry_count = 0; - silc_schedule_task_del_by_context(ske->schedule, ske); + silc_schedule_task_del_by_callback(ske->schedule, + silc_ske_packet_send_retry); /* Signal for new packet */ ske->packet = packet; @@ -988,6 +990,24 @@ static void silc_ske_finished(SilcFSM fsm, void *fsm_context, silc_ske_free(ske); } +/* Key exchange timeout task callback */ + +SILC_TASK_CALLBACK(silc_ske_timeout) +{ + SilcSKE ske = context; + + SILC_LOG_DEBUG(("Timeout")); + + ske->packet = NULL; + ske->status = SILC_SKE_STATUS_TIMEOUT; + if (ske->responder) + silc_fsm_next(&ske->fsm, silc_ske_st_responder_failure); + else + silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure); + + silc_fsm_continue_sync(&ske->fsm); +} + /******************************* Protocol API *******************************/ /* Allocates new SKE object. */ @@ -1034,6 +1054,17 @@ void silc_ske_free(SilcSKE ske) if (ske->running) { ske->freed = TRUE; + + if (ske->aborted) { + /* If already aborted, destroy the session immediately */ + ske->packet = NULL; + ske->status = SILC_SKE_STATUS_ERROR; + if (ske->responder) + silc_fsm_next(&ske->fsm, silc_ske_st_responder_failure); + else + silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure); + silc_fsm_continue_sync(&ske->fsm); + } return; } @@ -1120,7 +1151,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_start) if (ske->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_ske_st_initiator_aborted); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Encode the payload */ @@ -1130,7 +1161,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_start) /** Error encoding Start Payload */ ske->status = status; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Save the the payload buffer for future use. It is later used to @@ -1145,15 +1176,17 @@ SILC_FSM_STATE(silc_ske_st_initiator_start) SILC_LOG_DEBUG(("Error sending packet")); ske->status = SILC_SKE_STATUS_ERROR; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } - /* XXX timeout */ + /* Add key exchange timeout */ + silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout, + ske, ske->timeout, 0); /** Wait for responder proposal */ - SILC_LOG_DEBUG(("Waiting for reponder proposal")); + SILC_LOG_DEBUG(("Waiting for responder proposal")); silc_fsm_next(fsm, silc_ske_st_initiator_phase1); - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } /* Phase-1. Receives responder's proposal */ @@ -1177,7 +1210,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1) silc_ske_install_retransmission(ske); silc_packet_free(ske->packet); ske->packet = NULL; - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } /* Decode the payload */ @@ -1188,7 +1221,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1) ske->packet = NULL; ske->status = status; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Get remote ID and set it to stream */ @@ -1221,7 +1254,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1) SILC_LOG_ERROR(("Invalid cookie, modified or unsupported feature")); ske->status = SILC_SKE_STATUS_INVALID_COOKIE; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Check version string */ @@ -1231,7 +1264,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1) /** Version mismatch */ ske->status = status; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Free our KE Start Payload context, we don't need it anymore. */ @@ -1274,7 +1307,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1) /** Send KE Payload */ silc_fsm_next(fsm, silc_ske_st_initiator_phase2); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; err: if (payload) @@ -1296,7 +1329,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1) /** Error */ ske->status = status; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Phase-2. Send KE payload */ @@ -1318,7 +1351,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) /** Out of memory */ ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } silc_mp_init(x); status = @@ -1331,7 +1364,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) silc_free(x); ske->status = status; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Encode the result to Key Exchange Payload. */ @@ -1343,7 +1376,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) silc_free(x); ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } ske->ke1_payload = payload; @@ -1365,7 +1398,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) ske->ke1_payload = NULL; ske->status = SILC_SKE_STATUS_ERROR; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } payload->pk_len = pk_len; payload->pk_type = silc_pkcs_get_type(ske->public_key); @@ -1386,7 +1419,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) /* Sign the hash value */ if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign, - sizeof(sign) - 1, &sign_len, NULL)) { + sizeof(sign) - 1, &sign_len, FALSE, ske->prop->hash)) { /** Error computing signature */ silc_mp_uninit(x); silc_free(x); @@ -1396,7 +1429,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) ske->ke1_payload = NULL; ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } payload->sign_data = silc_memdup(sign, sign_len); if (payload->sign_data) @@ -1416,7 +1449,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) ske->ke1_payload = NULL; ske->status = status; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } ske->x = x; @@ -1431,14 +1464,14 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) SILC_LOG_DEBUG(("Error sending packet")); ske->status = SILC_SKE_STATUS_ERROR; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } silc_buffer_free(payload_buf); /** Waiting responder's KE payload */ silc_fsm_next(fsm, silc_ske_st_initiator_phase3); - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } /* Phase-3. Process responder's KE payload */ @@ -1458,7 +1491,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase3) silc_ske_install_retransmission(ske); silc_packet_free(ske->packet); ske->packet = NULL; - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } /* Decode the payload */ @@ -1469,7 +1502,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase3) ske->packet = NULL; ske->status = status; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } silc_packet_free(ske->packet); ske->packet = NULL; @@ -1535,7 +1568,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase3) /** Process key material */ silc_fsm_next(fsm, silc_ske_st_initiator_phase4); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; err: silc_ske_payload_ke_free(payload); @@ -1551,7 +1584,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase3) /** Error */ ske->status = status; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Process key material */ @@ -1568,7 +1601,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase4) if (ske->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_ske_st_initiator_aborted); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Check result of public key verification */ @@ -1576,7 +1609,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase4) /** Public key not verified */ SILC_LOG_DEBUG(("Public key verification failed")); silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } payload = ske->ke2_payload; @@ -1612,7 +1645,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase4) if (ske->rekey) { /** Finish rekey */ silc_fsm_next(fsm, silc_ske_st_rekey_initiator_done); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Process key material */ @@ -1635,12 +1668,12 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase4) SILC_LOG_DEBUG(("Error sending packet")); ske->status = SILC_SKE_STATUS_ERROR; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /** Waiting completion */ silc_fsm_next(fsm, silc_ske_st_initiator_end); - SILC_FSM_WAIT; + return SILC_FSM_WAIT; err: memset(hash, 'F', sizeof(hash)); @@ -1663,7 +1696,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase4) /** Error */ ske->status = status; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Protocol completed */ @@ -1679,7 +1712,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_end) silc_ske_install_retransmission(ske); silc_packet_free(ske->packet); ske->packet = NULL; - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } SILC_LOG_DEBUG(("Key exchange completed successfully")); @@ -1689,7 +1722,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_end) silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); silc_schedule_task_del_by_context(ske->schedule, ske); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } /* Aborted by application */ @@ -1708,7 +1741,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_aborted) silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); silc_schedule_task_del_by_context(ske->schedule, ske); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } /* Error occurred. Send error to remote host */ @@ -1733,7 +1766,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_error) silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); silc_schedule_task_del_by_context(ske->schedule, ske); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } /* Failure received from remote */ @@ -1756,7 +1789,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_failure) silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); silc_schedule_task_del_by_context(ske->schedule, ske); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } /* Starts the protocol as initiator */ @@ -1790,6 +1823,7 @@ silc_ske_initiator(SilcSKE ske, return NULL; } + ske->timeout = params->timeout_secs ? params->timeout_secs : 30; ske->start_payload = start_payload; ske->version = params->version; ske->running = TRUE; @@ -1821,15 +1855,16 @@ SILC_FSM_STATE(silc_ske_st_responder_start) if (ske->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_ske_st_responder_aborted); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } - /* Start timeout */ - /* XXX */ + /* Add key exchange timeout */ + silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout, + ske, ske->timeout, 0); /** Wait for initiator */ silc_fsm_next(fsm, silc_ske_st_responder_phase1); - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } /* Decode initiator's start payload. Select the security properties from @@ -1852,7 +1887,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase1) ske->packet = NULL; ske->status = status; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Take a copy of the payload buffer for future use. It is used to @@ -1889,7 +1924,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase1) silc_ske_payload_start_free(remote_payload); ske->status = status; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } silc_ske_payload_start_free(remote_payload); @@ -1910,7 +1945,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase1) /** Waiting initiator's KE payload */ silc_fsm_next(fsm, silc_ske_st_responder_phase2); - SILC_FSM_WAIT; + return SILC_FSM_WAIT; err: if (ske->prop->group) @@ -1930,7 +1965,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase1) /** Error */ ske->status = status; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Phase-2. Decode initiator's KE payload */ @@ -1949,7 +1984,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase2) silc_ske_install_retransmission(ske); silc_packet_free(ske->packet); ske->packet = NULL; - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } /* Decode Key Exchange Payload */ @@ -1960,7 +1995,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase2) ske->packet = NULL; ske->status = status; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } ske->ke1_payload = recv_payload; @@ -1982,7 +2017,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase2) "certificate), even though we require it")); ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Decode the remote's public key */ @@ -1995,7 +2030,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase2) SILC_LOG_ERROR(("Unsupported/malformed public key received")); ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } if (ske->prop->public_key && (ske->callbacks->verify_key || @@ -2013,7 +2048,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase2) if (!find) { ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } silc_skr_find_set_pkcs_type(find, silc_pkcs_get_type(ske->prop->public_key)); @@ -2035,7 +2070,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase2) /** Generate KE2 payload */ silc_fsm_next(fsm, silc_ske_st_responder_phase4); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Phase-4. Generate KE2 payload */ @@ -2050,7 +2085,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase4) if (ske->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_ske_st_responder_aborted); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Check result of public key verification */ @@ -2058,7 +2093,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase4) /** Public key not verified */ SILC_LOG_DEBUG(("Public key verification failed")); silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } recv_payload = ske->ke1_payload; @@ -2078,7 +2113,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase4) /** Error computing hash */ ske->status = status; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } SILC_LOG_DEBUG(("Verifying signature (HASH_i)")); @@ -2090,7 +2125,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase4) SILC_LOG_ERROR(("Signature verification failed, incorrect signature")); ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } SILC_LOG_DEBUG(("Signature is Ok")); @@ -2111,7 +2146,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase4) silc_free(x); ske->status = status; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Save the results for later processing */ @@ -2137,7 +2172,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase4) /** Send KE2 payload */ silc_fsm_next(fsm, silc_ske_st_responder_phase5); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Phase-5. Send KE2 payload */ @@ -2161,7 +2196,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase5) /** Error encoding public key */ status = SILC_SKE_STATUS_OUT_OF_MEMORY; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } ske->ke2_payload->pk_data = pk; ske->ke2_payload->pk_len = pk_len; @@ -2175,7 +2210,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase5) /** Error computing hash */ ske->status = status; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } ske->hash = silc_memdup(hash, hash_len); @@ -2185,11 +2220,11 @@ SILC_FSM_STATE(silc_ske_st_responder_phase5) /* Sign the hash value */ if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign, - sizeof(sign) - 1, &sign_len, NULL)) { + sizeof(sign) - 1, &sign_len, FALSE, ske->prop->hash)) { /** Error computing signature */ status = SILC_SKE_STATUS_SIGNATURE_ERROR; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } ske->ke2_payload->sign_data = silc_memdup(sign, sign_len); ske->ke2_payload->sign_len = sign_len; @@ -2204,7 +2239,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase5) /** Error encoding KE payload */ ske->status = status; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Send the packet. */ @@ -2213,14 +2248,14 @@ SILC_FSM_STATE(silc_ske_st_responder_phase5) SILC_LOG_DEBUG(("Error sending packet")); ske->status = SILC_SKE_STATUS_ERROR; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } silc_buffer_free(payload_buf); /** Waiting completion */ silc_fsm_next(fsm, silc_ske_st_responder_end); - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } /* Protocol completed */ @@ -2236,7 +2271,7 @@ SILC_FSM_STATE(silc_ske_st_responder_end) silc_ske_install_retransmission(ske); silc_packet_free(ske->packet); ske->packet = NULL; - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } silc_packet_free(ske->packet); ske->packet = NULL; @@ -2252,7 +2287,7 @@ SILC_FSM_STATE(silc_ske_st_responder_end) /** Error processing key material */ ske->status = SILC_SKE_STATUS_ERROR; silc_fsm_next(fsm, silc_ske_st_responder_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Send SUCCESS packet */ @@ -2262,7 +2297,7 @@ SILC_FSM_STATE(silc_ske_st_responder_end) silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); silc_schedule_task_del_by_context(ske->schedule, ske); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } /* Aborted by application */ @@ -2281,7 +2316,7 @@ SILC_FSM_STATE(silc_ske_st_responder_aborted) silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); silc_schedule_task_del_by_context(ske->schedule, ske); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } /* Failure received from remote */ @@ -2303,7 +2338,7 @@ SILC_FSM_STATE(silc_ske_st_responder_failure) silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); silc_schedule_task_del_by_context(ske->schedule, ske); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } /* Error occurred */ @@ -2325,7 +2360,7 @@ SILC_FSM_STATE(silc_ske_st_responder_error) silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); silc_schedule_task_del_by_context(ske->schedule, ske); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } /* Starts the protocol as responder. */ @@ -2348,6 +2383,7 @@ silc_ske_responder(SilcSKE ske, ske->responder = TRUE; ske->flags = params->flags; + ske->timeout = params->timeout_secs ? params->timeout_secs : 30; if (ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED) ske->session_port = params->session_port; ske->version = strdup(params->version); @@ -2383,17 +2419,19 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_start) if (ske->aborted) { /** Aborted */ silc_fsm_next(fsm, silc_ske_st_initiator_aborted); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } - /* XXX timeout */ + /* Add rekey exchange timeout */ + silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout, + ske, 30, 0); ske->prop = silc_calloc(1, sizeof(*ske->prop)); if (!ske->prop) { /** No memory */ ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Send REKEY packet to start rekey protocol */ @@ -2402,14 +2440,14 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_start) SILC_LOG_DEBUG(("Error sending packet")); ske->status = SILC_SKE_STATUS_ERROR; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* If doing rekey without PFS, move directly to the end of the protocol. */ if (!ske->rekey->pfs) { /** Rekey without PFS */ silc_fsm_next(fsm, silc_ske_st_rekey_initiator_done); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } status = silc_ske_group_get_by_number(ske->rekey->ske_group, @@ -2417,12 +2455,12 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_start) if (status != SILC_SKE_STATUS_OK) { /** Unknown group */ silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /** Rekey with PFS */ silc_fsm_next(fsm, silc_ske_st_initiator_phase2); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Sends REKEY_DONE packet to finish the protocol. */ @@ -2446,7 +2484,7 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_done) /** Cannot allocate hash */ ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } hash_len = silc_hash_len(hash); @@ -2473,7 +2511,7 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_done) if (!ske->keymat) { SILC_LOG_ERROR(("Error processing key material")); silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } ske->prop->cipher = send_key; @@ -2486,7 +2524,7 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_done) /** Cannot get keys */ ske->status = SILC_SKE_STATUS_ERROR; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Set the new keys into use. This will also send REKEY_DONE packet. Any @@ -2497,12 +2535,12 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_done) SILC_LOG_DEBUG(("Cannot set new keys, error sending REKEY_DONE")); ske->status = SILC_SKE_STATUS_ERROR; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /** Wait for REKEY_DONE */ silc_fsm_next(fsm, silc_ske_st_rekey_initiator_end); - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } /* Rekey protocol end */ @@ -2520,7 +2558,7 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_end) SILC_LOG_DEBUG(("Remote retransmitted an old packet")); silc_packet_free(ske->packet); ske->packet = NULL; - SILC_FSM_WAIT; + return SILC_FSM_WAIT; } silc_packet_get_keys(ske->stream, NULL, &receive_key, NULL, &hmac_receive); @@ -2533,7 +2571,7 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_end) /** Cannot get keys */ ske->status = SILC_SKE_STATUS_ERROR; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } /* Set new receiving keys into use. All packets received after this will @@ -2544,7 +2582,7 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_end) SILC_LOG_DEBUG(("Cannot set new keys")); ske->status = SILC_SKE_STATUS_ERROR; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } SILC_LOG_DEBUG(("Rekey completed successfully")); @@ -2555,7 +2593,7 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_end) /** No memory */ ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY; silc_fsm_next(fsm, silc_ske_st_initiator_error); - SILC_FSM_CONTINUE; + return SILC_FSM_CONTINUE; } rekey->pfs = ske->rekey->pfs; ske->rekey = rekey; @@ -2567,7 +2605,7 @@ SILC_FSM_STATE(silc_ske_st_rekey_initiator_end) silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); silc_schedule_task_del_by_context(ske->schedule, ske); - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } /* Starts rekey protocol as initiator */ @@ -2614,7 +2652,7 @@ SILC_FSM_STATE(silc_ske_st_rekey_responder_start); SILC_FSM_STATE(silc_ske_st_rekey_responder_start) { - SILC_FSM_FINISH; + return SILC_FSM_FINISH; } /* Starts rekey protocol as responder */ @@ -3077,6 +3115,7 @@ const char *silc_ske_status_string[] = "Bad payload length in packet", "Error computing signature", "System out of memory", + "Key exchange timeout", NULL }; diff --git a/lib/silcske/silcske.h b/lib/silcske/silcske.h index 62880540..92bf6218 100644 --- a/lib/silcske/silcske.h +++ b/lib/silcske/silcske.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2000 - 2006 Pekka Riikonen + Copyright (C) 2000 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -207,6 +207,11 @@ typedef struct { the key exchange protocol. Ignored without SILC_SKE_SP_FLAG_IV_INCLUDED flag. */ SilcUInt16 session_port; + + /* Key exchange timeout in seconds. If key exchange is not completed in + this time it will timeout. If not specified (zero), default value + (30 seconds) will be used. */ + SilcUInt16 timeout_secs; } *SilcSKEParams, SilcSKEParamsStruct; /***/ diff --git a/lib/silcske/silcske_i.h b/lib/silcske/silcske_i.h index 7edfa04a..ba75050a 100644 --- a/lib/silcske/silcske_i.h +++ b/lib/silcske/silcske_i.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2005 - 2006 Pekka Riikonen + Copyright (C) 2005 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -87,6 +87,8 @@ struct SilcSKEStruct { SilcUInt32 data_len; } retrans; + SilcUInt16 timeout; /* SKE timeout */ + unsigned int aborted : 1; /* Set when SKE aborted */ unsigned int freed : 1; /* Set when freed during session */ unsigned int responder : 1; /* Set when we are responder side */ -- 2.24.0