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