5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2014 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
22 #include "silcclient.h"
23 #include "client_internal.h"
25 /************************** Private Message Send ****************************/
27 /* Sends private message to remote client. */
29 SilcBool silc_client_send_private_message(SilcClient client,
30 SilcClientConnection conn,
31 SilcClientEntry client_entry,
32 SilcMessageFlags flags,
41 if (silc_unlikely(!client || !conn || !client_entry))
43 if (silc_unlikely(flags & SILC_MESSAGE_FLAG_SIGNED && !hash))
45 if (silc_unlikely(conn->internal->disconnected))
48 SILC_LOG_DEBUG(("Sending private message"));
50 /* Auto-negotiate private message key (AKE) if there is no key or
51 it's time to rekey. */
52 if (!client->internal->params->dont_autoneg_prvmsg_keys &&
53 !client_entry->internal.no_ake && client_entry != conn->local_entry &&
54 (!client_entry->internal.send_key ||
55 (client_entry->internal.ake_rekey <= silc_time() ||
56 client_entry->internal.ake_generation !=
57 conn->internal->ake_generation))) {
58 return silc_client_autoneg_private_message_key(
59 client, conn, client_entry, NULL,
60 flags, hash, data, data_len);
63 sid.type = SILC_ID_CLIENT;
64 sid.u.client_id = *conn->local_id;
65 rid.type = SILC_ID_CLIENT;
66 rid.u.client_id = client_entry->id;
68 /* Encode private message payload */
70 silc_message_payload_encode(flags, data, data_len,
71 (!client_entry->internal.send_key ? FALSE :
72 !client_entry->internal.generated),
73 TRUE, client_entry->internal.send_key,
74 client_entry->internal.hmac_send,
75 client->rng, NULL, conn->private_key,
76 hash, &sid, &rid, NULL);
77 if (silc_unlikely(!buffer)) {
78 SILC_LOG_ERROR(("Error encoding private message"));
82 /* Send the private message packet */
83 ret = silc_packet_send_ext(conn->stream, SILC_PACKET_PRIVATE_MESSAGE,
84 client_entry->internal.send_key ?
85 SILC_PACKET_FLAG_PRIVMSG_KEY : 0,
86 0, NULL, SILC_ID_CLIENT, &client_entry->id,
87 silc_buffer_datalen(buffer), NULL, NULL);
89 silc_buffer_free(buffer);
93 /************************* Private Message Receive **************************/
95 /* Client resolving callback. Continues with the private message processing */
97 static void silc_client_private_message_resolved(SilcClient client,
98 SilcClientConnection conn,
103 /* If no client found, ignore the private message, a silent error */
105 silc_fsm_next(context, silc_client_private_message_error);
107 /* Continue processing the private message packet */
108 SILC_FSM_CALL_CONTINUE(context);
111 /* Private message received. */
113 SILC_FSM_STATE(silc_client_private_message)
115 SilcClientConnection conn = fsm_context;
116 SilcClient client = conn->client;
117 SilcPacket packet = state_context;
118 SilcMessagePayload payload = NULL;
119 SilcClientID remote_id;
120 SilcClientEntry remote_client = NULL;
121 SilcMessageFlags flags;
122 unsigned char *message;
123 SilcUInt32 message_len;
125 SILC_LOG_DEBUG(("Received private message"));
127 if (silc_unlikely(packet->src_id_type != SILC_ID_CLIENT)) {
128 /** Invalid packet */
129 silc_fsm_next(fsm, silc_client_private_message_error);
130 return SILC_FSM_CONTINUE;
133 if (silc_unlikely(!silc_id_str2id(packet->src_id, packet->src_id_len,
134 SILC_ID_CLIENT, &remote_id,
135 sizeof(remote_id)))) {
136 /** Invalid source ID */
137 silc_fsm_next(fsm, silc_client_private_message_error);
138 return SILC_FSM_CONTINUE;
141 /* Check whether we know this client already */
142 remote_client = silc_client_get_client_by_id(client, conn, &remote_id);
143 if (!remote_client || !remote_client->nickname[0]) {
144 /** Resolve client info */
145 silc_client_unref_client(client, conn, remote_client);
146 SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
147 client, conn, &remote_id, NULL,
148 silc_client_private_message_resolved,
153 if (silc_unlikely(packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY &&
154 !remote_client->internal.receive_key &&
155 !remote_client->internal.hmac_receive)) {
157 /* Kludge to check if the message has SKE packet inside, and then start
158 key exchange protocol. Remove this once AKE support is everywhere. */
159 payload = silc_message_payload_parse(silc_buffer_datalen(&packet->buffer),
160 TRUE, FALSE, NULL, NULL,
161 packet->src_id, packet->src_id_len,
162 packet->dst_id, packet->dst_id_len,
167 flags = silc_message_get_flags(payload);
168 if (flags & SILC_MESSAGE_FLAG_PACKET &&
169 silc_client_autoneg_private_message_key(client, conn, remote_client,
170 packet, 0, NULL, NULL, 0))
176 /* Parse the payload and decrypt it also if private message key is set */
178 silc_message_payload_parse(silc_buffer_datalen(&packet->buffer),
179 TRUE, !remote_client->internal.generated,
180 remote_client->internal.receive_key,
181 remote_client->internal.hmac_receive,
182 packet->src_id, packet->src_id_len,
183 packet->dst_id, packet->dst_id_len,
185 if (silc_unlikely(!payload)) {
186 /* Private message key is set but the sender may have removed it,
187 try to parse without it. */
188 if (remote_client->internal.receive_key) {
189 SILC_LOG_DEBUG(("Parse payload without using private message key"));
191 silc_message_payload_parse(silc_buffer_datalen(&packet->buffer),
192 TRUE, FALSE, NULL, NULL,
193 packet->src_id, packet->src_id_len,
194 packet->dst_id, packet->dst_id_len,
201 flags = silc_message_get_flags(payload);
203 /* If message contains SILC packet, process the packet here */
204 if (flags & SILC_MESSAGE_FLAG_PACKET) {
205 if (silc_client_autoneg_private_message_key(client, conn, remote_client,
206 packet, 0, NULL, NULL, 0))
211 message = silc_message_get_data(payload, &message_len);
213 /* Pass the private message to application */
214 client->internal->ops->private_message(client, conn, remote_client, payload,
215 flags, message, message_len);
217 /* See if we are away (gone). If we are away we will reply to the
218 sender with the set away message. */
219 if (conn->internal->away_message &&
220 !(flags & SILC_MESSAGE_FLAG_NOREPLY)) {
221 /* If it's me, ignore */
222 if (SILC_ID_CLIENT_COMPARE(&remote_id, conn->local_id))
225 /* Send the away message */
226 silc_client_send_private_message(client, conn, remote_client,
227 SILC_MESSAGE_FLAG_AUTOREPLY |
228 SILC_MESSAGE_FLAG_NOREPLY, NULL,
229 conn->internal->away_message,
230 strlen(conn->internal->away_message));
234 /** Packet processed */
236 silc_packet_free(packet);
237 silc_client_unref_client(client, conn, remote_client);
239 silc_message_payload_free(payload);
240 return SILC_FSM_FINISH;
243 /* Private message error. */
245 SILC_FSM_STATE(silc_client_private_message_error)
247 SilcPacket packet = state_context;
248 silc_packet_free(packet);
249 return SILC_FSM_FINISH;
252 /* Initialize private message waiter for the `conn' connection. */
254 SilcBool silc_client_private_message_wait_init(SilcClient client,
255 SilcClientConnection conn,
256 SilcClientEntry client_entry)
260 if (client_entry->internal.prv_waiter)
263 /* We want SILC_PACKET_PRIVATE_MESSAGE packets from this source ID. */
264 id.type = SILC_ID_CLIENT;
265 id.u.client_id = client_entry->id;
267 client_entry->internal.prv_waiter =
268 silc_packet_wait_init(conn->stream, &id, SILC_PACKET_PRIVATE_MESSAGE, -1);
269 if (!client_entry->internal.prv_waiter)
275 /* Uninitializes private message waiter. */
277 void silc_client_private_message_wait_uninit(SilcClient client,
278 SilcClientConnection conn,
279 SilcClientEntry client_entry)
281 if (!client_entry->internal.prv_waiter)
283 silc_packet_wait_uninit(client_entry->internal.prv_waiter, conn->stream);
284 client_entry->internal.prv_waiter = NULL;
287 /* Blocks the calling process or thread until private message has been
288 received from the specified client. */
290 SilcBool silc_client_private_message_wait(SilcClient client,
291 SilcClientConnection conn,
292 SilcClientEntry client_entry,
293 SilcMessagePayload *payload)
297 if (!client_entry->internal.prv_waiter)
300 /* Block until private message arrives */
302 if ((silc_packet_wait(client_entry->internal.prv_waiter, 0, &packet)) < 0)
305 /* Parse the payload and decrypt it also if private message key is set */
307 silc_message_payload_parse(silc_buffer_data(&packet->buffer),
308 silc_buffer_len(&packet->buffer),
309 TRUE, !client_entry->internal.generated,
310 client_entry->internal.receive_key,
311 client_entry->internal.hmac_receive,
312 packet->src_id, packet->src_id_len,
313 packet->dst_id, packet->dst_id_len,
316 silc_packet_free(packet);
323 silc_packet_free(packet);
327 /*************************** Private Message Key ****************************/
329 /* Sends private message key request. Sender of this packet is initiator
330 when setting the private message key. */
333 silc_client_send_private_message_key_request(SilcClient client,
334 SilcClientConnection conn,
335 SilcClientEntry client_entry)
337 const char *cipher, *hmac;
339 SILC_LOG_DEBUG(("Sending private message key request"));
341 cipher = silc_cipher_get_name(client_entry->internal.send_key);
342 hmac = silc_hmac_get_name(client_entry->internal.hmac_send);
344 /* Send the packet */
345 return silc_packet_send_va_ext(conn->stream,
346 SILC_PACKET_PRIVATE_MESSAGE_KEY,
347 0, 0, NULL, SILC_ID_CLIENT,
348 &client_entry->id, NULL, NULL,
349 SILC_STR_UI_SHORT(strlen(cipher)),
350 SILC_STR_DATA(cipher, strlen(cipher)),
351 SILC_STR_UI_SHORT(strlen(hmac)),
352 SILC_STR_DATA(hmac, strlen(hmac)),
356 /* Client resolving callback. Here we simply mark that we are the responder
357 side of this private message key request. */
359 static void silc_client_private_message_key_cb(SilcClient client,
360 SilcClientConnection conn,
365 SilcFSMThread thread = context;
366 SilcPacket packet = silc_fsm_get_state_context(thread);
367 unsigned char *cipher = NULL, *hmac = NULL;
368 SilcClientEntry client_entry;
372 silc_packet_free(packet);
373 silc_fsm_finish(thread);
377 /* Parse the private message key payload */
378 ret = silc_buffer_unformat(&packet->buffer,
379 SILC_STR_UI16_STRING_ALLOC(&cipher),
380 SILC_STR_UI16_STRING_ALLOC(&hmac),
385 /* Mark that we are responder */
386 client_entry = silc_dlist_get(clients);
388 client_entry->internal.prv_resp = TRUE;
390 /* XXX we should notify application that remote wants to set up the
391 static key. And we should tell if we already have key with remote.
392 Application should return status telling whether to delete the key
398 silc_packet_free(packet);
399 silc_fsm_finish(thread);
402 /* Processes incoming Private Message Key payload to indicate that the
403 sender whishes to set up a static private message key. */
405 SILC_FSM_STATE(silc_client_private_message_key)
407 SilcClientConnection conn = fsm_context;
408 SilcClient client = conn->client;
409 SilcPacket packet = state_context;
410 SilcClientID remote_id;
412 if (packet->src_id_type != SILC_ID_CLIENT) {
413 silc_packet_free(packet);
414 return SILC_FSM_FINISH;
417 if (!silc_id_str2id(packet->src_id, packet->src_id_len, SILC_ID_CLIENT,
418 &remote_id, sizeof(remote_id))) {
419 silc_packet_free(packet);
420 return SILC_FSM_FINISH;
423 /* Always resolve the remote client. The actual packet is processed
424 in the resolving callback. */
425 SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
426 client, conn, &remote_id, NULL,
427 silc_client_private_message_key_cb,
431 /* Adds new private message key to `client_entry'. If we are setting this
432 before receiving request for it from `client_entry' we will send the
433 request to the client. Otherwise, we are responder side. */
435 SilcBool silc_client_add_private_message_key(SilcClient client,
436 SilcClientConnection conn,
437 SilcClientEntry client_entry,
443 SilcSKEKeyMaterial keymat;
446 if (!client || !client_entry)
449 /* Return FALSE if key already set */
450 if (client_entry->internal.send_key && client_entry->internal.receive_key)
454 cipher = SILC_DEFAULT_CIPHER;
456 hmac = SILC_DEFAULT_HMAC;
458 /* Check the requested cipher and HMAC */
459 if (!silc_cipher_is_supported(cipher))
461 if (!silc_hmac_is_supported(hmac))
465 client_entry->internal.key = silc_memdup(key, key_len);
466 client_entry->internal.key_len = key_len;
468 /* Produce the key material as the protocol defines */
469 keymat = silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
470 conn->internal->sha1hash);
474 /* Set the key into use */
475 ret = silc_client_add_private_message_key_ske(client, conn, client_entry,
476 cipher, hmac, keymat);
477 client_entry->internal.generated = FALSE;
479 /* Free the key material */
480 silc_ske_free_key_material(keymat);
482 /* If we are setting the key without a request from the remote client,
483 we will send request to remote. */
484 if (!client_entry->internal.prv_resp)
485 silc_client_send_private_message_key_request(client, conn, client_entry);
490 /* Same as above but takes the key material from the SKE key material
493 SilcBool silc_client_add_private_message_key_ske(SilcClient client,
494 SilcClientConnection conn,
495 SilcClientEntry client_entry,
498 SilcSKEKeyMaterial keymat)
500 if (!client || !client_entry)
503 /* Return FALSE if key already set */
504 if (client_entry->internal.send_key && client_entry->internal.receive_key)
508 cipher = SILC_DEFAULT_CIPHER;
510 hmac = SILC_DEFAULT_HMAC;
512 /* Check the requested cipher and HMAC */
513 if (!silc_cipher_is_supported(cipher))
515 if (!silc_hmac_is_supported(hmac))
518 client_entry->internal.generated = TRUE;
519 client_entry->internal.no_ake = TRUE;
521 /* Allocate the cipher and HMAC */
522 if (!silc_cipher_alloc(cipher, &client_entry->internal.send_key))
524 if (!silc_cipher_alloc(cipher, &client_entry->internal.receive_key))
526 if (!silc_hmac_alloc(hmac, NULL, &client_entry->internal.hmac_send))
528 if (!silc_hmac_alloc(hmac, NULL, &client_entry->internal.hmac_receive))
532 if (client_entry->internal.prv_resp) {
533 silc_cipher_set_key(client_entry->internal.send_key,
534 keymat->receive_enc_key,
535 keymat->enc_key_len, TRUE);
536 silc_cipher_set_iv(client_entry->internal.send_key,
538 silc_cipher_set_key(client_entry->internal.receive_key,
539 keymat->send_enc_key,
540 keymat->enc_key_len, FALSE);
541 silc_cipher_set_iv(client_entry->internal.receive_key, keymat->send_iv);
542 silc_hmac_set_key(client_entry->internal.hmac_send,
543 keymat->receive_hmac_key,
544 keymat->hmac_key_len);
545 silc_hmac_set_key(client_entry->internal.hmac_receive,
546 keymat->send_hmac_key,
547 keymat->hmac_key_len);
549 silc_cipher_set_key(client_entry->internal.send_key,
550 keymat->send_enc_key,
551 keymat->enc_key_len, TRUE);
552 silc_cipher_set_iv(client_entry->internal.send_key,
554 silc_cipher_set_key(client_entry->internal.receive_key,
555 keymat->receive_enc_key,
556 keymat->enc_key_len, FALSE);
557 silc_cipher_set_iv(client_entry->internal.receive_key, keymat->receive_iv);
558 silc_hmac_set_key(client_entry->internal.hmac_send,
559 keymat->send_hmac_key,
560 keymat->hmac_key_len);
561 silc_hmac_set_key(client_entry->internal.hmac_receive,
562 keymat->receive_hmac_key,
563 keymat->hmac_key_len);
569 /* Removes the private message from the library. The key won't be used
570 after this to protect the private messages with the remote `client_entry'
571 client. Returns FALSE on error, TRUE otherwise. */
573 SilcBool silc_client_del_private_message_key(SilcClient client,
574 SilcClientConnection conn,
575 SilcClientEntry client_entry)
577 if (!client || !client_entry)
580 if (!client_entry->internal.send_key && !client_entry->internal.receive_key)
583 silc_cipher_free(client_entry->internal.send_key);
584 silc_cipher_free(client_entry->internal.receive_key);
586 if (client_entry->internal.key) {
587 memset(client_entry->internal.key, 0, client_entry->internal.key_len);
588 silc_free(client_entry->internal.key);
591 client_entry->internal.send_key = NULL;
592 client_entry->internal.receive_key = NULL;
593 client_entry->internal.key = NULL;
594 client_entry->internal.prv_resp = FALSE;
599 /* Returns array of set private message keys associated to the connection
600 `conn'. Returns allocated SilcPrivateMessageKeys array and the array
601 count to the `key_count' argument. The array must be freed by the caller
602 by calling the silc_client_free_private_message_keys function. Note:
603 the keys returned in the array is in raw format. It might not be desired
604 to show the keys as is. The application might choose not to show the keys
605 at all or to show the fingerprints of the keys. */
607 SilcPrivateMessageKeys
608 silc_client_list_private_message_keys(SilcClient client,
609 SilcClientConnection conn,
610 SilcUInt32 *key_count)
612 SilcPrivateMessageKeys keys;
613 SilcUInt32 count = 0;
615 SilcIDCacheEntry id_cache;
616 SilcClientEntry entry;
618 if (!client || !conn)
621 silc_mutex_lock(conn->internal->lock);
622 if (!silc_idcache_get_all(conn->internal->client_cache, &list)) {
623 silc_mutex_unlock(conn->internal->lock);
627 keys = silc_calloc(silc_list_count(list), sizeof(*keys));
629 silc_mutex_unlock(conn->internal->lock);
633 silc_list_start(list);
634 while ((id_cache = silc_list_get(list))) {
635 entry = id_cache->context;
636 if (entry->internal.send_key) {
637 keys[count].client_entry = entry;
638 keys[count].cipher = (char *)silc_cipher_get_name(entry->internal.
640 keys[count].key = (entry->internal.generated == FALSE ?
641 entry->internal.key : NULL);
642 keys[count].key_len = (entry->internal.generated == FALSE ?
643 entry->internal.key_len : 0);
648 silc_mutex_unlock(conn->internal->lock);
656 /* Frees the SilcPrivateMessageKeys array returned by the function
657 silc_client_list_private_message_keys. */
659 void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
660 SilcUInt32 key_count)
665 /* Return private message key from the client entry. */
668 silc_client_private_message_key_is_set(SilcClient client,
669 SilcClientConnection conn,
670 SilcClientEntry client_entry)
672 return client_entry->internal.send_key != NULL;
675 /********************* Private Message Key Autoneg (AKE) ********************/
677 /* Private message key auto-negotiation context */
678 struct SilcClientAutonegMessageKeyStruct {
679 SilcClientConnection conn; /* Connection to server */
680 SilcSKE ske; /* SKE with remote client */
681 SilcAsyncOperation ske_op; /* SKE operation */
682 SilcStream stream; /* PRIVATE_MESSAGE stream */
683 SilcPacketStream ske_stream; /* Packet stream for SKE (inside
684 the PRIVATE_MESSAGE stream) */
685 SilcDList messages; /* Message queue */
686 SilcHash hash; /* Initial message hash */
687 SilcPublicKey public_key; /* Remote client public key */
688 SilcVerifyKeyContext verify;
689 SilcSKEParamsStruct params;
690 SilcUInt32 generation; /* Starting AKE generation */
694 silc_client_autoneg_key_recv_ske(SilcPacketEngine engine,
695 SilcPacketStream stream,
697 void *callback_context,
698 void *stream_context);
700 static const SilcPacketCallbacks autoneg_key_ske_cbs =
702 silc_client_autoneg_key_recv_ske, NULL, NULL
705 /* Destroy auto-negotiation context */
707 static void silc_client_autoneg_key_free(SilcClient client,
708 SilcClientConnection conn,
709 SilcClientEntry client_entry)
711 SilcClientAutonegMessageKey ake = client_entry->internal.ake;
715 silc_async_abort(ake->ske_op, NULL, NULL);
717 silc_ske_free(ake->ske);
718 silc_packet_stream_unlink(ake->ske_stream, &autoneg_key_ske_cbs, NULL);
719 silc_packet_stream_destroy(ake->ske_stream);
721 silc_hash_free(ake->hash);
723 silc_dlist_start(ake->messages);
724 while ((m = silc_dlist_get(ake->messages)) != SILC_LIST_END) {
725 silc_dlist_del(ake->messages, m);
728 silc_dlist_uninit(ake->messages);
730 client_entry->internal.op = NULL;
731 client_entry->internal.ake = NULL;
732 silc_client_unref_client(client, conn, client_entry);
735 ake->verify->aborted = TRUE;
736 else if (ake->public_key)
737 silc_pkcs_public_key_free(ake->public_key);
742 /* Destroy auto-negotiation context */
744 SILC_TASK_CALLBACK(silc_client_autoneg_key_finish)
746 SilcClientEntry client_entry = context;
747 SilcClientAutonegMessageKey ake = client_entry->internal.ake;
748 SilcClientConnection conn = ake->conn;
749 SilcClient client = conn->client;
751 silc_client_autoneg_key_free(client, conn, client_entry);
754 /* Abort callback. This aborts the auto-negotiation and the SKE */
757 silc_client_autoneg_key_abort(SilcAsyncOperation op, void *context)
759 SilcClientEntry client_entry = context;
760 SilcClientAutonegMessageKey ake = client_entry->internal.ake;
761 SilcClientConnection conn = ake->conn;
762 SilcClient client = conn->client;
767 silc_client_autoneg_key_free(client, conn, client_entry);
770 /* SKE packet stream callback. Here we verify that the packets we got
771 from the private message are actually SKE packets for us. */
774 silc_client_autoneg_key_recv_ske(SilcPacketEngine engine,
775 SilcPacketStream stream,
777 void *callback_context,
778 void *stream_context)
780 SilcClientEntry client_entry = stream_context;
781 SilcClientAutonegMessageKey ake = client_entry->internal.ake;
782 SilcClientID remote_id;
784 SILC_LOG_DEBUG(("Packet %p type %d inside private message", packet,
787 /* Take only SKE packets, drop others, no support for anything else */
788 if (packet->type != SILC_PACKET_KEY_EXCHANGE &&
789 packet->type != SILC_PACKET_KEY_EXCHANGE_1 &&
790 packet->type != SILC_PACKET_KEY_EXCHANGE_2 &&
791 packet->type != SILC_PACKET_FAILURE)
794 /* Must be from client to client */
795 if (packet->dst_id_type != SILC_ID_CLIENT ||
796 packet->src_id_type != SILC_ID_CLIENT)
799 if (!silc_id_str2id(packet->src_id, packet->src_id_len, SILC_ID_CLIENT,
800 &remote_id, sizeof(remote_id)))
803 if (!SILC_ID_CLIENT_COMPARE(&client_entry->id, &remote_id)) {
804 /* The packet is not for this client, but it must be */
805 SILC_LOG_DEBUG(("Client ids do not match"));
809 /* Responder is started here if correct packet comes in */
811 if (packet->type == SILC_PACKET_KEY_EXCHANGE) {
812 /* Ignore pre-set proposal */
813 if (ake->params.prop) {
814 silc_ske_group_free(ake->params.prop->group);
815 silc_cipher_free(ake->params.prop->cipher);
816 silc_hash_free(ake->params.prop->hash);
817 silc_hmac_free(ake->params.prop->hmac);
818 silc_pkcs_public_key_free(ake->params.prop->public_key);
819 silc_free(ake->params.prop);
820 ake->params.prop = NULL;
822 } else if (packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
823 SILC_LOG_DEBUG(("Invalid SKE packet for responder"));
824 silc_async_abort(client_entry->internal.op, NULL, NULL);
828 ake->ske_op = silc_ske_responder(ake->ske, ake->ske_stream, &ake->params);
830 silc_async_abort(client_entry->internal.op, NULL, NULL);
834 /* We have to re-inject the packet to SKE stream because SKE wasn't
835 listenning to these packets until silc_ske_responder() was called */
836 silc_packet_stream_inject(ake->ske_stream, packet);
840 /* Packet is ok and is for us, let it pass to SKE */
841 SILC_LOG_DEBUG(("Pass packet %p type %d", packet, packet->type));
845 silc_packet_free(packet);
849 /* Coder callback for actually encoding/decoding the SKE packets inside
852 static SilcBool silc_client_autoneg_key_coder(SilcStream stream,
853 SilcStreamStatus status,
857 SilcBool ret = FALSE;
859 SilcMessagePayload payload = NULL;
860 SilcMessageFlags flags;
862 SilcUInt32 message_len;
865 case SILC_STREAM_CAN_READ:
866 /* Decode private message. We get all private messages here from
867 the remote client while we're doing SKE, so we must take the
869 SILC_LOG_DEBUG(("Decode packet inside private message"));
871 payload = silc_message_payload_parse(silc_buffer_datalen(buffer),
872 TRUE, FALSE, NULL, NULL, NULL, 0,
873 NULL, 0, NULL, FALSE, NULL);
875 SILC_LOG_DEBUG(("Error decoding private message payload"));
879 /* Ignore this message if it's not packet */
880 flags = silc_message_get_flags(payload);
881 if (!(flags & SILC_MESSAGE_FLAG_PACKET)) {
882 SILC_LOG_DEBUG(("Private message doesn't contain packet"));
883 silc_message_payload_free(payload);
887 /* Take the packet */
890 msg = silc_message_get_data(payload, &message_len);
891 silc_buffer_reset(buffer);
892 if (!silc_buffer_enlarge(buffer, message_len)) {
893 silc_message_payload_free(payload);
896 silc_buffer_put(buffer, msg, message_len);
898 silc_message_payload_free(payload);
901 case SILC_STREAM_CAN_WRITE:
902 /* Encode private message */
903 SILC_LOG_DEBUG(("Encode packet inside private message"));
908 silc_message_payload_encode(SILC_MESSAGE_FLAG_PACKET,
909 silc_buffer_datalen(buffer),
910 FALSE, TRUE, NULL, NULL, NULL,
911 NULL, NULL, NULL, NULL, NULL, NULL);
913 SILC_LOG_DEBUG(("Error encoding private message payload"));
917 silc_buffer_reset(buffer);
918 if (!silc_buffer_enlarge(buffer, silc_buffer_len(message)))
920 silc_buffer_put(buffer, silc_buffer_datalen(message));
932 /* Called after application has verified remote client's public key */
935 silc_client_autoneg_key_verify_pubkey_cb(SilcBool success, void *context)
937 SilcVerifyKeyContext verify = context;
938 SilcClientAutonegMessageKey ake = verify->context;
940 SILC_LOG_DEBUG(("Start, verify %p, ake %p", context, ake));
942 /* Call the completion callback back to the SKE */
943 if (!verify->aborted) {
945 verify->completion(verify->ske, success ? SILC_SKE_STATUS_OK :
946 SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
947 verify->completion_context);
949 silc_pkcs_public_key_free(verify->public_key);
955 /* Remote client's public key verification callback */
958 silc_client_autoneg_key_verify_pubkey(SilcSKE ske,
959 SilcPublicKey public_key,
961 SilcSKEVerifyCbCompletion completion,
962 void *completion_context)
964 SilcClientEntry client_entry = context;
965 SilcClientAutonegMessageKey ake = client_entry->internal.ake;
966 SilcClientConnection conn = ake->conn;
967 SilcClient client = conn->client;
968 SilcVerifyKeyContext verify;
970 /* Use public key we cached earlier in AKE for direction verification */
971 if (client_entry->internal.send_key && client_entry->public_key &&
972 silc_pkcs_public_key_compare(public_key, client_entry->public_key)) {
973 SILC_LOG_DEBUG(("Client's cached public key matches"));
974 completion(ske, SILC_SKE_STATUS_OK, completion_context);
978 /* If we provided repository for SKE and we got here the key was not
979 found from the repository. */
980 if (conn->internal->params.repository &&
981 !conn->internal->params.verify_notfound) {
982 completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
987 SILC_LOG_DEBUG(("Verify remote client public key"));
989 ake->public_key = silc_pkcs_public_key_copy(public_key);
990 if (!ake->public_key) {
991 completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
996 verify = silc_calloc(1, sizeof(*verify));
998 completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
1002 verify->public_key = ake->public_key;
1004 verify->completion = completion;
1005 verify->completion_context = completion_context;
1006 verify->context = ake;
1007 ake->verify = verify;
1009 /* Verify public key in application */
1010 client->internal->ops->verify_public_key(
1012 SILC_CONN_CLIENT, ake->public_key,
1013 silc_client_autoneg_key_verify_pubkey_cb,
1017 /* Key exchange protocol completion callback */
1019 static void silc_client_autoneg_key_done(SilcSKE ske,
1020 SilcSKEStatus status,
1021 SilcSKESecurityProperties prop,
1022 SilcSKEKeyMaterial keymat,
1023 SilcSKERekeyMaterial rekey,
1026 SilcClientEntry client_entry = context;
1027 SilcClientAutonegMessageKey ake = client_entry->internal.ake;
1028 SilcClientConnection conn = ake->conn;
1029 SilcClient client = conn->client;
1030 SilcBool initiator = !client_entry->internal.prv_resp;
1031 SilcMessageFlags flags;
1036 conn->context_type = SILC_ID_CLIENT;
1037 conn->client_entry = client_entry;
1039 if (status != SILC_SKE_STATUS_OK) {
1040 /* Key exchange failed */
1041 SILC_LOG_DEBUG(("Error during key exchange: %s (%d)",
1042 silc_ske_map_status(status), status));
1045 if (status != SILC_SKE_STATUS_PROBE_TIMEOUT)
1046 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1047 "Cannot send private message to %s (%s)",
1048 client_entry->nickname,
1049 silc_ske_map_status(status));
1050 else if (client_entry->mode & SILC_UMODE_DETACHED)
1051 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1052 "Cannot send private message to detached "
1053 "client %s", client_entry->nickname);
1054 } else if (status != SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
1055 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1056 "Private message key exchange failed "
1057 "with %s (%s)", client_entry->nickname,
1058 silc_ske_map_status(status));
1061 /* Errors that occur due to user not responding or deciding not to
1062 trust the public key will not cause us to stop trying AKE next time.
1063 Other errors disable AKE to allow communication with other means. */
1064 if (initiator && status != SILC_SKE_STATUS_TIMEOUT &&
1065 status != SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY &&
1066 !(client_entry->mode & SILC_UMODE_DETACHED)) {
1067 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO,
1068 "Cannot auto-negotiate key with %s, "
1069 "messages will be protected with "
1070 "session key", client_entry->nickname);
1072 /* Don't try this again with this client */
1073 client_entry->internal.no_ake = TRUE;
1078 /* Set the new private message key into use */
1079 silc_client_del_private_message_key(client, conn, client_entry);
1080 client_entry->internal.prv_resp = !initiator;
1081 if (!silc_client_add_private_message_key_ske(
1082 client, conn, client_entry,
1083 silc_cipher_get_name(prop->cipher),
1084 silc_hmac_get_name(prop->hmac),
1086 SILC_LOG_DEBUG(("Error adding private message key"));
1088 client->internal->ops->say(client, conn,
1089 SILC_CLIENT_MESSAGE_ERROR,
1090 "Private message key exchange error: "
1093 /* Don't try this again with this client */
1094 client_entry->internal.no_ake = TRUE;
1098 /* Save the public key to client entry */
1099 if (!client_entry->public_key) {
1100 client_entry->public_key = ake->public_key;
1101 ake->public_key = NULL;
1104 /* Rekey periodically */
1105 client_entry->internal.ake_rekey = silc_time() + 300;
1107 client_entry->internal.ake_rekey -= 30;
1108 client_entry->internal.ake_generation = conn->internal->ake_generation;
1109 client_entry->internal.no_ake = FALSE;
1111 SILC_LOG_DEBUG(("AKE completed as %s with %s, rekey in %u secs, "
1112 "generation %u", initiator ? "initiator" : "responder",
1113 client_entry->nickname, 300,
1114 conn->internal->ake_generation));
1116 /* Send queued messages */
1117 silc_dlist_start(ake->messages);
1118 while ((m = silc_dlist_get(ake->messages)) != SILC_LIST_END) {
1119 SILC_GET16_MSB(flags, m->data - 2);
1120 silc_client_send_private_message(client, conn, client_entry,
1122 silc_buffer_datalen(m));
1126 conn->context_type = SILC_ID_NONE;
1127 conn->client_entry = NULL;
1128 silc_schedule_task_add_timeout(client->schedule,
1129 silc_client_autoneg_key_finish,
1130 client_entry, 0, 1);
1133 /* Auto-negotiate private message key with the remote client using the
1134 SKE protocol, which is tunneled through the SILC network inside private
1135 messages shared between the us and the remote client.
1137 This operation is naturally asynchronous and will involve exchanging
1138 multiple messages back and forth. Despite this, we don't run this
1139 operation in own FSM thread here, but instead will use the SKE library
1140 to do the asynchronous operation which we can abort at any time in
1141 case user disconnects.
1143 Messages and packets we receive during this operation will be processed
1144 in the normal connection thread. */
1147 silc_client_autoneg_private_message_key(SilcClient client,
1148 SilcClientConnection conn,
1149 SilcClientEntry client_entry,
1150 SilcPacket initiator_packet,
1151 SilcMessageFlags flags,
1153 unsigned char *data,
1154 SilcUInt32 data_len)
1156 SilcClientAutonegMessageKey ake;
1157 SilcBool initiator = initiator_packet == NULL;
1160 SILC_LOG_DEBUG(("Start private message AKE as %s with %s",
1161 initiator ? "initiator" : "responder",
1162 client_entry->nickname));
1164 if (client_entry->internal.op) {
1165 ake = client_entry->internal.ake;
1167 /* If generation has changed, we must abort this exchange and
1169 if (ake->generation != conn->internal->ake_generation) {
1170 SILC_LOG_DEBUG(("Abort ongoing AKE and start new one"));
1171 silc_async_abort(client_entry->internal.op, NULL, NULL);
1173 SILC_LOG_DEBUG(("AKE is ongoing, queue the message"));
1175 m = silc_buffer_alloc_size(data_len + 2);
1178 SILC_PUT16_MSB(flags, m->data);
1179 silc_buffer_pull(m, 2);
1180 silc_buffer_put(m, data, data_len);
1181 silc_dlist_add(ake->messages, m);
1185 SILC_LOG_DEBUG(("Cannot start AKE, operation %p is ongoing",
1186 client_entry->internal.op));
1191 ake = silc_calloc(1, sizeof(*ake));
1195 ake->generation = conn->internal->ake_generation;
1197 ake->messages = silc_dlist_init();
1201 /* Wrap our packet stream to a generic stream for the private messages
1202 we are going to exchange. We send the packets with packet flag
1203 SILC_PACKET_FLAG_PRIVMSG_KEY which is a lie, but is a way to get
1204 clients which do not support this protocol to ignore these messages.
1205 This kludge should be removed once support is everywhere and
1206 responder should look only for the SILC_MESSAGE_FLAG_PACKET. */
1207 ake->stream = silc_packet_stream_wrap(conn->stream,
1208 SILC_PACKET_PRIVATE_MESSAGE,
1209 SILC_PACKET_FLAG_PRIVMSG_KEY, FALSE,
1211 SILC_ID_CLIENT, &client_entry->id,
1212 silc_client_autoneg_key_coder,
1217 /* Create a new packet stream for the SKE library using the wrapped
1218 stream as the underlaying stream, in effect creating a tunnel to
1219 send SKE packets inside private message packets. */
1220 ake->ske_stream = silc_packet_stream_create(client->internal->packet_engine,
1221 conn->internal->schedule,
1223 if (!ake->ske_stream)
1226 silc_packet_set_context(ake->ske_stream, client_entry);
1227 silc_packet_set_ids(ake->ske_stream, SILC_ID_CLIENT, conn->local_id,
1228 SILC_ID_CLIENT, &client_entry->id);
1230 /* Link to the new packet stream to intercept the packets before they
1231 go to SKE library so that we can do additional checks and decide if
1232 we really want to process the packets. */
1233 if (!silc_packet_stream_link(ake->ske_stream, &autoneg_key_ske_cbs, NULL,
1234 1000001, SILC_PACKET_ANY, -1))
1238 ake->ske = silc_ske_alloc(client->rng, conn->internal->schedule,
1239 conn->internal->params.repository,
1240 conn->public_key, conn->private_key,
1245 silc_ske_set_callbacks(ake->ske, silc_client_autoneg_key_verify_pubkey,
1246 silc_client_autoneg_key_done, client_entry);
1247 ake->params.version = client->internal->silc_client_version;
1248 ake->params.probe_timeout_secs = 5;
1249 ake->params.timeout_secs = 120;
1250 ake->params.flags = SILC_SKE_SP_FLAG_MUTUAL | SILC_SKE_SP_FLAG_PFS;
1251 ake->params.small_proposal = TRUE;
1252 ake->params.no_acks = TRUE;
1254 if (client_entry->internal.send_key &&
1255 client_entry->internal.ake_generation == ake->generation) {
1256 /* Security properties for rekey */
1257 SilcSKESecurityProperties prop = silc_calloc(1, sizeof(*prop));
1260 silc_cipher_alloc(silc_cipher_get_name(client_entry->internal.send_key),
1262 silc_hmac_alloc(silc_hmac_get_name(client_entry->internal.hmac_send),
1264 silc_hash_alloc(silc_hash_get_name(silc_hmac_get_hash(
1265 client_entry->internal.hmac_send)), &prop->hash);
1266 prop->public_key = silc_pkcs_public_key_copy(client_entry->public_key);
1267 silc_ske_group_get_by_number(2, &prop->group);
1268 prop->flags = ake->params.flags;
1269 ake->params.prop = prop;
1272 /* Start key exchange, responder is started in the packet callback */
1274 ake->ske_op = silc_ske_initiator(ake->ske, ake->ske_stream, &ake->params,
1280 /* Finally, set up the client entry */
1281 client_entry->internal.op = silc_async_alloc(silc_client_autoneg_key_abort,
1282 NULL, client_entry);
1283 if (!client_entry->internal.op)
1285 client_entry->internal.ake = ake;
1286 client_entry->internal.no_ake = FALSE;
1287 client_entry->internal.prv_resp = !initiator;
1288 silc_client_ref_client(client, conn, client_entry);
1290 /* As responder reinject the packet to the new stream so it gets decoded
1291 from the private message payload. */
1292 if (initiator_packet)
1293 silc_packet_stream_inject(conn->stream, initiator_packet);
1295 /* Save the initial message, it will be sent after the key has been
1297 if (data && data_len) {
1298 m = silc_buffer_alloc_size(data_len + 2);
1300 SILC_PUT16_MSB(flags, m->data);
1301 silc_buffer_pull(m, 2);
1302 silc_buffer_put(m, data, data_len);
1303 silc_dlist_add(ake->messages, m);
1306 silc_hash_alloc(silc_hash_get_name(hash), &ake->hash);
1313 silc_ske_free(ake->ske);
1314 if (ake->ske_stream) {
1315 silc_packet_stream_unlink(ake->ske_stream, &autoneg_key_ske_cbs, NULL);
1316 silc_packet_stream_destroy(ake->ske_stream);
1317 } else if (ake->stream)
1318 silc_stream_destroy(ake->stream);
1319 silc_dlist_uninit(ake->messages);
1324 /* Sets away `message'. The away message may be set when the client's
1325 mode is changed to SILC_UMODE_GONE and the client whishes to reply
1326 to anyone who sends private message. The `message' will be sent
1327 automatically back to the the client who send private message. If
1328 away message is already set this replaces the old message with the
1329 new one. If `message' is NULL the old away message is removed.
1330 The sender may freely free the memory of the `message'. */
1332 SilcBool silc_client_set_away_message(SilcClient client,
1333 SilcClientConnection conn,
1336 if (!client || !conn)
1340 silc_free(conn->internal->away_message);
1341 conn->internal->away_message = NULL;
1345 if (conn->internal->away_message)
1346 silc_free(conn->internal->away_message);
1348 conn->internal->away_message = strdup(message);
1349 if (!conn->internal->away_message)