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