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. */
59 silc_client_protocol_ke_verify_key(SilcSKE ske,
60 unsigned char *pk_data,
62 SilcSKEPKType pk_type,
65 SilcProtocol protocol = (SilcProtocol)context;
66 SilcClientKEInternalContext *ctx =
67 (SilcClientKEInternalContext *)protocol->context;
68 SilcClient client = (SilcClient)ctx->client;
70 SILC_LOG_DEBUG(("Start"));
72 /* Verify server key from user. */
73 if (!client->ops->verify_server_key(client, ctx->sock->user_data,
74 pk_data, pk_len, pk_type))
75 return SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
77 return SILC_SKE_STATUS_OK;
80 /* Sets the negotiated key material into use for particular connection. */
82 void silc_client_protocol_ke_set_keys(SilcSKE ske,
83 SilcSocketConnection sock,
84 SilcSKEKeyMaterial *keymat,
90 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
92 SILC_LOG_DEBUG(("Setting new keys into use"));
94 /* Allocate cipher to be used in the communication */
95 silc_cipher_alloc(cipher->cipher->name, &conn->send_key);
96 silc_cipher_alloc(cipher->cipher->name, &conn->receive_key);
98 conn->send_key->cipher->set_key(conn->send_key->context,
100 keymat->enc_key_len);
101 conn->send_key->set_iv(conn->send_key, keymat->send_iv);
102 conn->receive_key->cipher->set_key(conn->receive_key->context,
103 keymat->receive_enc_key,
104 keymat->enc_key_len);
105 conn->receive_key->set_iv(conn->receive_key, keymat->receive_iv);
107 /* Allocate PKCS to be used */
109 /* XXX Do we ever need to allocate PKCS for the connection??
110 If yes, we need to change KE protocol to get the initiators
112 silc_pkcs_alloc(pkcs->pkcs->name, &conn->public_Key);
113 silc_pkcs_set_public_key(conn->public_key, ske->ke2_payload->pk_data,
114 ske->ke2_payload->pk_len);
117 /* Save HMAC key to be used in the communication. */
118 silc_hmac_alloc(hmac->hmac->name, NULL, &conn->hmac);
119 silc_hmac_set_key(conn->hmac, keymat->hmac_key, keymat->hmac_key_len);
122 /* Checks the version string of the server. */
124 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
127 SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
128 SilcClient client = (SilcClient)ske->user_data;
129 SilcSKEStatus status = SILC_SKE_STATUS_OK;
131 /* Check for initial version string */
132 if (!strstr(version, "SILC-1.0-"))
133 status = SILC_SKE_STATUS_BAD_VERSION;
135 /* Check software version */
137 if (len < strlen(silc_version_string))
138 status = SILC_SKE_STATUS_BAD_VERSION;
140 /* XXX for now there is no other tests due to the abnormal version
141 string that is used */
143 if (status != SILC_SKE_STATUS_OK)
144 client->ops->say(client, conn,
145 "We don't support server version `%s'", version);
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 SilcClientConnection conn = ctx->sock->user_data;
160 SilcSKEStatus status = 0;
162 SILC_LOG_DEBUG(("Start"));
164 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
165 protocol->state = SILC_PROTOCOL_STATE_START;
167 switch(protocol->state) {
168 case SILC_PROTOCOL_STATE_START:
175 /* Allocate Key Exchange object */
176 ske = silc_ske_alloc();
178 ske->rng = client->rng;
179 ske->user_data = (void *)client;
181 if (ctx->responder == TRUE) {
182 /* Start the key exchange by processing the received security
183 properties packet from initiator. */
184 status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
186 ctx->packet->buffer, NULL, NULL);
188 SilcSKEStartPayload *start_payload;
190 /* Assemble security properties. */
191 silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE,
195 /* Start the key exchange by sending our security properties
196 to the remote end. */
197 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
203 if (status != SILC_SKE_STATUS_OK) {
204 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
206 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
209 protocol->state = SILC_PROTOCOL_STATE_ERROR;
210 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
214 /* Advance protocol state and call the next state if we are responder */
216 if (ctx->responder == TRUE)
217 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
225 if (ctx->responder == TRUE) {
226 /* Sends the selected security properties to the initiator. */
228 silc_ske_responder_phase_1(ctx->ske,
229 ctx->ske->start_payload,
233 /* Call Phase-1 function. This processes the Key Exchange Start
234 paylaod reply we just got from the responder. The callback
235 function will receive the processed payload where we will
237 status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer,
241 if (status != SILC_SKE_STATUS_OK) {
242 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
244 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
247 protocol->state = SILC_PROTOCOL_STATE_ERROR;
248 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
252 /* Advance protocol state and call next state if we are initiator */
254 if (ctx->responder == FALSE)
255 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
263 if (ctx->responder == TRUE) {
264 /* Process the received Key Exchange 1 Payload packet from
265 the initiator. This also creates our parts of the Diffie
266 Hellman algorithm. */
267 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer,
270 /* Call the Phase-2 function. This creates Diffie Hellman
271 key exchange parameters and sends our public part inside
272 Key Exhange 1 Payload to the responder. */
274 silc_ske_initiator_phase_2(ctx->ske,
280 if (status != SILC_SKE_STATUS_OK) {
281 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
283 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
286 protocol->state = SILC_PROTOCOL_STATE_ERROR;
287 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
291 /* Advance protocol state and call the next state if we are responder */
293 if (ctx->responder == TRUE)
294 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
302 if (ctx->responder == TRUE) {
303 /* This creates the key exchange material and sends our
304 public parts to the initiator inside Key Exchange 2 Payload. */
306 silc_ske_responder_finish(ctx->ske,
307 client->public_key, client->private_key,
308 SILC_SKE_PK_TYPE_SILC,
313 /* Finish the protocol. This verifies the Key Exchange 2 payload
314 sent by responder. */
315 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
316 silc_client_protocol_ke_verify_key,
317 context, NULL, NULL);
320 if (status != SILC_SKE_STATUS_OK) {
322 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
323 client->ops->say(client, conn,
324 "Received unsupported server %s public key",
325 ctx->sock->hostname);
327 client->ops->say(client, conn,
328 "Error during key exchange protocol with server %s",
329 ctx->sock->hostname);
331 protocol->state = SILC_PROTOCOL_STATE_ERROR;
332 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
336 /* Send Ok to the other end. We will end the protocol as server
337 sends Ok to us when we will take the new keys into use. */
338 if (ctx->responder == FALSE)
339 silc_ske_end(ctx->ske, ctx->send_packet, context);
341 /* End the protocol on the next round */
342 protocol->state = SILC_PROTOCOL_STATE_END;
346 case SILC_PROTOCOL_STATE_END:
351 SilcSKEKeyMaterial *keymat;
352 int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
353 int hash_len = ctx->ske->prop->hash->hash->hash_len;
355 /* Process the key material */
356 keymat = silc_calloc(1, sizeof(*keymat));
357 status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
359 if (status != SILC_SKE_STATUS_OK) {
360 protocol->state = SILC_PROTOCOL_STATE_ERROR;
361 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
362 silc_ske_free_key_material(keymat);
365 ctx->keymat = keymat;
367 /* Send Ok to the other end if we are responder. If we are initiator
368 we have sent this already. */
369 if (ctx->responder == TRUE)
370 silc_ske_end(ctx->ske, ctx->send_packet, context);
372 /* Unregister the timeout task since the protocol has ended.
373 This was the timeout task to be executed if the protocol is
374 not completed fast enough. */
375 if (ctx->timeout_task)
376 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
378 /* Protocol has ended, call the final callback */
379 if (protocol->final_callback)
380 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
382 silc_protocol_free(protocol);
386 case SILC_PROTOCOL_STATE_ERROR:
388 * Error during protocol
391 /* Send abort notification */
392 silc_ske_abort(ctx->ske, ctx->ske->status,
393 ctx->send_packet, context);
395 /* On error the final callback is always called. */
396 if (protocol->final_callback)
397 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
399 silc_protocol_free(protocol);
402 case SILC_PROTOCOL_STATE_FAILURE:
404 * Received failure from remote.
407 /* Unregister the timeout task since the protocol has ended.
408 This was the timeout task to be executed if the protocol is
409 not completed fast enough. */
410 if (ctx->timeout_task)
411 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
413 /* On error the final callback is always called. */
414 if (protocol->final_callback)
415 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
417 silc_protocol_free(protocol);
419 case SILC_PROTOCOL_STATE_UNKNOWN:
425 * Connection Authentication protocol functions
428 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
430 SilcProtocol protocol = (SilcProtocol)context;
431 SilcClientConnAuthInternalContext *ctx =
432 (SilcClientConnAuthInternalContext *)protocol->context;
433 SilcClient client = (SilcClient)ctx->client;
434 SilcClientConnection conn = ctx->sock->user_data;
436 SILC_LOG_DEBUG(("Start"));
438 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
439 protocol->state = SILC_PROTOCOL_STATE_START;
441 switch(protocol->state) {
442 case SILC_PROTOCOL_STATE_START:
445 * Start protocol. We send authentication data to the server
446 * to be authenticated.
450 unsigned char *auth_data = NULL;
451 unsigned int auth_data_len = 0;
453 switch(ctx->auth_meth) {
455 /* No authentication required */
458 case SILC_AUTH_PASSWORD:
459 /* Password authentication */
460 if (ctx->auth_data && ctx->auth_data_len) {
461 auth_data = ctx->auth_data;
462 auth_data_len = ctx->auth_data_len;
466 client->ops->say(client, conn,
467 "Password authentication required by server %s",
468 ctx->sock->hostname);
469 auth_data = client->ops->ask_passphrase(client, conn);
470 auth_data_len = strlen(auth_data);
473 case SILC_AUTH_PUBLIC_KEY:
478 payload_len = 4 + auth_data_len;
479 packet = silc_buffer_alloc(payload_len);
480 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
481 silc_buffer_format(packet,
482 SILC_STR_UI_SHORT(payload_len),
483 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
484 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
487 /* Send the packet to server */
488 silc_client_packet_send(client, ctx->sock,
489 SILC_PACKET_CONNECTION_AUTH,
491 packet->data, packet->len, TRUE);
494 memset(auth_data, 0, auth_data_len);
495 silc_free(auth_data);
497 silc_buffer_free(packet);
499 /* Next state is end of protocol */
500 protocol->state = SILC_PROTOCOL_STATE_END;
504 case SILC_PROTOCOL_STATE_END:
507 * End protocol. Nothing special to be done here.
510 /* Protocol has ended, call the final callback */
511 if (protocol->final_callback)
512 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
514 silc_protocol_free(protocol);
518 case SILC_PROTOCOL_STATE_ERROR:
521 * Error. Send notify to remote.
523 unsigned char error[4];
525 SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
527 /* Error in protocol. Send FAILURE packet. Although I don't think
528 this could ever happen on client side. */
529 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
530 NULL, 0, NULL, NULL, error, 4, TRUE);
532 /* On error the final callback is always called. */
533 if (protocol->final_callback)
534 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
536 silc_protocol_free(protocol);
539 case SILC_PROTOCOL_STATE_FAILURE:
541 * Received failure from remote.
544 /* On error the final callback is always called. */
545 if (protocol->final_callback)
546 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
548 silc_protocol_free(protocol);
551 case SILC_PROTOCOL_STATE_UNKNOWN:
556 /* Registers protocols used in client */
558 void silc_client_protocols_register(void)
560 silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
561 silc_client_protocol_connection_auth);
562 silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
563 silc_client_protocol_key_exchange);
566 /* Unregisters protocols */
568 void silc_client_protocols_unregister(void)
570 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
571 silc_client_protocol_connection_auth);
572 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
573 silc_client_protocol_key_exchange);