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 (!client || !conn || !channel)
48 if (flags & SILC_MESSAGE_FLAG_SIGNED && !hash)
50 if (conn->internal->disconnected)
53 chu = silc_client_on_channel(channel, conn->local_entry);
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 (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS && !chu->mode)
64 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS &&
65 chu->mode & SILC_CHANNEL_UMODE_CHANOP &&
66 !(chu->mode & SILC_CHANNEL_UMODE_CHANFO))
68 if (chu->mode & SILC_CHANNEL_UMODE_QUIET)
71 /* Take the key to be used */
72 if (channel->internal.private_keys) {
74 /* Use key application specified */
77 } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
78 channel->internal.curr_key) {
79 /* Use current private key */
80 cipher = channel->internal.curr_key->cipher;
81 hmac = channel->internal.curr_key->hmac;
82 } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
83 !channel->internal.curr_key &&
84 channel->internal.private_keys) {
85 /* Use just some private key since we don't know what to use
86 and private keys are set. */
87 silc_dlist_start(channel->internal.private_keys);
88 key = silc_dlist_get(channel->internal.private_keys);
92 /* Use this key as current private key */
93 channel->internal.curr_key = key;
95 /* Use normal channel key generated by the server */
96 cipher = channel->internal.channel_key;
97 hmac = channel->internal.hmac;
100 /* Use normal channel key generated by the server */
101 cipher = channel->internal.channel_key;
102 hmac = channel->internal.hmac;
105 if (!cipher || !hmac) {
106 SILC_LOG_ERROR(("No cipher and HMAC for channel"));
110 /* Encode the message payload. This also encrypts the message payload. */
111 buffer = silc_message_payload_encode(flags, data, data_len, TRUE, FALSE,
112 cipher, hmac, client->rng, NULL,
113 conn->private_key, hash, NULL);
115 SILC_LOG_ERROR(("Error encoding channel message"));
119 /* Send the channel message */
120 ret = silc_packet_send_ext(conn->stream, SILC_PACKET_CHANNEL_MESSAGE, 0,
121 0, NULL, SILC_ID_CHANNEL, &channel->id,
122 silc_buffer_datalen(buffer), NULL, NULL);
124 silc_buffer_free(buffer);
128 /************************* Channel Message Receive **************************/
130 /* Client resolving callback. Continues with the channel message processing */
132 static void silc_client_channel_message_resolved(SilcClient client,
133 SilcClientConnection conn,
138 /* If no client found, ignore the channel message, a silent error */
140 silc_fsm_next(context, silc_client_channel_message_error);
142 /* Continue processing the channel message packet */
143 SILC_FSM_CALL_CONTINUE(context);
146 /* Process received channel message */
148 SILC_FSM_STATE(silc_client_channel_message)
150 SilcClientConnection conn = fsm_context;
151 SilcClient client = conn->client;
152 SilcPacket packet = state_context;
153 SilcBuffer buffer = &packet->buffer;
154 SilcMessagePayload payload = NULL;
155 SilcChannelEntry channel;
156 SilcClientEntry client_entry;
157 SilcClientID remote_id;
158 SilcChannelID channel_id;
159 unsigned char *message;
160 SilcUInt32 message_len;
161 SilcChannelPrivateKey key = NULL;
163 SILC_LOG_DEBUG(("Received channel message"));
165 if (packet->dst_id_type != SILC_ID_CHANNEL) {
166 /** Invalid packet */
167 silc_fsm_next(fsm, silc_client_channel_message_error);
168 return SILC_FSM_CONTINUE;
171 if (!silc_id_str2id(packet->src_id, packet->src_id_len, SILC_ID_CLIENT,
172 &remote_id, sizeof(remote_id))) {
173 /** Invalid source ID */
174 silc_fsm_next(fsm, silc_client_channel_message_error);
175 return SILC_FSM_CONTINUE;
178 /* Get sender client entry */
179 client_entry = silc_client_get_client_by_id(client, conn, &remote_id);
180 if (!client_entry || !client_entry->nickname[0]) {
181 /** Resolve client info */
182 silc_client_unref_client(client, conn, client_entry);
183 SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
184 client, conn, &remote_id, NULL,
185 silc_client_channel_message_resolved,
190 if (!silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL,
191 &channel_id, sizeof(channel_id))) {
192 /** Invalid destination ID */
193 silc_fsm_next(fsm, silc_client_channel_message_error);
194 return SILC_FSM_CONTINUE;
197 /* Find the channel */
198 channel = silc_client_get_channel_by_id(client, conn, &channel_id);
200 /** Unknown channel */
201 silc_fsm_next(fsm, silc_client_channel_message_error);
202 return SILC_FSM_CONTINUE;
205 /* Check that user is on channel */
206 if (!silc_client_on_channel(channel, client_entry)) {
207 /** User not on channel */
208 silc_fsm_next(fsm, silc_client_channel_message_error);
209 return SILC_FSM_CONTINUE;
212 /* If there is no channel private key then just decrypt the message
213 with the channel key. If private keys are set then just go through
214 all private keys and check what decrypts correctly. */
215 if (!channel->internal.private_keys) {
216 /* Parse the channel message payload. This also decrypts the payload */
217 payload = silc_message_payload_parse(silc_buffer_data(buffer),
218 silc_buffer_len(buffer), FALSE,
219 FALSE, channel->internal.channel_key,
220 channel->internal.hmac, NULL,
223 /* If decryption failed and we have just performed channel key rekey
224 we will use the old key in decryption. If that fails too then we
225 cannot do more and will drop the packet. */
230 if (!channel->internal.old_channel_keys ||
231 !silc_dlist_count(channel->internal.old_channel_keys))
234 SILC_LOG_DEBUG(("Attempting to decrypt with old channel key(s)"));
236 silc_dlist_end(channel->internal.old_channel_keys);
237 silc_dlist_end(channel->internal.old_hmacs);
238 while ((cipher = silc_dlist_get(channel->internal.old_channel_keys))) {
239 hmac = silc_dlist_get(channel->internal.old_hmacs);
243 payload = silc_message_payload_parse(silc_buffer_data(buffer),
244 silc_buffer_len(buffer),
245 FALSE, FALSE, cipher, hmac,
254 /* If the private key mode is not set on the channel then try the actual
255 channel key first before trying private keys. */
256 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
257 payload = silc_message_payload_parse(silc_buffer_data(buffer),
258 silc_buffer_len(buffer),
260 channel->internal.channel_key,
261 channel->internal.hmac, NULL,
265 silc_dlist_start(channel->internal.private_keys);
266 while ((key = silc_dlist_get(channel->internal.private_keys))) {
267 /* Parse the message payload. This also decrypts the payload */
268 payload = silc_message_payload_parse(silc_buffer_data(buffer),
269 silc_buffer_len(buffer),
270 FALSE, FALSE, key->cipher,
271 key->hmac, NULL, FALSE, NULL);
275 if (key == SILC_LIST_END)
280 message = silc_message_get_data(payload, &message_len);
282 /* Pass the message to application */
283 client->internal->ops->channel_message(
284 client, conn, client_entry, channel, payload,
285 key, silc_message_get_flags(payload),
286 message, message_len);
289 silc_client_unref_client(client, conn, client_entry);
290 silc_client_unref_channel(client, conn, channel);
292 silc_message_payload_free(payload);
293 return SILC_FSM_FINISH;
296 /* Channel message error. */
298 SILC_FSM_STATE(silc_client_channel_message_error)
300 SilcPacket packet = state_context;
301 silc_packet_free(packet);
302 return SILC_FSM_FINISH;
305 /******************************* Channel Key ********************************/
307 /* Timeout callback that is called after a short period of time after the
308 new channel key has been created. This removes the first channel key
311 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
313 SilcChannelEntry channel = (SilcChannelEntry)context;
317 if (channel->internal.old_channel_keys) {
318 silc_dlist_start(channel->internal.old_channel_keys);
319 key = silc_dlist_get(channel->internal.old_channel_keys);
321 silc_dlist_del(channel->internal.old_channel_keys, key);
322 silc_cipher_free(key);
326 if (channel->internal.old_hmacs) {
327 silc_dlist_start(channel->internal.old_hmacs);
328 hmac = silc_dlist_get(channel->internal.old_hmacs);
330 silc_dlist_del(channel->internal.old_hmacs, hmac);
331 silc_hmac_free(hmac);
336 /* Saves channel key from encoded `key_payload'. This is used when we receive
337 Channel Key Payload and when we are processing JOIN command reply. */
339 SilcBool silc_client_save_channel_key(SilcClient client,
340 SilcClientConnection conn,
341 SilcBuffer key_payload,
342 SilcChannelEntry channel)
344 unsigned char *id_string, *key, *cipher, *hmac, hash[SILC_HASH_MAXLEN];
347 SilcChannelKeyPayload payload;
349 payload = silc_channel_key_payload_parse(silc_buffer_data(key_payload),
350 silc_buffer_len(key_payload));
354 id_string = silc_channel_key_get_id(payload, &tmp_len);
356 silc_channel_key_payload_free(payload);
360 if (!silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL, &id, sizeof(id))) {
361 silc_channel_key_payload_free(payload);
367 channel = silc_client_get_channel_by_id(client, conn, &id);
369 silc_channel_key_payload_free(payload);
373 silc_client_ref_channel(client, conn, channel);
376 /* Save the old key for a short period of time so that we can decrypt
377 channel message even after the rekey if some client would be sending
378 messages with the old key after the rekey. */
379 if (!channel->internal.old_channel_keys)
380 channel->internal.old_channel_keys = silc_dlist_init();
381 if (!channel->internal.old_hmacs)
382 channel->internal.old_hmacs = silc_dlist_init();
383 if (channel->internal.old_channel_keys && channel->internal.old_hmacs) {
384 silc_dlist_add(channel->internal.old_channel_keys,
385 channel->internal.channel_key);
386 silc_dlist_add(channel->internal.old_hmacs, channel->internal.hmac);
387 silc_schedule_task_add_timeout(client->schedule,
388 silc_client_save_channel_key_rekey,
392 /* Get channel cipher */
393 cipher = silc_channel_key_get_cipher(payload, NULL);
394 if (!silc_cipher_alloc(cipher, &channel->internal.channel_key)) {
395 client->internal->ops->say(
397 SILC_CLIENT_MESSAGE_AUDIT,
398 "Cannot talk to channel: unsupported cipher %s",
400 silc_client_unref_channel(client, conn, channel);
401 silc_channel_key_payload_free(payload);
405 /* Set the cipher key */
406 key = silc_channel_key_get_key(payload, &tmp_len);
407 silc_cipher_set_key(channel->internal.channel_key, key, tmp_len * 8);
409 /* Get channel HMAC */
410 hmac = (channel->internal.hmac ?
411 (char *)silc_hmac_get_name(channel->internal.hmac) :
413 if (!silc_hmac_alloc(hmac, NULL, &channel->internal.hmac)) {
414 client->internal->ops->say(
416 SILC_CLIENT_MESSAGE_AUDIT,
417 "Cannot talk to channel: unsupported HMAC %s",
419 silc_client_unref_channel(client, conn, channel);
420 silc_channel_key_payload_free(payload);
425 silc_hash_make(silc_hmac_get_hash(channel->internal.hmac), key,
427 silc_hmac_set_key(channel->internal.hmac, hash,
428 silc_hash_len(silc_hmac_get_hash(channel->internal.hmac)));
429 memset(hash, 0, sizeof(hash));
431 silc_client_unref_channel(client, conn, channel);
436 /* Received channel key packet. The key will replace old channel key. */
438 SILC_FSM_STATE(silc_client_channel_key)
440 SilcClientConnection conn = fsm_context;
441 SilcClient client = conn->client;
442 SilcPacket packet = state_context;
444 SILC_LOG_DEBUG(("Received channel key"));
447 silc_client_save_channel_key(client, conn, &packet->buffer, NULL);
448 silc_packet_free(packet);
450 return SILC_FSM_FINISH;
453 /**************************** Channel Private Key ***************************/
455 /* Add new channel private key */
457 SilcBool silc_client_add_channel_private_key(SilcClient client,
458 SilcClientConnection conn,
459 SilcChannelEntry channel,
465 SilcChannelPrivateKey *ret_key)
467 SilcChannelPrivateKey entry;
468 unsigned char hash[SILC_HASH_MAXLEN];
469 SilcSKEKeyMaterial keymat;
471 if (!client || !conn || !channel)
475 cipher = SILC_DEFAULT_CIPHER;
477 hmac = SILC_DEFAULT_HMAC;
479 if (!silc_cipher_is_supported(cipher))
481 if (!silc_hmac_is_supported(hmac))
484 if (!channel->internal.private_keys) {
485 channel->internal.private_keys = silc_dlist_init();
486 if (!channel->internal.private_keys)
490 /* Produce the key material */
491 keymat = silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
492 conn->internal->sha1hash);
497 entry = silc_calloc(1, sizeof(*entry));
499 silc_ske_free_key_material(keymat);
502 entry->name = name ? strdup(name) : NULL;
504 /* Allocate the cipher and set the key*/
505 if (!silc_cipher_alloc(cipher, &entry->cipher)) {
507 silc_free(entry->name);
508 silc_ske_free_key_material(keymat);
511 silc_cipher_set_key(entry->cipher, keymat->send_enc_key,
512 keymat->enc_key_len);
514 /* Generate HMAC key from the channel key data and set it */
515 if (!silc_hmac_alloc(hmac, NULL, &entry->hmac)) {
517 silc_free(entry->name);
518 silc_cipher_free(entry->cipher);
519 silc_ske_free_key_material(keymat);
522 silc_hash_make(silc_hmac_get_hash(entry->hmac), keymat->send_enc_key,
523 keymat->enc_key_len / 8, hash);
524 silc_hmac_set_key(entry->hmac, hash,
525 silc_hash_len(silc_hmac_get_hash(entry->hmac)));
526 memset(hash, 0, sizeof(hash));
528 /* Add to the private keys list */
529 silc_dlist_add(channel->internal.private_keys, entry);
531 if (!channel->internal.curr_key)
532 channel->internal.curr_key = entry;
534 /* Free the key material */
535 silc_ske_free_key_material(keymat);
543 /* Removes all private keys from the `channel'. The old channel key is used
544 after calling this to protect the channel messages. Returns FALSE on
545 on error, TRUE otherwise. */
547 SilcBool silc_client_del_channel_private_keys(SilcClient client,
548 SilcClientConnection conn,
549 SilcChannelEntry channel)
551 SilcChannelPrivateKey entry;
553 if (!client || !conn || !channel)
556 if (!channel->internal.private_keys)
559 silc_dlist_start(channel->internal.private_keys);
560 while ((entry = silc_dlist_get(channel->internal.private_keys))) {
561 silc_dlist_del(channel->internal.private_keys, entry);
562 silc_free(entry->name);
563 silc_cipher_free(entry->cipher);
564 silc_hmac_free(entry->hmac);
568 channel->internal.curr_key = NULL;
570 silc_dlist_uninit(channel->internal.private_keys);
571 channel->internal.private_keys = NULL;
576 /* Removes and frees private key `key' from the channel `channel'. The `key'
577 is retrieved by calling the function silc_client_list_channel_private_keys.
578 The key is not used after this. If the key was last private key then the
579 old channel key is used hereafter to protect the channel messages. This
580 returns FALSE on error, TRUE otherwise. */
582 SilcBool silc_client_del_channel_private_key(SilcClient client,
583 SilcClientConnection conn,
584 SilcChannelEntry channel,
585 SilcChannelPrivateKey key)
587 SilcChannelPrivateKey entry;
589 if (!client || !conn || !channel)
592 if (!channel->internal.private_keys)
595 silc_dlist_start(channel->internal.private_keys);
596 while ((entry = silc_dlist_get(channel->internal.private_keys))) {
600 if (channel->internal.curr_key == entry)
601 channel->internal.curr_key = NULL;
603 silc_dlist_del(channel->internal.private_keys, entry);
604 silc_free(entry->name);
605 silc_cipher_free(entry->cipher);
606 silc_hmac_free(entry->hmac);
609 if (silc_dlist_count(channel->internal.private_keys) == 0) {
610 silc_dlist_uninit(channel->internal.private_keys);
611 channel->internal.private_keys = NULL;
620 /* Returns array (pointers) of private keys associated to the `channel'.
621 The caller must free the array by calling the function
622 silc_client_free_channel_private_keys. The pointers in the array may be
623 used to delete the specific key by giving the pointer as argument to the
624 function silc_client_del_channel_private_key. */
626 SilcDList silc_client_list_channel_private_keys(SilcClient client,
627 SilcClientConnection conn,
628 SilcChannelEntry channel)
630 SilcChannelPrivateKey entry;
633 if (!client || !conn || !channel)
636 if (!channel->internal.private_keys)
639 list = silc_dlist_init();
643 silc_dlist_start(channel->internal.private_keys);
644 while ((entry = silc_dlist_get(channel->internal.private_keys)))
645 silc_dlist_add(list, entry);
650 /* Sets the `key' to be used as current channel private key on the
651 `channel'. Packet sent after calling this function will be secured
654 void silc_client_current_channel_private_key(SilcClient client,
655 SilcClientConnection conn,
656 SilcChannelEntry channel,
657 SilcChannelPrivateKey key)
661 channel->internal.curr_key = key;
664 /***************************** Utility routines *****************************/
666 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the
667 channel indicated by the `channel'. NULL if client is not joined on
670 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
671 SilcClientEntry client_entry)
675 if (silc_hash_table_find(channel->user_list, client_entry, NULL,
682 /* Adds client to channel. Returns TRUE if user was added or is already
683 added to the channel, FALSE on error. */
685 SilcBool silc_client_add_to_channel(SilcClient client,
686 SilcClientConnection conn,
687 SilcChannelEntry channel,
688 SilcClientEntry client_entry,
693 if (silc_client_on_channel(channel, client_entry))
696 chu = silc_calloc(1, sizeof(*chu));
700 chu->client = client_entry;
701 chu->channel = channel;
704 silc_client_ref_client(client, conn, client_entry);
705 silc_client_ref_channel(client, conn, channel);
707 silc_hash_table_add(channel->user_list, client_entry, chu);
708 silc_hash_table_add(client_entry->channels, channel, chu);
713 /* Removes client from a channel */
715 SilcBool silc_client_remove_from_channel(SilcClient client,
716 SilcClientConnection conn,
717 SilcChannelEntry channel,
718 SilcClientEntry client_entry)
722 chu = silc_client_on_channel(channel, client_entry);
726 silc_hash_table_del(chu->client->channels, chu->channel);
727 silc_hash_table_del(chu->channel->user_list, chu->client);
730 silc_client_unref_client(client, conn, client_entry);
731 silc_client_unref_channel(client, conn, channel);
736 /* Removes a client entry from all channels it has joined. */
738 void silc_client_remove_from_channels(SilcClient client,
739 SilcClientConnection conn,
740 SilcClientEntry client_entry)
742 SilcHashTableList htl;
745 silc_hash_table_list(client_entry->channels, &htl);
746 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
747 silc_hash_table_del(chu->client->channels, chu->channel);
748 silc_hash_table_del(chu->channel->user_list, chu->client);
749 silc_client_unref_client(client, conn, chu->client);
750 silc_client_unref_channel(client, conn, chu->channel);
754 silc_hash_table_list_reset(&htl);
757 /* Empties channel from users. */
759 void silc_client_empty_channel(SilcClient client,
760 SilcClientConnection conn,
761 SilcChannelEntry channel)
763 SilcHashTableList htl;
766 silc_hash_table_list(channel->user_list, &htl);
767 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
768 silc_hash_table_del(chu->client->channels, chu->channel);
769 silc_hash_table_del(chu->channel->user_list, chu->client);
770 silc_client_unref_client(client, conn, chu->client);
771 silc_client_unref_channel(client, conn, chu->channel);
774 silc_hash_table_list_reset(&htl);