updates.
[silc.git] / lib / silcclient / client.c
1 /*
2
3   client.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
22 #include "clientlibincludes.h"
23
24 /* Static task callback prototypes */
25 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
28 SILC_TASK_CALLBACK(silc_client_packet_process);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
30
31 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
32 static void silc_client_packet_parse_type(SilcClient client, 
33                                           SilcSocketConnection sock,
34                                           SilcPacketContext *packet);
35
36 /* Allocates new client object. This has to be done before client may
37    work. After calling this one must call silc_client_init to initialize
38    the client. The `application' is application specific user data pointer
39    and caller must free it. */
40
41 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
42 {
43   SilcClient new_client;
44
45   new_client = silc_calloc(1, sizeof(*new_client));
46   new_client->application = application;
47   new_client->ops = ops;
48
49   return new_client;
50 }
51
52 /* Frees client object and its internals. */
53
54 void silc_client_free(SilcClient client)
55 {
56   if (client) {
57     if (client->rng)
58       silc_rng_free(client->rng);
59
60     silc_free(client);
61   }
62 }
63
64 /* Initializes the client. This makes all the necessary steps to make
65    the client ready to be run. One must call silc_client_run to run the
66    client. Returns FALSE if error occured, TRUE otherwise. */
67
68 int silc_client_init(SilcClient client)
69 {
70   SILC_LOG_DEBUG(("Initializing client"));
71
72   /* Initialize hash functions for client to use */
73   silc_hash_alloc("md5", &client->md5hash);
74   silc_hash_alloc("sha1", &client->sha1hash);
75
76   /* Initialize none cipher */
77   silc_cipher_alloc("none", &client->none_cipher);
78
79   /* Initialize random number generator */
80   client->rng = silc_rng_alloc();
81   silc_rng_init(client->rng);
82   silc_rng_global_init(client->rng);
83
84   /* Register protocols */
85   silc_client_protocols_register();
86
87   /* Initialize the scheduler */
88   silc_schedule_init(&client->io_queue, &client->timeout_queue, 
89                      &client->generic_queue, 5000);
90
91   return TRUE;
92 }
93
94 /* Stops the client. This is called to stop the client and thus to stop
95    the program. */
96
97 void silc_client_stop(SilcClient client)
98 {
99   SILC_LOG_DEBUG(("Stopping client"));
100
101   /* Stop the scheduler, although it might be already stopped. This
102      doesn't hurt anyone. This removes all the tasks and task queues,
103      as well. */
104   silc_schedule_stop();
105   silc_schedule_uninit();
106
107   silc_client_protocols_unregister();
108
109   SILC_LOG_DEBUG(("Client stopped"));
110 }
111
112 /* Runs the client. This starts the scheduler from the utility library.
113    When this functions returns the execution of the appliation is over. */
114
115 void silc_client_run(SilcClient client)
116 {
117   SILC_LOG_DEBUG(("Running client"));
118
119   /* Start the scheduler, the heart of the SILC client. When this returns
120      the program will be terminated. */
121   silc_schedule();
122 }
123
124 /* Allocates and adds new connection to the client. This adds the allocated
125    connection to the connection table and returns a pointer to it. A client
126    can have multiple connections to multiple servers. Every connection must
127    be added to the client using this function. User data `context' may
128    be sent as argument. This function is normally used only if the 
129    application performed the connecting outside the library. The library
130    however may use this internally. */
131
132 SilcClientConnection silc_client_add_connection(SilcClient client,
133                                                 char *hostname,
134                                                 int port,
135                                                 void *context)
136 {
137   SilcClientConnection conn;
138   int i;
139
140   conn = silc_calloc(1, sizeof(*conn));
141
142   /* Initialize ID caches */
143   conn->client_cache = silc_idcache_alloc(0);
144   conn->channel_cache = silc_idcache_alloc(0);
145   conn->server_cache = silc_idcache_alloc(0);
146   conn->client = client;
147   conn->remote_host = strdup(hostname);
148   conn->remote_port = port;
149   conn->context = context;
150   conn->pending_commands = silc_dlist_init();
151
152   /* Add the connection to connections table */
153   for (i = 0; i < client->conns_count; i++)
154     if (client->conns && !client->conns[i]) {
155       client->conns[i] = conn;
156       return conn;
157     }
158
159   client->conns = silc_realloc(client->conns, sizeof(*client->conns)
160                                * (client->conns_count + 1));
161   client->conns[client->conns_count] = conn;
162   client->conns_count++;
163
164   return conn;
165 }
166
167 /* Removes connection from client. Frees all memory. */
168
169 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
170 {
171   int i;
172
173   for (i = 0; i < client->conns_count; i++)
174     if (client->conns[i] == conn) {
175       if (conn->pending_commands)
176         silc_dlist_uninit(conn->pending_commands);
177       silc_free(conn);
178       client->conns[i] = NULL;
179     }
180 }
181
182 /* Internal context for connection process. This is needed as we
183    doing asynchronous connecting. */
184 typedef struct {
185   SilcClient client;
186   SilcClientConnection conn;
187   SilcTask task;
188   int sock;
189   char *host;
190   int port;
191   int tries;
192 } SilcClientInternalConnectContext;
193
194 static int 
195 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
196 {
197   int sock;
198
199   /* XXX In the future we should give up this non-blocking connect all
200      together and use threads instead. */
201   /* Create connection to server asynchronously */
202   sock = silc_net_create_connection_async(ctx->port, ctx->host);
203   if (sock < 0)
204     return -1;
205
206   /* Register task that will receive the async connect and will
207      read the result. */
208   ctx->task = silc_task_register(ctx->client->io_queue, sock, 
209                                  silc_client_connect_to_server_start,
210                                  (void *)ctx, 0, 0, 
211                                  SILC_TASK_FD,
212                                  SILC_TASK_PRI_NORMAL);
213   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
214   silc_schedule_set_listen_fd(sock, ctx->task->iomask);
215
216   ctx->sock = sock;
217
218   return sock;
219 }
220
221 /* Connects to remote server. This is the main routine used to connect
222    to SILC server. Returns -1 on error and the created socket otherwise. 
223    The `context' is user context that is saved into the SilcClientConnection
224    that is created after the connection is created. Note that application
225    may handle the connecting process outside the library. If this is the
226    case then this function is not used at all. When the connecting is
227    done the `connect' client operation is called. */
228
229 int silc_client_connect_to_server(SilcClient client, int port,
230                                   char *host, void *context)
231 {
232   SilcClientInternalConnectContext *ctx;
233   SilcClientConnection conn;
234   int sock;
235
236   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
237                   port, host));
238
239   conn = silc_client_add_connection(client, host, port, context);
240
241   client->ops->say(client, conn, 
242                    "Connecting to port %d of server %s", port, host);
243
244   /* Allocate internal context for connection process. This is
245      needed as we are doing async connecting. */
246   ctx = silc_calloc(1, sizeof(*ctx));
247   ctx->client = client;
248   ctx->conn = conn;
249   ctx->host = strdup(host);
250   ctx->port = port;
251   ctx->tries = 0;
252
253   /* Do the actual connecting process */
254   sock = silc_client_connect_to_server_internal(ctx);
255   if (sock == -1)
256     silc_client_del_connection(client, conn);
257   return sock;
258 }
259
260 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
261    key material between client and server.  This function can be called
262    directly if application is performing its own connecting and does not
263    use the connecting provided by this library. This function is normally
264    used only if the application performed the connecting outside the library.
265    The library however may use this internally. */
266
267 int silc_client_start_key_exchange(SilcClient client,
268                                    SilcClientConnection conn,
269                                    int fd)
270 {
271   SilcProtocol protocol;
272   SilcClientKEInternalContext *proto_ctx;
273   void *context;
274
275   /* Allocate new socket connection object */
276   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
277   if (conn->sock == NULL) {
278     client->ops->say(client, conn, 
279                      "Error: Could not allocate connection socket");
280     return FALSE;
281   }
282
283   conn->nickname = strdup(client->username);
284   conn->sock->hostname = conn->remote_host;
285   conn->sock->ip = strdup(conn->remote_host);
286   conn->sock->port = conn->remote_port;
287
288   /* Allocate internal Key Exchange context. This is sent to the
289      protocol as context. */
290   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
291   proto_ctx->client = (void *)client;
292   proto_ctx->sock = conn->sock;
293   proto_ctx->rng = client->rng;
294   proto_ctx->responder = FALSE;
295
296   /* Perform key exchange protocol. silc_client_connect_to_server_final
297      will be called after the protocol is finished. */
298   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
299                       &protocol, (void *)proto_ctx,
300                       silc_client_connect_to_server_second);
301   if (!protocol) {
302     client->ops->say(client, conn, 
303                      "Error: Could not start authentication protocol");
304     return FALSE;
305   }
306   conn->sock->protocol = protocol;
307
308   /* Register the connection for network input and output. This sets
309      that scheduler will listen for incoming packets for this connection 
310      and sets that outgoing packets may be sent to this connection as well.
311      However, this doesn't set the scheduler for outgoing traffic, it will 
312      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
313      later when outgoing data is available. */
314   context = (void *)client;
315   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
316
317   /* Execute the protocol */
318   protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
319   return TRUE;
320 }
321
322 /* Start of the connection to the remote server. This is called after
323    succesful TCP/IP connection has been established to the remote host. */
324
325 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
326 {
327   SilcClientInternalConnectContext *ctx =
328     (SilcClientInternalConnectContext *)context;
329   SilcClient client = ctx->client;
330   SilcClientConnection conn = ctx->conn;
331   int opt, opt_len = sizeof(opt);
332
333   SILC_LOG_DEBUG(("Start"));
334
335   /* Check the socket status as it might be in error */
336   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
337   if (opt != 0) {
338     if (ctx->tries < 2) {
339       /* Connection failed but lets try again */
340       client->ops->say(client, conn, "Could not connect to server %s: %s",
341                        ctx->host, strerror(opt));
342       client->ops->say(client, conn, 
343                        "Connecting to port %d of server %s resumed", 
344                        ctx->port, ctx->host);
345
346       /* Unregister old connection try */
347       silc_schedule_unset_listen_fd(fd);
348       silc_net_close_connection(fd);
349       silc_task_unregister(client->io_queue, ctx->task);
350
351       /* Try again */
352       silc_client_connect_to_server_internal(ctx);
353       ctx->tries++;
354     } else {
355       /* Connection failed and we won't try anymore */
356       client->ops->say(client, conn, "Could not connect to server %s: %s",
357                        ctx->host, strerror(opt));
358       silc_schedule_unset_listen_fd(fd);
359       silc_net_close_connection(fd);
360       silc_task_unregister(client->io_queue, ctx->task);
361       silc_free(ctx);
362
363       /* Notify application of failure */
364       client->ops->connect(client, conn, FALSE);
365       silc_client_del_connection(client, conn);
366     }
367     return;
368   }
369
370   silc_schedule_unset_listen_fd(fd);
371   silc_task_unregister(client->io_queue, ctx->task);
372   silc_free(ctx);
373
374   if (!silc_client_start_key_exchange(client, conn, fd)) {
375     silc_net_close_connection(fd);
376     client->ops->connect(client, conn, FALSE);
377   }
378 }
379
380 /* Second part of the connecting to the server. This executed 
381    authentication protocol. */
382
383 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
384 {
385   SilcProtocol protocol = (SilcProtocol)context;
386   SilcClientKEInternalContext *ctx = 
387     (SilcClientKEInternalContext *)protocol->context;
388   SilcClient client = (SilcClient)ctx->client;
389   SilcSocketConnection sock = NULL;
390   SilcClientConnAuthInternalContext *proto_ctx;
391
392   SILC_LOG_DEBUG(("Start"));
393
394   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
395       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
396     /* Error occured during protocol */
397     SILC_LOG_DEBUG(("Error during KE protocol"));
398     silc_protocol_free(protocol);
399     if (ctx->ske)
400       silc_ske_free(ctx->ske);
401     if (ctx->dest_id)
402       silc_free(ctx->dest_id);
403     ctx->sock->protocol = NULL;
404
405     /* Notify application of failure */
406     client->ops->connect(client, ctx->sock->user_data, FALSE);
407     silc_free(ctx);
408     return;
409   }
410
411   /* Allocate internal context for the authentication protocol. This
412      is sent as context for the protocol. */
413   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
414   proto_ctx->client = (void *)client;
415   proto_ctx->sock = sock = ctx->sock;
416   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
417   proto_ctx->dest_id_type = ctx->dest_id_type;
418   proto_ctx->dest_id = ctx->dest_id;
419
420   /* Resolve the authentication method to be used in this connection */
421   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
422                                     sock->port, &proto_ctx->auth_meth,
423                                     &proto_ctx->auth_data, 
424                                     &proto_ctx->auth_data_len))
425     {
426       /* XXX do AUTH_REQUEST resolcing with server */
427       proto_ctx->auth_meth = SILC_AUTH_NONE;
428     }
429
430   /* Free old protocol as it is finished now */
431   silc_protocol_free(protocol);
432   if (ctx->packet)
433     silc_packet_context_free(ctx->packet);
434   silc_free(ctx);
435   /* silc_free(ctx->keymat....); */
436   sock->protocol = NULL;
437
438   /* Allocate the authentication protocol. This is allocated here
439      but we won't start it yet. We will be receiving party of this
440      protocol thus we will wait that connecting party will make
441      their first move. */
442   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
443                       &sock->protocol, (void *)proto_ctx, 
444                       silc_client_connect_to_server_final);
445
446   /* Execute the protocol */
447   sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
448 }
449
450 /* Finalizes the connection to the remote SILC server. This is called
451    after authentication protocol has been completed. This send our
452    user information to the server to receive our client ID from
453    server. */
454
455 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
456 {
457   SilcProtocol protocol = (SilcProtocol)context;
458   SilcClientConnAuthInternalContext *ctx = 
459     (SilcClientConnAuthInternalContext *)protocol->context;
460   SilcClient client = (SilcClient)ctx->client;
461   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
462   SilcBuffer packet;
463
464   SILC_LOG_DEBUG(("Start"));
465
466   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
467       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
468     /* Error occured during protocol */
469     SILC_LOG_DEBUG(("Error during authentication protocol"));
470     silc_protocol_free(protocol);
471     if (ctx->auth_data)
472       silc_free(ctx->auth_data);
473     if (ctx->ske)
474       silc_ske_free(ctx->ske);
475     if (ctx->dest_id)
476       silc_free(ctx->dest_id);
477     conn->sock->protocol = NULL;
478
479     /* Notify application of failure */
480     client->ops->connect(client, ctx->sock->user_data, FALSE);
481     silc_free(ctx);
482     return;
483   }
484
485   /* Send NEW_CLIENT packet to the server. We will become registered
486      to the SILC network after sending this packet and we will receive
487      client ID from the server. */
488   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
489                              strlen(client->realname));
490   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
491   silc_buffer_format(packet,
492                      SILC_STR_UI_SHORT(strlen(client->username)),
493                      SILC_STR_UI_XNSTRING(client->username,
494                                           strlen(client->username)),
495                      SILC_STR_UI_SHORT(strlen(client->realname)),
496                      SILC_STR_UI_XNSTRING(client->realname,
497                                           strlen(client->realname)),
498                      SILC_STR_END);
499
500   /* Send the packet */
501   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
502                           NULL, 0, NULL, NULL, 
503                           packet->data, packet->len, TRUE);
504   silc_buffer_free(packet);
505
506   /* Save remote ID. */
507   conn->remote_id = ctx->dest_id;
508   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
509   conn->remote_id_data_len = SILC_ID_SERVER_LEN;
510
511   silc_protocol_free(protocol);
512   if (ctx->auth_data)
513     silc_free(ctx->auth_data);
514   if (ctx->ske)
515     silc_ske_free(ctx->ske);
516   silc_free(ctx);
517   conn->sock->protocol = NULL;
518 }
519
520 /* Internal routine that sends packet or marks packet to be sent. This
521    is used directly only in special cases. Normal cases should use
522    silc_server_packet_send. Returns < 0 on error. */
523
524 static int silc_client_packet_send_real(SilcClient client,
525                                         SilcSocketConnection sock,
526                                         int force_send)
527 {
528   int ret;
529
530   /* Send the packet */
531   ret = silc_packet_send(sock, force_send);
532   if (ret != -2)
533     return ret;
534
535   /* Mark that there is some outgoing data available for this connection. 
536      This call sets the connection both for input and output (the input
537      is set always and this call keeps the input setting, actually). 
538      Actual data sending is performed by silc_client_packet_process. */
539   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
540
541   /* Mark to socket that data is pending in outgoing buffer. This flag
542      is needed if new data is added to the buffer before the earlier
543      put data is sent to the network. */
544   SILC_SET_OUTBUF_PENDING(sock);
545
546   return 0;
547 }
548
549 /* Packet processing callback. This is used to send and receive packets
550    from network. This is generic task. */
551
552 SILC_TASK_CALLBACK(silc_client_packet_process)
553 {
554   SilcClient client = (SilcClient)context;
555   SilcSocketConnection sock = NULL;
556   SilcClientConnection conn;
557   int ret;
558
559   SILC_LOG_DEBUG(("Processing packet"));
560
561   SILC_CLIENT_GET_SOCK(client, fd, sock);
562   if (sock == NULL)
563     return;
564
565   conn = (SilcClientConnection)sock->user_data;
566
567   /* Packet sending */
568   if (type == SILC_TASK_WRITE) {
569     SILC_LOG_DEBUG(("Writing data to connection"));
570
571     if (sock->outbuf->data - sock->outbuf->head)
572       silc_buffer_push(sock->outbuf, 
573                        sock->outbuf->data - sock->outbuf->head);
574
575     ret = silc_client_packet_send_real(client, sock, TRUE);
576
577     /* If returned -2 could not write to connection now, will do
578        it later. */
579     if (ret == -2)
580       return;
581     
582     /* The packet has been sent and now it is time to set the connection
583        back to only for input. When there is again some outgoing data 
584        available for this connection it will be set for output as well. 
585        This call clears the output setting and sets it only for input. */
586     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
587     SILC_UNSET_OUTBUF_PENDING(sock);
588
589     silc_buffer_clear(sock->outbuf);
590     return;
591   }
592
593   /* Packet receiving */
594   if (type == SILC_TASK_READ) {
595     SILC_LOG_DEBUG(("Reading data from connection"));
596
597     /* Read data from network */
598     ret = silc_packet_receive(sock);
599     if (ret < 0)
600       return;
601     
602     /* EOF */
603     if (ret == 0) {
604       SILC_LOG_DEBUG(("Read EOF"));
605
606       /* If connection is disconnecting already we will finally
607          close the connection */
608       if (SILC_IS_DISCONNECTING(sock)) {
609         client->ops->disconnect(client, conn);
610         silc_client_close_connection(client, conn);
611         return;
612       }
613       
614       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
615       client->ops->disconnect(client, conn);
616       silc_client_close_connection(client, conn);
617       return;
618     }
619
620     /* Process the packet. This will call the parser that will then
621        decrypt and parse the packet. */
622     silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
623                                 silc_client_packet_parse, client);
624   }
625 }
626
627 /* Parses whole packet, received earlier. */
628
629 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
630 {
631   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
632   SilcClient client = (SilcClient)parse_ctx->context;
633   SilcPacketContext *packet = parse_ctx->packet;
634   SilcBuffer buffer = packet->buffer;
635   SilcSocketConnection sock = parse_ctx->sock;
636   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
637   int ret;
638
639   SILC_LOG_DEBUG(("Start"));
640
641   /* Decrypt the received packet */
642   ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
643   if (ret < 0)
644     goto out;
645
646   if (ret == 0) {
647     /* Parse the packet. Packet type is returned. */
648     ret = silc_packet_parse(packet);
649   } else {
650     /* Parse the packet header in special way as this is "special"
651        packet type. */
652     ret = silc_packet_parse_special(packet);
653   }
654
655   if (ret == SILC_PACKET_NONE)
656     goto out;
657
658   /* Parse the incoming packet type */
659   silc_client_packet_parse_type(client, sock, packet);
660
661  out:
662   silc_buffer_clear(sock->inbuf);
663   silc_packet_context_free(packet);
664   silc_free(parse_ctx);
665 }
666
667 /* Parser callback called by silc_packet_receive_process. Thie merely
668    registers timeout that will handle the actual parsing when appropriate. */
669
670 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
671 {
672   SilcClient client = (SilcClient)parser_context->context;
673
674   /* Parse the packet */
675   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
676                      silc_client_packet_parse_real,
677                      (void *)parser_context, 0, 1, 
678                      SILC_TASK_TIMEOUT,
679                      SILC_TASK_PRI_NORMAL);
680 }
681   
682 /* Parses the packet type and calls what ever routines the packet type
683    requires. This is done for all incoming packets. */
684
685 void silc_client_packet_parse_type(SilcClient client, 
686                                    SilcSocketConnection sock,
687                                    SilcPacketContext *packet)
688 {
689   SilcBuffer buffer = packet->buffer;
690   SilcPacketType type = packet->type;
691
692   SILC_LOG_DEBUG(("Parsing packet type %d", type));
693
694   /* Parse the packet type */
695   switch(type) {
696   case SILC_PACKET_DISCONNECT:
697     silc_client_disconnected_by_server(client, sock, buffer);
698     break;
699   case SILC_PACKET_SUCCESS:
700     /*
701      * Success received for something. For now we can have only
702      * one protocol for connection executing at once hence this
703      * success message is for whatever protocol is executing currently.
704      */
705     if (sock->protocol) {
706       sock->protocol->execute(client->timeout_queue, 0,
707                               sock->protocol, sock->sock, 0, 0);
708     }
709     break;
710   case SILC_PACKET_FAILURE:
711     /*
712      * Failure received for some protocol. Set the protocol state to 
713      * error and call the protocol callback. This fill cause error on
714      * protocol and it will call the final callback.
715      */
716     if (sock->protocol) {
717       sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
718       sock->protocol->execute(client->timeout_queue, 0,
719                               sock->protocol, sock->sock, 0, 0);
720
721       /* XXX We have only two protocols currently thus we know what this
722          failure indication is. */
723       if (buffer->len >= 4) {
724         unsigned int failure;
725
726         SILC_GET32_MSB(failure, buffer->data);
727
728         /* Notify application */
729         client->ops->failure(client, sock->user_data, sock->protocol,
730                              (void *)failure);
731       }
732     }
733     break;
734   case SILC_PACKET_REJECT:
735     break;
736
737   case SILC_PACKET_NOTIFY:
738     /*
739      * Received notify message 
740      */
741     silc_client_notify_by_server(client, sock, packet);
742     break;
743
744   case SILC_PACKET_ERROR:
745     /*
746      * Received error message
747      */
748     silc_client_error_by_server(client, sock, buffer);
749     break;
750
751   case SILC_PACKET_CHANNEL_MESSAGE:
752     /*
753      * Received message to (from, actually) a channel
754      */
755     silc_client_channel_message(client, sock, packet);
756     break;
757   case SILC_PACKET_CHANNEL_KEY:
758     /*
759      * Received key for a channel. By receiving this key the client will be
760      * able to talk to the channel it has just joined. This can also be
761      * a new key for existing channel as keys expire peridiocally.
762      */
763     silc_client_receive_channel_key(client, sock, buffer);
764     break;
765
766   case SILC_PACKET_PRIVATE_MESSAGE:
767     /*
768      * Received private message
769      */
770     silc_client_private_message(client, sock, packet);
771     break;
772   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
773     /*
774      * Received private message key
775      */
776     break;
777
778   case SILC_PACKET_COMMAND_REPLY:
779     /*
780      * Recived reply for a command
781      */
782     silc_client_command_reply_process(client, sock, packet);
783     break;
784
785   case SILC_PACKET_KEY_EXCHANGE:
786     if (sock->protocol) {
787       SilcClientKEInternalContext *proto_ctx = 
788         (SilcClientKEInternalContext *)sock->protocol->context;
789
790       proto_ctx->packet = silc_packet_context_dup(packet);
791       proto_ctx->dest_id_type = packet->src_id_type;
792       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
793                                           packet->src_id_type);
794       if (!proto_ctx->dest_id)
795         break;
796
797       /* Let the protocol handle the packet */
798       sock->protocol->execute(client->timeout_queue, 0,
799                               sock->protocol, sock->sock, 0, 0);
800     } else {
801       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
802                       "protocol active, packet dropped."));
803
804       /* XXX Trigger KE protocol?? Rekey actually! */
805     }
806     break;
807
808   case SILC_PACKET_KEY_EXCHANGE_1:
809     if (sock->protocol) {
810
811     } else {
812       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
813                       "protocol active, packet dropped."));
814     }
815     break;
816   case SILC_PACKET_KEY_EXCHANGE_2:
817     if (sock->protocol) {
818       SilcClientKEInternalContext *proto_ctx = 
819         (SilcClientKEInternalContext *)sock->protocol->context;
820
821       if (proto_ctx->packet)
822         silc_packet_context_free(proto_ctx->packet);
823
824       proto_ctx->packet = silc_packet_context_dup(packet);
825       proto_ctx->dest_id_type = packet->src_id_type;
826       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
827                                           packet->src_id_type);
828       if (!proto_ctx->dest_id)
829         break;
830
831       /* Let the protocol handle the packet */
832       sock->protocol->execute(client->timeout_queue, 0,
833                               sock->protocol, sock->sock, 0, 0);
834     } else {
835       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
836                       "protocol active, packet dropped."));
837     }
838     break;
839
840   case SILC_PACKET_NEW_ID:
841     {
842       /*
843        * Received new ID from server. This packet is received at
844        * the connection to the server.  New ID is also received when 
845        * user changes nickname but in that case the new ID is received
846        * as command reply and not as this packet type.
847        */
848       SilcIDPayload idp;
849
850       idp = silc_id_payload_parse(buffer);
851       if (!idp)
852         break;
853       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
854         break;
855
856       silc_client_receive_new_id(client, sock, idp);
857       silc_id_payload_free(idp);
858       break;
859     }
860
861   case SILC_PACKET_HEARTBEAT:
862     /*
863      * Received heartbeat packet
864      */
865     SILC_LOG_DEBUG(("Heartbeat packet"));
866     break;
867
868   default:
869     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
870     break;
871   }
872 }
873
874 /* Sends packet. This doesn't actually send the packet instead it assembles
875    it and marks it to be sent. However, if force_send is TRUE the packet
876    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
877    will be derived from sock argument. Otherwise the valid arguments sent
878    are used. */
879
880 void silc_client_packet_send(SilcClient client, 
881                              SilcSocketConnection sock,
882                              SilcPacketType type, 
883                              void *dst_id,
884                              SilcIdType dst_id_type,
885                              SilcCipher cipher,
886                              SilcHmac hmac,
887                              unsigned char *data, 
888                              unsigned int data_len, 
889                              int force_send)
890 {
891   SilcPacketContext packetdata;
892
893   SILC_LOG_DEBUG(("Sending packet, type %d", type));
894
895   /* Get data used in the packet sending, keys and stuff */
896   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
897     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
898       cipher = ((SilcClientConnection)sock->user_data)->send_key;
899
900     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
901       hmac = ((SilcClientConnection)sock->user_data)->hmac;
902
903     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
904       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
905       dst_id_type = SILC_ID_SERVER;
906     }
907   }
908
909   /* Set the packet context pointers */
910   packetdata.flags = 0;
911   packetdata.type = type;
912   if (((SilcClientConnection)sock->user_data)->local_id_data)
913     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
914   else 
915     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
916   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
917   packetdata.src_id_type = SILC_ID_CLIENT;
918   if (dst_id) {
919     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
920     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
921     packetdata.dst_id_type = dst_id_type;
922   } else {
923     packetdata.dst_id = NULL;
924     packetdata.dst_id_len = 0;
925     packetdata.dst_id_type = SILC_ID_NONE;
926   }
927   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
928     packetdata.src_id_len + packetdata.dst_id_len;
929   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
930
931   /* Prepare outgoing data buffer for packet sending */
932   silc_packet_send_prepare(sock, 
933                            SILC_PACKET_HEADER_LEN +
934                            packetdata.src_id_len + 
935                            packetdata.dst_id_len,
936                            packetdata.padlen,
937                            data_len);
938
939   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
940
941   packetdata.buffer = sock->outbuf;
942
943   /* Put the data to the buffer */
944   if (data && data_len)
945     silc_buffer_put(sock->outbuf, data, data_len);
946
947   /* Create the outgoing packet */
948   silc_packet_assemble(&packetdata);
949
950   /* Encrypt the packet */
951   if (cipher)
952     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
953
954   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
955                    sock->outbuf->data, sock->outbuf->len);
956
957   /* Now actually send the packet */
958   silc_client_packet_send_real(client, sock, force_send);
959 }
960
961 /* Sends packet to the `channel'. Packet to channel is always encrypted
962    differently from "normal" packets. SILC header of the packet is 
963    encrypted with the next receiver's key and the rest of the packet is
964    encrypted with the channel specific key. Padding and HMAC is computed
965    with the next receiver's key. The `data' is the channel message. If
966    the `force_send' is TRUE then the packet is sent immediately. */
967
968 void silc_client_send_channel_message(SilcClient client, 
969                                       SilcClientConnection conn,
970                                       SilcChannelEntry channel,
971                                       unsigned char *data, 
972                                       unsigned int data_len, 
973                                       int force_send)
974 {
975   int i;
976   SilcSocketConnection sock = conn->sock;
977   SilcBuffer payload;
978   SilcPacketContext packetdata;
979   SilcCipher cipher;
980   SilcHmac hmac;
981   unsigned char *id_string;
982   unsigned int block_len;
983
984   SILC_LOG_DEBUG(("Sending packet to channel"));
985
986   if (!channel || !channel->key) {
987     client->ops->say(client, conn, 
988                      "Cannot talk to channel: key does not exist");
989     return;
990   }
991
992   /* Generate IV */
993   block_len = silc_cipher_get_block_len(channel->channel_key);
994   if (channel->iv[0] == '\0')
995     for (i = 0; i < block_len; i++) channel->iv[i] = 
996                                       silc_rng_get_byte(client->rng);
997   else
998     silc_hash_make(client->md5hash, channel->iv, block_len, channel->iv);
999
1000   /* Encode the channel payload */
1001   payload = silc_channel_payload_encode(data_len, data, block_len, 
1002                                         channel->iv, client->rng);
1003   if (!payload) {
1004     client->ops->say(client, conn, 
1005                      "Error: Could not create packet to be sent to channel");
1006     return;
1007   }
1008
1009   /* Get data used in packet header encryption, keys and stuff. Rest
1010      of the packet (the payload) is, however, encrypted with the 
1011      specified channel key. */
1012   cipher = conn->send_key;
1013   hmac = conn->hmac;
1014   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1015
1016   /* Set the packet context pointers. The destination ID is always
1017      the Channel ID of the channel. Server and router will handle the
1018      distribution of the packet. */
1019   packetdata.flags = 0;
1020   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1021   packetdata.src_id = conn->local_id_data;
1022   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1023   packetdata.src_id_type = SILC_ID_CLIENT;
1024   packetdata.dst_id = id_string;
1025   packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1026   packetdata.dst_id_type = SILC_ID_CHANNEL;
1027   packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN + 
1028     packetdata.src_id_len + packetdata.dst_id_len;
1029   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1030                                           packetdata.src_id_len +
1031                                           packetdata.dst_id_len));
1032
1033   /* Prepare outgoing data buffer for packet sending */
1034   silc_packet_send_prepare(sock, 
1035                            SILC_PACKET_HEADER_LEN +
1036                            packetdata.src_id_len + 
1037                            packetdata.dst_id_len,
1038                            packetdata.padlen,
1039                            payload->len);
1040
1041   packetdata.buffer = sock->outbuf;
1042
1043   /* Encrypt payload of the packet. This is encrypted with the channel key. */
1044   channel->channel_key->cipher->encrypt(channel->channel_key->context,
1045                                         payload->data, payload->data,
1046                                         payload->len - block_len, /* -IV_LEN */
1047                                         channel->iv);
1048
1049   /* Put the actual encrypted payload data into the buffer. */
1050   silc_buffer_put(sock->outbuf, payload->data, payload->len);
1051
1052   /* Create the outgoing packet */
1053   silc_packet_assemble(&packetdata);
1054
1055   /* Encrypt the header and padding of the packet. This is encrypted 
1056      with normal session key shared with our server. */
1057   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1058                       packetdata.src_id_len + packetdata.dst_id_len +
1059                       packetdata.padlen);
1060
1061   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1062                    sock->outbuf->data, sock->outbuf->len);
1063
1064   /* Now actually send the packet */
1065   silc_client_packet_send_real(client, sock, force_send);
1066   silc_buffer_free(payload);
1067   silc_free(id_string);
1068 }
1069
1070 /* Sends private message to remote client. If private message key has
1071    not been set with this client then the message will be encrypted using
1072    normal session keys. Private messages are special packets in SILC
1073    network hence we need this own function for them. This is similiar
1074    to silc_client_packet_send_to_channel except that we send private
1075    message. The `data' is the private message. If the `force_send' is
1076    TRUE the packet is sent immediately. */
1077
1078 void silc_client_send_private_message(SilcClient client,
1079                                       SilcClientConnection conn,
1080                                       SilcClientEntry client_entry,
1081                                       unsigned char *data, 
1082                                       unsigned int data_len, 
1083                                       int force_send)
1084 {
1085   SilcSocketConnection sock = conn->sock;
1086   SilcBuffer buffer;
1087   SilcPacketContext packetdata;
1088   unsigned int nick_len;
1089   SilcCipher cipher;
1090   SilcHmac hmac;
1091
1092   SILC_LOG_DEBUG(("Sending private message"));
1093
1094   /* Create private message payload */
1095   nick_len = strlen(conn->nickname);
1096   buffer = silc_buffer_alloc(2 + nick_len + data_len);
1097   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1098   silc_buffer_format(buffer,
1099                      SILC_STR_UI_SHORT(nick_len),
1100                      SILC_STR_UI_XNSTRING(conn->nickname,
1101                                           nick_len),
1102                      SILC_STR_UI_XNSTRING(data, data_len),
1103                      SILC_STR_END);
1104
1105   /* If we don't have private message specific key then private messages
1106      are just as any normal packet thus call normal packet sending.  If
1107      the key exist then the encryption process is a bit different and
1108      will be done in the rest of this function. */
1109   if (!client_entry->send_key) {
1110     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1111                             client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1112                             buffer->data, buffer->len, force_send);
1113     goto out;
1114   }
1115
1116   /* We have private message specific key */
1117
1118   /* Get data used in the encryption */
1119   cipher = client_entry->send_key;
1120   hmac = conn->hmac;
1121
1122   /* Set the packet context pointers. */
1123   packetdata.flags = SILC_PACKET_FLAG_PRIVMSG_KEY;
1124   packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1125   packetdata.src_id = conn->local_id_data;
1126   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1127   packetdata.src_id_type = SILC_ID_CLIENT;
1128   packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1129   packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1130   packetdata.dst_id_type = SILC_ID_CLIENT;
1131   packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN + 
1132     packetdata.src_id_len + packetdata.dst_id_len;
1133   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1134                                           packetdata.src_id_len +
1135                                           packetdata.dst_id_len));
1136
1137   /* Prepare outgoing data buffer for packet sending */
1138   silc_packet_send_prepare(sock, 
1139                            SILC_PACKET_HEADER_LEN +
1140                            packetdata.src_id_len + 
1141                            packetdata.dst_id_len,
1142                            packetdata.padlen,
1143                            buffer->len);
1144   
1145   packetdata.buffer = sock->outbuf;
1146
1147   /* Encrypt payload of the packet. Encrypt with private message specific
1148      key */
1149   cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1150                           buffer->len, cipher->iv);
1151       
1152   /* Put the actual encrypted payload data into the buffer. */
1153   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1154
1155   /* Create the outgoing packet */
1156   silc_packet_assemble(&packetdata);
1157
1158   /* Encrypt the header and padding of the packet. */
1159   cipher = conn->send_key;
1160   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1161                       packetdata.src_id_len + packetdata.dst_id_len +
1162                       packetdata.padlen);
1163
1164   SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1165                    sock->outbuf->data, sock->outbuf->len);
1166
1167   /* Now actually send the packet */
1168   silc_client_packet_send_real(client, sock, force_send);
1169   silc_free(packetdata.dst_id);
1170
1171  out:
1172   silc_free(buffer);
1173 }     
1174
1175 /* Closes connection to remote end. Free's all allocated data except
1176    for some information such as nickname etc. that are valid at all time. */
1177
1178 void silc_client_close_connection(SilcClient client,
1179                                   SilcClientConnection conn)
1180 {
1181   SilcSocketConnection sock = conn->sock;
1182
1183   /* We won't listen for this connection anymore */
1184   silc_schedule_unset_listen_fd(sock->sock);
1185
1186   /* Unregister all tasks */
1187   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1188   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1189
1190   /* Close the actual connection */
1191   silc_net_close_connection(sock->sock);
1192
1193   client->ops->say(client, sock->user_data,
1194                    "Closed connection to host %s", sock->hostname);
1195
1196   /* Free everything */
1197   if (sock->user_data) {
1198     /* XXX Free all client entries and channel entries. */
1199
1200     /* Clear ID caches */
1201     silc_idcache_del_all(conn->client_cache);
1202     silc_idcache_del_all(conn->channel_cache);
1203
1204     /* Free data */
1205     if (conn->remote_host)
1206       silc_free(conn->remote_host);
1207     if (conn->local_id)
1208       silc_free(conn->local_id);
1209     if (conn->local_id_data)
1210       silc_free(conn->local_id_data);
1211     if (conn->send_key)
1212       silc_cipher_free(conn->send_key);
1213     if (conn->receive_key)
1214       silc_cipher_free(conn->receive_key);
1215     if (conn->hmac)
1216       silc_hmac_free(conn->hmac);
1217     if (conn->hmac_key) {
1218       memset(conn->hmac_key, 0, conn->hmac_key_len);
1219       silc_free(conn->hmac_key);
1220     }
1221     if (conn->pending_commands)
1222       silc_dlist_uninit(conn->pending_commands);
1223
1224     conn->sock = NULL;
1225     conn->remote_port = 0;
1226     conn->remote_type = 0;
1227     conn->send_key = NULL;
1228     conn->receive_key = NULL;
1229     conn->hmac = NULL;
1230     conn->hmac_key = NULL;
1231     conn->hmac_key_len = 0;
1232     conn->local_id = NULL;
1233     conn->local_id_data = NULL;
1234     conn->remote_host = NULL;
1235     conn->current_channel = NULL;
1236     conn->pending_commands = NULL;
1237
1238     silc_client_del_connection(client, conn);
1239   }
1240
1241   if (sock->protocol) {
1242     silc_protocol_free(sock->protocol);
1243     sock->protocol = NULL;
1244   }
1245   silc_socket_free(sock);
1246 }
1247
1248 /* Called when we receive disconnection packet from server. This 
1249    closes our end properly and displays the reason of the disconnection
1250    on the screen. */
1251
1252 void silc_client_disconnected_by_server(SilcClient client,
1253                                         SilcSocketConnection sock,
1254                                         SilcBuffer message)
1255 {
1256   char *msg;
1257
1258   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1259
1260   msg = silc_calloc(message->len + 1, sizeof(char));
1261   memcpy(msg, message->data, message->len);
1262   client->ops->say(client, sock->user_data, msg);
1263   silc_free(msg);
1264
1265   SILC_SET_DISCONNECTED(sock);
1266   silc_client_close_connection(client, sock->user_data);
1267 }
1268
1269 /* Received error message from server. Display it on the screen. 
1270    We don't take any action what so ever of the error message. */
1271
1272 void silc_client_error_by_server(SilcClient client,
1273                                  SilcSocketConnection sock,
1274                                  SilcBuffer message)
1275 {
1276   char *msg;
1277
1278   msg = silc_calloc(message->len + 1, sizeof(char));
1279   memcpy(msg, message->data, message->len);
1280   client->ops->say(client, sock->user_data, msg);
1281   silc_free(msg);
1282 }
1283
1284 /* Called when notify is received and some async operation (such as command)
1285    is required before processing the notify message. This calls again the
1286    silc_client_notify_by_server and reprocesses the original notify packet. */
1287
1288 static void silc_client_notify_by_server_pending(void *context)
1289 {
1290   SilcPacketContext *p = (SilcPacketContext *)context;
1291   silc_client_notify_by_server(p->context, p->sock, p);
1292 }
1293
1294 /* Destructor for the pending command callback */
1295
1296 static void silc_client_notify_by_server_destructor(void *context)
1297 {
1298   silc_packet_context_free((SilcPacketContext *)context);
1299 }
1300
1301 /* Resolve client information from server by Client ID. */
1302
1303 static void silc_client_notify_by_server_resolve(SilcClient client,
1304                                                  SilcClientConnection conn,
1305                                                  SilcPacketContext *packet,
1306                                                  SilcClientID *client_id)
1307 {
1308   SilcPacketContext *p = silc_packet_context_dup(packet);
1309   SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1310
1311   p->context = (void *)client;
1312   p->sock = conn->sock;
1313
1314   silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, ++conn->cmd_ident,
1315                            1, 3, idp->data, idp->len);
1316   silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
1317                               silc_client_notify_by_server_destructor,
1318                               silc_client_notify_by_server_pending, p);
1319   silc_buffer_free(idp);
1320 }
1321
1322 /* Received notify message from server */
1323
1324 void silc_client_notify_by_server(SilcClient client,
1325                                   SilcSocketConnection sock,
1326                                   SilcPacketContext *packet)
1327 {
1328   SilcBuffer buffer = packet->buffer;
1329   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1330   SilcNotifyPayload payload;
1331   SilcNotifyType type;
1332   SilcArgumentPayload args;
1333
1334   SilcClientID *client_id = NULL;
1335   SilcChannelID *channel_id = NULL;
1336   SilcClientEntry client_entry;
1337   SilcClientEntry client_entry2;
1338   SilcChannelEntry channel;
1339   SilcChannelUser chu;
1340   SilcIDCacheEntry id_cache = NULL;
1341   unsigned char *tmp;
1342   unsigned int tmp_len, mode;
1343
1344   payload = silc_notify_payload_parse(buffer);
1345   if (!payload)
1346     goto out;
1347
1348   type = silc_notify_get_type(payload);
1349   args = silc_notify_get_args(payload);
1350   if (!args)
1351     goto out;
1352
1353   switch(type) {
1354   case SILC_NOTIFY_TYPE_NONE:
1355     /* Notify application */
1356     client->ops->notify(client, conn, type, 
1357                         silc_argument_get_arg_type(args, 1, NULL));
1358     break;
1359
1360   case SILC_NOTIFY_TYPE_INVITE:
1361     /* 
1362      * Someone invited me to a channel. Find Client and Channel entries
1363      * for the application.
1364      */
1365     
1366     /* Get Client ID */
1367     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1368     if (!tmp)
1369       goto out;
1370
1371     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1372     if (!client_id)
1373       goto out;
1374
1375     /* Find Client entry and if not found query it */
1376     client_entry = silc_client_get_client_by_id(client, conn, client_id);
1377     if (!client_entry) {
1378       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1379       goto out;
1380     }
1381
1382     /* Get Channel ID */
1383     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1384     if (!tmp)
1385       goto out;
1386
1387     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1388     if (!channel_id)
1389       goto out;
1390
1391     /* XXX Will ALWAYS fail because currently we don't have way to resolve
1392        channel information for channel that we're not joined to. */
1393     /* XXX ways to fix: use (extended) LIST command, or define the channel
1394        name to the notfy type when name resolving is not mandatory. */
1395     /* Find channel entry */
1396     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1397                                      SILC_ID_CHANNEL, &id_cache))
1398       goto out;
1399
1400     channel = (SilcChannelEntry)id_cache->context;
1401
1402     /* Notify application */
1403     client->ops->notify(client, conn, type, client_entry, channel);
1404     break;
1405
1406   case SILC_NOTIFY_TYPE_JOIN:
1407     /*
1408      * Someone has joined to a channel. Get their ID and nickname and
1409      * cache them for later use.
1410      */
1411
1412     /* Get Client ID */
1413     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1414     if (!tmp)
1415       goto out;
1416
1417     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1418     if (!client_id)
1419       goto out;
1420
1421     /* Find Client entry and if not found query it */
1422     client_entry = silc_client_get_client_by_id(client, conn, client_id);
1423     if (!client_entry) {
1424       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1425       goto out;
1426     }
1427
1428     /* If nickname or username hasn't been resolved, do so */
1429     if (!client_entry->nickname || !client_entry->username) {
1430       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1431       goto out;
1432     }
1433
1434     /* Get Channel ID */
1435     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1436     if (!tmp)
1437       goto out;
1438
1439     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1440     if (!channel_id)
1441       goto out;
1442
1443     /* Get channel entry */
1444     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1445                                      SILC_ID_CHANNEL, &id_cache))
1446       break;
1447
1448     channel = (SilcChannelEntry)id_cache->context;
1449
1450     /* Add client to channel */
1451     chu = silc_calloc(1, sizeof(*chu));
1452     chu->client = client_entry;
1453     silc_list_add(channel->clients, chu);
1454
1455     /* XXX add support for multiple same nicks on same channel. Check
1456        for them here */
1457
1458     /* Notify application. The channel entry is sent last as this notify
1459        is for channel but application don't know it from the arguments
1460        sent by server. */
1461     client->ops->notify(client, conn, type, client_entry, channel);
1462     break;
1463
1464   case SILC_NOTIFY_TYPE_LEAVE:
1465     /*
1466      * Someone has left a channel. We will remove it from the channel but
1467      * we'll keep it in the cache in case we'll need it later.
1468      */
1469     
1470     /* Get Client ID */
1471     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1472     if (!tmp)
1473       goto out;
1474
1475     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1476     if (!client_id)
1477       goto out;
1478
1479     /* Find Client entry */
1480     client_entry = 
1481       silc_client_get_client_by_id(client, conn, client_id);
1482     if (!client_entry)
1483       goto out;
1484
1485     /* Get channel entry */
1486     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1487                                 SILC_ID_CHANNEL);
1488     if (!channel_id)
1489       goto out;
1490     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1491                                      SILC_ID_CHANNEL, &id_cache))
1492       break;
1493
1494     channel = (SilcChannelEntry)id_cache->context;
1495
1496     /* Remove client from channel */
1497     silc_list_start(channel->clients);
1498     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1499       if (chu->client == client_entry) {
1500         silc_list_del(channel->clients, chu);
1501         silc_free(chu);
1502         break;
1503       }
1504     }
1505
1506     /* Notify application. The channel entry is sent last as this notify
1507        is for channel but application don't know it from the arguments
1508        sent by server. */
1509     client->ops->notify(client, conn, type, client_entry, channel);
1510     break;
1511
1512   case SILC_NOTIFY_TYPE_SIGNOFF:
1513     /*
1514      * Someone left SILC. We'll remove it from all channels and from cache.
1515      */
1516
1517     /* Get Client ID */
1518     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1519     if (!tmp)
1520       goto out;
1521
1522     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1523     if (!client_id)
1524       goto out;
1525
1526     /* Find Client entry */
1527     client_entry = 
1528       silc_client_get_client_by_id(client, conn, client_id);
1529     if (!client_entry)
1530       goto out;
1531
1532     /* Remove from all channels */
1533     silc_client_remove_from_channels(client, conn, client_entry);
1534
1535     /* Remove from cache */
1536     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1537                            client_entry->id);
1538
1539     /* Get signoff message */
1540     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1541     if (tmp_len > 128)
1542       tmp = NULL;
1543
1544     /* Notify application */
1545     client->ops->notify(client, conn, type, client_entry, tmp);
1546
1547     /* Free data */
1548     if (client_entry->nickname)
1549       silc_free(client_entry->nickname);
1550     if (client_entry->server)
1551       silc_free(client_entry->server);
1552     if (client_entry->id)
1553       silc_free(client_entry->id);
1554     if (client_entry->send_key)
1555       silc_cipher_free(client_entry->send_key);
1556     if (client_entry->receive_key)
1557       silc_cipher_free(client_entry->receive_key);
1558     break;
1559
1560   case SILC_NOTIFY_TYPE_TOPIC_SET:
1561     /*
1562      * Someone set the topic on a channel.
1563      */
1564
1565     /* Get Client ID */
1566     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1567     if (!tmp)
1568       goto out;
1569
1570     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1571     if (!client_id)
1572       goto out;
1573
1574     /* Find Client entry */
1575     client_entry = 
1576       silc_client_get_client_by_id(client, conn, client_id);
1577     if (!client_entry)
1578       goto out;
1579
1580     /* Get topic */
1581     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1582     if (!tmp)
1583       goto out;
1584
1585     /* Get channel entry */
1586     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1587                                 SILC_ID_CHANNEL);
1588     if (!channel_id)
1589       goto out;
1590     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1591                                      SILC_ID_CHANNEL, &id_cache))
1592       break;
1593
1594     channel = (SilcChannelEntry)id_cache->context;
1595
1596     /* Notify application. The channel entry is sent last as this notify
1597        is for channel but application don't know it from the arguments
1598        sent by server. */
1599     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1600     break;
1601
1602   case SILC_NOTIFY_TYPE_NICK_CHANGE:
1603     /*
1604      * Someone changed their nickname. If we don't have entry for the new
1605      * ID we will query it and return here after it's done. After we've
1606      * returned we fetch the old entry and free it and notify the 
1607      * application.
1608      */
1609
1610     /* Get new Client ID */
1611     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1612     if (!tmp)
1613       goto out;
1614
1615     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1616     if (!client_id)
1617       goto out;
1618
1619     /* Ignore my ID */
1620     if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1621       break;
1622
1623     /* Find Client entry and if not found query it */
1624     client_entry2 = 
1625       silc_client_get_client_by_id(client, conn, client_id);
1626     if (!client_entry2) {
1627       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1628       goto out;
1629     }
1630     silc_free(client_id);
1631
1632     /* Get old Client ID */
1633     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1634     if (!tmp)
1635       goto out;
1636
1637     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1638     if (!client_id)
1639       goto out;
1640
1641     /* Find old Client entry */
1642     client_entry = 
1643       silc_client_get_client_by_id(client, conn, client_id);
1644     if (!client_entry)
1645       goto out;
1646
1647     /* Remove the old from cache */
1648     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1649                            client_entry->id);
1650
1651     /* Replace old ID entry with new one on all channels. */
1652     silc_client_replace_from_channels(client, conn, client_entry,
1653                                       client_entry2);
1654
1655     /* Notify application */
1656     client->ops->notify(client, conn, type, client_entry, client_entry2);
1657
1658     /* Free data */
1659     if (client_entry->nickname)
1660       silc_free(client_entry->nickname);
1661     if (client_entry->server)
1662       silc_free(client_entry->server);
1663     if (client_entry->id)
1664       silc_free(client_entry->id);
1665     if (client_entry->send_key)
1666       silc_cipher_free(client_entry->send_key);
1667     if (client_entry->receive_key)
1668       silc_cipher_free(client_entry->receive_key);
1669     break;
1670
1671   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1672     /*
1673      * Someone changed a channel mode
1674      */
1675
1676     /* Get Client ID */
1677     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1678     if (!tmp)
1679       goto out;
1680
1681     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1682     if (!client_id)
1683       goto out;
1684
1685     /* Find Client entry */
1686     client_entry = 
1687       silc_client_get_client_by_id(client, conn, client_id);
1688     if (!client_entry)
1689       goto out;
1690
1691     /* Get the mode */
1692     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1693     if (!tmp)
1694       goto out;
1695
1696     SILC_GET32_MSB(mode, tmp);
1697
1698     /* Get channel entry */
1699     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1700                                 SILC_ID_CHANNEL);
1701     if (!channel_id)
1702       goto out;
1703     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1704                                      SILC_ID_CHANNEL, &id_cache))
1705       break;
1706
1707     channel = (SilcChannelEntry)id_cache->context;
1708
1709     /* Save the new mode */
1710     channel->mode = mode;
1711
1712     /* Notify application. The channel entry is sent last as this notify
1713        is for channel but application don't know it from the arguments
1714        sent by server. */
1715     client->ops->notify(client, conn, type, client_entry, mode, channel);
1716     break;
1717
1718   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1719     /*
1720      * Someone changed user's mode on a channel
1721      */
1722
1723     /* Get Client ID */
1724     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1725     if (!tmp)
1726       goto out;
1727
1728     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1729     if (!client_id)
1730       goto out;
1731
1732     /* Find Client entry */
1733     client_entry = 
1734       silc_client_get_client_by_id(client, conn, client_id);
1735     if (!client_entry)
1736       goto out;
1737
1738     /* Get the mode */
1739     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1740     if (!tmp)
1741       goto out;
1742
1743     SILC_GET32_MSB(mode, tmp);
1744
1745     /* Get target Client ID */
1746     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1747     if (!tmp)
1748       goto out;
1749
1750     silc_free(client_id);
1751     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1752     if (!client_id)
1753       goto out;
1754
1755     /* Find target Client entry */
1756     client_entry2 = 
1757       silc_client_get_client_by_id(client, conn, client_id);
1758     if (!client_entry2)
1759       goto out;
1760
1761     /* Get channel entry */
1762     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1763                                 SILC_ID_CHANNEL);
1764     if (!channel_id)
1765       goto out;
1766     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1767                                      SILC_ID_CHANNEL, &id_cache))
1768       break;
1769
1770     channel = (SilcChannelEntry)id_cache->context;
1771
1772     /* Save the mode */
1773     silc_list_start(channel->clients);
1774     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1775       if (chu->client == client_entry) {
1776         chu->mode = mode;
1777         break;
1778       }
1779     }
1780
1781     /* Notify application. The channel entry is sent last as this notify
1782        is for channel but application don't know it from the arguments
1783        sent by server. */
1784     client->ops->notify(client, conn, type, client_entry, mode, 
1785                         client_entry2, channel);
1786     break;
1787
1788   case SILC_NOTIFY_TYPE_MOTD:
1789     /*
1790      * Received Message of the day
1791      */
1792
1793     /* Get motd */
1794     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1795     if (!tmp)
1796       goto out;
1797     
1798     /* Notify application */
1799     client->ops->notify(client, conn, type, tmp);
1800     break;
1801
1802   case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1803     /*
1804      * Router has enforced a new ID to a channel. Let's change the old
1805      * ID to the one provided here.
1806      */
1807
1808     /* Get the old ID */
1809     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1810     if (!tmp)
1811       goto out;
1812     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1813     if (!channel_id)
1814       goto out;
1815     
1816     /* Get the channel entry */
1817     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1818                                      SILC_ID_CHANNEL, &id_cache))
1819       break;
1820
1821     channel = (SilcChannelEntry)id_cache->context;
1822
1823     /* Free the old ID */
1824     silc_free(channel_id);
1825     silc_free(channel->id);
1826
1827     /* Get the new ID */
1828     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1829     if (!tmp)
1830       goto out;
1831     channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1832     if (!channel->id)
1833       goto out;
1834
1835     id_cache->id = (void *)channel->id;
1836
1837     /* Notify application */
1838     client->ops->notify(client, conn, type, channel, channel);
1839     break;
1840
1841   case SILC_NOTIFY_TYPE_KICKED:
1842     /*
1843      * A client (maybe me) was kicked from a channel
1844      */
1845
1846     /* Get Client ID */
1847     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1848     if (!tmp)
1849       goto out;
1850
1851     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1852     if (!client_id)
1853       goto out;
1854
1855     /* Find Client entry */
1856     client_entry = 
1857       silc_client_get_client_by_id(client, conn, client_id);
1858     if (!client_entry)
1859       goto out;
1860
1861     /* Get channel entry */
1862     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1863                                 SILC_ID_CHANNEL);
1864     if (!channel_id)
1865       goto out;
1866     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1867                                      SILC_ID_CHANNEL, &id_cache))
1868       break;
1869
1870     channel = (SilcChannelEntry)id_cache->context;
1871
1872     /* Get comment */
1873     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1874
1875     /* Notify application. The channel entry is sent last as this notify
1876        is for channel but application don't know it from the arguments
1877        sent by server. */
1878     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1879
1880     /* If I was kicked from channel, remove the channel */
1881     if (client_entry == conn->local_entry) {
1882       if (conn->current_channel == channel)
1883         conn->current_channel = NULL;
1884       silc_idcache_del_by_id(conn->channel_cache, 
1885                              SILC_ID_CHANNEL, channel->id);
1886       silc_free(channel->channel_name);
1887       silc_free(channel->id);
1888       silc_free(channel->key);
1889       silc_cipher_free(channel->channel_key);
1890       silc_free(channel);
1891     }
1892     break;
1893     
1894   default:
1895     break;
1896   }
1897
1898  out:
1899   silc_notify_payload_free(payload);
1900   if (client_id)
1901     silc_free(client_id);
1902   if (channel_id)
1903     silc_free(channel_id);
1904 }
1905
1906 /* Processes the received new Client ID from server. Old Client ID is
1907    deleted from cache and new one is added. */
1908
1909 void silc_client_receive_new_id(SilcClient client,
1910                                 SilcSocketConnection sock,
1911                                 SilcIDPayload idp)
1912 {
1913   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1914   int connecting = FALSE;
1915
1916   if (!conn->local_entry)
1917     connecting = TRUE;
1918
1919   /* Delete old ID from ID cache */
1920   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1921   
1922   /* Save the new ID */
1923   if (conn->local_id)
1924     silc_free(conn->local_id);
1925   if (conn->local_id_data)
1926     silc_free(conn->local_id_data);
1927
1928   conn->local_id = silc_id_payload_get_id(idp);
1929   conn->local_id_data = silc_id_payload_get_data(idp);
1930   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1931
1932   if (!conn->local_entry)
1933     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1934
1935   conn->local_entry->nickname = conn->nickname;
1936   if (!conn->local_entry->username) {
1937     conn->local_entry->username = 
1938       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1939                   sizeof(conn->local_entry->username));
1940     sprintf(conn->local_entry->username, "%s@%s", client->username,
1941             client->hostname);
1942   }
1943   conn->local_entry->server = strdup(conn->remote_host);
1944   conn->local_entry->id = conn->local_id;
1945   
1946   /* Put it to the ID cache */
1947   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1948                    conn->local_id, (void *)conn->local_entry, TRUE);
1949
1950   /* Notify application of successful connection. We do it here now that
1951      we've received the Client ID and are allowed to send traffic. */
1952   if (connecting)
1953     client->ops->connect(client, conn, TRUE);
1954 }
1955
1956 /* Processed received Channel ID for a channel. This is called when client
1957    joins to channel and server replies with channel ID. The ID is cached. */
1958
1959 void silc_client_new_channel_id(SilcClient client,
1960                                 SilcSocketConnection sock,
1961                                 char *channel_name,
1962                                 unsigned int mode, SilcIDPayload idp)
1963 {
1964   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1965   SilcChannelEntry channel;
1966
1967   SILC_LOG_DEBUG(("New channel ID"));
1968
1969   channel = silc_calloc(1, sizeof(*channel));
1970   channel->channel_name = channel_name;
1971   channel->id = silc_id_payload_get_id(idp);
1972   channel->mode = mode;
1973   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1974
1975   conn->current_channel = channel;
1976
1977   /* Put it to the ID cache */
1978   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1979                    (void *)channel->id, (void *)channel, TRUE);
1980 }
1981
1982 /* Saves channel key from encoded `key_payload'. This is used when we
1983    receive Channel Key Payload and when we are processing JOIN command 
1984    reply. */
1985
1986 void silc_client_save_channel_key(SilcClientConnection conn,
1987                                   SilcBuffer key_payload, 
1988                                   SilcChannelEntry channel)
1989 {
1990   unsigned char *id_string, *key, *cipher;
1991   unsigned int tmp_len;
1992   SilcChannelID *id;
1993   SilcIDCacheEntry id_cache = NULL;
1994   SilcChannelKeyPayload payload;
1995
1996   payload = silc_channel_key_payload_parse(key_payload);
1997   if (!payload)
1998     return;
1999
2000   id_string = silc_channel_key_get_id(payload, &tmp_len);
2001   if (!id_string) {
2002     silc_channel_key_payload_free(payload);
2003     return;
2004   }
2005
2006   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
2007   if (!id) {
2008     silc_channel_key_payload_free(payload);
2009     return;
2010   }
2011
2012   /* Find channel. */
2013   if (!channel) {
2014     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2015                                      SILC_ID_CHANNEL, &id_cache))
2016       goto out;
2017     
2018     /* Get channel entry */
2019     channel = (SilcChannelEntry)id_cache->context;
2020   }
2021
2022   /* Save the key */
2023   key = silc_channel_key_get_key(payload, &tmp_len);
2024   cipher = silc_channel_key_get_cipher(payload, NULL);
2025   channel->key_len = tmp_len * 8;
2026   channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
2027   memcpy(channel->key, key, tmp_len);
2028
2029   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
2030     conn->client->ops->say(conn->client, conn,
2031                      "Cannot talk to channel: unsupported cipher %s", cipher);
2032     goto out;
2033   }
2034   channel->channel_key->cipher->set_key(channel->channel_key->context, 
2035                                         key, channel->key_len);
2036
2037   /* Client is now joined to the channel */
2038   channel->on_channel = TRUE;
2039
2040  out:
2041   silc_free(id);
2042   silc_channel_key_payload_free(payload);
2043 }
2044
2045 /* Processes received key for channel. The received key will be used
2046    to protect the traffic on the channel for now on. Client must receive
2047    the key to the channel before talking on the channel is possible. 
2048    This is the key that server has generated, this is not the channel
2049    private key, it is entirely local setting. */
2050
2051 void silc_client_receive_channel_key(SilcClient client,
2052                                      SilcSocketConnection sock,
2053                                      SilcBuffer packet)
2054 {
2055   SILC_LOG_DEBUG(("Received key for channel"));
2056
2057   /* Save the key */
2058   silc_client_save_channel_key(sock->user_data, packet, NULL);
2059 }
2060
2061 /* Process received message to a channel (or from a channel, really). This
2062    decrypts the channel message with channel specific key and parses the
2063    channel payload. Finally it displays the message on the screen. */
2064
2065 void silc_client_channel_message(SilcClient client, 
2066                                  SilcSocketConnection sock, 
2067                                  SilcPacketContext *packet)
2068 {
2069   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2070   SilcBuffer buffer = packet->buffer;
2071   SilcChannelPayload payload = NULL;
2072   SilcChannelID *id = NULL;
2073   SilcChannelEntry channel;
2074   SilcChannelUser chu;
2075   SilcIDCacheEntry id_cache = NULL;
2076   SilcClientID *client_id = NULL;
2077   int found = FALSE;
2078   unsigned int block_len;
2079
2080   SILC_LOG_DEBUG(("Start"));
2081
2082   /* Sanity checks */
2083   if (packet->dst_id_type != SILC_ID_CHANNEL)
2084     goto out;
2085
2086   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2087                              SILC_ID_CLIENT);
2088   if (!client_id)
2089     goto out;
2090   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2091   if (!id)
2092     goto out;
2093
2094   /* Find the channel entry from channels on this connection */
2095   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2096                                    SILC_ID_CHANNEL, &id_cache))
2097     goto out;
2098
2099   channel = (SilcChannelEntry)id_cache->context;
2100
2101   /* Decrypt the channel message payload. Push the IV out of the way,
2102      since it is not encrypted (after pushing buffer->tail has the IV). */
2103   block_len = silc_cipher_get_block_len(channel->channel_key);
2104   silc_buffer_push_tail(buffer, block_len);
2105   channel->channel_key->cipher->decrypt(channel->channel_key->context,
2106                                         buffer->data, buffer->data,
2107                                         buffer->len, buffer->tail);
2108   silc_buffer_pull_tail(buffer, block_len);
2109
2110   /* Parse the channel message payload */
2111   payload = silc_channel_payload_parse(buffer);
2112   if (!payload)
2113     goto out;
2114
2115   /* Find client entry */
2116   silc_list_start(channel->clients);
2117   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2118     if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2119       found = TRUE;
2120       break;
2121     }
2122   }
2123
2124   /* Pass the message to application */
2125   client->ops->channel_message(client, conn, found ? chu->client : NULL,
2126                                channel, silc_channel_get_data(payload, NULL));
2127
2128  out:
2129   if (id)
2130     silc_free(id);
2131   if (client_id)
2132     silc_free(client_id);
2133   if (payload)
2134     silc_channel_payload_free(payload);
2135 }
2136
2137 /* Private message received. This processes the private message and
2138    finally displays it on the screen. */
2139
2140 void silc_client_private_message(SilcClient client, 
2141                                  SilcSocketConnection sock, 
2142                                  SilcPacketContext *packet)
2143 {
2144   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2145   SilcBuffer buffer = packet->buffer;
2146   SilcIDCacheEntry id_cache;
2147   SilcClientID *remote_id = NULL;
2148   SilcClientEntry remote_client;
2149   unsigned short nick_len;
2150   unsigned char *nickname, *message = NULL;
2151   int ret;
2152
2153   if (packet->src_id_type != SILC_ID_CLIENT)
2154     goto out;
2155
2156   /* Get nickname */
2157   ret = silc_buffer_unformat(buffer, 
2158                              SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2159                              SILC_STR_END);
2160   if (ret == -1)
2161     return;
2162
2163   silc_buffer_pull(buffer, 2 + nick_len);
2164
2165   message = silc_calloc(buffer->len + 1, sizeof(char));
2166   memcpy(message, buffer->data, buffer->len);
2167
2168   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
2169                              SILC_ID_CLIENT);
2170   if (!remote_id)
2171     goto out;
2172
2173   /* Check whether we know this client already */
2174   if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2175                                    SILC_ID_CLIENT, &id_cache))
2176     {
2177       /* Allocate client entry */
2178       remote_client = silc_calloc(1, sizeof(*remote_client));
2179       remote_client->id = remote_id;
2180       silc_parse_nickname(nickname, &remote_client->nickname, 
2181                           &remote_client->server, &remote_client->num);
2182       
2183       /* Save the client to cache */
2184       silc_idcache_add(conn->client_cache, remote_client->nickname,
2185                        SILC_ID_CLIENT, remote_client->id, remote_client, 
2186                        TRUE);
2187     } else {
2188       remote_client = (SilcClientEntry)id_cache->context;
2189     }
2190
2191   /* Pass the private message to application */
2192   client->ops->private_message(client, conn, remote_client, message);
2193
2194   /* See if we are away (gone). If we are away we will reply to the
2195      sender with the set away message. */
2196   if (conn->away && conn->away->away) {
2197     /* If it's me, ignore */
2198     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2199       goto out;
2200
2201     /* Send the away message */
2202     silc_client_send_private_message(client, conn, remote_client,
2203                                      conn->away->away,
2204                                      strlen(conn->away->away), TRUE);
2205   }
2206
2207  out:
2208   if (remote_id)
2209     silc_free(remote_id);
2210
2211   if (message) {
2212     memset(message, 0, buffer->len);
2213     silc_free(message);
2214   }
2215   silc_free(nickname);
2216 }
2217
2218 /* Removes a client entry from all channel it has joined. This really is
2219    a performance killer (client_entry should have pointers to channel 
2220    entry list). */
2221
2222 void silc_client_remove_from_channels(SilcClient client,
2223                                       SilcClientConnection conn,
2224                                       SilcClientEntry client_entry)
2225 {
2226   SilcIDCacheEntry id_cache;
2227   SilcIDCacheList list;
2228   SilcChannelEntry channel;
2229   SilcChannelUser chu;
2230
2231   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2232                                SILC_ID_CHANNEL, &list))
2233     return;
2234
2235   silc_idcache_list_first(list, &id_cache);
2236   channel = (SilcChannelEntry)id_cache->context;
2237   
2238   while (channel) {
2239     
2240     /* Remove client from channel */
2241     silc_list_start(channel->clients);
2242     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2243       if (chu->client == client_entry) {
2244         silc_list_del(channel->clients, chu);
2245         silc_free(chu);
2246         break;
2247       }
2248     }
2249
2250     if (!silc_idcache_list_next(list, &id_cache))
2251       break;
2252     
2253     channel = (SilcChannelEntry)id_cache->context;
2254   }
2255
2256   silc_idcache_list_free(list);
2257 }
2258
2259 /* Replaces `old' client entries from all channels to `new' client entry.
2260    This can be called for example when nickname changes and old ID entry
2261    is replaced from ID cache with the new one. If the old ID entry is only
2262    updated, then this fucntion needs not to be called. */
2263
2264 void silc_client_replace_from_channels(SilcClient client, 
2265                                        SilcClientConnection conn,
2266                                        SilcClientEntry old,
2267                                        SilcClientEntry new)
2268 {
2269   SilcIDCacheEntry id_cache;
2270   SilcIDCacheList list;
2271   SilcChannelEntry channel;
2272   SilcChannelUser chu;
2273
2274   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2275                                SILC_ID_CHANNEL, &list))
2276     return;
2277
2278   silc_idcache_list_first(list, &id_cache);
2279   channel = (SilcChannelEntry)id_cache->context;
2280   
2281   while (channel) {
2282     
2283     /* Replace client entry */
2284     silc_list_start(channel->clients);
2285     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2286       if (chu->client == old) {
2287         chu->client = new;
2288         break;
2289       }
2290     }
2291
2292     if (!silc_idcache_list_next(list, &id_cache))
2293       break;
2294     
2295     channel = (SilcChannelEntry)id_cache->context;
2296   }
2297
2298   silc_idcache_list_free(list);
2299 }
2300
2301 /* Parses mode mask and returns the mode as string. */
2302
2303 char *silc_client_chmode(unsigned int mode)
2304 {
2305   char string[20];
2306
2307   if (!mode)
2308     return NULL;
2309
2310   memset(string, 0, sizeof(string));
2311
2312   if (mode & SILC_CHANNEL_MODE_PRIVATE)
2313     strncat(string, "p", 1);
2314
2315   if (mode & SILC_CHANNEL_MODE_SECRET)
2316     strncat(string, "s", 1);
2317
2318   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2319     strncat(string, "k", 1);
2320
2321   if (mode & SILC_CHANNEL_MODE_INVITE)
2322     strncat(string, "i", 1);
2323
2324   if (mode & SILC_CHANNEL_MODE_TOPIC)
2325     strncat(string, "t", 1);
2326
2327   if (mode & SILC_CHANNEL_MODE_ULIMIT)
2328     strncat(string, "l", 1);
2329
2330   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2331     strncat(string, "a", 1);
2332
2333   /* Rest of mode is ignored */
2334
2335   return strdup(string);
2336 }
2337
2338 /* Parses channel user mode mask and returns te mode as string */
2339
2340 char *silc_client_chumode(unsigned int mode)
2341 {
2342   char string[4];
2343
2344   if (!mode)
2345     return NULL;
2346
2347   memset(string, 0, sizeof(string));
2348
2349   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2350     strncat(string, "f", 1);
2351
2352   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2353     strncat(string, "o", 1);
2354
2355   return strdup(string);
2356 }
2357
2358 /* Parses channel user mode and returns it as special mode character. */
2359
2360 char *silc_client_chumode_char(unsigned int mode)
2361 {
2362   char string[4];
2363
2364   if (!mode)
2365     return NULL;
2366
2367   memset(string, 0, sizeof(string));
2368
2369   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2370     strncat(string, "*", 1);
2371
2372   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2373     strncat(string, "@", 1);
2374
2375   return strdup(string);
2376 }
2377
2378 /* Function that actually employes the received private message key */
2379
2380 static void silc_client_private_message_key_cb(SilcClient client,
2381                                                SilcClientConnection conn,
2382                                                SilcClientEntry *clients,
2383                                                unsigned int clients_count,
2384                                                void *context)
2385 {
2386   SilcPacketContext *packet = (SilcPacketContext *)context;
2387   unsigned char *key;
2388   unsigned short key_len;
2389   unsigned char *cipher;
2390   int ret;
2391
2392   if (!clients)
2393     goto out;
2394
2395   /* Parse the private message key payload */
2396   ret = silc_buffer_unformat(packet->buffer,
2397                              SILC_STR_UI16_NSTRING(&key, &key_len),
2398                              SILC_STR_UI16_STRING(&cipher),
2399                              SILC_STR_END);
2400   if (!ret)
2401     goto out;
2402
2403   if (key_len > packet->buffer->len)
2404     goto out;
2405
2406   /* Now take the key in use */
2407   if (!silc_client_add_private_message_key(client, conn, clients[0],
2408                                            cipher, key, key_len, FALSE))
2409     goto out;
2410
2411   /* Print some info for application */
2412   client->ops->say(client, conn, 
2413                    "Received private message key from %s%s%s %s%s%s", 
2414                    clients[0]->nickname,
2415                    clients[0]->server ? "@" : "",
2416                    clients[0]->server ? clients[0]->server : "",
2417                    clients[0]->username ? "(" : "",
2418                    clients[0]->username ? clients[0]->username : "",
2419                    clients[0]->username ? ")" : "");
2420
2421  out:
2422   silc_packet_context_free(packet);
2423 }
2424
2425 /* Processes incoming Private Message Key payload. The libary always
2426    accepts the key and takes it into use. */
2427
2428 void silc_client_private_message_key(SilcClient client,
2429                                      SilcSocketConnection sock,
2430                                      SilcPacketContext *packet)
2431 {
2432   SilcClientID *remote_id;
2433
2434   if (packet->src_id_type != SILC_ID_CLIENT)
2435     return;
2436
2437   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
2438                              SILC_ID_CLIENT);
2439   if (!remote_id)
2440     return;
2441
2442   silc_client_get_client_by_id_resolve(client, sock->user_data, remote_id,
2443                                        silc_client_private_message_key_cb,
2444                                        silc_packet_context_dup(packet));
2445   silc_free(remote_id);
2446 }
2447
2448 /* Adds private message key to the client library. The key will be used to
2449    encrypt all private message between the client and the remote client
2450    indicated by the `client_entry'. If the `key' is NULL and the boolean
2451    value `generate_key' is TRUE the library will generate random key.
2452    The `key' maybe for example pre-shared-key, passphrase or similar.
2453    The `cipher' MAY be provided but SHOULD be NULL to assure that the
2454    requirements of the SILC protocol are met. The API, however, allows
2455    to allocate any cipher.
2456
2457    It is not necessary to set key for normal private message usage. If the
2458    key is not set then the private messages are encrypted using normal
2459    session keys. Setting the private key, however, increases the security. 
2460
2461    Returns FALSE if the key is already set for the `client_entry', TRUE
2462    otherwise. */
2463
2464 int silc_client_add_private_message_key(SilcClient client,
2465                                         SilcClientConnection conn,
2466                                         SilcClientEntry client_entry,
2467                                         char *cipher,
2468                                         unsigned char *key,
2469                                         unsigned int key_len,
2470                                         int generate_key)
2471 {
2472   unsigned char private_key[32];
2473   unsigned int len;
2474   int i;
2475   SilcSKEKeyMaterial *keymat;
2476
2477   assert(client_entry);
2478
2479   /* Return FALSE if key already set */
2480   if (client_entry->send_key && client_entry->receive_key)
2481     return FALSE;
2482
2483   if (!cipher)
2484     cipher = "aes-256-cbc";
2485
2486   /* Check the requested cipher */
2487   if (!silc_cipher_is_supported(cipher))
2488     return FALSE;
2489
2490   /* Generate key if not provided */
2491   if (!key && generate_key == TRUE) {
2492     len = 32;
2493     for (i = 0; i < len; i++) private_key[i] = silc_rng_get_byte(client->rng);
2494     key = private_key;
2495     key_len = len;
2496     client_entry->generated = TRUE;
2497   }
2498
2499   /* Save the key */
2500   client_entry->key = silc_calloc(key_len, sizeof(*client_entry->key));
2501   memcpy(client_entry->key, key, key_len);
2502   client_entry->key_len = key_len;
2503
2504   /* Produce the key material as the protocol defines */
2505   keymat = silc_calloc(1, sizeof(*keymat));
2506   if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16, 
2507                                          client->md5hash, keymat) 
2508       != SILC_SKE_STATUS_OK)
2509     return FALSE;
2510
2511   /* Allocate the ciphers */
2512   silc_cipher_alloc(cipher, &client_entry->send_key);
2513   silc_cipher_alloc(cipher, &client_entry->receive_key);
2514
2515   /* Set the keys */
2516   silc_cipher_set_key(client_entry->send_key, keymat->send_enc_key,
2517                       keymat->enc_key_len);
2518   silc_cipher_set_iv(client_entry->send_key, keymat->send_iv);
2519   silc_cipher_set_key(client_entry->receive_key, keymat->receive_enc_key,
2520                       keymat->enc_key_len);
2521   silc_cipher_set_iv(client_entry->receive_key, keymat->receive_iv);
2522
2523   /* Free the key material */
2524   silc_ske_free_key_material(keymat);
2525
2526   return TRUE;
2527 }
2528
2529 /* Same as above but takes the key material from the SKE key material
2530    structure. This structure is received if the application uses the
2531    silc_client_send_key_agreement to negotiate the key material. The
2532    `cipher' SHOULD be provided as it is negotiated also in the SKE
2533    protocol. */
2534
2535 int silc_client_add_private_message_key_ske(SilcClient client,
2536                                             SilcClientConnection conn,
2537                                             SilcClientEntry client_entry,
2538                                             char *cipher,
2539                                             SilcSKEKeyMaterial *key)
2540 {
2541   assert(client_entry);
2542
2543   /* Return FALSE if key already set */
2544   if (client_entry->send_key && client_entry->receive_key)
2545     return FALSE;
2546
2547   if (!cipher)
2548     cipher = "aes-256-cbc";
2549
2550   /* Check the requested cipher */
2551   if (!silc_cipher_is_supported(cipher))
2552     return FALSE;
2553
2554   /* Allocate the ciphers */
2555   silc_cipher_alloc(cipher, &client_entry->send_key);
2556   silc_cipher_alloc(cipher, &client_entry->receive_key);
2557
2558   /* Set the keys */
2559   silc_cipher_set_key(client_entry->send_key, key->send_enc_key,
2560                       key->enc_key_len);
2561   silc_cipher_set_iv(client_entry->send_key, key->send_iv);
2562   silc_cipher_set_key(client_entry->receive_key, key->receive_enc_key,
2563                       key->enc_key_len);
2564   silc_cipher_set_iv(client_entry->receive_key, key->receive_iv);
2565
2566   return TRUE;
2567 }
2568
2569 /* Sends private message key payload to the remote client indicated by
2570    the `client_entry'. If the `force_send' is TRUE the packet is sent
2571    immediately. Returns FALSE if error occurs, TRUE otherwise. The
2572    application should call this function after setting the key to the
2573    client.
2574
2575    Note that the key sent using this function is sent to the remote client
2576    through the SILC network. The packet is protected using normal session
2577    keys. */
2578
2579 int silc_client_send_private_message_key(SilcClient client,
2580                                          SilcClientConnection conn,
2581                                          SilcClientEntry client_entry,
2582                                          int force_send)
2583 {
2584   SilcSocketConnection sock = conn->sock;
2585   SilcBuffer buffer;
2586   int cipher_len;
2587
2588   if (!client_entry->send_key || !client_entry->key)
2589     return FALSE;
2590
2591   SILC_LOG_DEBUG(("Sending private message key"));
2592
2593   cipher_len = strlen(client_entry->send_key->cipher->name);
2594
2595   /* Create private message key payload */
2596   buffer = silc_buffer_alloc(2 + client_entry->key_len);
2597   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
2598   silc_buffer_format(buffer,
2599                      SILC_STR_UI_SHORT(client_entry->key_len),
2600                      SILC_STR_UI_XNSTRING(client_entry->key, 
2601                                           client_entry->key_len),
2602                      SILC_STR_UI_SHORT(cipher_len),
2603                      SILC_STR_UI_XNSTRING(client_entry->send_key->cipher->name,
2604                                           cipher_len),
2605                      SILC_STR_END);
2606
2607   /* Send the packet */
2608   silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE_KEY,
2609                           client_entry->id, SILC_ID_CLIENT, NULL, NULL,
2610                           buffer->data, buffer->len, force_send);
2611   silc_free(buffer);
2612
2613   return TRUE;
2614 }
2615
2616 /* Removes the private message from the library. The key won't be used
2617    after this to protect the private messages with the remote `client_entry'
2618    client. Returns FALSE on error, TRUE otherwise. */
2619
2620 int silc_client_del_private_message_key(SilcClient client,
2621                                         SilcClientConnection conn,
2622                                         SilcClientEntry client_entry)
2623 {
2624   assert(client_entry);
2625
2626   if (!client_entry->send_key && !client_entry->receive_key)
2627     return FALSE;
2628
2629   silc_cipher_free(client_entry->send_key);
2630   silc_cipher_free(client_entry->receive_key);
2631
2632   if (client_entry->key) {
2633     memset(client_entry->key, 0, client_entry->key_len);
2634     silc_free(client_entry->key);
2635   }
2636
2637   client_entry->send_key = NULL;
2638   client_entry->receive_key = NULL;
2639   client_entry->key = NULL;
2640
2641   return TRUE;
2642 }
2643
2644 /* Returns array of set private message keys associated to the connection
2645    `conn'. Returns allocated SilcPrivateMessageKeys array and the array
2646    count to the `key_count' argument. The array must be freed by the caller
2647    by calling the silc_client_free_private_message_keys function. Note: 
2648    the keys returned in the array is in raw format. It might not be desired
2649    to show the keys as is. The application might choose not to show the keys
2650    at all or to show the fingerprints of the keys. */
2651
2652 SilcPrivateMessageKeys
2653 silc_client_list_private_message_keys(SilcClient client,
2654                                       SilcClientConnection conn,
2655                                       unsigned int *key_count)
2656 {
2657   SilcPrivateMessageKeys keys;
2658   unsigned int count = 0;
2659   SilcIDCacheEntry id_cache;
2660   SilcIDCacheList list;
2661   SilcClientEntry entry;
2662
2663   if (!silc_idcache_find_by_id(conn->client_cache, SILC_ID_CACHE_ANY, 
2664                                SILC_ID_CLIENT, &list))
2665     return NULL;
2666
2667   if (!silc_idcache_list_count(list)) {
2668     silc_idcache_list_free(list);
2669     return NULL;
2670   }
2671
2672   keys = silc_calloc(silc_idcache_list_count(list), sizeof(*keys));
2673
2674   silc_idcache_list_first(list, &id_cache);
2675   while (id_cache) {
2676     entry = (SilcClientEntry)id_cache->context;
2677
2678     if (entry->send_key) {
2679       keys[count].client_entry = entry;
2680       keys[count].cipher = entry->send_key->cipher->name;
2681       keys[count].key = entry->generated == FALSE ? entry->key : NULL;
2682       keys[count].key_len = entry->generated == FALSE ? entry->key_len : 0;
2683       count++;
2684     }
2685
2686     if (!silc_idcache_list_next(list, &id_cache))
2687       break;
2688   }
2689
2690   if (key_count)
2691     *key_count = count;
2692
2693   return keys;
2694 }
2695
2696 /* Frees the SilcPrivateMessageKeys array returned by the function
2697    silc_client_list_private_message_keys. */
2698
2699 void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
2700                                            unsigned int key_count)
2701 {
2702   silc_free(keys);
2703 }
2704
2705 /* Adds private key for channel. This may be set only if the channel's mode
2706    mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
2707    mode is not set. When channel has private key then the messages are
2708    encrypted using that key. All clients on the channel must also know the
2709    key in order to decrypt the messages. However, it is possible to have
2710    several private keys per one channel. In this case only some of the
2711    clients on the channel may now the one key and only some the other key.
2712
2713    The private key for channel is optional. If it is not set then the
2714    channel messages are encrypted using the channel key generated by the
2715    server. However, setting the private key (or keys) for the channel 
2716    significantly adds security. If more than one key is set the library
2717    will automatically try all keys at the message decryption phase. Note:
2718    setting many keys slows down the decryption phase as all keys has to
2719    be tried in order to find the correct decryption key. However, setting
2720    a few keys does not have big impact to the decryption performace. 
2721
2722    NOTE: that this is entirely local setting. The key set using this function
2723    is not sent to the network at any phase.
2724
2725    NOTE: If the key material was originated by the SKE protocol (using
2726    silc_client_send_key_agreement) then the `key' MUST be the
2727    key->send_enc_key as this is dictated by the SILC protocol. However,
2728    currently it is not expected that the SKE key material would be used
2729    as channel private key. However, this API allows it. */
2730
2731 int silc_client_add_channel_private_key(SilcClient client,
2732                                         SilcClientConnection conn,
2733                                         SilcChannelEntry channel,
2734                                         char *cipher,
2735                                         unsigned char *key,
2736                                         unsigned int key_len)
2737 {
2738
2739   return TRUE;
2740 }
2741
2742 /* Removes all private keys from the `channel'. The old channel key is used
2743    after calling this to protect the channel messages. Returns FALSE on
2744    on error, TRUE otherwise. */
2745
2746 int silc_client_del_channel_private_keys(SilcClient client,
2747                                          SilcClientConnection conn,
2748                                          SilcChannelEntry channel)
2749 {
2750
2751   return TRUE;
2752 }
2753
2754 /* Removes and frees private key `key' from the channel `channel'. The `key'
2755    is retrieved by calling the function silc_client_list_channel_private_keys.
2756    The key is not used after this. If the key was last private key then the
2757    old channel key is used hereafter to protect the channel messages. This
2758    returns FALSE on error, TRUE otherwise. */
2759
2760 int silc_client_del_channel_private_key(SilcClient client,
2761                                         SilcClientConnection conn,
2762                                         SilcChannelEntry channel,
2763                                         SilcChannelPrivateKey key)
2764 {
2765
2766   return TRUE;
2767 }
2768
2769 /* Returns array (pointers) of private keys associated to the `channel'.
2770    The caller must free the array by calling the function
2771    silc_client_free_channel_private_keys. The pointers in the array may be
2772    used to delete the specific key by giving the pointer as argument to the
2773    function silc_client_del_channel_private_key. */
2774
2775 SilcChannelPrivateKey *
2776 silc_client_list_channel_private_keys(SilcClient client,
2777                                       SilcClientConnection conn,
2778                                       SilcChannelEntry channel,
2779                                       unsigned int key_count)
2780 {
2781
2782   return NULL;
2783 }
2784
2785 /* Frees the SilcChannelPrivateKey array. */
2786
2787 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
2788                                            unsigned int key_count)
2789 {
2790
2791 }
2792
2793 /* Sends key agreement request to the remote client indicated by the
2794    `client_entry'. If the caller provides the `hostname' and the `port'
2795    arguments then the library will bind the client to that hostname and
2796    that port for the key agreement protocol. It also sends the `hostname'
2797    and the `port' in the key agreement packet to the remote client. This
2798    would indicate that the remote client may initiate the key agreement
2799    protocol to the `hostname' on the `port'.
2800
2801    If the `hostname' and `port' is not provided then empty key agreement
2802    packet is sent to the remote client. The remote client may reply with
2803    the same packet including its hostname and port. If the library receives
2804    the reply from the remote client the `key_agreement' client operation
2805    callback will be called to verify whether the user wants to perform the
2806    key agreement or not. 
2807
2808    NOTE: If the application provided the `hostname' and the `port' and the 
2809    remote side initiates the key agreement protocol it is not verified
2810    from the user anymore whether the protocol should be executed or not.
2811    By setting the `hostname' and `port' the user gives permission to
2812    perform the protocol (we are responder in this case).
2813
2814    NOTE: If the remote side decides not to initiate the key agreement
2815    or decides not to reply with the key agreement packet then we cannot
2816    perform the key agreement at all. If the key agreement protocol is
2817    performed the `completion' callback with the `context' will be called.
2818    If remote side decides to ignore the request the `completion' will never
2819    be called and the caller is responsible of freeing the `context' memory. 
2820    The application can do this by setting, for example, timeout. */
2821
2822 void silc_client_send_key_agreement(SilcClient client,
2823                                     SilcClientConnection conn,
2824                                     SilcClientEntry client_entry,
2825                                     char *hostname,
2826                                     int port,
2827                                     SilcKeyAgreementCallback completion,
2828                                     void *context)
2829 {
2830
2831 }
2832
2833 /* Performs the actual key agreement protocol. Application may use this
2834    to initiate the key agreement protocol. This can be called for example
2835    after the application has received the `key_agreement' client operation,
2836    and did not return TRUE from it.
2837
2838    The `hostname' is the remote hostname (or IP address) and the `port'
2839    is the remote port. The `completion' callblack with the `context' will
2840    be called after the key agreement protocol.
2841    
2842    NOTE: If the application returns TRUE in the `key_agreement' client
2843    operation the library will automatically start the key agreement. In this
2844    case the application must not call this function. However, application
2845    may choose to just ignore the `key_agreement' client operation (and
2846    merely just print information about it on the screen) and call this
2847    function when the user whishes to do so (by, for example, giving some
2848    specific command). Thus, the API provides both, automatic and manual
2849    initiation of the key agreement. Calling this function is the manual
2850    initiation and returning TRUE in the `key_agreement' client operation
2851    is the automatic initiation. */
2852
2853 void silc_client_perform_key_agreement(SilcClient client,
2854                                        SilcClientConnection conn,
2855                                        SilcClientEntry client_entry,
2856                                        char *hostname,
2857                                        int port,
2858                                        SilcKeyAgreementCallback completion,
2859                                        void *context)
2860 {
2861
2862 }
2863
2864 /* This function can be called to unbind the hostname and the port for
2865    the key agreement protocol. However, this function has effect only 
2866    before the key agreement protocol has been performed. After it has
2867    been performed the library will automatically unbind the port. The 
2868    `client_entry' is the client to which we sent the key agreement 
2869    request. */
2870
2871 void silc_client_abort_key_agreement(SilcClient client,
2872                                      SilcClientConnection conn,
2873                                      SilcClientEntry client_entry)
2874 {
2875
2876 }