/*
* $Id$
* $Log$
+ * Revision 1.8 2000/07/20 10:17:25 priikone
+ * Added dynamic protocol registering/unregistering support. The
+ * patch was provided by cras.
+ *
+ * Revision 1.7 2000/07/19 07:07:47 priikone
+ * Added version detection support to SKE.
+ *
+ * Revision 1.6 2000/07/14 06:12:29 priikone
+ * Put the HMAC keys into the HMAC object instead on having them
+ * saved elsewhere; we can use now silc_hmac_make instead of
+ * silc_hmac_make_with_key.
+ *
+ * Revision 1.5 2000/07/07 11:36:09 priikone
+ * Inform user when received unsupported public key from server.
+ *
+ * Revision 1.4 2000/07/07 06:53:45 priikone
+ * Added support for server public key verification.
+ *
* Revision 1.3 2000/07/06 07:14:16 priikone
* Deprecated old `channel_auth' protocol.
*
SILC_TASK_CALLBACK(silc_client_protocol_connection_auth);
SILC_TASK_CALLBACK(silc_client_protocol_key_exchange);
-/* SILC client protocol list */
-const SilcProtocolObject silc_protocol_list[] =
-{
- { SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
- silc_client_protocol_connection_auth },
- { SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
- silc_client_protocol_key_exchange },
-
- { SILC_PROTOCOL_CLIENT_NONE, NULL },
-};
+extern char *silc_version_string;
/*
* Key Exhange protocol functions
*/
+/* Function that is called when SKE protocol sends packets to network. */
+
static void silc_client_protocol_ke_send_packet(SilcSKE ske,
SilcBuffer packet,
SilcPacketType type,
}
-static void silc_client_protocol_ke_phase1_cb(SilcSKE ske,
- void *context)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcClientKEInternalContext *ctx =
- (SilcClientKEInternalContext *)protocol->context;
- SilcClient client = (SilcClient)ctx->client;
-
- SILC_LOG_DEBUG(("Start"));
-
-}
+/* Callback that is called when we have received KE2 payload from
+ responder. We try to verify the public key now. */
-static void silc_client_protocol_ke_finish_cb(SilcSKE ske,
- void *context)
+static SilcSKEStatus
+silc_client_protocol_ke_verify_key(SilcSKE ske,
+ unsigned char *pk_data,
+ unsigned int pk_len,
+ SilcSKEPKType pk_type,
+ void *context)
{
SilcProtocol protocol = (SilcProtocol)context;
SilcClientKEInternalContext *ctx =
SILC_LOG_DEBUG(("Start"));
+ if (!silc_client_verify_server_key(client, ctx->sock,
+ pk_data, pk_len, pk_type))
+ return SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
+
+ return SILC_SKE_STATUS_OK;
}
/* Sets the negotiated key material into use for particular connection. */
/* Save HMAC key to be used in the communication. */
silc_hash_alloc(hash->hash->name, &nhash);
silc_hmac_alloc(nhash, &win->hmac);
- win->hmac_key_len = keymat->hmac_key_len;
- win->hmac_key = silc_calloc(win->hmac_key_len,
- sizeof(unsigned char));
- memcpy(win->hmac_key, keymat->hmac_key, keymat->hmac_key_len);
-
+ silc_hmac_set_key(win->hmac, keymat->hmac_key, keymat->hmac_key_len);
}
/* Performs key exchange protocol. This is used for both initiator
SilcSKEStartPayload *start_payload;
/* Assemble security properties. */
- silc_ske_assemble_security_properties(ske, &start_payload);
+ silc_ske_assemble_security_properties(ske, silc_version_string,
+ &start_payload);
/* Start the key exchange by sending our security properties
to the remote end. */
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,
- silc_client_protocol_ke_phase1_cb,
- context);
+ status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet, NULL, NULL);
}
switch(status) {
Key Exhange 1 Payload to the responder. */
status =
silc_ske_initiator_phase_2(ctx->ske,
+ client->public_key,
silc_client_protocol_ke_send_packet,
context);
}
* Finish protocol
*/
if (ctx->responder == TRUE) {
+ status = 0;
#if 0
status =
silc_ske_responder_phase_2(ctx->ske,
} else {
/* Finish the protocol. This verifies the Key Exchange 2 payload
sent by responder. */
- status =
- silc_ske_initiator_finish(ctx->ske,
- ctx->packet,
- silc_client_protocol_ke_finish_cb,
- context);
+ status = silc_ske_initiator_finish(ctx->ske, ctx->packet,
+ silc_client_protocol_ke_verify_key,
+ context, NULL, NULL);
}
- switch(status) {
- default:
- break;
+ if (status != SILC_SKE_STATUS_OK) {
+
+ if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
+ silc_say(client, "Received unsupported server %s public key",
+ ctx->sock->hostname);
+ } else {
+ silc_say(client, "Error during key exchange protocol with server %s",
+ ctx->sock->hostname);
+ }
+ protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
+ return;
}
/* Send Ok to the other end. We will end the protocol as server
case SILC_PROTOCOL_STATE_ERROR:
/* On error the final callback is always called. */
- /* protocol->final_callback(pptr, context);*/
+ 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;
}
}
+/* Registers protocols used in client */
+
+void silc_client_protocols_register(void)
+{
+ silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
+ silc_client_protocol_connection_auth);
+ silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
+ silc_client_protocol_key_exchange);
+}
+
+/* Unregisters protocols */
+
+void silc_client_protocols_unregister(void)
+{
+ silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
+ silc_client_protocol_connection_auth);
+ silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
+ silc_client_protocol_key_exchange);
+}