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