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 /* If there is no channel private key then just decrypt the message
206 with the channel key. If private keys are set then just go through
207 all private keys and check what decrypts correctly. */
208 if (!channel->internal.private_keys) {
209 /* Parse the channel message payload. This also decrypts the payload */
210 payload = silc_message_payload_parse(silc_buffer_data(buffer),
211 silc_buffer_len(buffer), FALSE,
212 FALSE, channel->internal.channel_key,
213 channel->internal.hmac, NULL,
216 /* If decryption failed and we have just performed channel key rekey
217 we will use the old key in decryption. If that fails too then we
218 cannot do more and will drop the packet. */
223 if (!channel->internal.old_channel_keys ||
224 !silc_dlist_count(channel->internal.old_channel_keys))
227 SILC_LOG_DEBUG(("Attempting to decrypt with old channel key(s)"));
229 silc_dlist_end(channel->internal.old_channel_keys);
230 silc_dlist_end(channel->internal.old_hmacs);
231 while ((cipher = silc_dlist_get(channel->internal.old_channel_keys))) {
232 hmac = silc_dlist_get(channel->internal.old_hmacs);
236 payload = silc_message_payload_parse(silc_buffer_data(buffer),
237 silc_buffer_len(buffer),
238 FALSE, FALSE, cipher, hmac,
247 /* If the private key mode is not set on the channel then try the actual
248 channel key first before trying private keys. */
249 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
250 payload = silc_message_payload_parse(silc_buffer_data(buffer),
251 silc_buffer_len(buffer),
253 channel->internal.channel_key,
254 channel->internal.hmac, NULL,
258 silc_dlist_start(channel->internal.private_keys);
259 while ((key = silc_dlist_get(channel->internal.private_keys))) {
260 /* Parse the message payload. This also decrypts the payload */
261 payload = silc_message_payload_parse(silc_buffer_data(buffer),
262 silc_buffer_len(buffer),
263 FALSE, FALSE, key->cipher,
264 key->hmac, NULL, FALSE, NULL);
268 if (key == SILC_LIST_END)
273 message = silc_message_get_data(payload, &message_len);
275 /* Pass the message to application */
276 client->internal->ops->channel_message(
277 client, conn, client_entry, channel, payload,
278 key, silc_message_get_flags(payload),
279 message, message_len);
282 silc_client_unref_client(client, conn, client_entry);
283 silc_client_unref_channel(client, conn, channel);
285 silc_message_payload_free(payload);
286 return SILC_FSM_FINISH;
289 /* Channel message error. */
291 SILC_FSM_STATE(silc_client_channel_message_error)
293 SilcPacket packet = state_context;
294 silc_packet_free(packet);
295 return SILC_FSM_FINISH;
298 /******************************* Channel Key ********************************/
300 /* Timeout callback that is called after a short period of time after the
301 new channel key has been created. This removes the first channel key
304 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
306 SilcChannelEntry channel = (SilcChannelEntry)context;
310 if (channel->internal.old_channel_keys) {
311 silc_dlist_start(channel->internal.old_channel_keys);
312 key = silc_dlist_get(channel->internal.old_channel_keys);
314 silc_dlist_del(channel->internal.old_channel_keys, key);
315 silc_cipher_free(key);
319 if (channel->internal.old_hmacs) {
320 silc_dlist_start(channel->internal.old_hmacs);
321 hmac = silc_dlist_get(channel->internal.old_hmacs);
323 silc_dlist_del(channel->internal.old_hmacs, hmac);
324 silc_hmac_free(hmac);
329 /* Saves channel key from encoded `key_payload'. This is used when we receive
330 Channel Key Payload and when we are processing JOIN command reply. */
332 SilcBool silc_client_save_channel_key(SilcClient client,
333 SilcClientConnection conn,
334 SilcBuffer key_payload,
335 SilcChannelEntry channel)
337 unsigned char *id_string, *key, *cipher, *hmac, hash[SILC_HASH_MAXLEN];
340 SilcChannelKeyPayload payload;
342 payload = silc_channel_key_payload_parse(silc_buffer_data(key_payload),
343 silc_buffer_len(key_payload));
347 id_string = silc_channel_key_get_id(payload, &tmp_len);
349 silc_channel_key_payload_free(payload);
353 if (!silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL, &id, sizeof(id))) {
354 silc_channel_key_payload_free(payload);
360 channel = silc_client_get_channel_by_id(client, conn, &id);
362 silc_channel_key_payload_free(payload);
366 silc_client_ref_channel(client, conn, channel);
369 /* Save the old key for a short period of time so that we can decrypt
370 channel message even after the rekey if some client would be sending
371 messages with the old key after the rekey. */
372 if (!channel->internal.old_channel_keys)
373 channel->internal.old_channel_keys = silc_dlist_init();
374 if (!channel->internal.old_hmacs)
375 channel->internal.old_hmacs = silc_dlist_init();
376 if (channel->internal.old_channel_keys && channel->internal.old_hmacs) {
377 silc_dlist_add(channel->internal.old_channel_keys,
378 channel->internal.channel_key);
379 silc_dlist_add(channel->internal.old_hmacs, channel->internal.hmac);
380 silc_schedule_task_add_timeout(client->schedule,
381 silc_client_save_channel_key_rekey,
385 /* Get channel cipher */
386 cipher = silc_channel_key_get_cipher(payload, NULL);
387 if (!silc_cipher_alloc(cipher, &channel->internal.channel_key)) {
388 client->internal->ops->say(
390 SILC_CLIENT_MESSAGE_AUDIT,
391 "Cannot talk to channel: unsupported cipher %s",
393 silc_client_unref_channel(client, conn, channel);
394 silc_channel_key_payload_free(payload);
398 /* Set the cipher key */
399 key = silc_channel_key_get_key(payload, &tmp_len);
400 silc_cipher_set_key(channel->internal.channel_key, key, tmp_len * 8);
402 /* Get channel HMAC */
403 hmac = (channel->internal.hmac ?
404 (char *)silc_hmac_get_name(channel->internal.hmac) :
406 if (!silc_hmac_alloc(hmac, NULL, &channel->internal.hmac)) {
407 client->internal->ops->say(
409 SILC_CLIENT_MESSAGE_AUDIT,
410 "Cannot talk to channel: unsupported HMAC %s",
412 silc_client_unref_channel(client, conn, channel);
413 silc_channel_key_payload_free(payload);
418 silc_hash_make(silc_hmac_get_hash(channel->internal.hmac), key,
420 silc_hmac_set_key(channel->internal.hmac, hash,
421 silc_hash_len(silc_hmac_get_hash(channel->internal.hmac)));
422 memset(hash, 0, sizeof(hash));
424 silc_client_unref_channel(client, conn, channel);
429 /* Received channel key packet. The key will replace old channel key. */
431 SILC_FSM_STATE(silc_client_channel_key)
433 SilcClientConnection conn = fsm_context;
434 SilcClient client = conn->client;
435 SilcPacket packet = state_context;
437 SILC_LOG_DEBUG(("Received channel key"));
440 silc_client_save_channel_key(client, conn, &packet->buffer, NULL);
441 silc_packet_free(packet);
443 return SILC_FSM_FINISH;
446 /**************************** Channel Private Key ***************************/
448 /* Add new channel private key */
450 SilcBool silc_client_add_channel_private_key(SilcClient client,
451 SilcClientConnection conn,
452 SilcChannelEntry channel,
458 SilcChannelPrivateKey *ret_key)
460 SilcChannelPrivateKey entry;
461 unsigned char hash[SILC_HASH_MAXLEN];
462 SilcSKEKeyMaterial keymat;
464 if (!client || !conn || !channel)
468 cipher = SILC_DEFAULT_CIPHER;
470 hmac = SILC_DEFAULT_HMAC;
472 if (!silc_cipher_is_supported(cipher))
474 if (!silc_hmac_is_supported(hmac))
477 if (!channel->internal.private_keys) {
478 channel->internal.private_keys = silc_dlist_init();
479 if (!channel->internal.private_keys)
483 /* Produce the key material */
484 keymat = silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
485 conn->internal->sha1hash);
490 entry = silc_calloc(1, sizeof(*entry));
492 silc_ske_free_key_material(keymat);
495 entry->name = name ? strdup(name) : NULL;
497 /* Allocate the cipher and set the key*/
498 if (!silc_cipher_alloc(cipher, &entry->cipher)) {
500 silc_free(entry->name);
501 silc_ske_free_key_material(keymat);
504 silc_cipher_set_key(entry->cipher, keymat->send_enc_key,
505 keymat->enc_key_len);
507 /* Generate HMAC key from the channel key data and set it */
508 if (!silc_hmac_alloc(hmac, NULL, &entry->hmac)) {
510 silc_free(entry->name);
511 silc_cipher_free(entry->cipher);
512 silc_ske_free_key_material(keymat);
515 silc_hash_make(silc_hmac_get_hash(entry->hmac), keymat->send_enc_key,
516 keymat->enc_key_len / 8, hash);
517 silc_hmac_set_key(entry->hmac, hash,
518 silc_hash_len(silc_hmac_get_hash(entry->hmac)));
519 memset(hash, 0, sizeof(hash));
521 /* Add to the private keys list */
522 silc_dlist_add(channel->internal.private_keys, entry);
524 if (!channel->internal.curr_key)
525 channel->internal.curr_key = entry;
527 /* Free the key material */
528 silc_ske_free_key_material(keymat);
536 /* Removes all private keys from the `channel'. The old channel key is used
537 after calling this to protect the channel messages. Returns FALSE on
538 on error, TRUE otherwise. */
540 SilcBool silc_client_del_channel_private_keys(SilcClient client,
541 SilcClientConnection conn,
542 SilcChannelEntry channel)
544 SilcChannelPrivateKey entry;
546 if (!client || !conn || !channel)
549 if (!channel->internal.private_keys)
552 silc_dlist_start(channel->internal.private_keys);
553 while ((entry = silc_dlist_get(channel->internal.private_keys))) {
554 silc_dlist_del(channel->internal.private_keys, entry);
555 silc_free(entry->name);
556 silc_cipher_free(entry->cipher);
557 silc_hmac_free(entry->hmac);
561 channel->internal.curr_key = NULL;
563 silc_dlist_uninit(channel->internal.private_keys);
564 channel->internal.private_keys = NULL;
569 /* Removes and frees private key `key' from the channel `channel'. The `key'
570 is retrieved by calling the function silc_client_list_channel_private_keys.
571 The key is not used after this. If the key was last private key then the
572 old channel key is used hereafter to protect the channel messages. This
573 returns FALSE on error, TRUE otherwise. */
575 SilcBool silc_client_del_channel_private_key(SilcClient client,
576 SilcClientConnection conn,
577 SilcChannelEntry channel,
578 SilcChannelPrivateKey key)
580 SilcChannelPrivateKey entry;
582 if (!client || !conn || !channel)
585 if (!channel->internal.private_keys)
588 silc_dlist_start(channel->internal.private_keys);
589 while ((entry = silc_dlist_get(channel->internal.private_keys))) {
593 if (channel->internal.curr_key == entry)
594 channel->internal.curr_key = NULL;
596 silc_dlist_del(channel->internal.private_keys, entry);
597 silc_free(entry->name);
598 silc_cipher_free(entry->cipher);
599 silc_hmac_free(entry->hmac);
602 if (silc_dlist_count(channel->internal.private_keys) == 0) {
603 silc_dlist_uninit(channel->internal.private_keys);
604 channel->internal.private_keys = NULL;
613 /* Returns array (pointers) of private keys associated to the `channel'.
614 The caller must free the array by calling the function
615 silc_client_free_channel_private_keys. The pointers in the array may be
616 used to delete the specific key by giving the pointer as argument to the
617 function silc_client_del_channel_private_key. */
619 SilcDList silc_client_list_channel_private_keys(SilcClient client,
620 SilcClientConnection conn,
621 SilcChannelEntry channel)
623 SilcChannelPrivateKey entry;
626 if (!client || !conn || !channel)
629 if (!channel->internal.private_keys)
632 list = silc_dlist_init();
636 silc_dlist_start(channel->internal.private_keys);
637 while ((entry = silc_dlist_get(channel->internal.private_keys)))
638 silc_dlist_add(list, entry);
643 /* Sets the `key' to be used as current channel private key on the
644 `channel'. Packet sent after calling this function will be secured
647 void silc_client_current_channel_private_key(SilcClient client,
648 SilcClientConnection conn,
649 SilcChannelEntry channel,
650 SilcChannelPrivateKey key)
654 channel->internal.curr_key = key;
657 /***************************** Utility routines *****************************/
659 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the
660 channel indicated by the `channel'. NULL if client is not joined on
663 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
664 SilcClientEntry client_entry)
668 if (silc_hash_table_find(channel->user_list, client_entry, NULL,
675 /* Adds client to channel. Returns TRUE if user was added or is already
676 added to the channel, FALSE on error. */
678 SilcBool silc_client_add_to_channel(SilcClient client,
679 SilcClientConnection conn,
680 SilcChannelEntry channel,
681 SilcClientEntry client_entry,
686 if (silc_client_on_channel(channel, client_entry))
689 chu = silc_calloc(1, sizeof(*chu));
693 chu->client = client_entry;
694 chu->channel = channel;
697 silc_client_ref_client(client, conn, client_entry);
698 silc_client_ref_channel(client, conn, channel);
700 silc_hash_table_add(channel->user_list, client_entry, chu);
701 silc_hash_table_add(client_entry->channels, channel, chu);
706 /* Removes client from a channel */
708 SilcBool silc_client_remove_from_channel(SilcClient client,
709 SilcClientConnection conn,
710 SilcChannelEntry channel,
711 SilcClientEntry client_entry)
715 chu = silc_client_on_channel(channel, client_entry);
719 silc_hash_table_del(chu->client->channels, chu->channel);
720 silc_hash_table_del(chu->channel->user_list, chu->client);
723 silc_client_unref_client(client, conn, client_entry);
724 silc_client_unref_channel(client, conn, channel);
729 /* Removes a client entry from all channels it has joined. */
731 void silc_client_remove_from_channels(SilcClient client,
732 SilcClientConnection conn,
733 SilcClientEntry client_entry)
735 SilcHashTableList htl;
738 silc_hash_table_list(client_entry->channels, &htl);
739 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
740 silc_hash_table_del(chu->client->channels, chu->channel);
741 silc_hash_table_del(chu->channel->user_list, chu->client);
742 silc_client_unref_client(client, conn, chu->client);
743 silc_client_unref_channel(client, conn, chu->channel);
747 silc_hash_table_list_reset(&htl);
750 /* Empties channel from users. */
752 void silc_client_empty_channel(SilcClient client,
753 SilcClientConnection conn,
754 SilcChannelEntry channel)
756 SilcHashTableList htl;
759 silc_hash_table_list(channel->user_list, &htl);
760 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
761 silc_hash_table_del(chu->client->channels, chu->channel);
762 silc_hash_table_del(chu->channel->user_list, chu->client);
763 silc_client_unref_client(client, conn, chu->client);
764 silc_client_unref_channel(client, conn, chu->channel);
767 silc_hash_table_list_reset(&htl);