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