5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
21 * Client side of the protocols.
26 * Revision 1.2 2000/07/05 06:12:05 priikone
27 * Global cosmetic changes.
29 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
30 * Imported from internal CVS/Added Log headers.
35 #include "clientincludes.h"
37 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth);
38 SILC_TASK_CALLBACK(silc_client_protocol_channel_auth);
39 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange);
41 /* SILC client protocol list */
42 const SilcProtocolObject silc_protocol_list[] =
44 { SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
45 silc_client_protocol_connection_auth },
46 { SILC_PROTOCOL_CLIENT_CHANNEL_AUTH,
47 silc_client_protocol_channel_auth },
48 { SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
49 silc_client_protocol_key_exchange },
51 { SILC_PROTOCOL_CLIENT_NONE, NULL },
55 * Key Exhange protocol functions
58 static void silc_client_protocol_ke_send_packet(SilcSKE ske,
63 SilcProtocol protocol = (SilcProtocol)context;
64 SilcClientKEInternalContext *ctx =
65 (SilcClientKEInternalContext *)protocol->context;
66 SilcClient client = (SilcClient)ctx->client;
68 /* Send the packet immediately */
69 silc_client_packet_send(client, ske->sock, type, NULL, 0, NULL, NULL,
70 packet->data, packet->len, TRUE);
74 static void silc_client_protocol_ke_phase1_cb(SilcSKE ske,
77 SilcProtocol protocol = (SilcProtocol)context;
78 SilcClientKEInternalContext *ctx =
79 (SilcClientKEInternalContext *)protocol->context;
80 SilcClient client = (SilcClient)ctx->client;
82 SILC_LOG_DEBUG(("Start"));
86 static void silc_client_protocol_ke_finish_cb(SilcSKE ske,
89 SilcProtocol protocol = (SilcProtocol)context;
90 SilcClientKEInternalContext *ctx =
91 (SilcClientKEInternalContext *)protocol->context;
92 SilcClient client = (SilcClient)ctx->client;
94 SILC_LOG_DEBUG(("Start"));
98 /* Sets the negotiated key material into use for particular connection. */
100 static void silc_client_protocol_ke_set_keys(SilcSKE ske,
101 SilcSocketConnection sock,
102 SilcSKEKeyMaterial *keymat,
107 SilcClientWindow win = (SilcClientWindow)sock->user_data;
110 SILC_LOG_DEBUG(("Setting new keys into use"));
112 /* Allocate cipher to be used in the communication */
113 silc_cipher_alloc(cipher->cipher->name, &win->send_key);
114 silc_cipher_alloc(cipher->cipher->name, &win->receive_key);
116 win->send_key->cipher->set_key(win->send_key->context,
117 keymat->send_enc_key,
118 keymat->enc_key_len);
119 win->send_key->set_iv(win->send_key, keymat->send_iv);
120 win->receive_key->cipher->set_key(win->receive_key->context,
121 keymat->receive_enc_key,
122 keymat->enc_key_len);
123 win->receive_key->set_iv(win->receive_key, keymat->receive_iv);
125 /* Allocate PKCS to be used */
127 /* XXX Do we ever need to allocate PKCS for the connection??
128 If yes, we need to change KE protocol to get the initiators
130 silc_pkcs_alloc(pkcs->pkcs->name, &win->public_Key);
131 silc_pkcs_set_public_key(win->public_key, ske->ke2_payload->pk_data,
132 ske->ke2_payload->pk_len);
135 /* Save HMAC key to be used in the communication. */
136 silc_hash_alloc(hash->hash->name, &nhash);
137 silc_hmac_alloc(nhash, &win->hmac);
138 win->hmac_key_len = keymat->hmac_key_len;
139 win->hmac_key = silc_calloc(win->hmac_key_len,
140 sizeof(unsigned char));
141 memcpy(win->hmac_key, keymat->hmac_key, keymat->hmac_key_len);
145 /* Performs key exchange protocol. This is used for both initiator
146 and responder key exchange. This may be called recursively. */
148 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
150 SilcProtocol protocol = (SilcProtocol)context;
151 SilcClientKEInternalContext *ctx =
152 (SilcClientKEInternalContext *)protocol->context;
153 SilcClient client = (SilcClient)ctx->client;
154 SilcSKEStatus status;
156 SILC_LOG_DEBUG(("Start"));
158 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
159 protocol->state = SILC_PROTOCOL_STATE_START;
161 switch(protocol->state) {
162 case SILC_PROTOCOL_STATE_START:
169 /* Allocate Key Exchange object */
170 ske = silc_ske_alloc();
173 if (ctx->responder == TRUE) {
175 SilcBuffer start_payload;
178 /* Start the key exchange by processing the received security
179 properties packet from initiator. */
180 status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
182 silc_client_protocol_ke_send_packet,
186 SilcSKEStartPayload *start_payload;
188 /* Assemble security properties. */
189 silc_ske_assemble_security_properties(ske, &start_payload);
191 /* Start the key exchange by sending our security properties
192 to the remote end. */
193 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
195 silc_client_protocol_ke_send_packet,
199 if (status != SILC_SKE_STATUS_OK) {
207 /* Advance the state of the protocol. */
216 if (ctx->responder == TRUE) {
219 silc_ske_responder_phase_1(ctx->ske,
220 ctx->ske->start_payload,
221 silc_server_protocol_ke_send_packet,
225 /* Call Phase-1 function. This processes the Key Exchange Start
226 paylaod reply we just got from the responder. The callback
227 function will receive the processed payload where we will
230 silc_ske_initiator_phase_1(ctx->ske,
232 silc_client_protocol_ke_phase1_cb,
241 /* Advance the state of the protocol and call the next state. */
243 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
251 if (ctx->responder == TRUE) {
254 silc_ske_responder_phase_2(ctx->ske,
255 ctx->ske->start_payload,
256 silc_server_protocol_ke_send_packet,
260 /* Call the Phase-2 function. This creates Diffie Hellman
261 key exchange parameters and sends our public part inside
262 Key Exhange 1 Payload to the responder. */
264 silc_ske_initiator_phase_2(ctx->ske,
265 silc_client_protocol_ke_send_packet,
274 /* Advance the state of the protocol. */
283 if (ctx->responder == TRUE) {
286 silc_ske_responder_phase_2(ctx->ske,
287 ctx->ske->start_payload,
288 silc_server_protocol_ke_send_packet,
292 /* Finish the protocol. This verifies the Key Exchange 2 payload
293 sent by responder. */
295 silc_ske_initiator_finish(ctx->ske,
297 silc_client_protocol_ke_finish_cb,
306 /* Send Ok to the other end. We will end the protocol as server
307 sends Ok to us when we will take the new keys into use. */
308 silc_ske_end(ctx->ske, silc_client_protocol_ke_send_packet, context);
310 /* End the protocol on the next round */
311 protocol->state = SILC_PROTOCOL_STATE_END;
314 case SILC_PROTOCOL_STATE_END:
319 SilcSKEKeyMaterial *keymat;
321 /* Process the key material */
322 keymat = silc_calloc(1, sizeof(*keymat));
323 silc_ske_process_key_material(ctx->ske, 16, (16 * 8), 16, keymat);
325 /* Take the negotiated keys into use. */
326 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, keymat,
327 ctx->ske->prop->cipher,
328 ctx->ske->prop->pkcs,
329 ctx->ske->prop->hash);
331 /* Protocol has ended, call the final callback */
332 if (protocol->final_callback)
333 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
335 silc_protocol_free(protocol);
338 case SILC_PROTOCOL_STATE_ERROR:
340 /* On error the final callback is always called. */
341 /* protocol->final_callback(pptr, context);*/
343 case SILC_PROTOCOL_STATE_UNKNOWN:
349 * Connection Authentication protocol functions
352 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
354 SilcProtocol protocol = (SilcProtocol)context;
355 SilcClientConnAuthInternalContext *ctx =
356 (SilcClientConnAuthInternalContext *)protocol->context;
357 SilcClient client = (SilcClient)ctx->client;
359 SILC_LOG_DEBUG(("Start"));
361 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
362 protocol->state = SILC_PROTOCOL_STATE_START;
364 switch(protocol->state) {
365 case SILC_PROTOCOL_STATE_START:
368 * Start protocol. We send authentication data to the server
369 * to be authenticated.
373 unsigned char *auth_data = NULL;
374 unsigned int auth_data_len = 0;
376 switch(ctx->auth_meth) {
377 case SILC_PROTOCOL_CONN_AUTH_NONE:
378 /* No authentication required */
381 case SILC_PROTOCOL_CONN_AUTH_PASSWORD:
382 /* Password authentication */
383 if (ctx->auth_data && ctx->auth_data_len) {
384 auth_data = ctx->auth_data;
385 auth_data_len = ctx->auth_data_len;
389 silc_say(client, "Password authentication required by server %s",
390 ctx->sock->hostname);
391 auth_data = silc_client_ask_passphrase(client);
392 auth_data_len = strlen(auth_data);
395 case SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY:
402 payload_len = 4 + auth_data_len;
403 packet = silc_buffer_alloc(payload_len);
404 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
405 silc_buffer_format(packet,
406 SILC_STR_UI_SHORT(payload_len),
407 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
408 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
411 /* Send the packet to server */
412 silc_client_packet_send(client, ctx->sock,
413 SILC_PACKET_CONNECTION_AUTH,
415 packet->data, packet->len, TRUE);
418 memset(auth_data, 0, auth_data_len);
419 silc_free(auth_data);
421 silc_buffer_free(packet);
423 /* Next state is end of protocol */
424 protocol->state = SILC_PROTOCOL_STATE_END;
428 case SILC_PROTOCOL_STATE_END:
431 * End protocol. Nothing special to be done here.
434 /* Protocol has ended, call the final callback */
435 if (protocol->final_callback)
436 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
438 silc_protocol_free(protocol);
442 case SILC_PROTOCOL_STATE_ERROR:
448 /* Error in protocol. Send FAILURE packet. Although I don't think
449 this could ever happen on client side. */
450 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
451 NULL, 0, NULL, NULL, NULL, 0, TRUE);
453 /* On error the final callback is always called. */
454 if (protocol->final_callback)
455 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
457 silc_protocol_free(protocol);
460 case SILC_PROTOCOL_STATE_UNKNOWN:
465 SILC_TASK_CALLBACK(silc_client_protocol_channel_auth)