updates.
[silc.git] / lib / silcclient / client_channel.c
1 /*
2
3   client_channel.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
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; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21 /* This file includes channel message sending and receiving routines,
22    channel key receiving and setting, and channel private key handling 
23    routines. */
24
25 #include "silcincludes.h"
26 #include "silcclient.h"
27 #include "client_internal.h"
28
29 /* Sends packet to the `channel'. Packet to channel is always encrypted
30    differently from "normal" packets. SILC header of the packet is 
31    encrypted with the next receiver's key and the rest of the packet is
32    encrypted with the channel specific key. Padding and HMAC is computed
33    with the next receiver's key. The `data' is the channel message. If
34    the `force_send' is TRUE then the packet is sent immediately. */
35
36 void silc_client_send_channel_message(SilcClient client, 
37                                       SilcClientConnection conn,
38                                       SilcChannelEntry channel,
39                                       SilcChannelPrivateKey key,
40                                       SilcMessageFlags flags,
41                                       unsigned char *data, 
42                                       SilcUInt32 data_len, 
43                                       int force_send)
44 {
45   int i;
46   SilcSocketConnection sock = conn->sock;
47   SilcBuffer payload;
48   SilcPacketContext packetdata;
49   const SilcBufferStruct packet;
50   SilcCipher cipher;
51   SilcHmac hmac;
52   unsigned char *id_string;
53   SilcUInt32 iv_len;
54   int block_len;
55   SilcChannelUser chu;
56
57   SILC_LOG_DEBUG(("Sending packet to channel"));
58
59   chu = silc_client_on_channel(channel, conn->local_entry);
60   if (!chu) {
61     SILC_LOG_ERROR(("Cannot send message to channel we are not joined"));
62     return;
63   }
64
65   /* Check if it is allowed to send messages to this channel by us. */
66   if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS && !chu->mode)
67     return;
68   if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS && 
69       chu->mode & SILC_CHANNEL_UMODE_CHANOP &&
70       !(chu->mode & SILC_CHANNEL_UMODE_CHANFO))
71     return;
72   if (chu->mode & SILC_CHANNEL_UMODE_QUIET)
73     return;
74
75   /* Take the key to be used */
76   if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
77     if (key) {
78       /* Use key application specified */
79       cipher = key->cipher;
80       hmac = key->hmac;
81     } else if (channel->curr_key) {
82       /* Use current private key */
83       cipher = channel->curr_key->cipher;
84       hmac = channel->curr_key->hmac;
85     } else if (!channel->curr_key && channel->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->private_keys);
89       key = silc_dlist_get(channel->private_keys);
90       cipher = key->cipher;
91       hmac = key->hmac;
92       
93       /* Use this key as current private key */
94       channel->curr_key = key;
95     } else {
96       /* Use normal channel key generated by the server */
97       cipher = channel->channel_key;
98       hmac = channel->hmac;
99     }
100   } else {
101     /* Use normal channel key generated by the server */
102     cipher = channel->channel_key;
103     hmac = channel->hmac;
104   }
105
106   if (!cipher || !hmac)
107     return;
108
109   block_len = silc_cipher_get_block_len(cipher);
110
111   /* Generate IV */
112   iv_len = silc_cipher_get_block_len(cipher);
113   if (channel->iv[0] == '\0')
114     for (i = 0; i < iv_len; i++) channel->iv[i] = 
115                                    silc_rng_get_byte(client->rng);
116   else
117     silc_hash_make(client->internal->md5hash, channel->iv, iv_len, 
118                    channel->iv);
119
120   /* Encode the channel payload. This also encrypts the message payload. */
121   payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len, 
122                                                 channel->iv, cipher, hmac,
123                                                 client->rng);
124
125   /* Get data used in packet header encryption, keys and stuff. */
126   cipher = conn->send_key;
127   hmac = conn->hmac_send;
128   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
129
130   /* Set the packet context pointers. The destination ID is always
131      the Channel ID of the channel. Server and router will handle the
132      distribution of the packet. */
133   data = payload->data;
134   data_len = payload->len;
135   packetdata.flags = 0;
136   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
137   packetdata.src_id = conn->local_id_data;
138   packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
139   packetdata.src_id_type = SILC_ID_CLIENT;
140   packetdata.dst_id = id_string;
141   packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
142   packetdata.dst_id_type = SILC_ID_CHANNEL;
143   data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
144                                  packetdata.src_id_len +
145                                  packetdata.dst_id_len);
146   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
147     packetdata.src_id_len + packetdata.dst_id_len;
148   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
149                                           packetdata.src_id_len +
150                                           packetdata.dst_id_len), block_len);
151
152   /* Create the outgoing packet */
153   if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
154                             data, data_len, (const SilcBuffer)&packet)) {
155     SILC_LOG_ERROR(("Error assembling packet"));
156     goto out;
157   }
158
159   /* Encrypt the header and padding of the packet. This is encrypted 
160      with normal session key shared with our server. */
161   silc_packet_encrypt(cipher, hmac, conn->psn_send++,
162                       (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN + 
163                       packetdata.src_id_len + packetdata.dst_id_len +
164                       packetdata.padlen);
165
166   SILC_LOG_HEXDUMP(("Packet to channel, len %d", packet.len),
167                     packet.data, packet.len);
168
169   /* Now actually send the packet */
170   silc_client_packet_send_real(client, sock, force_send);
171
172  out:
173   silc_buffer_free(payload);
174   silc_free(id_string);
175 }
176
177 typedef struct {
178   SilcChannelMessagePayload payload;
179   SilcChannelID *channel_id;
180 } *SilcChannelClientResolve;
181
182 static void silc_client_channel_message_cb(SilcClient client,
183                                            SilcClientConnection conn,
184                                            SilcClientEntry *clients,
185                                            SilcUInt32 clients_count,
186                                            void *context)
187 {
188   SilcChannelClientResolve res = (SilcChannelClientResolve)context;
189
190   if (clients_count == 1) {
191     SilcChannelEntry channel;
192     unsigned char *message;
193     SilcUInt32 message_len;
194
195     channel = silc_client_get_channel_by_id(client, conn, res->channel_id);
196     if (!channel)
197       goto out;
198
199     /* If this client is not on channel, add it there since it clearly
200        is there. */
201     if (!silc_client_on_channel(channel, clients[0])) {
202       SilcChannelUser chu = silc_calloc(1, sizeof(*chu));
203       chu->client = clients[0];
204       chu->channel = channel;
205       silc_hash_table_add(channel->user_list, clients[0], chu);
206       silc_hash_table_add(clients[0]->channels, channel, chu);
207     }
208
209     message = silc_channel_message_get_data(res->payload, &message_len);
210     
211     /* Pass the message to application */
212     client->internal->ops->channel_message(
213                                client, conn, clients[0], channel,
214                                silc_channel_message_get_flags(res->payload),
215                                message, message_len);
216   }
217
218  out:
219   silc_channel_message_payload_free(res->payload);
220   silc_free(res->channel_id);
221   silc_free(res);
222 }
223
224 /* Process received message to a channel (or from a channel, really). This
225    decrypts the channel message with channel specific key and parses the
226    channel payload. Finally it displays the message on the screen. */
227
228 void silc_client_channel_message(SilcClient client, 
229                                  SilcSocketConnection sock, 
230                                  SilcPacketContext *packet)
231 {
232   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
233   SilcBuffer buffer = packet->buffer;
234   SilcChannelMessagePayload payload = NULL;
235   SilcChannelID *id = NULL;
236   SilcChannelEntry channel;
237   SilcClientEntry client_entry;
238   SilcClientID *client_id = NULL;
239   unsigned char *message;
240   SilcUInt32 message_len;
241
242   SILC_LOG_DEBUG(("Start"));
243
244   /* Sanity checks */
245   if (packet->dst_id_type != SILC_ID_CHANNEL)
246     goto out;
247
248   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
249                              SILC_ID_CLIENT);
250   if (!client_id)
251     goto out;
252   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
253   if (!id)
254     goto out;
255
256   /* Find the channel entry from channels on this connection */
257   channel = silc_client_get_channel_by_id(client, conn, id);
258   if (!channel)
259     goto out;
260
261   /* If there is no channel private key then just decrypt the message 
262      with the channel key. If private keys are set then just go through
263      all private keys and check what decrypts correctly. */
264   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
265     /* Parse the channel message payload. This also decrypts the payload */
266     payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
267                                                  channel->channel_key,
268                                                  channel->hmac);
269
270     /* If decryption failed and we have just performed channel key rekey
271        we will use the old key in decryption. If that fails too then we
272        cannot do more and will drop the packet. */
273     if (!payload) {
274       if (!channel->old_channel_key) {
275         goto out;
276       }
277
278       payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
279                                                    channel->old_channel_key,
280                                                    channel->old_hmac);
281       if (!payload) {
282         goto out;
283       }
284     }
285   } else if (channel->private_keys) {
286     SilcChannelPrivateKey entry;
287
288     silc_dlist_start(channel->private_keys);
289     while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
290       /* Parse the channel message payload. This also decrypts the payload */
291       payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
292                                                    entry->cipher,
293                                                    entry->hmac);
294       if (payload)
295         break;
296     }
297     if (entry == SILC_LIST_END)
298       goto out;
299   } else {
300     goto out;
301   }
302
303   /* Find client entry */
304   client_entry = silc_client_get_client_by_id(client, conn, client_id);
305   if (!client_entry || !client_entry->nickname) {
306     /* Resolve the client info */
307     SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
308     res->payload = payload;
309     res->channel_id = id;
310     silc_client_get_client_by_id_resolve(client, conn, client_id,
311                                          silc_client_channel_message_cb,
312                                          res);
313     payload = NULL;
314     id = NULL;
315     goto out;
316   }
317
318   if (!silc_client_on_channel(channel, client_entry)) {
319     SILC_LOG_WARNING(("Received channel message from client not on channel"));
320     goto out;
321   }
322
323   message = silc_channel_message_get_data(payload, &message_len);
324
325   /* Pass the message to application */
326   client->internal->ops->channel_message(
327                                  client, conn, client_entry, channel,
328                                  silc_channel_message_get_flags(payload),
329                                  message, message_len);
330
331  out:
332   silc_free(id);
333   silc_free(client_id);
334   if (payload)
335     silc_channel_message_payload_free(payload);
336 }
337
338 /* Timeout callback that is called after a short period of time after the
339    new channel key has been created. This removes the old channel key all
340    together. */
341
342 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
343 {
344   SilcChannelEntry channel = (SilcChannelEntry)context;
345
346   if (channel->old_channel_key)
347     silc_cipher_free(channel->old_channel_key);
348   if (channel->old_hmac)
349     silc_hmac_free(channel->old_hmac);
350   channel->old_channel_key = NULL;
351   channel->old_hmac = NULL;
352   channel->rekey_task = NULL;
353 }
354
355 /* Saves channel key from encoded `key_payload'. This is used when we
356    receive Channel Key Payload and when we are processing JOIN command 
357    reply. */
358
359 void silc_client_save_channel_key(SilcClient client,
360                                   SilcClientConnection conn,
361                                   SilcBuffer key_payload, 
362                                   SilcChannelEntry channel)
363 {
364   unsigned char *id_string, *key, *cipher, *hmac, hash[32];
365   SilcUInt32 tmp_len;
366   SilcChannelID *id;
367   SilcChannelKeyPayload payload;
368
369   payload = silc_channel_key_payload_parse(key_payload->data,
370                                            key_payload->len);
371   if (!payload)
372     return;
373
374   id_string = silc_channel_key_get_id(payload, &tmp_len);
375   if (!id_string) {
376     silc_channel_key_payload_free(payload);
377     return;
378   }
379
380   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
381   if (!id) {
382     silc_channel_key_payload_free(payload);
383     return;
384   }
385
386   /* Find channel. */
387   if (!channel) {
388     channel = silc_client_get_channel_by_id(client, conn, id);
389     if (!channel)
390       goto out;
391   }
392
393   hmac = (channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) : 
394           SILC_DEFAULT_HMAC);
395
396   /* Save the old key for a short period of time so that we can decrypt
397      channel message even after the rekey if some client would be sending
398      messages with the old key after the rekey. */
399   if (channel->old_channel_key)
400     silc_cipher_free(channel->old_channel_key);
401   if (channel->old_hmac)
402     silc_hmac_free(channel->old_hmac);
403   if (channel->rekey_task)
404     silc_schedule_task_del(client->schedule, channel->rekey_task);
405   channel->old_channel_key = channel->channel_key;
406   channel->old_hmac = channel->hmac;
407   channel->rekey_task = 
408     silc_schedule_task_add(client->schedule, 0,
409                            silc_client_save_channel_key_rekey, channel,
410                            10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
411
412   /* Free the old channel key data */
413   silc_free(channel->key);
414
415   /* Save the key */
416   key = silc_channel_key_get_key(payload, &tmp_len);
417   cipher = silc_channel_key_get_cipher(payload, NULL);
418   channel->key_len = tmp_len * 8;
419   channel->key = silc_memdup(key, tmp_len);
420
421   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
422     client->internal->ops->say(
423                            conn->client, conn, 
424                            SILC_CLIENT_MESSAGE_AUDIT,
425                            "Cannot talk to channel: unsupported cipher %s", 
426                            cipher);
427     goto out;
428   }
429
430   /* Set the cipher key */
431   silc_cipher_set_key(channel->channel_key, key, channel->key_len);
432
433   /* Generate HMAC key from the channel key data and set it */
434   silc_hmac_alloc(hmac, NULL, &channel->hmac);
435   silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
436   silc_hmac_set_key(channel->hmac, hash, 
437                     silc_hash_len(silc_hmac_get_hash(channel->hmac)));
438   memset(hash, 0, sizeof(hash));
439
440  out:
441   silc_free(id);
442   silc_channel_key_payload_free(payload);
443 }
444
445 /* Processes received key for channel. The received key will be used
446    to protect the traffic on the channel for now on. Client must receive
447    the key to the channel before talking on the channel is possible. 
448    This is the key that server has generated, this is not the channel
449    private key, it is entirely local setting. */
450
451 void silc_client_receive_channel_key(SilcClient client,
452                                      SilcSocketConnection sock,
453                                      SilcBuffer packet)
454 {
455   SILC_LOG_DEBUG(("Received key for channel"));
456
457   /* Save the key */
458   silc_client_save_channel_key(client, sock->user_data, packet, NULL);
459 }
460
461 /* Adds private key for channel. This may be set only if the channel's mode
462    mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
463    mode is not set. When channel has private key then the messages are
464    encrypted using that key. All clients on the channel must also know the
465    key in order to decrypt the messages. However, it is possible to have
466    several private keys per one channel. In this case only some of the
467    clients on the channel may know the one key and only some the other key.
468
469    If `cipher' and/or `hmac' is NULL then default values will be used 
470    (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
471
472    The private key for channel is optional. If it is not set then the
473    channel messages are encrypted using the channel key generated by the
474    server. However, setting the private key (or keys) for the channel 
475    significantly adds security. If more than one key is set the library
476    will automatically try all keys at the message decryption phase. Note:
477    setting many keys slows down the decryption phase as all keys has to
478    be tried in order to find the correct decryption key. However, setting
479    a few keys does not have big impact to the decryption performace. 
480
481    NOTE: that this is entirely local setting. The key set using this function
482    is not sent to the network at any phase.
483
484    NOTE: If the key material was originated by the SKE protocol (using
485    silc_client_send_key_agreement) then the `key' MUST be the
486    key->send_enc_key as this is dictated by the SILC protocol. However,
487    currently it is not expected that the SKE key material would be used
488    as channel private key. However, this API allows it. */
489
490 int silc_client_add_channel_private_key(SilcClient client,
491                                         SilcClientConnection conn,
492                                         SilcChannelEntry channel,
493                                         const char *name,
494                                         char *cipher,
495                                         char *hmac,
496                                         unsigned char *key,
497                                         SilcUInt32 key_len)
498 {
499   SilcChannelPrivateKey entry;
500   unsigned char hash[32];
501   SilcSKEKeyMaterial *keymat;
502
503   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
504     return FALSE;
505
506   if (!cipher)
507     cipher = SILC_DEFAULT_CIPHER;
508   if (!hmac)
509     hmac = SILC_DEFAULT_HMAC;
510
511   if (!silc_cipher_is_supported(cipher))
512     return FALSE;
513
514   if (!silc_hmac_is_supported(hmac))
515     return FALSE;
516
517   /* Produce the key material */
518   keymat = silc_calloc(1, sizeof(*keymat));
519   if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16, 
520                                          client->internal->md5hash, keymat) 
521       != SILC_SKE_STATUS_OK)
522     return FALSE;
523
524   /* Remove the current key, if it exists. */
525   if (channel->channel_key) {
526     silc_cipher_free(channel->channel_key);
527     memset(channel->key, 0, channel->key_len / 8);
528     silc_free(channel->key);
529     channel->channel_key = NULL;
530     channel->key = NULL;
531     channel->key_len = 0;
532   }
533   if (channel->hmac) {
534     silc_hmac_free(channel->hmac);
535     channel->hmac = NULL;
536   }
537
538   if (!channel->private_keys)
539     channel->private_keys = silc_dlist_init();
540
541   /* Save the key */
542   entry = silc_calloc(1, sizeof(*entry));
543   entry->name = name ? strdup(name) : NULL;
544   entry->key = silc_memdup(keymat->send_enc_key, keymat->enc_key_len / 8);
545   entry->key_len = keymat->enc_key_len / 8;
546
547   /* Allocate the cipher and set the key*/
548   silc_cipher_alloc(cipher, &entry->cipher);
549   silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
550
551   /* Generate HMAC key from the channel key data and set it */
552   silc_hmac_alloc(hmac, NULL, &entry->hmac);
553   silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key, 
554                  entry->key_len, hash);
555   silc_hmac_set_key(entry->hmac, hash, 
556                     silc_hash_len(silc_hmac_get_hash(entry->hmac)));
557   memset(hash, 0, sizeof(hash));
558
559   /* Add to the private keys list */
560   silc_dlist_add(channel->private_keys, entry);
561
562   if (!channel->curr_key)
563     channel->curr_key = entry;
564
565   /* Free the key material */
566   silc_ske_free_key_material(keymat);
567
568   return TRUE;
569 }
570
571 /* Removes all private keys from the `channel'. The old channel key is used
572    after calling this to protect the channel messages. Returns FALSE on
573    on error, TRUE otherwise. */
574
575 int silc_client_del_channel_private_keys(SilcClient client,
576                                          SilcClientConnection conn,
577                                          SilcChannelEntry channel)
578 {
579   SilcChannelPrivateKey entry;
580
581   if (!channel->private_keys)
582     return FALSE;
583
584   silc_dlist_start(channel->private_keys);
585   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
586     silc_dlist_del(channel->private_keys, entry);
587     memset(entry->key, 0, entry->key_len);
588     silc_free(entry->key);
589     silc_free(entry->name);
590     silc_cipher_free(entry->cipher);
591     silc_hmac_free(entry->hmac);
592     silc_free(entry);
593   }
594
595   channel->curr_key = NULL;
596
597   silc_dlist_uninit(channel->private_keys);
598   channel->private_keys = NULL;
599
600   return TRUE;
601 }
602
603 /* Removes and frees private key `key' from the channel `channel'. The `key'
604    is retrieved by calling the function silc_client_list_channel_private_keys.
605    The key is not used after this. If the key was last private key then the
606    old channel key is used hereafter to protect the channel messages. This
607    returns FALSE on error, TRUE otherwise. */
608
609 int silc_client_del_channel_private_key(SilcClient client,
610                                         SilcClientConnection conn,
611                                         SilcChannelEntry channel,
612                                         SilcChannelPrivateKey key)
613 {
614   SilcChannelPrivateKey entry;
615
616   if (!channel->private_keys)
617     return FALSE;
618
619   silc_dlist_start(channel->private_keys);
620   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
621     if (entry == key) {
622       if (channel->curr_key == entry)
623         channel->curr_key = NULL;
624
625       silc_dlist_del(channel->private_keys, entry);
626       memset(entry->key, 0, entry->key_len);
627       silc_free(entry->key);
628       silc_free(entry->name);
629       silc_cipher_free(entry->cipher);
630       silc_hmac_free(entry->hmac);
631       silc_free(entry);
632
633       if (silc_dlist_count(channel->private_keys) == 0) {
634         silc_dlist_uninit(channel->private_keys);
635         channel->private_keys = NULL;
636       }
637
638       return TRUE;
639     }
640   }
641
642   return FALSE;
643 }
644
645 /* Returns array (pointers) of private keys associated to the `channel'.
646    The caller must free the array by calling the function
647    silc_client_free_channel_private_keys. The pointers in the array may be
648    used to delete the specific key by giving the pointer as argument to the
649    function silc_client_del_channel_private_key. */
650
651 SilcChannelPrivateKey *
652 silc_client_list_channel_private_keys(SilcClient client,
653                                       SilcClientConnection conn,
654                                       SilcChannelEntry channel,
655                                       SilcUInt32 *key_count)
656 {
657   SilcChannelPrivateKey *keys = NULL, entry;
658   SilcUInt32 count = 0;
659
660   if (!channel->private_keys)
661     return NULL;
662
663   silc_dlist_start(channel->private_keys);
664   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
665     keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
666     keys[count] = entry;
667     count++;
668   }
669
670   if (key_count)
671     *key_count = count;
672
673   return keys;
674 }
675
676 /* Frees the SilcChannelPrivateKey array. */
677
678 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
679                                            SilcUInt32 key_count)
680 {
681   silc_free(keys);
682 }
683
684 /* Sets the `key' to be used as current channel private key on the
685    `channel'.  Packet sent after calling this function will be secured
686    with `key'. */
687
688 void silc_client_current_channel_private_key(SilcClient client,
689                                              SilcClientConnection conn,
690                                              SilcChannelEntry channel,
691                                              SilcChannelPrivateKey key)
692 {
693   channel->curr_key = key;
694 }
695
696 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the 
697    channel indicated by the `channel'. NULL if client is not joined on
698    the channel. */
699
700 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
701                                        SilcClientEntry client_entry)
702 {
703   SilcChannelUser chu;
704
705   if (silc_hash_table_find(channel->user_list, client_entry, NULL, 
706                            (void *)&chu))
707     return chu;
708
709   return NULL;
710 }