5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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.
25 #include "clientlibincludes.h"
26 #include "client_internal.h"
28 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth);
29 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange);
31 extern char *silc_version_string;
34 * Key Exhange protocol functions
37 /* Function that is called when SKE protocol sends packets to network. */
39 void silc_client_protocol_ke_send_packet(SilcSKE ske,
44 SilcProtocol protocol = (SilcProtocol)context;
45 SilcClientKEInternalContext *ctx =
46 (SilcClientKEInternalContext *)protocol->context;
47 SilcClient client = (SilcClient)ctx->client;
49 /* Send the packet immediately */
50 silc_client_packet_send(client, ske->sock, type, NULL, 0, NULL, NULL,
51 packet->data, packet->len, TRUE);
55 /* Callback that is called when we have received KE2 payload from
56 responder. We try to verify the public key now. */
58 SilcSKEStatus silc_client_protocol_ke_verify_key(SilcSKE ske,
59 unsigned char *pk_data,
61 SilcSKEPKType pk_type,
64 SilcProtocol protocol = (SilcProtocol)context;
65 SilcClientKEInternalContext *ctx =
66 (SilcClientKEInternalContext *)protocol->context;
67 SilcClient client = (SilcClient)ctx->client;
69 SILC_LOG_DEBUG(("Start"));
71 /* Verify server key from user. */
72 if (!client->ops->verify_server_key(client, ctx->sock->user_data,
73 pk_data, pk_len, pk_type))
74 return SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
76 return SILC_SKE_STATUS_OK;
79 /* Sets the negotiated key material into use for particular connection. */
81 void silc_client_protocol_ke_set_keys(SilcSKE ske,
82 SilcSocketConnection sock,
83 SilcSKEKeyMaterial *keymat,
89 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
91 SILC_LOG_DEBUG(("Setting new keys into use"));
93 /* Allocate cipher to be used in the communication */
94 silc_cipher_alloc(cipher->cipher->name, &conn->send_key);
95 silc_cipher_alloc(cipher->cipher->name, &conn->receive_key);
97 conn->send_key->cipher->set_key(conn->send_key->context,
100 conn->send_key->set_iv(conn->send_key, keymat->send_iv);
101 conn->receive_key->cipher->set_key(conn->receive_key->context,
102 keymat->receive_enc_key,
103 keymat->enc_key_len);
104 conn->receive_key->set_iv(conn->receive_key, keymat->receive_iv);
106 /* Allocate PKCS to be used */
108 /* XXX Do we ever need to allocate PKCS for the connection??
109 If yes, we need to change KE protocol to get the initiators
111 silc_pkcs_alloc(pkcs->pkcs->name, &conn->public_Key);
112 silc_pkcs_set_public_key(conn->public_key, ske->ke2_payload->pk_data,
113 ske->ke2_payload->pk_len);
116 /* Save HMAC key to be used in the communication. */
117 silc_hmac_alloc(hmac->hmac->name, NULL, &conn->hmac);
118 silc_hmac_set_key(conn->hmac, keymat->hmac_key, keymat->hmac_key_len);
121 /* Checks the version string of the server. */
123 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
126 SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
127 SilcClient client = (SilcClient)ske->user_data;
128 SilcSKEStatus status = SILC_SKE_STATUS_OK;
130 /* Check for initial version string */
131 if (!strstr(version, "SILC-1.0-"))
132 status = SILC_SKE_STATUS_BAD_VERSION;
134 /* Check software version */
136 if (len < strlen(silc_version_string))
137 status = SILC_SKE_STATUS_BAD_VERSION;
139 /* XXX for now there is no other tests due to the abnormal version
140 string that is used */
142 if (status != SILC_SKE_STATUS_OK)
143 client->ops->say(client, conn,
144 "We don't support server version `%s'", version);
149 /* Performs key exchange protocol. This is used for both initiator
150 and responder key exchange. This may be called recursively. */
152 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
154 SilcProtocol protocol = (SilcProtocol)context;
155 SilcClientKEInternalContext *ctx =
156 (SilcClientKEInternalContext *)protocol->context;
157 SilcClient client = (SilcClient)ctx->client;
158 SilcClientConnection conn = ctx->sock->user_data;
159 SilcSKEStatus status = 0;
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();
177 ske->rng = client->rng;
178 ske->user_data = (void *)client;
180 if (ctx->responder == TRUE) {
181 /* Start the key exchange by processing the received security
182 properties packet from initiator. */
183 status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
185 ctx->packet->buffer, NULL, NULL);
187 SilcSKEStartPayload *start_payload;
189 /* Assemble security properties. */
190 silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE,
194 /* Start the key exchange by sending our security properties
195 to the remote end. */
196 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
202 if (status != SILC_SKE_STATUS_OK) {
203 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
205 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
208 protocol->state = SILC_PROTOCOL_STATE_ERROR;
209 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
213 /* Advance protocol state and call the next state if we are responder */
215 if (ctx->responder == TRUE)
216 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
224 if (ctx->responder == TRUE) {
225 /* Sends the selected security properties to the initiator. */
227 silc_ske_responder_phase_1(ctx->ske,
228 ctx->ske->start_payload,
232 /* Call Phase-1 function. This processes the Key Exchange Start
233 paylaod reply we just got from the responder. The callback
234 function will receive the processed payload where we will
236 status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer,
240 if (status != SILC_SKE_STATUS_OK) {
241 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
243 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
246 protocol->state = SILC_PROTOCOL_STATE_ERROR;
247 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
251 /* Advance protocol state and call next state if we are initiator */
253 if (ctx->responder == FALSE)
254 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
262 if (ctx->responder == TRUE) {
263 /* Process the received Key Exchange 1 Payload packet from
264 the initiator. This also creates our parts of the Diffie
265 Hellman algorithm. */
266 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer,
269 /* Call the Phase-2 function. This creates Diffie Hellman
270 key exchange parameters and sends our public part inside
271 Key Exhange 1 Payload to the responder. */
273 silc_ske_initiator_phase_2(ctx->ske,
279 if (status != SILC_SKE_STATUS_OK) {
280 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
282 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
285 protocol->state = SILC_PROTOCOL_STATE_ERROR;
286 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
290 /* Advance protocol state and call the next state if we are responder */
292 if (ctx->responder == TRUE)
293 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
301 if (ctx->responder == TRUE) {
302 /* This creates the key exchange material and sends our
303 public parts to the initiator inside Key Exchange 2 Payload. */
305 silc_ske_responder_finish(ctx->ske,
306 client->public_key, client->private_key,
307 SILC_SKE_PK_TYPE_SILC,
312 /* Finish the protocol. This verifies the Key Exchange 2 payload
313 sent by responder. */
314 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
315 ctx->verify, context, NULL, NULL);
318 if (status != SILC_SKE_STATUS_OK) {
320 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
321 client->ops->say(client, conn,
322 "Received unsupported server %s public key",
323 ctx->sock->hostname);
325 client->ops->say(client, conn,
326 "Error during key exchange protocol with server %s",
327 ctx->sock->hostname);
329 protocol->state = SILC_PROTOCOL_STATE_ERROR;
330 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
334 /* Send Ok to the other end. We will end the protocol as server
335 sends Ok to us when we will take the new keys into use. */
336 if (ctx->responder == FALSE)
337 silc_ske_end(ctx->ske, ctx->send_packet, context);
339 /* End the protocol on the next round */
340 protocol->state = SILC_PROTOCOL_STATE_END;
344 case SILC_PROTOCOL_STATE_END:
349 SilcSKEKeyMaterial *keymat;
350 int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
351 int hash_len = ctx->ske->prop->hash->hash->hash_len;
353 /* Process the key material */
354 keymat = silc_calloc(1, sizeof(*keymat));
355 status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
357 if (status != SILC_SKE_STATUS_OK) {
358 protocol->state = SILC_PROTOCOL_STATE_ERROR;
359 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
360 silc_ske_free_key_material(keymat);
363 ctx->keymat = keymat;
365 /* Send Ok to the other end if we are responder. If we are initiator
366 we have sent this already. */
367 if (ctx->responder == TRUE)
368 silc_ske_end(ctx->ske, ctx->send_packet, context);
370 /* Unregister the timeout task since the protocol has ended.
371 This was the timeout task to be executed if the protocol is
372 not completed fast enough. */
373 if (ctx->timeout_task)
374 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
376 /* Protocol has ended, call the final callback */
377 if (protocol->final_callback)
378 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
380 silc_protocol_free(protocol);
384 case SILC_PROTOCOL_STATE_ERROR:
386 * Error during protocol
389 /* Send abort notification */
390 silc_ske_abort(ctx->ske, ctx->ske->status,
391 ctx->send_packet, context);
393 /* On error the final callback is always called. */
394 if (protocol->final_callback)
395 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
397 silc_protocol_free(protocol);
400 case SILC_PROTOCOL_STATE_FAILURE:
402 * Received failure from remote.
405 /* Unregister the timeout task since the protocol has ended.
406 This was the timeout task to be executed if the protocol is
407 not completed fast enough. */
408 if (ctx->timeout_task)
409 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
411 /* On error the final callback is always called. */
412 if (protocol->final_callback)
413 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
415 silc_protocol_free(protocol);
417 case SILC_PROTOCOL_STATE_UNKNOWN:
423 * Connection Authentication protocol functions
426 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
428 SilcProtocol protocol = (SilcProtocol)context;
429 SilcClientConnAuthInternalContext *ctx =
430 (SilcClientConnAuthInternalContext *)protocol->context;
431 SilcClient client = (SilcClient)ctx->client;
432 SilcClientConnection conn = ctx->sock->user_data;
434 SILC_LOG_DEBUG(("Start"));
436 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
437 protocol->state = SILC_PROTOCOL_STATE_START;
439 switch(protocol->state) {
440 case SILC_PROTOCOL_STATE_START:
443 * Start protocol. We send authentication data to the server
444 * to be authenticated.
448 unsigned char *auth_data = NULL;
449 unsigned int auth_data_len = 0;
451 switch(ctx->auth_meth) {
453 /* No authentication required */
456 case SILC_AUTH_PASSWORD:
457 /* Password authentication */
458 if (ctx->auth_data && ctx->auth_data_len) {
459 auth_data = ctx->auth_data;
460 auth_data_len = ctx->auth_data_len;
464 client->ops->say(client, conn,
465 "Password authentication required by server %s",
466 ctx->sock->hostname);
467 auth_data = client->ops->ask_passphrase(client, conn);
468 auth_data_len = strlen(auth_data);
471 case SILC_AUTH_PUBLIC_KEY:
476 payload_len = 4 + auth_data_len;
477 packet = silc_buffer_alloc(payload_len);
478 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
479 silc_buffer_format(packet,
480 SILC_STR_UI_SHORT(payload_len),
481 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
482 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
485 /* Send the packet to server */
486 silc_client_packet_send(client, ctx->sock,
487 SILC_PACKET_CONNECTION_AUTH,
489 packet->data, packet->len, TRUE);
492 memset(auth_data, 0, auth_data_len);
493 silc_free(auth_data);
495 silc_buffer_free(packet);
497 /* Next state is end of protocol */
498 protocol->state = SILC_PROTOCOL_STATE_END;
502 case SILC_PROTOCOL_STATE_END:
505 * End protocol. Nothing special to be done here.
508 /* Protocol has ended, call the final callback */
509 if (protocol->final_callback)
510 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
512 silc_protocol_free(protocol);
516 case SILC_PROTOCOL_STATE_ERROR:
519 * Error. Send notify to remote.
521 unsigned char error[4];
523 SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
525 /* Error in protocol. Send FAILURE packet. Although I don't think
526 this could ever happen on client side. */
527 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
528 NULL, 0, NULL, NULL, error, 4, TRUE);
530 /* On error the final callback is always called. */
531 if (protocol->final_callback)
532 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
534 silc_protocol_free(protocol);
537 case SILC_PROTOCOL_STATE_FAILURE:
539 * Received failure from remote.
542 /* On error the final callback is always called. */
543 if (protocol->final_callback)
544 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
546 silc_protocol_free(protocol);
549 case SILC_PROTOCOL_STATE_UNKNOWN:
554 /* Registers protocols used in client */
556 void silc_client_protocols_register(void)
558 silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
559 silc_client_protocol_connection_auth);
560 silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
561 silc_client_protocol_key_exchange);
564 /* Unregisters protocols */
566 void silc_client_protocols_unregister(void)
568 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
569 silc_client_protocol_connection_auth);
570 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
571 silc_client_protocol_key_exchange);