Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
- Copyright (C) 1997 - 2000 Pekka Riikonen
+ Copyright (C) 1997 - 2001 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
silc_hmac_set_key(conn->hmac, keymat->hmac_key, keymat->hmac_key_len);
}
+/* Checks the version string of the server. */
+
+SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
+ unsigned int len)
+{
+ SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
+ SilcClient client = (SilcClient)ske->user_data;
+ SilcSKEStatus status = SILC_SKE_STATUS_OK;
+
+ /* Check for initial version string */
+ if (!strstr(version, "SILC-1.0-"))
+ status = SILC_SKE_STATUS_BAD_VERSION;
+
+ /* Check software version */
+
+ if (len < strlen(silc_version_string))
+ status = SILC_SKE_STATUS_BAD_VERSION;
+
+ /* XXX for now there is no other tests due to the abnormal version
+ string that is used */
+
+ if (status != SILC_SKE_STATUS_OK)
+ client->ops->say(client, conn,
+ "We don't support server version `%s'", version);
+
+ return status;
+}
+
/* Performs key exchange protocol. This is used for both initiator
and responder key exchange. This may be called recursively. */
(SilcClientKEInternalContext *)protocol->context;
SilcClient client = (SilcClient)ctx->client;
SilcClientConnection conn = ctx->sock->user_data;
- SilcSKEStatus status;
+ SilcSKEStatus status = 0;
SILC_LOG_DEBUG(("Start"));
/* Allocate Key Exchange object */
ske = silc_ske_alloc();
ctx->ske = ske;
+ ske->rng = client->rng;
+ ske->user_data = (void *)client;
if (ctx->responder == TRUE) {
#if 0
SilcSKEStartPayload *start_payload;
/* Assemble security properties. */
- silc_ske_assemble_security_properties(ske, silc_version_string,
+ silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE,
+ silc_version_string,
&start_payload);
/* Start the key exchange by sending our security properties
}
if (status != SILC_SKE_STATUS_OK) {
- switch(status) {
-
- default:
- break;
- }
+ SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
+ status));
+ SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
+ status));
+
+ protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
+ return;
}
/* Advance the state of the protocol. */
paylaod reply we just got from the responder. The callback
function will receive the processed payload where we will
save it. */
- status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet, NULL, NULL);
+ status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer,
+ NULL, NULL);
}
- switch(status) {
- default:
- break;
+ if (status != SILC_SKE_STATUS_OK) {
+ SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
+ status));
+ SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
+ status));
+
+ protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
+ return;
}
/* Advance the state of the protocol and call the next state. */
context);
}
- switch(status) {
- default:
- break;
+ if (status != SILC_SKE_STATUS_OK) {
+ SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
+ status));
+ SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
+ status));
+
+ protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
+ return;
}
/* Advance the state of the protocol. */
} else {
/* Finish the protocol. This verifies the Key Exchange 2 payload
sent by responder. */
- status = silc_ske_initiator_finish(ctx->ske, ctx->packet,
+ status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
silc_client_protocol_ke_verify_key,
context, NULL, NULL);
}
protocol->state = SILC_PROTOCOL_STATE_END;
}
break;
+
case SILC_PROTOCOL_STATE_END:
{
/*
* End protocol
*/
SilcSKEKeyMaterial *keymat;
+ int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher, NULL);
+ int hash_len = ctx->ske->prop->hash->hash->hash_len;
/* Process the key material */
keymat = silc_calloc(1, sizeof(*keymat));
- silc_ske_process_key_material(ctx->ske, 16, (16 * 8), 16, keymat);
+ silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
+ keymat);
/* Take the negotiated keys into use. */
silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, keymat,
ctx->ske->prop->pkcs,
ctx->ske->prop->hash);
+ silc_ske_free_key_material(keymat);
+
/* Protocol has ended, call the final callback */
if (protocol->final_callback)
protocol->execute_final(client->timeout_queue, 0, protocol, fd);
silc_protocol_free(protocol);
}
break;
+
case SILC_PROTOCOL_STATE_ERROR:
+ /*
+ * Error during protocol
+ */
+ /* Send abort notification */
+ silc_ske_abort(ctx->ske, ctx->ske->status,
+ silc_client_protocol_ke_send_packet,
+ context);
+
+ /* On error the final callback is always called. */
+ if (protocol->final_callback)
+ protocol->execute_final(client->timeout_queue, 0, protocol, fd);
+ else
+ silc_protocol_free(protocol);
+ break;
+
+ case SILC_PROTOCOL_STATE_FAILURE:
+ /*
+ * Received failure from remote.
+ */
+
/* On error the final callback is always called. */
if (protocol->final_callback)
protocol->execute_final(client->timeout_queue, 0, protocol, fd);
unsigned int auth_data_len = 0;
switch(ctx->auth_meth) {
- case SILC_PROTOCOL_CONN_AUTH_NONE:
+ case SILC_AUTH_NONE:
/* No authentication required */
break;
- case SILC_PROTOCOL_CONN_AUTH_PASSWORD:
+ case SILC_AUTH_PASSWORD:
/* Password authentication */
if (ctx->auth_data && ctx->auth_data_len) {
auth_data = ctx->auth_data;
auth_data_len = strlen(auth_data);
break;
- case SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY:
+ case SILC_AUTH_PUBLIC_KEY:
/* XXX */
break;
}
case SILC_PROTOCOL_STATE_ERROR:
{
/*
- * Error
+ * Error. Send notify to remote.
*/
+ unsigned char error[4];
+
+ SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
/* Error in protocol. Send FAILURE packet. Although I don't think
this could ever happen on client side. */
silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
- NULL, 0, NULL, NULL, NULL, 0, TRUE);
+ NULL, 0, NULL, NULL, error, 4, TRUE);
/* On error the final callback is always called. */
if (protocol->final_callback)
else
silc_protocol_free(protocol);
}
+
+ case SILC_PROTOCOL_STATE_FAILURE:
+ /*
+ * Received failure from remote.
+ */
+
+ /* On error the final callback is always called. */
+ if (protocol->final_callback)
+ protocol->execute_final(client->timeout_queue, 0, protocol, fd);
+ else
+ silc_protocol_free(protocol);
break;
+
case SILC_PROTOCOL_STATE_UNKNOWN:
break;
}