/*
* 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,
}
-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"));
+ /* 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. */
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
SilcClientKEInternalContext *ctx =
(SilcClientKEInternalContext *)protocol->context;
SilcClient client = (SilcClient)ctx->client;
+ SilcClientConnection conn = ctx->sock->user_data;
SilcSKEStatus status;
SILC_LOG_DEBUG(("Start"));
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) {
+ 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
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;
SilcClientConnAuthInternalContext *ctx =
(SilcClientConnAuthInternalContext *)protocol->context;
SilcClient client = (SilcClient)ctx->client;
+ SilcClientConnection conn = ctx->sock->user_data;
SILC_LOG_DEBUG(("Start"));
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;
}
}
}
-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);
}