Implemented CHANNEL_UMODE_QUEIT mode. Fixed fatal bugs in server.
[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 0
73   if (chu->mode & SILC_CHANNEL_UMODE_QUIET)
74     return;
75 #endif
76
77   /* Take the key to be used */
78   if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
79     if (key) {
80       /* Use key application specified */
81       cipher = key->cipher;
82       hmac = key->hmac;
83     } else if (channel->curr_key) {
84       /* Use current private key */
85       cipher = channel->curr_key->cipher;
86       hmac = channel->curr_key->hmac;
87     } else if (!channel->curr_key && channel->private_keys) {
88       /* Use just some private key since we don't know what to use 
89          and private keys are set. */
90       silc_dlist_start(channel->private_keys);
91       key = silc_dlist_get(channel->private_keys);
92       cipher = key->cipher;
93       hmac = key->hmac;
94       
95       /* Use this key as current private key */
96       channel->curr_key = key;
97     } else {
98       /* Use normal channel key generated by the server */
99       cipher = channel->channel_key;
100       hmac = channel->hmac;
101     }
102   } else {
103     /* Use normal channel key generated by the server */
104     cipher = channel->channel_key;
105     hmac = channel->hmac;
106   }
107
108   if (!cipher || !hmac)
109     return;
110
111   block_len = silc_cipher_get_block_len(cipher);
112
113   /* Generate IV */
114   iv_len = silc_cipher_get_block_len(cipher);
115   if (channel->iv[0] == '\0')
116     for (i = 0; i < iv_len; i++) channel->iv[i] = 
117                                    silc_rng_get_byte(client->rng);
118   else
119     silc_hash_make(client->internal->md5hash, channel->iv, iv_len, 
120                    channel->iv);
121
122   /* Encode the channel payload. This also encrypts the message payload. */
123   payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len, 
124                                                 channel->iv, cipher, hmac,
125                                                 client->rng);
126
127   /* Get data used in packet header encryption, keys and stuff. */
128   cipher = conn->send_key;
129   hmac = conn->hmac_send;
130   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
131
132   /* Set the packet context pointers. The destination ID is always
133      the Channel ID of the channel. Server and router will handle the
134      distribution of the packet. */
135   data = payload->data;
136   data_len = payload->len;
137   packetdata.flags = 0;
138   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
139   packetdata.src_id = conn->local_id_data;
140   packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
141   packetdata.src_id_type = SILC_ID_CLIENT;
142   packetdata.dst_id = id_string;
143   packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
144   packetdata.dst_id_type = SILC_ID_CHANNEL;
145   data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
146                                  packetdata.src_id_len +
147                                  packetdata.dst_id_len);
148   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
149     packetdata.src_id_len + packetdata.dst_id_len;
150   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
151                                           packetdata.src_id_len +
152                                           packetdata.dst_id_len), block_len);
153
154   /* Create the outgoing packet */
155   if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
156                             data, data_len, (const SilcBuffer)&packet)) {
157     SILC_LOG_ERROR(("Error assembling packet"));
158     goto out;
159   }
160
161   /* Encrypt the header and padding of the packet. This is encrypted 
162      with normal session key shared with our server. */
163   silc_packet_encrypt(cipher, hmac, conn->psn_send++,
164                       (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN + 
165                       packetdata.src_id_len + packetdata.dst_id_len +
166                       packetdata.padlen);
167
168   SILC_LOG_HEXDUMP(("Packet to channel, len %d", packet.len),
169                     packet.data, packet.len);
170
171   /* Now actually send the packet */
172   silc_client_packet_send_real(client, sock, force_send);
173
174  out:
175   silc_buffer_free(payload);
176   silc_free(id_string);
177 }
178
179 typedef struct {
180   SilcChannelMessagePayload payload;
181   SilcChannelID *channel_id;
182 } *SilcChannelClientResolve;
183
184 static void silc_client_channel_message_cb(SilcClient client,
185                                            SilcClientConnection conn,
186                                            SilcClientEntry *clients,
187                                            SilcUInt32 clients_count,
188                                            void *context)
189 {
190   SilcChannelClientResolve res = (SilcChannelClientResolve)context;
191
192   if (clients_count == 1) {
193     SilcChannelEntry channel;
194     unsigned char *message;
195     SilcUInt32 message_len;
196
197     channel = silc_client_get_channel_by_id(client, conn, res->channel_id);
198     if (!channel)
199       goto out;
200
201     /* If this client is not on channel, add it there since it clearly
202        is there. */
203     if (!silc_client_on_channel(channel, clients[0])) {
204       SilcChannelUser chu = silc_calloc(1, sizeof(*chu));
205       chu->client = clients[0];
206       chu->channel = channel;
207       silc_hash_table_add(channel->user_list, clients[0], chu);
208       silc_hash_table_add(clients[0]->channels, channel, chu);
209     }
210
211     message = silc_channel_message_get_data(res->payload, &message_len);
212     
213     /* Pass the message to application */
214     client->internal->ops->channel_message(
215                                client, conn, clients[0], channel,
216                                silc_channel_message_get_flags(res->payload),
217                                message, message_len);
218   }
219
220  out:
221   silc_channel_message_payload_free(res->payload);
222   silc_free(res->channel_id);
223   silc_free(res);
224 }
225
226 /* Process received message to a channel (or from a channel, really). This
227    decrypts the channel message with channel specific key and parses the
228    channel payload. Finally it displays the message on the screen. */
229
230 void silc_client_channel_message(SilcClient client, 
231                                  SilcSocketConnection sock, 
232                                  SilcPacketContext *packet)
233 {
234   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
235   SilcBuffer buffer = packet->buffer;
236   SilcChannelMessagePayload payload = NULL;
237   SilcChannelID *id = NULL;
238   SilcChannelEntry channel;
239   SilcClientEntry client_entry;
240   SilcClientID *client_id = NULL;
241   unsigned char *message;
242   SilcUInt32 message_len;
243
244   SILC_LOG_DEBUG(("Start"));
245
246   /* Sanity checks */
247   if (packet->dst_id_type != SILC_ID_CHANNEL)
248     goto out;
249
250   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
251                              SILC_ID_CLIENT);
252   if (!client_id)
253     goto out;
254   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
255   if (!id)
256     goto out;
257
258   /* Find the channel entry from channels on this connection */
259   channel = silc_client_get_channel_by_id(client, conn, id);
260   if (!channel)
261     goto out;
262
263   /* If there is no channel private key then just decrypt the message 
264      with the channel key. If private keys are set then just go through
265      all private keys and check what decrypts correctly. */
266   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
267     /* Parse the channel message payload. This also decrypts the payload */
268     payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
269                                                  channel->channel_key,
270                                                  channel->hmac);
271
272     /* If decryption failed and we have just performed channel key rekey
273        we will use the old key in decryption. If that fails too then we
274        cannot do more and will drop the packet. */
275     if (!payload) {
276       if (!channel->old_channel_key) {
277         goto out;
278       }
279
280       payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
281                                                    channel->old_channel_key,
282                                                    channel->old_hmac);
283       if (!payload) {
284         goto out;
285       }
286     }
287   } else if (channel->private_keys) {
288     SilcChannelPrivateKey entry;
289
290     silc_dlist_start(channel->private_keys);
291     while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
292       /* Parse the channel message payload. This also decrypts the payload */
293       payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
294                                                    entry->cipher,
295                                                    entry->hmac);
296       if (payload)
297         break;
298     }
299     if (entry == SILC_LIST_END)
300       goto out;
301   } else {
302     goto out;
303   }
304
305   /* Find client entry */
306   client_entry = silc_client_get_client_by_id(client, conn, client_id);
307   if (!client_entry || !client_entry->nickname) {
308     /* Resolve the client info */
309     SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
310     res->payload = payload;
311     res->channel_id = id;
312     silc_client_get_client_by_id_resolve(client, conn, client_id,
313                                          silc_client_channel_message_cb,
314                                          res);
315     payload = NULL;
316     id = NULL;
317     goto out;
318   }
319
320   if (!silc_client_on_channel(channel, client_entry)) {
321     SILC_LOG_WARNING(("Received channel message from client not on channel"));
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 int 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   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
506     return FALSE;
507
508   if (!cipher)
509     cipher = SILC_DEFAULT_CIPHER;
510   if (!hmac)
511     hmac = SILC_DEFAULT_HMAC;
512
513   if (!silc_cipher_is_supported(cipher))
514     return FALSE;
515
516   if (!silc_hmac_is_supported(hmac))
517     return FALSE;
518
519   /* Produce the key material */
520   keymat = silc_calloc(1, sizeof(*keymat));
521   if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16, 
522                                          client->internal->md5hash, keymat) 
523       != SILC_SKE_STATUS_OK)
524     return FALSE;
525
526   /* Remove the current key, if it exists. */
527   if (channel->channel_key) {
528     silc_cipher_free(channel->channel_key);
529     memset(channel->key, 0, channel->key_len / 8);
530     silc_free(channel->key);
531     channel->channel_key = NULL;
532     channel->key = NULL;
533     channel->key_len = 0;
534   }
535   if (channel->hmac) {
536     silc_hmac_free(channel->hmac);
537     channel->hmac = NULL;
538   }
539
540   if (!channel->private_keys)
541     channel->private_keys = silc_dlist_init();
542
543   /* Save the key */
544   entry = silc_calloc(1, sizeof(*entry));
545   entry->name = name ? strdup(name) : NULL;
546   entry->key = silc_memdup(keymat->send_enc_key, keymat->enc_key_len / 8);
547   entry->key_len = keymat->enc_key_len / 8;
548
549   /* Allocate the cipher and set the key*/
550   silc_cipher_alloc(cipher, &entry->cipher);
551   silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
552
553   /* Generate HMAC key from the channel key data and set it */
554   silc_hmac_alloc(hmac, NULL, &entry->hmac);
555   silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key, 
556                  entry->key_len, hash);
557   silc_hmac_set_key(entry->hmac, hash, 
558                     silc_hash_len(silc_hmac_get_hash(entry->hmac)));
559   memset(hash, 0, sizeof(hash));
560
561   /* Add to the private keys list */
562   silc_dlist_add(channel->private_keys, entry);
563
564   if (!channel->curr_key)
565     channel->curr_key = entry;
566
567   /* Free the key material */
568   silc_ske_free_key_material(keymat);
569
570   return TRUE;
571 }
572
573 /* Removes all private keys from the `channel'. The old channel key is used
574    after calling this to protect the channel messages. Returns FALSE on
575    on error, TRUE otherwise. */
576
577 int silc_client_del_channel_private_keys(SilcClient client,
578                                          SilcClientConnection conn,
579                                          SilcChannelEntry channel)
580 {
581   SilcChannelPrivateKey entry;
582
583   if (!channel->private_keys)
584     return FALSE;
585
586   silc_dlist_start(channel->private_keys);
587   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
588     silc_dlist_del(channel->private_keys, entry);
589     memset(entry->key, 0, entry->key_len);
590     silc_free(entry->key);
591     silc_free(entry->name);
592     silc_cipher_free(entry->cipher);
593     silc_hmac_free(entry->hmac);
594     silc_free(entry);
595   }
596
597   channel->curr_key = NULL;
598
599   silc_dlist_uninit(channel->private_keys);
600   channel->private_keys = NULL;
601
602   return TRUE;
603 }
604
605 /* Removes and frees private key `key' from the channel `channel'. The `key'
606    is retrieved by calling the function silc_client_list_channel_private_keys.
607    The key is not used after this. If the key was last private key then the
608    old channel key is used hereafter to protect the channel messages. This
609    returns FALSE on error, TRUE otherwise. */
610
611 int silc_client_del_channel_private_key(SilcClient client,
612                                         SilcClientConnection conn,
613                                         SilcChannelEntry channel,
614                                         SilcChannelPrivateKey key)
615 {
616   SilcChannelPrivateKey entry;
617
618   if (!channel->private_keys)
619     return FALSE;
620
621   silc_dlist_start(channel->private_keys);
622   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
623     if (entry == key) {
624       if (channel->curr_key == entry)
625         channel->curr_key = NULL;
626
627       silc_dlist_del(channel->private_keys, entry);
628       memset(entry->key, 0, entry->key_len);
629       silc_free(entry->key);
630       silc_free(entry->name);
631       silc_cipher_free(entry->cipher);
632       silc_hmac_free(entry->hmac);
633       silc_free(entry);
634
635       if (silc_dlist_count(channel->private_keys) == 0) {
636         silc_dlist_uninit(channel->private_keys);
637         channel->private_keys = NULL;
638       }
639
640       return TRUE;
641     }
642   }
643
644   return FALSE;
645 }
646
647 /* Returns array (pointers) of private keys associated to the `channel'.
648    The caller must free the array by calling the function
649    silc_client_free_channel_private_keys. The pointers in the array may be
650    used to delete the specific key by giving the pointer as argument to the
651    function silc_client_del_channel_private_key. */
652
653 SilcChannelPrivateKey *
654 silc_client_list_channel_private_keys(SilcClient client,
655                                       SilcClientConnection conn,
656                                       SilcChannelEntry channel,
657                                       SilcUInt32 *key_count)
658 {
659   SilcChannelPrivateKey *keys = NULL, entry;
660   SilcUInt32 count = 0;
661
662   if (!channel->private_keys)
663     return NULL;
664
665   silc_dlist_start(channel->private_keys);
666   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
667     keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
668     keys[count] = entry;
669     count++;
670   }
671
672   if (key_count)
673     *key_count = count;
674
675   return keys;
676 }
677
678 /* Frees the SilcChannelPrivateKey array. */
679
680 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
681                                            SilcUInt32 key_count)
682 {
683   silc_free(keys);
684 }
685
686 /* Sets the `key' to be used as current channel private key on the
687    `channel'.  Packet sent after calling this function will be secured
688    with `key'. */
689
690 void silc_client_current_channel_private_key(SilcClient client,
691                                              SilcClientConnection conn,
692                                              SilcChannelEntry channel,
693                                              SilcChannelPrivateKey key)
694 {
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 }