5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2004, 2006 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 /************************** Channel Message Send ****************************/
27 /* Sends channel message to `channel'. */
29 SilcBool silc_client_send_channel_message(SilcClient client,
30 SilcClientConnection conn,
31 SilcChannelEntry channel,
32 SilcChannelPrivateKey key,
33 SilcMessageFlags flags,
44 SILC_LOG_DEBUG(("Sending channel message"));
46 if (silc_unlikely(!client || !conn || !channel))
48 if (silc_unlikely(flags & SILC_MESSAGE_FLAG_SIGNED && !hash))
50 if (silc_unlikely(conn->internal->disconnected))
53 chu = silc_client_on_channel(channel, conn->local_entry);
54 if (silc_unlikely(!chu)) {
55 client->internal->ops->say(conn->client, conn,
56 SILC_CLIENT_MESSAGE_AUDIT,
57 "Cannot talk to channel: not joined");
61 /* Check if it is allowed to send messages to this channel by us. */
62 if (silc_unlikely(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS &&
65 if (silc_unlikely(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS &&
66 chu->mode & SILC_CHANNEL_UMODE_CHANOP &&
67 !(chu->mode & SILC_CHANNEL_UMODE_CHANFO)))
69 if (silc_unlikely(chu->mode & SILC_CHANNEL_UMODE_QUIET))
72 /* Take the key to be used */
73 if (channel->internal.private_keys) {
75 /* Use key application specified */
78 } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
79 channel->internal.curr_key) {
80 /* Use current private key */
81 cipher = channel->internal.curr_key->cipher;
82 hmac = channel->internal.curr_key->hmac;
83 } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
84 !channel->internal.curr_key &&
85 channel->internal.private_keys) {
86 /* Use just some private key since we don't know what to use
87 and private keys are set. */
88 silc_dlist_start(channel->internal.private_keys);
89 key = silc_dlist_get(channel->internal.private_keys);
93 /* Use this key as current private key */
94 channel->internal.curr_key = key;
96 /* Use normal channel key generated by the server */
97 cipher = channel->internal.channel_key;
98 hmac = channel->internal.hmac;
101 /* Use normal channel key generated by the server */
102 cipher = channel->internal.channel_key;
103 hmac = channel->internal.hmac;
106 if (silc_unlikely(!cipher || !hmac)) {
107 SILC_LOG_ERROR(("No cipher and HMAC for channel"));
111 /* Encode the message payload. This also encrypts the message payload. */
112 buffer = silc_message_payload_encode(flags, data, data_len, TRUE, FALSE,
113 cipher, hmac, client->rng, NULL,
114 conn->private_key, hash, NULL);
115 if (silc_unlikely(!buffer)) {
116 SILC_LOG_ERROR(("Error encoding channel message"));
120 /* Send the channel message */
121 ret = silc_packet_send_ext(conn->stream, SILC_PACKET_CHANNEL_MESSAGE, 0,
122 0, NULL, SILC_ID_CHANNEL, &channel->id,
123 silc_buffer_datalen(buffer), NULL, NULL);
125 silc_buffer_free(buffer);
129 /************************* Channel Message Receive **************************/
131 /* Client resolving callback. Continues with the channel message processing */
133 static void silc_client_channel_message_resolved(SilcClient client,
134 SilcClientConnection conn,
139 /* If no client found, ignore the channel message, a silent error */
141 silc_fsm_next(context, silc_client_channel_message_error);
143 /* Continue processing the channel message packet */
144 SILC_FSM_CALL_CONTINUE(context);
147 /* Process received channel message */
149 SILC_FSM_STATE(silc_client_channel_message)
151 SilcClientConnection conn = fsm_context;
152 SilcClient client = conn->client;
153 SilcPacket packet = state_context;
154 SilcBuffer buffer = &packet->buffer;
155 SilcMessagePayload payload = NULL;
156 SilcChannelEntry channel;
157 SilcClientEntry client_entry;
158 SilcClientID remote_id;
159 SilcChannelID channel_id;
160 unsigned char *message;
161 SilcUInt32 message_len;
162 SilcChannelPrivateKey key = NULL;
164 SILC_LOG_DEBUG(("Received channel message"));
166 if (silc_unlikely(packet->dst_id_type != SILC_ID_CHANNEL)) {
167 /** Invalid packet */
168 silc_fsm_next(fsm, silc_client_channel_message_error);
169 return SILC_FSM_CONTINUE;
172 if (silc_unlikely(!silc_id_str2id(packet->src_id,
173 packet->src_id_len, SILC_ID_CLIENT,
174 &remote_id, sizeof(remote_id)))) {
175 /** Invalid source ID */
176 silc_fsm_next(fsm, silc_client_channel_message_error);
177 return SILC_FSM_CONTINUE;
180 /* Get sender client entry */
181 client_entry = silc_client_get_client_by_id(client, conn, &remote_id);
182 if (!client_entry || !client_entry->nickname[0]) {
183 /** Resolve client info */
184 silc_client_unref_client(client, conn, client_entry);
185 SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
186 client, conn, &remote_id, NULL,
187 silc_client_channel_message_resolved,
192 if (silc_unlikely(!silc_id_str2id(packet->dst_id, packet->dst_id_len,
193 SILC_ID_CHANNEL, &channel_id,
194 sizeof(channel_id)))) {
195 /** Invalid destination ID */
196 silc_fsm_next(fsm, silc_client_channel_message_error);
197 return SILC_FSM_CONTINUE;
200 /* Find the channel */
201 channel = silc_client_get_channel_by_id(client, conn, &channel_id);
202 if (silc_unlikely(!channel)) {
203 /** Unknown channel */
204 silc_fsm_next(fsm, silc_client_channel_message_error);
205 return SILC_FSM_CONTINUE;
208 /* Check that user is on channel */
209 if (silc_unlikely(!silc_client_on_channel(channel, client_entry))) {
210 /** User not on channel */
211 SILC_LOG_WARNING(("Message from user not on channel, client or "
213 silc_fsm_next(fsm, silc_client_channel_message_error);
214 return SILC_FSM_CONTINUE;
217 /* If there is no channel private key then just decrypt the message
218 with the channel key. If private keys are set then just go through
219 all private keys and check what decrypts correctly. */
220 if (!channel->internal.private_keys) {
221 /* Parse the channel message payload. This also decrypts the payload */
222 payload = silc_message_payload_parse(silc_buffer_data(buffer),
223 silc_buffer_len(buffer), FALSE,
224 FALSE, channel->internal.channel_key,
225 channel->internal.hmac, NULL,
228 /* If decryption failed and we have just performed channel key rekey
229 we will use the old key in decryption. If that fails too then we
230 cannot do more and will drop the packet. */
231 if (silc_unlikely(!payload)) {
235 if (!channel->internal.old_channel_keys ||
236 !silc_dlist_count(channel->internal.old_channel_keys))
239 SILC_LOG_DEBUG(("Attempting to decrypt with old channel key(s)"));
241 silc_dlist_end(channel->internal.old_channel_keys);
242 silc_dlist_end(channel->internal.old_hmacs);
243 while ((cipher = silc_dlist_get(channel->internal.old_channel_keys))) {
244 hmac = silc_dlist_get(channel->internal.old_hmacs);
248 payload = silc_message_payload_parse(silc_buffer_data(buffer),
249 silc_buffer_len(buffer),
250 FALSE, FALSE, cipher, hmac,
259 /* If the private key mode is not set on the channel then try the actual
260 channel key first before trying private keys. */
261 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
262 payload = silc_message_payload_parse(silc_buffer_data(buffer),
263 silc_buffer_len(buffer),
265 channel->internal.channel_key,
266 channel->internal.hmac, NULL,
270 silc_dlist_start(channel->internal.private_keys);
271 while ((key = silc_dlist_get(channel->internal.private_keys))) {
272 /* Parse the message payload. This also decrypts the payload */
273 payload = silc_message_payload_parse(silc_buffer_data(buffer),
274 silc_buffer_len(buffer),
275 FALSE, FALSE, key->cipher,
276 key->hmac, NULL, FALSE, NULL);
280 if (key == SILC_LIST_END)
285 message = silc_message_get_data(payload, &message_len);
287 /* Pass the message to application */
288 client->internal->ops->channel_message(
289 client, conn, client_entry, channel, payload,
290 key, silc_message_get_flags(payload),
291 message, message_len);
294 silc_client_unref_client(client, conn, client_entry);
295 silc_client_unref_channel(client, conn, channel);
297 silc_message_payload_free(payload);
298 return SILC_FSM_FINISH;
301 /* Channel message error. */
303 SILC_FSM_STATE(silc_client_channel_message_error)
305 SilcPacket packet = state_context;
306 silc_packet_free(packet);
307 return SILC_FSM_FINISH;
310 /******************************* Channel Key ********************************/
312 /* Timeout callback that is called after a short period of time after the
313 new channel key has been created. This removes the first channel key
316 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
318 SilcChannelEntry channel = (SilcChannelEntry)context;
322 if (channel->internal.old_channel_keys) {
323 silc_dlist_start(channel->internal.old_channel_keys);
324 key = silc_dlist_get(channel->internal.old_channel_keys);
326 silc_dlist_del(channel->internal.old_channel_keys, key);
327 silc_cipher_free(key);
331 if (channel->internal.old_hmacs) {
332 silc_dlist_start(channel->internal.old_hmacs);
333 hmac = silc_dlist_get(channel->internal.old_hmacs);
335 silc_dlist_del(channel->internal.old_hmacs, hmac);
336 silc_hmac_free(hmac);
341 /* Saves channel key from encoded `key_payload'. This is used when we receive
342 Channel Key Payload and when we are processing JOIN command reply. */
344 SilcBool silc_client_save_channel_key(SilcClient client,
345 SilcClientConnection conn,
346 SilcBuffer key_payload,
347 SilcChannelEntry channel)
349 unsigned char *id_string, *key, *cipher, *hmac, hash[SILC_HASH_MAXLEN];
352 SilcChannelKeyPayload payload;
354 SILC_LOG_DEBUG(("New channel key"));
356 payload = silc_channel_key_payload_parse(silc_buffer_data(key_payload),
357 silc_buffer_len(key_payload));
361 id_string = silc_channel_key_get_id(payload, &tmp_len);
363 silc_channel_key_payload_free(payload);
367 if (!silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL, &id, sizeof(id))) {
368 silc_channel_key_payload_free(payload);
374 channel = silc_client_get_channel_by_id(client, conn, &id);
376 SILC_LOG_DEBUG(("Key for unknown channel"));
377 silc_channel_key_payload_free(payload);
381 silc_client_ref_channel(client, conn, channel);
384 /* Save the old key for a short period of time so that we can decrypt
385 channel message even after the rekey if some client would be sending
386 messages with the old key after the rekey. */
387 if (!channel->internal.old_channel_keys)
388 channel->internal.old_channel_keys = silc_dlist_init();
389 if (!channel->internal.old_hmacs)
390 channel->internal.old_hmacs = silc_dlist_init();
391 if (channel->internal.old_channel_keys && channel->internal.old_hmacs) {
392 silc_dlist_add(channel->internal.old_channel_keys,
393 channel->internal.channel_key);
394 silc_dlist_add(channel->internal.old_hmacs, channel->internal.hmac);
395 silc_schedule_task_add_timeout(client->schedule,
396 silc_client_save_channel_key_rekey,
400 /* Get channel cipher */
401 cipher = silc_channel_key_get_cipher(payload, NULL);
402 if (!silc_cipher_alloc(cipher, &channel->internal.channel_key)) {
403 client->internal->ops->say(
405 SILC_CLIENT_MESSAGE_AUDIT,
406 "Cannot talk to channel: unsupported cipher %s",
408 silc_client_unref_channel(client, conn, channel);
409 silc_channel_key_payload_free(payload);
413 /* Set the cipher key */
414 key = silc_channel_key_get_key(payload, &tmp_len);
415 silc_cipher_set_key(channel->internal.channel_key, key, tmp_len * 8, TRUE);
417 /* Get channel HMAC */
418 hmac = (channel->internal.hmac ?
419 (char *)silc_hmac_get_name(channel->internal.hmac) :
421 if (!silc_hmac_alloc(hmac, NULL, &channel->internal.hmac)) {
422 client->internal->ops->say(
424 SILC_CLIENT_MESSAGE_AUDIT,
425 "Cannot talk to channel: unsupported HMAC %s",
427 silc_client_unref_channel(client, conn, channel);
428 silc_channel_key_payload_free(payload);
433 silc_hash_make(silc_hmac_get_hash(channel->internal.hmac), key,
435 silc_hmac_set_key(channel->internal.hmac, hash,
436 silc_hash_len(silc_hmac_get_hash(channel->internal.hmac)));
437 memset(hash, 0, sizeof(hash));
439 silc_client_unref_channel(client, conn, channel);
444 /* Received channel key packet. The key will replace old channel key. */
446 SILC_FSM_STATE(silc_client_channel_key)
448 SilcClientConnection conn = fsm_context;
449 SilcClient client = conn->client;
450 SilcPacket packet = state_context;
452 SILC_LOG_DEBUG(("Received channel key"));
455 silc_client_save_channel_key(client, conn, &packet->buffer, NULL);
456 silc_packet_free(packet);
458 return SILC_FSM_FINISH;
461 /**************************** Channel Private Key ***************************/
463 /* Add new channel private key */
465 SilcBool silc_client_add_channel_private_key(SilcClient client,
466 SilcClientConnection conn,
467 SilcChannelEntry channel,
473 SilcChannelPrivateKey *ret_key)
475 SilcChannelPrivateKey entry;
476 unsigned char hash[SILC_HASH_MAXLEN];
477 SilcSKEKeyMaterial keymat;
479 if (!client || !conn || !channel)
483 cipher = SILC_DEFAULT_CIPHER;
485 hmac = SILC_DEFAULT_HMAC;
487 if (!silc_cipher_is_supported(cipher))
489 if (!silc_hmac_is_supported(hmac))
492 if (!channel->internal.private_keys) {
493 channel->internal.private_keys = silc_dlist_init();
494 if (!channel->internal.private_keys)
498 /* Produce the key material */
499 keymat = silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
500 conn->internal->sha1hash);
505 entry = silc_calloc(1, sizeof(*entry));
507 silc_ske_free_key_material(keymat);
510 entry->name = name ? strdup(name) : NULL;
512 /* Allocate the cipher and set the key */
513 if (!silc_cipher_alloc(cipher, &entry->cipher)) {
515 silc_free(entry->name);
516 silc_ske_free_key_material(keymat);
519 silc_cipher_set_key(entry->cipher, keymat->send_enc_key,
520 keymat->enc_key_len, TRUE);
522 /* Generate HMAC key from the channel key data and set it */
523 if (!silc_hmac_alloc(hmac, NULL, &entry->hmac)) {
525 silc_free(entry->name);
526 silc_cipher_free(entry->cipher);
527 silc_ske_free_key_material(keymat);
530 silc_hash_make(silc_hmac_get_hash(entry->hmac), keymat->send_enc_key,
531 keymat->enc_key_len / 8, hash);
532 silc_hmac_set_key(entry->hmac, hash,
533 silc_hash_len(silc_hmac_get_hash(entry->hmac)));
534 memset(hash, 0, sizeof(hash));
536 /* Add to the private keys list */
537 silc_dlist_add(channel->internal.private_keys, entry);
539 if (!channel->internal.curr_key)
540 channel->internal.curr_key = entry;
542 /* Free the key material */
543 silc_ske_free_key_material(keymat);
551 /* Removes all private keys from the `channel'. The old channel key is used
552 after calling this to protect the channel messages. Returns FALSE on
553 on error, TRUE otherwise. */
555 SilcBool silc_client_del_channel_private_keys(SilcClient client,
556 SilcClientConnection conn,
557 SilcChannelEntry channel)
559 SilcChannelPrivateKey entry;
561 if (!client || !conn || !channel)
564 if (!channel->internal.private_keys)
567 silc_dlist_start(channel->internal.private_keys);
568 while ((entry = silc_dlist_get(channel->internal.private_keys))) {
569 silc_dlist_del(channel->internal.private_keys, entry);
570 silc_free(entry->name);
571 silc_cipher_free(entry->cipher);
572 silc_hmac_free(entry->hmac);
576 channel->internal.curr_key = NULL;
578 silc_dlist_uninit(channel->internal.private_keys);
579 channel->internal.private_keys = NULL;
584 /* Removes and frees private key `key' from the channel `channel'. The `key'
585 is retrieved by calling the function silc_client_list_channel_private_keys.
586 The key is not used after this. If the key was last private key then the
587 old channel key is used hereafter to protect the channel messages. This
588 returns FALSE on error, TRUE otherwise. */
590 SilcBool silc_client_del_channel_private_key(SilcClient client,
591 SilcClientConnection conn,
592 SilcChannelEntry channel,
593 SilcChannelPrivateKey key)
595 SilcChannelPrivateKey entry;
597 if (!client || !conn || !channel)
600 if (!channel->internal.private_keys)
603 silc_dlist_start(channel->internal.private_keys);
604 while ((entry = silc_dlist_get(channel->internal.private_keys))) {
608 if (channel->internal.curr_key == entry)
609 channel->internal.curr_key = NULL;
611 silc_dlist_del(channel->internal.private_keys, entry);
612 silc_free(entry->name);
613 silc_cipher_free(entry->cipher);
614 silc_hmac_free(entry->hmac);
617 if (silc_dlist_count(channel->internal.private_keys) == 0) {
618 silc_dlist_uninit(channel->internal.private_keys);
619 channel->internal.private_keys = NULL;
628 /* Returns array (pointers) of private keys associated to the `channel'.
629 The caller must free the array by calling the function
630 silc_client_free_channel_private_keys. The pointers in the array may be
631 used to delete the specific key by giving the pointer as argument to the
632 function silc_client_del_channel_private_key. */
634 SilcDList silc_client_list_channel_private_keys(SilcClient client,
635 SilcClientConnection conn,
636 SilcChannelEntry channel)
638 SilcChannelPrivateKey entry;
641 if (!client || !conn || !channel)
644 if (!channel->internal.private_keys)
647 list = silc_dlist_init();
651 silc_dlist_start(channel->internal.private_keys);
652 while ((entry = silc_dlist_get(channel->internal.private_keys)))
653 silc_dlist_add(list, entry);
658 /* Sets the `key' to be used as current channel private key on the
659 `channel'. Packet sent after calling this function will be secured
662 void silc_client_current_channel_private_key(SilcClient client,
663 SilcClientConnection conn,
664 SilcChannelEntry channel,
665 SilcChannelPrivateKey key)
669 channel->internal.curr_key = key;
672 /***************************** Utility routines *****************************/
674 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the
675 channel indicated by the `channel'. NULL if client is not joined on
678 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
679 SilcClientEntry client_entry)
683 if (silc_hash_table_find(channel->user_list, client_entry, NULL,
690 /* Adds client to channel. Returns TRUE if user was added or is already
691 added to the channel, FALSE on error. */
693 SilcBool silc_client_add_to_channel(SilcClient client,
694 SilcClientConnection conn,
695 SilcChannelEntry channel,
696 SilcClientEntry client_entry,
701 if (silc_client_on_channel(channel, client_entry))
704 chu = silc_calloc(1, sizeof(*chu));
708 chu->client = client_entry;
709 chu->channel = channel;
712 silc_client_ref_client(client, conn, client_entry);
713 silc_client_ref_channel(client, conn, channel);
715 silc_hash_table_add(channel->user_list, client_entry, chu);
716 silc_hash_table_add(client_entry->channels, channel, chu);
721 /* Removes client from a channel */
723 SilcBool silc_client_remove_from_channel(SilcClient client,
724 SilcClientConnection conn,
725 SilcChannelEntry channel,
726 SilcClientEntry client_entry)
730 chu = silc_client_on_channel(channel, client_entry);
734 silc_hash_table_del(chu->client->channels, chu->channel);
735 silc_hash_table_del(chu->channel->user_list, chu->client);
738 silc_client_unref_client(client, conn, client_entry);
739 silc_client_unref_channel(client, conn, channel);
744 /* Removes a client entry from all channels it has joined. */
746 void silc_client_remove_from_channels(SilcClient client,
747 SilcClientConnection conn,
748 SilcClientEntry client_entry)
750 SilcHashTableList htl;
753 silc_hash_table_list(client_entry->channels, &htl);
754 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
755 silc_hash_table_del(chu->client->channels, chu->channel);
756 silc_hash_table_del(chu->channel->user_list, chu->client);
757 silc_client_unref_client(client, conn, chu->client);
758 silc_client_unref_channel(client, conn, chu->channel);
762 silc_hash_table_list_reset(&htl);
765 /* Empties channel from users. */
767 void silc_client_empty_channel(SilcClient client,
768 SilcClientConnection conn,
769 SilcChannelEntry channel)
771 SilcHashTableList htl;
774 silc_hash_table_list(channel->user_list, &htl);
775 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
776 silc_hash_table_del(chu->client->channels, chu->channel);
777 silc_hash_table_del(chu->channel->user_list, chu->client);
778 silc_client_unref_client(client, conn, chu->client);
779 silc_client_unref_channel(client, conn, chu->channel);
782 silc_hash_table_list_reset(&htl);