X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcclient%2Fprotocol.c;fp=apps%2Fsilc%2Fprotocol.c;h=d0b8064c1093adc736e96f4cd8dbd5f3bd179f79;hp=ba89d9dcf80a4fb47ddd4d9b24a98aeee608d0f3;hb=318d79b391bf6288e3e28c840217a7097f3d0392;hpb=0f9738ce962b8498bbed0a75d5fb6fa127e3577f diff --git a/apps/silc/protocol.c b/lib/silcclient/protocol.c similarity index 75% rename from apps/silc/protocol.c rename to lib/silcclient/protocol.c index ba89d9dc..d0b8064c 100644 --- a/apps/silc/protocol.c +++ b/lib/silcclient/protocol.c @@ -20,38 +20,21 @@ /* * Client side of the protocols. */ -/* - * $Id$ - * $Log$ - * Revision 1.1.1.1 2000/06/27 11:36:56 priikone - * Importet from internal CVS/Added Log headers. - * - * - */ +/* $Id$ */ -#include "clientincludes.h" +#include "clientlibincludes.h" SILC_TASK_CALLBACK(silc_client_protocol_connection_auth); -SILC_TASK_CALLBACK(silc_client_protocol_channel_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_CHANNEL_AUTH, - silc_client_protocol_channel_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, @@ -68,20 +51,15 @@ static void silc_client_protocol_ke_send_packet(SilcSKE ske, } -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 = @@ -90,6 +68,12 @@ static void silc_client_protocol_ke_finish_cb(SilcSKE ske, SILC_LOG_DEBUG(("Start")); + /* Verify server key from user. */ + if (!client->ops->verify_server_key(client, ctx->sock->user_data, + 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. */ @@ -101,42 +85,38 @@ static void silc_client_protocol_ke_set_keys(SilcSKE ske, SilcPKCS pkcs, SilcHash hash) { - SilcClientWindow win = (SilcClientWindow)sock->user_data; + SilcClientConnection conn = (SilcClientConnection)sock->user_data; SilcHash nhash; SILC_LOG_DEBUG(("Setting new keys into use")); /* Allocate cipher to be used in the communication */ - silc_cipher_alloc(cipher->cipher->name, &win->send_key); - silc_cipher_alloc(cipher->cipher->name, &win->receive_key); + silc_cipher_alloc(cipher->cipher->name, &conn->send_key); + silc_cipher_alloc(cipher->cipher->name, &conn->receive_key); - win->send_key->cipher->set_key(win->send_key->context, + conn->send_key->cipher->set_key(conn->send_key->context, keymat->send_enc_key, keymat->enc_key_len); - win->send_key->set_iv(win->send_key, keymat->send_iv); - win->receive_key->cipher->set_key(win->receive_key->context, + conn->send_key->set_iv(conn->send_key, keymat->send_iv); + conn->receive_key->cipher->set_key(conn->receive_key->context, keymat->receive_enc_key, keymat->enc_key_len); - win->receive_key->set_iv(win->receive_key, keymat->receive_iv); + conn->receive_key->set_iv(conn->receive_key, keymat->receive_iv); /* Allocate PKCS to be used */ #if 0 /* XXX Do we ever need to allocate PKCS for the connection?? If yes, we need to change KE protocol to get the initiators public key. */ - silc_pkcs_alloc(pkcs->pkcs->name, &win->public_Key); - silc_pkcs_set_public_key(win->public_key, ske->ke2_payload->pk_data, + silc_pkcs_alloc(pkcs->pkcs->name, &conn->public_Key); + silc_pkcs_set_public_key(conn->public_key, ske->ke2_payload->pk_data, ske->ke2_payload->pk_len); #endif /* 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_alloc(nhash, &conn->hmac); + silc_hmac_set_key(conn->hmac, keymat->hmac_key, keymat->hmac_key_len); } /* Performs key exchange protocol. This is used for both initiator @@ -148,6 +128,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) SilcClientKEInternalContext *ctx = (SilcClientKEInternalContext *)protocol->context; SilcClient client = (SilcClient)ctx->client; + SilcClientConnection conn = ctx->sock->user_data; SilcSKEStatus status; SILC_LOG_DEBUG(("Start")); @@ -183,7 +164,8 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) 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. */ @@ -223,11 +205,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) 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) { @@ -259,6 +237,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) 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); } @@ -278,6 +257,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) * Finish protocol */ if (ctx->responder == TRUE) { + status = 0; #if 0 status = silc_ske_responder_phase_2(ctx->ske, @@ -288,16 +268,25 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) } 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) { + client->ops->say(client, conn, + "Received unsupported server %s public key", + ctx->sock->hostname); + } else { + client->ops->say(client, conn, + "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 @@ -335,7 +324,10 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) 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; @@ -352,6 +344,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_connection_auth) SilcClientConnAuthInternalContext *ctx = (SilcClientConnAuthInternalContext *)protocol->context; SilcClient client = (SilcClient)ctx->client; + SilcClientConnection conn = ctx->sock->user_data; SILC_LOG_DEBUG(("Start")); @@ -383,16 +376,15 @@ SILC_TASK_CALLBACK(silc_client_protocol_connection_auth) break; } - silc_say(client, "Password authentication required by server %s", - ctx->sock->hostname); - auth_data = silc_client_ask_passphrase(client); + client->ops->say(client, conn, + "Password authentication required by server %s", + ctx->sock->hostname); + auth_data = client->ops->ask_passphrase(client, conn); auth_data_len = strlen(auth_data); break; case SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY: -#if 0 - -#endif + /* XXX */ break; } @@ -459,6 +451,22 @@ SILC_TASK_CALLBACK(silc_client_protocol_connection_auth) } } -SILC_TASK_CALLBACK(silc_client_protocol_channel_auth) +/* 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); }