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 SilcUInt32 generation; /* Starting AKE generation */
693 silc_client_autoneg_key_recv_ske(SilcPacketEngine engine,
694 SilcPacketStream stream,
696 void *callback_context,
697 void *stream_context);
699 static const SilcPacketCallbacks autoneg_key_ske_cbs =
701 silc_client_autoneg_key_recv_ske, NULL, NULL
704 /* Destroy auto-negotiation context */
706 static void silc_client_autoneg_key_free(SilcClient client,
707 SilcClientConnection conn,
708 SilcClientEntry client_entry)
710 SilcClientAutonegMessageKey ake = client_entry->internal.ake;
714 silc_async_abort(ake->ske_op, NULL, NULL);
716 silc_ske_free(ake->ske);
717 silc_packet_stream_unlink(ake->ske_stream, &autoneg_key_ske_cbs, NULL);
718 silc_packet_stream_destroy(ake->ske_stream);
720 silc_hash_free(ake->hash);
722 silc_dlist_start(ake->messages);
723 while ((m = silc_dlist_get(ake->messages)) != SILC_LIST_END) {
724 silc_dlist_del(ake->messages, m);
727 silc_dlist_uninit(ake->messages);
729 client_entry->internal.op = NULL;
730 client_entry->internal.ake = NULL;
731 silc_client_unref_client(client, conn, client_entry);
734 ake->verify->aborted = TRUE;
735 else if (ake->public_key)
736 silc_pkcs_public_key_free(ake->public_key);
741 /* Destroy auto-negotiation context */
743 SILC_TASK_CALLBACK(silc_client_autoneg_key_finish)
745 SilcClientEntry client_entry = context;
746 SilcClientAutonegMessageKey ake = client_entry->internal.ake;
747 SilcClientConnection conn = ake->conn;
748 SilcClient client = conn->client;
750 silc_client_autoneg_key_free(client, conn, client_entry);
753 /* Abort callback. This aborts the auto-negotiation and the SKE */
756 silc_client_autoneg_key_abort(SilcAsyncOperation op, void *context)
758 SilcClientEntry client_entry = context;
759 SilcClientAutonegMessageKey ake = client_entry->internal.ake;
760 SilcClientConnection conn = ake->conn;
761 SilcClient client = conn->client;
766 silc_client_autoneg_key_free(client, conn, client_entry);
769 /* SKE packet stream callback. Here we verify that the packets we got
770 from the private message are actually SKE packets for us. */
773 silc_client_autoneg_key_recv_ske(SilcPacketEngine engine,
774 SilcPacketStream stream,
776 void *callback_context,
777 void *stream_context)
779 SilcClientEntry client_entry = stream_context;
780 SilcClientID remote_id;
782 SILC_LOG_DEBUG(("Packet %p type %d inside private message", packet,
785 /* Take only SKE packets, drop others, no support for anything else */
786 if (packet->type != SILC_PACKET_KEY_EXCHANGE &&
787 packet->type != SILC_PACKET_KEY_EXCHANGE_1 &&
788 packet->type != SILC_PACKET_KEY_EXCHANGE_2 &&
789 packet->type != SILC_PACKET_FAILURE)
792 /* Must be from client to client */
793 if (packet->dst_id_type != SILC_ID_CLIENT ||
794 packet->src_id_type != SILC_ID_CLIENT)
797 if (!silc_id_str2id(packet->src_id, packet->src_id_len, SILC_ID_CLIENT,
798 &remote_id, sizeof(remote_id)))
801 if (!SILC_ID_CLIENT_COMPARE(&client_entry->id, &remote_id)) {
802 /* The packet is not for this client, but it must be */
803 SILC_LOG_DEBUG(("Client ids do not match"));
807 /* Packet is ok and is for us, let it pass to SKE */
808 SILC_LOG_DEBUG(("Pass packet %p type %d", packet, packet->type));
812 silc_packet_free(packet);
816 /* Coder callback for actually encoding/decoding the SKE packets inside
819 static SilcBool silc_client_autoneg_key_coder(SilcStream stream,
820 SilcStreamStatus status,
824 SilcBool ret = FALSE;
826 SilcMessagePayload payload = NULL;
827 SilcMessageFlags flags;
829 SilcUInt32 message_len;
832 case SILC_STREAM_CAN_READ:
833 /* Decode private message. We get all private messages here from
834 the remote client while we're doing SKE, so we must take the
836 SILC_LOG_DEBUG(("Decode packet inside private message"));
838 payload = silc_message_payload_parse(silc_buffer_datalen(buffer),
839 TRUE, FALSE, NULL, NULL, NULL, 0,
840 NULL, 0, NULL, FALSE, NULL);
842 SILC_LOG_DEBUG(("Error decoding private message payload"));
846 /* Ignore this message if it's not packet */
847 flags = silc_message_get_flags(payload);
848 if (!(flags & SILC_MESSAGE_FLAG_PACKET)) {
849 SILC_LOG_DEBUG(("Private message doesn't contain packet"));
850 silc_message_payload_free(payload);
854 /* Take the packet */
857 msg = silc_message_get_data(payload, &message_len);
858 silc_buffer_reset(buffer);
859 if (!silc_buffer_enlarge(buffer, message_len)) {
860 silc_message_payload_free(payload);
863 silc_buffer_put(buffer, msg, message_len);
865 silc_message_payload_free(payload);
868 case SILC_STREAM_CAN_WRITE:
869 /* Encode private message */
870 SILC_LOG_DEBUG(("Encode packet inside private message"));
875 silc_message_payload_encode(SILC_MESSAGE_FLAG_PACKET,
876 silc_buffer_datalen(buffer),
877 FALSE, TRUE, NULL, NULL, NULL,
878 NULL, NULL, NULL, NULL, NULL, NULL);
880 SILC_LOG_DEBUG(("Error encoding private message payload"));
884 silc_buffer_reset(buffer);
885 if (!silc_buffer_enlarge(buffer, silc_buffer_len(message)))
887 silc_buffer_put(buffer, silc_buffer_datalen(message));
899 /* Called after application has verified remote client's public key */
902 silc_client_autoneg_key_verify_pubkey_cb(SilcBool success, void *context)
904 SilcVerifyKeyContext verify = context;
905 SilcClientAutonegMessageKey ake = verify->context;
907 SILC_LOG_DEBUG(("Start"));
909 /* Call the completion callback back to the SKE */
910 if (!verify->aborted) {
912 verify->completion(verify->ske, success ? SILC_SKE_STATUS_OK :
913 SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
914 verify->completion_context);
916 silc_pkcs_public_key_free(verify->public_key);
922 /* Remote client's public key verification callback */
925 silc_client_autoneg_key_verify_pubkey(SilcSKE ske,
926 SilcPublicKey public_key,
928 SilcSKEVerifyCbCompletion completion,
929 void *completion_context)
931 SilcClientEntry client_entry = context;
932 SilcClientAutonegMessageKey ake = client_entry->internal.ake;
933 SilcClientConnection conn = ake->conn;
934 SilcClient client = conn->client;
935 SilcVerifyKeyContext verify;
937 /* Use public key we cached earlier in AKE for direction verification */
938 if (client_entry->internal.send_key && client_entry->public_key &&
939 silc_pkcs_public_key_compare(public_key, client_entry->public_key)) {
940 SILC_LOG_DEBUG(("Client's cached public key matches"));
941 completion(ske, SILC_SKE_STATUS_OK, completion_context);
945 /* If we provided repository for SKE and we got here the key was not
946 found from the repository. */
947 if (conn->internal->params.repository &&
948 !conn->internal->params.verify_notfound) {
949 completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
954 SILC_LOG_DEBUG(("Verify remote client public key"));
956 ake->public_key = silc_pkcs_public_key_copy(public_key);
957 if (!ake->public_key) {
958 completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
963 verify = silc_calloc(1, sizeof(*verify));
965 completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
969 verify->public_key = ake->public_key;
971 verify->completion = completion;
972 verify->completion_context = completion_context;
973 verify->context = ake;
974 ake->verify = verify;
976 /* Verify public key in application */
977 client->internal->ops->verify_public_key(
979 SILC_CONN_CLIENT, ake->public_key,
980 silc_client_autoneg_key_verify_pubkey_cb,
984 /* Key exchange protocol completion callback */
986 static void silc_client_autoneg_key_done(SilcSKE ske,
987 SilcSKEStatus status,
988 SilcSKESecurityProperties prop,
989 SilcSKEKeyMaterial keymat,
990 SilcSKERekeyMaterial rekey,
993 SilcClientEntry client_entry = context;
994 SilcClientAutonegMessageKey ake = client_entry->internal.ake;
995 SilcClientConnection conn = ake->conn;
996 SilcClient client = conn->client;
997 SilcBool initiator = !client_entry->internal.prv_resp;
998 SilcMessageFlags flags;
1003 conn->context_type = SILC_ID_CLIENT;
1004 conn->client_entry = client_entry;
1006 if (status != SILC_SKE_STATUS_OK) {
1007 /* Key exchange failed */
1008 SILC_LOG_DEBUG(("Error during key exchange: %s (%d)",
1009 silc_ske_map_status(status), status));
1012 if (status != SILC_SKE_STATUS_PROBE_TIMEOUT)
1013 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1014 "Cannot send private message to %s (%s)",
1015 client_entry->nickname,
1016 silc_ske_map_status(status));
1017 else if (client_entry->mode & SILC_UMODE_DETACHED)
1018 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1019 "Cannot send private message to detached "
1020 "client %s", client_entry->nickname);
1021 } else if (status != SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
1022 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1023 "Private message key exchange failed "
1024 "with %s (%s)", client_entry->nickname,
1025 silc_ske_map_status(status));
1028 /* Errors that occur due to user not responding or deciding not to
1029 trust the public key will not cause us to stop trying AKE next time.
1030 Other errors disable AKE to allow communication with other means. */
1031 if (initiator && status != SILC_SKE_STATUS_TIMEOUT &&
1032 status != SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY &&
1033 !(client_entry->mode & SILC_UMODE_DETACHED)) {
1034 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO,
1035 "Cannot auto-negotiate key with %s, "
1036 "messages will be protected with "
1037 "session key", client_entry->nickname);
1039 /* Don't try this again with this client */
1040 client_entry->internal.no_ake = TRUE;
1045 /* Set the new private message key into use */
1046 silc_client_del_private_message_key(client, conn, client_entry);
1047 client_entry->internal.prv_resp = !initiator;
1048 if (!silc_client_add_private_message_key_ske(
1049 client, conn, client_entry,
1050 silc_cipher_get_name(prop->cipher),
1051 silc_hmac_get_name(prop->hmac),
1053 SILC_LOG_DEBUG(("Error adding private message key"));
1055 client->internal->ops->say(client, conn,
1056 SILC_CLIENT_MESSAGE_ERROR,
1057 "Private message key exchange error: "
1060 /* Don't try this again with this client */
1061 client_entry->internal.no_ake = TRUE;
1065 /* Save the public key to client entry */
1066 if (!client_entry->public_key) {
1067 client_entry->public_key = ake->public_key;
1068 ake->public_key = NULL;
1071 /* Rekey periodically */
1072 client_entry->internal.ake_rekey = silc_time() + 300;
1074 client_entry->internal.ake_rekey -= 30;
1075 client_entry->internal.ake_generation = conn->internal->ake_generation;
1076 client_entry->internal.no_ake = FALSE;
1078 SILC_LOG_DEBUG(("AKE completed as %s with %s, rekey in %u secs, "
1079 "generation %u", initiator ? "initiator" : "responder",
1080 client_entry->nickname, 300,
1081 conn->internal->ake_generation));
1083 /* Send queued messages */
1084 silc_dlist_start(ake->messages);
1085 while ((m = silc_dlist_get(ake->messages)) != SILC_LIST_END) {
1086 SILC_GET16_MSB(flags, m->data - 2);
1087 silc_client_send_private_message(client, conn, client_entry,
1089 silc_buffer_datalen(m));
1093 conn->context_type = SILC_ID_NONE;
1094 conn->client_entry = NULL;
1095 silc_schedule_task_add_timeout(client->schedule,
1096 silc_client_autoneg_key_finish,
1097 client_entry, 0, 1);
1100 /* Auto-negotiate private message key with the remote client using the
1101 SKE protocol, which is tunneled through the SILC network inside private
1102 messages shared between the us and the remote client.
1104 This operation is naturally asynchronous and will involve exchanging
1105 multiple messages back and forth. Despite this, we don't run this
1106 operation in own FSM thread here, but instead will use the SKE library
1107 to do the asynchronous operation which we can abort at any time in
1108 case user disconnects.
1110 Messages and packets we receive during this operation will be processed
1111 in the normal connection thread. */
1114 silc_client_autoneg_private_message_key(SilcClient client,
1115 SilcClientConnection conn,
1116 SilcClientEntry client_entry,
1117 SilcPacket initiator_packet,
1118 SilcMessageFlags flags,
1120 unsigned char *data,
1121 SilcUInt32 data_len)
1123 SilcClientAutonegMessageKey ake;
1124 SilcSKEParamsStruct params = {};
1125 SilcBool initiator = initiator_packet == NULL;
1128 SILC_LOG_DEBUG(("Start private message AKE as %s with %s",
1129 initiator ? "initiator" : "responder",
1130 client_entry->nickname));
1132 if (client_entry->internal.op) {
1133 ake = client_entry->internal.ake;
1135 /* If generation has changed, we must abort this exchange and
1137 if (ake->generation != conn->internal->ake_generation) {
1138 SILC_LOG_DEBUG(("Abort ongoing AKE and start new one"));
1139 silc_async_abort(client_entry->internal.op, NULL, NULL);
1141 SILC_LOG_DEBUG(("AKE is ongoing, queue the message"));
1143 m = silc_buffer_alloc_size(data_len + 2);
1146 SILC_PUT16_MSB(flags, m->data);
1147 silc_buffer_pull(m, 2);
1148 silc_buffer_put(m, data, data_len);
1149 silc_dlist_add(ake->messages, m);
1153 SILC_LOG_DEBUG(("Cannot start AKE, operation %p is ongoing",
1154 client_entry->internal.op));
1159 ake = silc_calloc(1, sizeof(*ake));
1163 ake->generation = conn->internal->ake_generation;
1165 ake->messages = silc_dlist_init();
1169 /* Wrap our packet stream to a generic stream for the private messages
1170 we are going to exchange. We send the packets with packet flag
1171 SILC_PACKET_FLAG_PRIVMSG_KEY which is a lie, but is a way to get
1172 clients which do not support this protocol to ignore these messages.
1173 This kludge should be removed once support is everywhere and
1174 responder should look only for the SILC_MESSAGE_FLAG_PACKET. */
1175 ake->stream = silc_packet_stream_wrap(conn->stream,
1176 SILC_PACKET_PRIVATE_MESSAGE,
1177 SILC_PACKET_FLAG_PRIVMSG_KEY, FALSE,
1179 SILC_ID_CLIENT, &client_entry->id,
1180 silc_client_autoneg_key_coder,
1185 /* Create a new packet stream for the SKE library using the wrapped
1186 stream as the underlaying stream, in effect creating a tunnel to
1187 send SKE packets inside private message packets. */
1188 ake->ske_stream = silc_packet_stream_create(client->internal->packet_engine,
1189 conn->internal->schedule,
1191 if (!ake->ske_stream)
1194 silc_packet_set_context(ake->ske_stream, client_entry);
1195 silc_packet_set_ids(ake->ske_stream, SILC_ID_CLIENT, conn->local_id,
1196 SILC_ID_CLIENT, &client_entry->id);
1198 /* Link to the new packet stream to intercept the packets before they
1199 go to SKE library so that we can do additional checks and decide if
1200 we really want to process the packets. */
1201 if (!silc_packet_stream_link(ake->ske_stream, &autoneg_key_ske_cbs, NULL,
1202 1000001, SILC_PACKET_ANY, -1))
1206 ake->ske = silc_ske_alloc(client->rng, conn->internal->schedule,
1207 conn->internal->params.repository,
1208 conn->public_key, conn->private_key,
1213 silc_ske_set_callbacks(ake->ske, silc_client_autoneg_key_verify_pubkey,
1214 silc_client_autoneg_key_done, client_entry);
1215 params.version = client->internal->silc_client_version;
1216 params.probe_timeout_secs = 5;
1217 params.timeout_secs = 120;
1218 params.flags = SILC_SKE_SP_FLAG_MUTUAL | SILC_SKE_SP_FLAG_PFS;
1219 params.small_proposal = TRUE;
1220 params.no_acks = TRUE;
1222 if (client_entry->internal.send_key &&
1223 client_entry->internal.ake_generation == ake->generation) {
1224 /* Security properties for rekey */
1225 SilcSKESecurityProperties prop = silc_calloc(1, sizeof(*prop));
1228 silc_cipher_alloc(silc_cipher_get_name(client_entry->internal.send_key),
1230 silc_hmac_alloc(silc_hmac_get_name(client_entry->internal.hmac_send),
1232 silc_hash_alloc(silc_hash_get_name(silc_hmac_get_hash(
1233 client_entry->internal.hmac_send)), &prop->hash);
1234 prop->public_key = silc_pkcs_public_key_copy(client_entry->public_key);
1235 silc_ske_group_get_by_number(2, &prop->group);
1236 prop->flags = params.flags;
1240 /* Start key exchange */
1242 ake->ske_op = silc_ske_initiator(ake->ske, ake->ske_stream, ¶ms, NULL);
1244 ake->ske_op = silc_ske_responder(ake->ske, ake->ske_stream, ¶ms);
1248 /* Finally, set up the client entry */
1249 client_entry->internal.op = silc_async_alloc(silc_client_autoneg_key_abort,
1250 NULL, client_entry);
1251 if (!client_entry->internal.op)
1253 client_entry->internal.ake = ake;
1254 client_entry->internal.no_ake = FALSE;
1255 client_entry->internal.prv_resp = !initiator;
1256 silc_client_ref_client(client, conn, client_entry);
1258 /* As responder, re-inject the initiator's private message back to the
1259 stream so that the new SKE gets it. */
1260 if (initiator_packet)
1261 silc_packet_stream_inject(conn->stream, initiator_packet);
1263 /* Save the initial message, it will be sent after the key has been
1265 if (data && data_len) {
1266 m = silc_buffer_alloc_size(data_len + 2);
1268 SILC_PUT16_MSB(flags, m->data);
1269 silc_buffer_pull(m, 2);
1270 silc_buffer_put(m, data, data_len);
1271 silc_dlist_add(ake->messages, m);
1274 silc_hash_alloc(silc_hash_get_name(hash), &ake->hash);
1281 silc_ske_free(ake->ske);
1282 if (ake->ske_stream) {
1283 silc_packet_stream_unlink(ake->ske_stream, &autoneg_key_ske_cbs, NULL);
1284 silc_packet_stream_destroy(ake->ske_stream);
1285 } else if (ake->stream)
1286 silc_stream_destroy(ake->stream);
1287 silc_dlist_uninit(ake->messages);
1292 /* Sets away `message'. The away message may be set when the client's
1293 mode is changed to SILC_UMODE_GONE and the client whishes to reply
1294 to anyone who sends private message. The `message' will be sent
1295 automatically back to the the client who send private message. If
1296 away message is already set this replaces the old message with the
1297 new one. If `message' is NULL the old away message is removed.
1298 The sender may freely free the memory of the `message'. */
1300 SilcBool silc_client_set_away_message(SilcClient client,
1301 SilcClientConnection conn,
1304 if (!client || !conn)
1308 silc_free(conn->internal->away_message);
1309 conn->internal->away_message = NULL;
1313 if (conn->internal->away_message)
1314 silc_free(conn->internal->away_message);
1316 conn->internal->away_message = strdup(message);
1317 if (!conn->internal->away_message)