protocol.c
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2001 Pekka Riikonen
+ Copyright (C) 1997 - 2004 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; version 2 of the License.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
-/*
- * Client side of the protocols.
- */
/* $Id$ */
#include "silcincludes.h"
void *context)
{
SilcProtocol protocol = (SilcProtocol)context;
- SilcClientKEInternalContext *ctx =
+ SilcClientKEInternalContext *ctx =
(SilcClientKEInternalContext *)protocol->context;
SilcClient client = (SilcClient)ctx->client;
void *completion_context;
} *VerifyKeyContext;
-static void silc_client_verify_key_cb(bool success, void *context)
+static void silc_client_verify_key_cb(SilcBool success, void *context)
{
VerifyKeyContext verify = (VerifyKeyContext)context;
SILC_LOG_DEBUG(("Start"));
/* Call the completion callback back to the SKE */
- verify->completion(verify->ske, success ? SILC_SKE_STATUS_OK :
- SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
+ verify->completion(verify->ske, success ? SILC_SKE_STATUS_OK :
+ SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
verify->completion_context);
silc_free(verify);
void *completion_context)
{
SilcProtocol protocol = (SilcProtocol)context;
- SilcClientKEInternalContext *ctx =
+ SilcClientKEInternalContext *ctx =
(SilcClientKEInternalContext *)protocol->context;
SilcClient client = (SilcClient)ctx->client;
VerifyKeyContext verify;
verify->completion_context = completion_context;
/* Verify public key from user. */
- client->internal->ops->verify_public_key(client, ctx->sock->user_data,
+ client->internal->ops->verify_public_key(client, ctx->sock->user_data,
ctx->sock->type,
pk_data, pk_len, pk_type,
silc_client_verify_key_cb, verify);
SilcHash hash,
SilcHmac hmac,
SilcSKEDiffieHellmanGroup group,
- bool is_responder)
+ SilcBool is_responder)
{
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
const char *cname = silc_cipher_get_name(cipher);
&conn->internal->hmac_receive);
if (is_responder == TRUE) {
- silc_cipher_set_key(conn->internal->send_key, keymat->receive_enc_key,
+ silc_cipher_set_key(conn->internal->send_key, keymat->receive_enc_key,
keymat->enc_key_len);
silc_cipher_set_iv(conn->internal->send_key, keymat->receive_iv);
- silc_cipher_set_key(conn->internal->receive_key, keymat->send_enc_key,
+ silc_cipher_set_key(conn->internal->receive_key, keymat->send_enc_key,
keymat->enc_key_len);
silc_cipher_set_iv(conn->internal->receive_key, keymat->send_iv);
- silc_hmac_set_key(conn->internal->hmac_send, keymat->receive_hmac_key,
+ silc_hmac_set_key(conn->internal->hmac_send, keymat->receive_hmac_key,
keymat->hmac_key_len);
- silc_hmac_set_key(conn->internal->hmac_receive, keymat->send_hmac_key,
+ silc_hmac_set_key(conn->internal->hmac_receive, keymat->send_hmac_key,
keymat->hmac_key_len);
} else {
- silc_cipher_set_key(conn->internal->send_key, keymat->send_enc_key,
+ silc_cipher_set_key(conn->internal->send_key, keymat->send_enc_key,
keymat->enc_key_len);
silc_cipher_set_iv(conn->internal->send_key, keymat->send_iv);
- silc_cipher_set_key(conn->internal->receive_key, keymat->receive_enc_key,
+ silc_cipher_set_key(conn->internal->receive_key, keymat->receive_enc_key,
keymat->enc_key_len);
silc_cipher_set_iv(conn->internal->receive_key, keymat->receive_iv);
- silc_hmac_set_key(conn->internal->hmac_send, keymat->send_hmac_key,
+ silc_hmac_set_key(conn->internal->hmac_send, keymat->send_hmac_key,
keymat->hmac_key_len);
- silc_hmac_set_key(conn->internal->hmac_receive, keymat->receive_hmac_key,
+ silc_hmac_set_key(conn->internal->hmac_receive, keymat->receive_hmac_key,
keymat->hmac_key_len);
}
/* Rekey stuff */
conn->internal->rekey = silc_calloc(1, sizeof(*conn->internal->rekey));
- conn->internal->rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
+ conn->internal->rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
keymat->enc_key_len / 8);
conn->internal->rekey->enc_key_len = keymat->enc_key_len / 8;
if (!silc_parse_version_string(version, &r_protocol_version, NULL, NULL,
NULL, NULL)) {
client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
- "We don't support server version `%s'",
+ "We don't support server version `%s'",
version);
return SILC_SKE_STATUS_BAD_VERSION;
}
- if (!silc_parse_version_string(client->internal->silc_client_version,
+ if (!silc_parse_version_string(client->internal->silc_client_version,
&l_protocol_version, NULL, NULL,
NULL, NULL)) {
client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
- "We don't support server version `%s'",
+ "We don't support server version `%s'",
version);
return SILC_SKE_STATUS_BAD_VERSION;
}
/* If remote is too new, don't connect */
if (l_protocol_version < r_protocol_version) {
client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
- "We don't support server version `%s'",
+ "We don't support server version `%s'",
version);
return SILC_SKE_STATUS_BAD_VERSION;
}
}
/* Callback that is called by the SKE to indicate that it is safe to
- continue the execution of the protocol. Is given as argument to the
- silc_ske_initiator_finish or silc_ske_responder_phase_2 functions.
+ continue the execution of the protocol. Is given as argument to the
+ silc_ske_initiator_finish or silc_ske_responder_phase_2 functions.
This is called due to the fact that the public key verification
process is asynchronous and we must not continue the protocl until
the public key has been verified and this callback is called. */
void *context)
{
SilcProtocol protocol = (SilcProtocol)context;
- SilcClientKEInternalContext *ctx =
+ SilcClientKEInternalContext *ctx =
(SilcClientKEInternalContext *)protocol->context;
SilcClient client = (SilcClient)ctx->client;
SilcClientConnection conn = ctx->sock->user_data;
if (ske->status != SILC_SKE_STATUS_OK) {
/* Call failure client operation */
- client->internal->ops->failure(client, conn, protocol,
+ client->internal->ops->failure(client, conn, protocol,
(void *)ske->status);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_protocol_execute(protocol, client->schedule, 0, 0);
protocol->state = SILC_PROTOCOL_STATE_END;
}
- /* Advance protocol state and call the next state if we are responder.
+ /* Advance protocol state and call the next state if we are responder.
This happens when this callback was sent to silc_ske_responder_phase_2
function. */
if (ctx->responder == TRUE) {
SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
{
SilcProtocol protocol = (SilcProtocol)context;
- SilcClientKEInternalContext *ctx =
+ SilcClientKEInternalContext *ctx =
(SilcClientKEInternalContext *)protocol->context;
SilcClient client = (SilcClient)ctx->client;
SilcClientConnection conn = ctx->sock->user_data;
silc_ske_set_callbacks(ske, ctx->send_packet, NULL,
ctx->verify,
silc_client_protocol_ke_continue,
- silc_ske_check_version,
+ silc_ske_check_version,
context);
-
+
if (ctx->responder == TRUE) {
+ if (!ctx->packet) {
+ SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
+ status));
+ protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ silc_protocol_execute(protocol, client->schedule, 0, 0);
+ return;
+ }
+
/* Start the key exchange by processing the received security
properties packet from initiator. */
- status =
+ status =
silc_ske_responder_start(ske, ctx->rng, ctx->sock,
client->internal->silc_client_version,
ctx->packet->buffer, TRUE);
/* Assemble security properties. */
silc_ske_assemble_security_properties(
- ske, SILC_SKE_SP_FLAG_MUTUAL,
+ ske, SILC_SKE_SP_FLAG_MUTUAL,
client->internal->silc_client_version,
&start_payload);
break;
case 2:
{
- /*
- * Phase 1
+ /*
+ * Phase 1
*/
if (ctx->responder == TRUE) {
/* Sends the selected security properties to the initiator. */
status = silc_ske_responder_phase_1(ctx->ske);
} else {
+ if (!ctx->packet) {
+ SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
+ status));
+ protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ silc_protocol_execute(protocol, client->schedule, 0, 0);
+ return;
+ }
+
/* Call Phase-1 function. This processes the Key Exchange Start
paylaod reply we just got from the responder. The callback
function will receive the processed payload where we will
break;
case 3:
{
- /*
- * Phase 2
+ /*
+ * Phase 2
*/
if (ctx->responder == TRUE) {
+ if (!ctx->packet) {
+ SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
+ status));
+ protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ silc_protocol_execute(protocol, client->schedule, 0, 0);
+ return;
+ }
+
/* Process the received Key Exchange 1 Payload packet from
the initiator. This also creates our parts of the Diffie
Hellman algorithm. The silc_client_protocol_ke_continue will
break;
case 4:
{
- /*
+ /*
* Finish protocol
*/
if (ctx->responder == TRUE) {
/* This creates the key exchange material and sends our
public parts to the initiator inside Key Exchange 2 Payload. */
- status =
- silc_ske_responder_finish(ctx->ske,
+ status =
+ silc_ske_responder_finish(ctx->ske,
client->public_key, client->private_key,
SILC_SKE_PK_TYPE_SILC);
/* End the protocol on the next round */
protocol->state = SILC_PROTOCOL_STATE_END;
} else {
+ if (!ctx->packet) {
+ SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
+ status));
+ protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ silc_protocol_execute(protocol, client->schedule, 0, 0);
+ return;
+ }
+
/* Finish the protocol. This verifies the Key Exchange 2 payload
sent by responder. The silc_client_protocol_ke_continue will
be called after the public key has been verified. */
if (status != SILC_SKE_STATUS_OK) {
if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
client->internal->ops->say(
- client, conn, SILC_CLIENT_MESSAGE_AUDIT,
+ client, conn, SILC_CLIENT_MESSAGE_AUDIT,
"Received unsupported server %s public key",
ctx->sock->hostname);
} else {
case SILC_PROTOCOL_STATE_END:
{
- /*
+ /*
* End protocol
*/
SilcSKEKeyMaterial *keymat;
if (ctx->responder == TRUE)
silc_ske_end(ctx->ske);
- /* Unregister the timeout task since the protocol has ended.
+ /* Unregister the timeout task since the protocol has ended.
This was the timeout task to be executed if the protocol is
not completed fast enough. */
if (ctx->timeout_task)
/*
* Error during protocol
*/
-
+
/* Send abort notification */
silc_ske_abort(ctx->ske, ctx->ske->status);
* Received failure from remote.
*/
- /* Unregister the timeout task since the protocol has ended.
+ /* Unregister the timeout task since the protocol has ended.
This was the timeout task to be executed if the protocol is
not completed fast enough. */
if (ctx->timeout_task)
ske->start_payload_copy->len),
SILC_STR_END);
- if (silc_pkcs_sign_with_hash(pkcs, ske->prop->hash, auth->data,
+ if (silc_pkcs_sign_with_hash(pkcs, ske->prop->hash, auth->data,
auth->len, auth_data, auth_data_len)) {
silc_buffer_free(auth);
return TRUE;
/* Continues the connection authentication protocol. This funtion may
be called directly or used as SilcAskPassphrase callback. */
-static void
+static void
silc_client_conn_auth_continue(unsigned char *auth_data,
SilcUInt32 auth_data_len, void *context)
{
SilcProtocol protocol = (SilcProtocol)context;
- SilcClientConnAuthInternalContext *ctx =
+ SilcClientConnAuthInternalContext *ctx =
(SilcClientConnAuthInternalContext *)protocol->context;
SilcClient client = (SilcClient)ctx->client;
SilcBuffer packet;
SILC_LOG_DEBUG(("Sending authentication to server"));
/* Passphrase must be UTF-8 encoded, if it isn't encode it */
- if (ctx->auth_meth == SILC_AUTH_PASSWORD &&
+ if (ctx->auth_meth == SILC_AUTH_PASSWORD &&
!silc_utf8_valid(auth_data, auth_data_len)) {
- payload_len = silc_utf8_encoded_len(auth_data, auth_data_len,
+ payload_len = silc_utf8_encoded_len(auth_data, auth_data_len,
SILC_STRING_ASCII);
autf8 = silc_calloc(payload_len, sizeof(*autf8));
- auth_data_len = silc_utf8_encode(auth_data, auth_data_len,
+ auth_data_len = silc_utf8_encode(auth_data, auth_data_len,
SILC_STRING_ASCII, autf8, payload_len);
auth_data = autf8;
}
packet->data, packet->len, TRUE);
silc_buffer_free(packet);
silc_free(autf8);
-
+
/* Next state is end of protocol */
protocol->state = SILC_PROTOCOL_STATE_END;
}
-
+
SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
{
SilcProtocol protocol = (SilcProtocol)context;
- SilcClientConnAuthInternalContext *ctx =
+ SilcClientConnAuthInternalContext *ctx =
(SilcClientConnAuthInternalContext *)protocol->context;
SilcClient client = (SilcClient)ctx->client;
SilcClientConnection conn = ctx->sock->user_data;
switch(protocol->state) {
case SILC_PROTOCOL_STATE_START:
{
- /*
+ /*
* Start protocol. We send authentication data to the server
* to be authenticated.
*/
unsigned char *auth_data = NULL;
SilcUInt32 auth_data_len = 0;
- unsigned char sign[1024];
+ unsigned char sign[2048 + 1];
switch(ctx->auth_meth) {
case SILC_AUTH_NONE:
case SILC_AUTH_PUBLIC_KEY:
if (!ctx->auth_data) {
/* Public key authentication */
- silc_client_get_public_key_auth(client, conn, sign, &auth_data_len,
+ silc_client_get_public_key_auth(client, conn, sign, &auth_data_len,
ctx->ske);
auth_data = sign;
} else {
auth_data = ctx->auth_data;
auth_data_len = ctx->auth_data_len;
}
-
+
break;
}
case SILC_PROTOCOL_STATE_END:
{
- /*
+ /*
* End protocol. Nothing special to be done here.
*/
case SILC_PROTOCOL_STATE_ERROR:
{
- /*
+ /*
* Error. Send notify to remote.
*/
unsigned char error[4];
/* Actually takes the new keys into use. */
-static void
+static void
silc_client_protocol_rekey_validate(SilcClient client,
SilcClientRekeyInternalContext *ctx,
SilcSocketConnection sock,
SilcSKEKeyMaterial *keymat,
- bool send)
+ SilcBool send)
{
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
if (ctx->responder == TRUE) {
if (send) {
- silc_cipher_set_key(conn->internal->send_key, keymat->receive_enc_key,
+ silc_cipher_set_key(conn->internal->send_key, keymat->receive_enc_key,
keymat->enc_key_len);
silc_cipher_set_iv(conn->internal->send_key, keymat->receive_iv);
- silc_hmac_set_key(conn->internal->hmac_send, keymat->receive_hmac_key,
+ silc_hmac_set_key(conn->internal->hmac_send, keymat->receive_hmac_key,
keymat->hmac_key_len);
} else {
- silc_cipher_set_key(conn->internal->receive_key, keymat->send_enc_key,
+ silc_cipher_set_key(conn->internal->receive_key, keymat->send_enc_key,
keymat->enc_key_len);
silc_cipher_set_iv(conn->internal->receive_key, keymat->send_iv);
- silc_hmac_set_key(conn->internal->hmac_receive, keymat->send_hmac_key,
+ silc_hmac_set_key(conn->internal->hmac_receive, keymat->send_hmac_key,
keymat->hmac_key_len);
}
} else {
if (send) {
- silc_cipher_set_key(conn->internal->send_key, keymat->send_enc_key,
+ silc_cipher_set_key(conn->internal->send_key, keymat->send_enc_key,
keymat->enc_key_len);
silc_cipher_set_iv(conn->internal->send_key, keymat->send_iv);
- silc_hmac_set_key(conn->internal->hmac_send, keymat->send_hmac_key,
+ silc_hmac_set_key(conn->internal->hmac_send, keymat->send_hmac_key,
keymat->hmac_key_len);
} else {
silc_cipher_set_key(conn->internal->receive_key,
/* This function actually re-generates (when not using PFS) the keys and
takes them into use. */
-static void
+static void
silc_client_protocol_rekey_generate(SilcClient client,
SilcClientRekeyInternalContext *ctx,
- bool send)
+ SilcBool send)
{
SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
SilcSKEKeyMaterial *keymat;
keymat = silc_calloc(1, sizeof(*keymat));
silc_ske_process_key_material_data(conn->internal->rekey->send_enc_key,
conn->internal->rekey->enc_key_len,
- 16, key_len, hash_len,
+ 16, key_len, hash_len,
conn->internal->hash, keymat);
/* Set the keys into use */
/* This function actually re-generates (with PFS) the keys and
takes them into use. */
-static void
+static void
silc_client_protocol_rekey_generate_pfs(SilcClient client,
SilcClientRekeyInternalContext *ctx,
- bool send)
+ SilcBool send)
{
SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
SilcSKEKeyMaterial *keymat;
/* Generate the new key */
keymat = silc_calloc(1, sizeof(*keymat));
- silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len,
+ silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len,
conn->internal->hash, keymat);
/* Set the keys into use */
/* Packet sending callback. This function is provided as packet sending
routine to the Key Exchange functions. */
-static void
+static void
silc_client_protocol_rekey_send_packet(SilcSKE ske,
SilcBuffer packet,
SilcPacketType type,
void *context)
{
SilcProtocol protocol = (SilcProtocol)context;
- SilcClientRekeyInternalContext *ctx =
+ SilcClientRekeyInternalContext *ctx =
(SilcClientRekeyInternalContext *)protocol->context;
SilcClient client = (SilcClient)ctx->client;
SILC_TASK_CALLBACK(silc_client_protocol_rekey)
{
SilcProtocol protocol = (SilcProtocol)context;
- SilcClientRekeyInternalContext *ctx =
+ SilcClientRekeyInternalContext *ctx =
(SilcClientRekeyInternalContext *)protocol->context;
SilcClient client = (SilcClient)ctx->client;
SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
switch(protocol->state) {
case SILC_PROTOCOL_STATE_START:
{
- /*
+ /*
* Start protocol.
*/
*/
if (ctx->pfs == TRUE) {
- /*
+ /*
* Use Perfect Forward Secrecy, ie. negotiate the key material
* using the SKE protocol.
*/
+ if (!ctx->packet) {
+ SILC_LOG_WARNING(("Error during Re-key"));
+ protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ silc_protocol_execute(protocol, client->schedule, 0, 300000);
+ return;
+ }
+
if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
/* Error in protocol */
protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_ske_group_get_by_number(conn->internal->rekey->ske_group,
&ctx->ske->prop->group);
- silc_ske_set_callbacks(ctx->ske,
+ silc_ske_set_callbacks(ctx->ske,
silc_client_protocol_rekey_send_packet,
NULL, NULL, NULL, silc_ske_check_version,
context);
-
+
status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer);
if (status != SILC_SKE_STATUS_OK) {
SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
status));
-
+
protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_protocol_execute(protocol, client->schedule, 0, 300000);
return;
*/
/* Send the REKEY_DONE to indicate we will take new keys into use */
- silc_client_packet_send(client, ctx->sock,
- SILC_PACKET_REKEY_DONE,
+ silc_client_packet_queue_purge(client, ctx->sock);
+ silc_client_packet_send(client, ctx->sock,
+ SILC_PACKET_REKEY_DONE,
NULL, 0, NULL, NULL, NULL, 0, FALSE);
/* After we send REKEY_DONE we must set the sending encryption
key to the new key since all packets after this packet must
encrypted with the new key. */
silc_client_protocol_rekey_generate(client, ctx, TRUE);
+ silc_client_packet_queue_purge(client, ctx->sock);
/* The protocol ends in next stage. */
protocol->state = SILC_PROTOCOL_STATE_END;
}
-
+
} else {
/*
* We are the initiator of this protocol
*/
/* Start the re-key by sending the REKEY packet */
- silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY,
+ silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY,
NULL, 0, NULL, NULL, NULL, 0, FALSE);
if (ctx->pfs == TRUE) {
- /*
+ /*
* Use Perfect Forward Secrecy, ie. negotiate the key material
* using the SKE protocol.
*/
silc_ske_group_get_by_number(conn->internal->rekey->ske_group,
&ctx->ske->prop->group);
- silc_ske_set_callbacks(ctx->ske,
+ silc_ske_set_callbacks(ctx->ske,
silc_client_protocol_rekey_send_packet,
NULL, NULL, NULL, silc_ske_check_version,
context);
-
+
status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL, 0);
if (status != SILC_SKE_STATUS_OK) {
SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
status));
-
+
protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_protocol_execute(protocol, client->schedule, 0, 300000);
return;
* Do normal and simple re-key.
*/
- /* Send the REKEY_DONE to indicate we will take new keys into use
- now. */
- silc_client_packet_send(client, ctx->sock,
- SILC_PACKET_REKEY_DONE,
+ /* Send the REKEY_DONE to indicate we will take new keys into use
+ now. */
+ silc_client_packet_queue_purge(client, ctx->sock);
+ silc_client_packet_send(client, ctx->sock,
+ SILC_PACKET_REKEY_DONE,
NULL, 0, NULL, NULL, NULL, 0, FALSE);
/* After we send REKEY_DONE we must set the sending encryption
key to the new key since all packets after this packet must
encrypted with the new key. */
silc_client_protocol_rekey_generate(client, ctx, TRUE);
+ silc_client_packet_queue_purge(client, ctx->sock);
/* The protocol ends in next stage. */
protocol->state = SILC_PROTOCOL_STATE_END;
* Send our KE packe to the initiator now that we've processed
* the initiator's KE packet.
*/
- status = silc_ske_responder_finish(ctx->ske, NULL, NULL,
+ status = silc_ske_responder_finish(ctx->ske, NULL, NULL,
SILC_SKE_PK_TYPE_SILC);
if (status != SILC_SKE_STATUS_OK) {
SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
status));
-
+
protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_protocol_execute(protocol, client->schedule, 0, 300000);
return;
/*
* The packet type must be KE packet
*/
+ if (!ctx->packet) {
+ SILC_LOG_WARNING(("Error during Re-key"));
+ protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ silc_protocol_execute(protocol, client->schedule, 0, 300000);
+ return;
+ }
+
if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
/* Error in protocol */
protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_protocol_execute(protocol, client->schedule, 0, 300000);
}
-
+
status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
if (status != SILC_SKE_STATUS_OK) {
SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
status));
-
+
protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_protocol_execute(protocol, client->schedule, 0, 300000);
return;
}
}
- /* Send the REKEY_DONE to indicate we will take new keys into use
- now. */
- silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
+ /* Send the REKEY_DONE to indicate we will take new keys into use
+ now. */
+ silc_client_packet_queue_purge(client, ctx->sock);
+ silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
NULL, 0, NULL, NULL, NULL, 0, FALSE);
-
+
/* After we send REKEY_DONE we must set the sending encryption
key to the new key since all packets after this packet must
encrypted with the new key. */
silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
+ silc_client_packet_queue_purge(client, ctx->sock);
/* The protocol ends in next stage. */
protocol->state = SILC_PROTOCOL_STATE_END;
break;
case SILC_PROTOCOL_STATE_END:
- /*
+ /*
* End protocol
*/
+ if (!ctx->packet) {
+ SILC_LOG_WARNING(("Error during Re-key"));
+ protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ silc_protocol_execute(protocol, client->schedule, 0, 300000);
+ return;
+ }
+
if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
/* Error in protocol */
protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_client_protocol_rekey_generate_pfs(client, ctx, FALSE);
else
silc_client_protocol_rekey_generate(client, ctx, FALSE);
+ silc_client_packet_queue_purge(client, ctx->sock);
/* Protocol has ended, call the final callback */
if (protocol->final_callback)