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.4 2000/07/07 06:53:45 priikone
27 * Added support for server public key verification.
29 * Revision 1.3 2000/07/06 07:14:16 priikone
30 * Deprecated old `channel_auth' protocol.
32 * Revision 1.2 2000/07/05 06:12:05 priikone
33 * Global cosmetic changes.
35 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
36 * Imported from internal CVS/Added Log headers.
41 #include "clientincludes.h"
43 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth);
44 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange);
46 /* SILC client protocol list */
47 const SilcProtocolObject silc_protocol_list[] =
49 { SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
50 silc_client_protocol_connection_auth },
51 { SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
52 silc_client_protocol_key_exchange },
54 { SILC_PROTOCOL_CLIENT_NONE, NULL },
58 * Key Exhange protocol functions
61 /* Function that is called when SKE protocol sends packets to network. */
63 static void silc_client_protocol_ke_send_packet(SilcSKE ske,
68 SilcProtocol protocol = (SilcProtocol)context;
69 SilcClientKEInternalContext *ctx =
70 (SilcClientKEInternalContext *)protocol->context;
71 SilcClient client = (SilcClient)ctx->client;
73 /* Send the packet immediately */
74 silc_client_packet_send(client, ske->sock, type, NULL, 0, NULL, NULL,
75 packet->data, packet->len, TRUE);
79 /* Callback that is called when we have received KE2 payload from
80 responder. We try to verify the public key now. */
83 silc_client_protocol_ke_verify_key(SilcSKE ske,
84 unsigned char *pk_data,
86 SilcSKEPKType pk_type,
89 SilcProtocol protocol = (SilcProtocol)context;
90 SilcClientKEInternalContext *ctx =
91 (SilcClientKEInternalContext *)protocol->context;
92 SilcClient client = (SilcClient)ctx->client;
94 SILC_LOG_DEBUG(("Start"));
96 if (!silc_client_verify_server_key(client, ctx->sock,
97 pk_data, pk_len, pk_type))
98 return SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
100 return SILC_SKE_STATUS_OK;
103 /* Sets the negotiated key material into use for particular connection. */
105 static void silc_client_protocol_ke_set_keys(SilcSKE ske,
106 SilcSocketConnection sock,
107 SilcSKEKeyMaterial *keymat,
112 SilcClientWindow win = (SilcClientWindow)sock->user_data;
115 SILC_LOG_DEBUG(("Setting new keys into use"));
117 /* Allocate cipher to be used in the communication */
118 silc_cipher_alloc(cipher->cipher->name, &win->send_key);
119 silc_cipher_alloc(cipher->cipher->name, &win->receive_key);
121 win->send_key->cipher->set_key(win->send_key->context,
122 keymat->send_enc_key,
123 keymat->enc_key_len);
124 win->send_key->set_iv(win->send_key, keymat->send_iv);
125 win->receive_key->cipher->set_key(win->receive_key->context,
126 keymat->receive_enc_key,
127 keymat->enc_key_len);
128 win->receive_key->set_iv(win->receive_key, keymat->receive_iv);
130 /* Allocate PKCS to be used */
132 /* XXX Do we ever need to allocate PKCS for the connection??
133 If yes, we need to change KE protocol to get the initiators
135 silc_pkcs_alloc(pkcs->pkcs->name, &win->public_Key);
136 silc_pkcs_set_public_key(win->public_key, ske->ke2_payload->pk_data,
137 ske->ke2_payload->pk_len);
140 /* Save HMAC key to be used in the communication. */
141 silc_hash_alloc(hash->hash->name, &nhash);
142 silc_hmac_alloc(nhash, &win->hmac);
143 win->hmac_key_len = keymat->hmac_key_len;
144 win->hmac_key = silc_calloc(win->hmac_key_len,
145 sizeof(unsigned char));
146 memcpy(win->hmac_key, keymat->hmac_key, keymat->hmac_key_len);
150 /* Performs key exchange protocol. This is used for both initiator
151 and responder key exchange. This may be called recursively. */
153 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
155 SilcProtocol protocol = (SilcProtocol)context;
156 SilcClientKEInternalContext *ctx =
157 (SilcClientKEInternalContext *)protocol->context;
158 SilcClient client = (SilcClient)ctx->client;
159 SilcSKEStatus status;
161 SILC_LOG_DEBUG(("Start"));
163 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
164 protocol->state = SILC_PROTOCOL_STATE_START;
166 switch(protocol->state) {
167 case SILC_PROTOCOL_STATE_START:
174 /* Allocate Key Exchange object */
175 ske = silc_ske_alloc();
178 if (ctx->responder == TRUE) {
180 SilcBuffer start_payload;
183 /* Start the key exchange by processing the received security
184 properties packet from initiator. */
185 status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
187 silc_client_protocol_ke_send_packet,
191 SilcSKEStartPayload *start_payload;
193 /* Assemble security properties. */
194 silc_ske_assemble_security_properties(ske, &start_payload);
196 /* Start the key exchange by sending our security properties
197 to the remote end. */
198 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
200 silc_client_protocol_ke_send_packet,
204 if (status != SILC_SKE_STATUS_OK) {
212 /* Advance the state of the protocol. */
221 if (ctx->responder == TRUE) {
224 silc_ske_responder_phase_1(ctx->ske,
225 ctx->ske->start_payload,
226 silc_server_protocol_ke_send_packet,
230 /* Call Phase-1 function. This processes the Key Exchange Start
231 paylaod reply we just got from the responder. The callback
232 function will receive the processed payload where we will
234 status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet, NULL, NULL);
242 /* Advance the state of the protocol and call the next state. */
244 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
252 if (ctx->responder == TRUE) {
255 silc_ske_responder_phase_2(ctx->ske,
256 ctx->ske->start_payload,
257 silc_server_protocol_ke_send_packet,
261 /* Call the Phase-2 function. This creates Diffie Hellman
262 key exchange parameters and sends our public part inside
263 Key Exhange 1 Payload to the responder. */
265 silc_ske_initiator_phase_2(ctx->ske,
266 silc_client_protocol_ke_send_packet,
275 /* Advance the state of the protocol. */
284 if (ctx->responder == TRUE) {
288 silc_ske_responder_phase_2(ctx->ske,
289 ctx->ske->start_payload,
290 silc_server_protocol_ke_send_packet,
294 /* Finish the protocol. This verifies the Key Exchange 2 payload
295 sent by responder. */
296 status = silc_ske_initiator_finish(ctx->ske, ctx->packet,
297 silc_client_protocol_ke_verify_key,
298 context, NULL, NULL);
301 if (status != SILC_SKE_STATUS_OK) {
302 protocol->state = SILC_PROTOCOL_STATE_ERROR;
303 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
307 /* Send Ok to the other end. We will end the protocol as server
308 sends Ok to us when we will take the new keys into use. */
309 silc_ske_end(ctx->ske, silc_client_protocol_ke_send_packet, context);
311 /* End the protocol on the next round */
312 protocol->state = SILC_PROTOCOL_STATE_END;
315 case SILC_PROTOCOL_STATE_END:
320 SilcSKEKeyMaterial *keymat;
322 /* Process the key material */
323 keymat = silc_calloc(1, sizeof(*keymat));
324 silc_ske_process_key_material(ctx->ske, 16, (16 * 8), 16, keymat);
326 /* Take the negotiated keys into use. */
327 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, keymat,
328 ctx->ske->prop->cipher,
329 ctx->ske->prop->pkcs,
330 ctx->ske->prop->hash);
332 /* Protocol has ended, call the final callback */
333 if (protocol->final_callback)
334 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
336 silc_protocol_free(protocol);
339 case SILC_PROTOCOL_STATE_ERROR:
341 /* On error the final callback is always called. */
342 if (protocol->final_callback)
343 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
345 silc_protocol_free(protocol);
347 case SILC_PROTOCOL_STATE_UNKNOWN:
353 * Connection Authentication protocol functions
356 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
358 SilcProtocol protocol = (SilcProtocol)context;
359 SilcClientConnAuthInternalContext *ctx =
360 (SilcClientConnAuthInternalContext *)protocol->context;
361 SilcClient client = (SilcClient)ctx->client;
363 SILC_LOG_DEBUG(("Start"));
365 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
366 protocol->state = SILC_PROTOCOL_STATE_START;
368 switch(protocol->state) {
369 case SILC_PROTOCOL_STATE_START:
372 * Start protocol. We send authentication data to the server
373 * to be authenticated.
377 unsigned char *auth_data = NULL;
378 unsigned int auth_data_len = 0;
380 switch(ctx->auth_meth) {
381 case SILC_PROTOCOL_CONN_AUTH_NONE:
382 /* No authentication required */
385 case SILC_PROTOCOL_CONN_AUTH_PASSWORD:
386 /* Password authentication */
387 if (ctx->auth_data && ctx->auth_data_len) {
388 auth_data = ctx->auth_data;
389 auth_data_len = ctx->auth_data_len;
393 silc_say(client, "Password authentication required by server %s",
394 ctx->sock->hostname);
395 auth_data = silc_client_ask_passphrase(client);
396 auth_data_len = strlen(auth_data);
399 case SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY:
404 payload_len = 4 + auth_data_len;
405 packet = silc_buffer_alloc(payload_len);
406 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
407 silc_buffer_format(packet,
408 SILC_STR_UI_SHORT(payload_len),
409 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
410 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
413 /* Send the packet to server */
414 silc_client_packet_send(client, ctx->sock,
415 SILC_PACKET_CONNECTION_AUTH,
417 packet->data, packet->len, TRUE);
420 memset(auth_data, 0, auth_data_len);
421 silc_free(auth_data);
423 silc_buffer_free(packet);
425 /* Next state is end of protocol */
426 protocol->state = SILC_PROTOCOL_STATE_END;
430 case SILC_PROTOCOL_STATE_END:
433 * End protocol. Nothing special to be done here.
436 /* Protocol has ended, call the final callback */
437 if (protocol->final_callback)
438 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
440 silc_protocol_free(protocol);
444 case SILC_PROTOCOL_STATE_ERROR:
450 /* Error in protocol. Send FAILURE packet. Although I don't think
451 this could ever happen on client side. */
452 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
453 NULL, 0, NULL, NULL, NULL, 0, TRUE);
455 /* On error the final callback is always called. */
456 if (protocol->final_callback)
457 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
459 silc_protocol_free(protocol);
462 case SILC_PROTOCOL_STATE_UNKNOWN: