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] = silc_rng_get_byte(client->rng);
996   else
997     silc_hash_make(client->md5hash, channel->iv, block_len, channel->iv);
998
999   /* Encode the channel payload */
1000   payload = silc_channel_payload_encode(data_len, data, block_len, 
1001                                         channel->iv, client->rng);
1002   if (!payload) {
1003     client->ops->say(client, conn, 
1004                      "Error: Could not create packet to be sent to channel");
1005     return;
1006   }
1007
1008   /* Get data used in packet header encryption, keys and stuff. Rest
1009      of the packet (the payload) is, however, encrypted with the 
1010      specified channel key. */
1011   cipher = conn->send_key;
1012   hmac = conn->hmac;
1013   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1014
1015   /* Set the packet context pointers. The destination ID is always
1016      the Channel ID of the channel. Server and router will handle the
1017      distribution of the packet. */
1018   packetdata.flags = 0;
1019   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1020   packetdata.src_id = conn->local_id_data;
1021   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1022   packetdata.src_id_type = SILC_ID_CLIENT;
1023   packetdata.dst_id = id_string;
1024   packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1025   packetdata.dst_id_type = SILC_ID_CHANNEL;
1026   packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN + 
1027     packetdata.src_id_len + packetdata.dst_id_len;
1028   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1029                                           packetdata.src_id_len +
1030                                           packetdata.dst_id_len));
1031
1032   /* Prepare outgoing data buffer for packet sending */
1033   silc_packet_send_prepare(sock, 
1034                            SILC_PACKET_HEADER_LEN +
1035                            packetdata.src_id_len + 
1036                            packetdata.dst_id_len,
1037                            packetdata.padlen,
1038                            payload->len);
1039
1040   packetdata.buffer = sock->outbuf;
1041
1042   /* Encrypt payload of the packet. This is encrypted with the channel key. */
1043   channel->channel_key->cipher->encrypt(channel->channel_key->context,
1044                                         payload->data, payload->data,
1045                                         payload->len - block_len, /* -IV_LEN */
1046                                         channel->iv);
1047
1048   /* Put the actual encrypted payload data into the buffer. */
1049   silc_buffer_put(sock->outbuf, payload->data, payload->len);
1050
1051   /* Create the outgoing packet */
1052   silc_packet_assemble(&packetdata);
1053
1054   /* Encrypt the header and padding of the packet. This is encrypted 
1055      with normal session key shared with our server. */
1056   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1057                       packetdata.src_id_len + packetdata.dst_id_len +
1058                       packetdata.padlen);
1059
1060   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1061                    sock->outbuf->data, sock->outbuf->len);
1062
1063   /* Now actually send the packet */
1064   silc_client_packet_send_real(client, sock, force_send);
1065   silc_buffer_free(payload);
1066   silc_free(id_string);
1067 }
1068
1069 /* Sends private message to remote client. If private message key has
1070    not been set with this client then the message will be encrypted using
1071    normal session keys. Private messages are special packets in SILC
1072    network hence we need this own function for them. This is similiar
1073    to silc_client_packet_send_to_channel except that we send private
1074    message. The `data' is the private message. If the `force_send' is
1075    TRUE the packet is sent immediately. */
1076
1077 void silc_client_send_private_message(SilcClient client,
1078                                       SilcClientConnection conn,
1079                                       SilcClientEntry client_entry,
1080                                       unsigned char *data, 
1081                                       unsigned int data_len, 
1082                                       int force_send)
1083 {
1084   SilcSocketConnection sock = conn->sock;
1085   SilcBuffer buffer;
1086   SilcPacketContext packetdata;
1087   unsigned int nick_len;
1088   SilcCipher cipher;
1089   SilcHmac hmac;
1090
1091   SILC_LOG_DEBUG(("Sending private message"));
1092
1093   /* Create private message payload */
1094   nick_len = strlen(conn->nickname);
1095   buffer = silc_buffer_alloc(2 + nick_len + data_len);
1096   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1097   silc_buffer_format(buffer,
1098                      SILC_STR_UI_SHORT(nick_len),
1099                      SILC_STR_UI_XNSTRING(conn->nickname,
1100                                           nick_len),
1101                      SILC_STR_UI_XNSTRING(data, data_len),
1102                      SILC_STR_END);
1103
1104   /* If we don't have private message specific key then private messages
1105      are just as any normal packet thus call normal packet sending.  If
1106      the key exist then the encryption process is a bit different and
1107      will be done in the rest of this function. */
1108   if (!client_entry->send_key) {
1109     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1110                             client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1111                             buffer->data, buffer->len, force_send);
1112     goto out;
1113   }
1114
1115   /* We have private message specific key */
1116
1117   /* Get data used in the encryption */
1118   cipher = client_entry->send_key;
1119   hmac = conn->hmac;
1120
1121   /* Set the packet context pointers. */
1122   packetdata.flags = SILC_PACKET_FLAG_PRIVMSG_KEY;
1123   packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1124   packetdata.src_id = conn->local_id_data;
1125   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1126   packetdata.src_id_type = SILC_ID_CLIENT;
1127   packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1128   packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1129   packetdata.dst_id_type = SILC_ID_CLIENT;
1130   packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN + 
1131     packetdata.src_id_len + packetdata.dst_id_len;
1132   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1133                                           packetdata.src_id_len +
1134                                           packetdata.dst_id_len));
1135
1136   /* Prepare outgoing data buffer for packet sending */
1137   silc_packet_send_prepare(sock, 
1138                            SILC_PACKET_HEADER_LEN +
1139                            packetdata.src_id_len + 
1140                            packetdata.dst_id_len,
1141                            packetdata.padlen,
1142                            buffer->len);
1143   
1144   packetdata.buffer = sock->outbuf;
1145
1146   /* Encrypt payload of the packet. Encrypt with private message specific
1147      key */
1148   cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1149                           buffer->len, cipher->iv);
1150       
1151   /* Put the actual encrypted payload data into the buffer. */
1152   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1153
1154   /* Create the outgoing packet */
1155   silc_packet_assemble(&packetdata);
1156
1157   /* Encrypt the header and padding of the packet. */
1158   cipher = conn->send_key;
1159   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1160                       packetdata.src_id_len + packetdata.dst_id_len +
1161                       packetdata.padlen);
1162
1163   SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1164                    sock->outbuf->data, sock->outbuf->len);
1165
1166   /* Now actually send the packet */
1167   silc_client_packet_send_real(client, sock, force_send);
1168   silc_free(packetdata.dst_id);
1169
1170  out:
1171   silc_free(buffer);
1172 }     
1173
1174 /* Closes connection to remote end. Free's all allocated data except
1175    for some information such as nickname etc. that are valid at all time. */
1176
1177 void silc_client_close_connection(SilcClient client,
1178                                   SilcClientConnection conn)
1179 {
1180   SilcSocketConnection sock = conn->sock;
1181
1182   /* We won't listen for this connection anymore */
1183   silc_schedule_unset_listen_fd(sock->sock);
1184
1185   /* Unregister all tasks */
1186   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1187   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1188
1189   /* Close the actual connection */
1190   silc_net_close_connection(sock->sock);
1191
1192   client->ops->say(client, sock->user_data,
1193                    "Closed connection to host %s", sock->hostname);
1194
1195   /* Free everything */
1196   if (sock->user_data) {
1197     /* XXX Free all client entries and channel entries. */
1198
1199     /* Clear ID caches */
1200     silc_idcache_del_all(conn->client_cache);
1201     silc_idcache_del_all(conn->channel_cache);
1202
1203     /* Free data */
1204     if (conn->remote_host)
1205       silc_free(conn->remote_host);
1206     if (conn->local_id)
1207       silc_free(conn->local_id);
1208     if (conn->local_id_data)
1209       silc_free(conn->local_id_data);
1210     if (conn->send_key)
1211       silc_cipher_free(conn->send_key);
1212     if (conn->receive_key)
1213       silc_cipher_free(conn->receive_key);
1214     if (conn->hmac)
1215       silc_hmac_free(conn->hmac);
1216     if (conn->hmac_key) {
1217       memset(conn->hmac_key, 0, conn->hmac_key_len);
1218       silc_free(conn->hmac_key);
1219     }
1220     if (conn->pending_commands)
1221       silc_dlist_uninit(conn->pending_commands);
1222
1223     conn->sock = NULL;
1224     conn->remote_port = 0;
1225     conn->remote_type = 0;
1226     conn->send_key = NULL;
1227     conn->receive_key = NULL;
1228     conn->hmac = NULL;
1229     conn->hmac_key = NULL;
1230     conn->hmac_key_len = 0;
1231     conn->local_id = NULL;
1232     conn->local_id_data = NULL;
1233     conn->remote_host = NULL;
1234     conn->current_channel = NULL;
1235     conn->pending_commands = NULL;
1236
1237     silc_client_del_connection(client, conn);
1238   }
1239
1240   if (sock->protocol) {
1241     silc_protocol_free(sock->protocol);
1242     sock->protocol = NULL;
1243   }
1244   silc_socket_free(sock);
1245 }
1246
1247 /* Called when we receive disconnection packet from server. This 
1248    closes our end properly and displays the reason of the disconnection
1249    on the screen. */
1250
1251 void silc_client_disconnected_by_server(SilcClient client,
1252                                         SilcSocketConnection sock,
1253                                         SilcBuffer message)
1254 {
1255   char *msg;
1256
1257   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1258
1259   msg = silc_calloc(message->len + 1, sizeof(char));
1260   memcpy(msg, message->data, message->len);
1261   client->ops->say(client, sock->user_data, msg);
1262   silc_free(msg);
1263
1264   SILC_SET_DISCONNECTED(sock);
1265   silc_client_close_connection(client, sock->user_data);
1266 }
1267
1268 /* Received error message from server. Display it on the screen. 
1269    We don't take any action what so ever of the error message. */
1270
1271 void silc_client_error_by_server(SilcClient client,
1272                                  SilcSocketConnection sock,
1273                                  SilcBuffer message)
1274 {
1275   char *msg;
1276
1277   msg = silc_calloc(message->len + 1, sizeof(char));
1278   memcpy(msg, message->data, message->len);
1279   client->ops->say(client, sock->user_data, msg);
1280   silc_free(msg);
1281 }
1282
1283 /* Called when notify is received and some async operation (such as command)
1284    is required before processing the notify message. This calls again the
1285    silc_client_notify_by_server and reprocesses the original notify packet. */
1286
1287 static void silc_client_notify_by_server_pending(void *context)
1288 {
1289   SilcPacketContext *p = (SilcPacketContext *)context;
1290   silc_client_notify_by_server(p->context, p->sock, p);
1291 }
1292
1293 /* Destructor for the pending command callback */
1294
1295 static void silc_client_notify_by_server_destructor(void *context)
1296 {
1297   silc_packet_context_free((SilcPacketContext *)context);
1298 }
1299
1300 /* Resolve client information from server by Client ID. */
1301
1302 static void silc_client_notify_by_server_resolve(SilcClient client,
1303                                                  SilcClientConnection conn,
1304                                                  SilcPacketContext *packet,
1305                                                  SilcClientID *client_id)
1306 {
1307   SilcPacketContext *p = silc_packet_context_dup(packet);
1308   SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1309
1310   p->context = (void *)client;
1311   p->sock = conn->sock;
1312
1313   silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, ++conn->cmd_ident,
1314                            1, 3, idp->data, idp->len);
1315   silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
1316                               silc_client_notify_by_server_destructor,
1317                               silc_client_notify_by_server_pending, p);
1318   silc_buffer_free(idp);
1319 }
1320
1321 /* Received notify message from server */
1322
1323 void silc_client_notify_by_server(SilcClient client,
1324                                   SilcSocketConnection sock,
1325                                   SilcPacketContext *packet)
1326 {
1327   SilcBuffer buffer = packet->buffer;
1328   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1329   SilcNotifyPayload payload;
1330   SilcNotifyType type;
1331   SilcArgumentPayload args;
1332
1333   SilcClientID *client_id = NULL;
1334   SilcChannelID *channel_id = NULL;
1335   SilcClientEntry client_entry;
1336   SilcClientEntry client_entry2;
1337   SilcChannelEntry channel;
1338   SilcChannelUser chu;
1339   SilcIDCacheEntry id_cache = NULL;
1340   unsigned char *tmp;
1341   unsigned int tmp_len, mode;
1342
1343   payload = silc_notify_payload_parse(buffer);
1344   if (!payload)
1345     goto out;
1346
1347   type = silc_notify_get_type(payload);
1348   args = silc_notify_get_args(payload);
1349   if (!args)
1350     goto out;
1351
1352   switch(type) {
1353   case SILC_NOTIFY_TYPE_NONE:
1354     /* Notify application */
1355     client->ops->notify(client, conn, type, 
1356                         silc_argument_get_arg_type(args, 1, NULL));
1357     break;
1358
1359   case SILC_NOTIFY_TYPE_INVITE:
1360     /* 
1361      * Someone invited me to a channel. Find Client and Channel entries
1362      * for the application.
1363      */
1364     
1365     /* Get Client ID */
1366     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1367     if (!tmp)
1368       goto out;
1369
1370     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1371     if (!client_id)
1372       goto out;
1373
1374     /* Find Client entry and if not found query it */
1375     client_entry = silc_client_get_client_by_id(client, conn, client_id);
1376     if (!client_entry) {
1377       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1378       goto out;
1379     }
1380
1381     /* Get Channel ID */
1382     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1383     if (!tmp)
1384       goto out;
1385
1386     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1387     if (!channel_id)
1388       goto out;
1389
1390     /* XXX Will ALWAYS fail because currently we don't have way to resolve
1391        channel information for channel that we're not joined to. */
1392     /* XXX ways to fix: use (extended) LIST command, or define the channel
1393        name to the notfy type when name resolving is not mandatory. */
1394     /* Find channel entry */
1395     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1396                                      SILC_ID_CHANNEL, &id_cache))
1397       goto out;
1398
1399     channel = (SilcChannelEntry)id_cache->context;
1400
1401     /* Notify application */
1402     client->ops->notify(client, conn, type, client_entry, channel);
1403     break;
1404
1405   case SILC_NOTIFY_TYPE_JOIN:
1406     /*
1407      * Someone has joined to a channel. Get their ID and nickname and
1408      * cache them for later use.
1409      */
1410
1411     /* Get Client ID */
1412     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1413     if (!tmp)
1414       goto out;
1415
1416     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1417     if (!client_id)
1418       goto out;
1419
1420     /* Find Client entry and if not found query it */
1421     client_entry = silc_client_get_client_by_id(client, conn, client_id);
1422     if (!client_entry) {
1423       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1424       goto out;
1425     }
1426
1427     /* If nickname or username hasn't been resolved, do so */
1428     if (!client_entry->nickname || !client_entry->username) {
1429       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1430       goto out;
1431     }
1432
1433     /* Get Channel ID */
1434     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1435     if (!tmp)
1436       goto out;
1437
1438     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1439     if (!channel_id)
1440       goto out;
1441
1442     /* Get channel entry */
1443     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1444                                      SILC_ID_CHANNEL, &id_cache))
1445       break;
1446
1447     channel = (SilcChannelEntry)id_cache->context;
1448
1449     /* Add client to channel */
1450     chu = silc_calloc(1, sizeof(*chu));
1451     chu->client = client_entry;
1452     silc_list_add(channel->clients, chu);
1453
1454     /* XXX add support for multiple same nicks on same channel. Check
1455        for them here */
1456
1457     /* Notify application. The channel entry is sent last as this notify
1458        is for channel but application don't know it from the arguments
1459        sent by server. */
1460     client->ops->notify(client, conn, type, client_entry, channel);
1461     break;
1462
1463   case SILC_NOTIFY_TYPE_LEAVE:
1464     /*
1465      * Someone has left a channel. We will remove it from the channel but
1466      * we'll keep it in the cache in case we'll need it later.
1467      */
1468     
1469     /* Get Client ID */
1470     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1471     if (!tmp)
1472       goto out;
1473
1474     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1475     if (!client_id)
1476       goto out;
1477
1478     /* Find Client entry */
1479     client_entry = 
1480       silc_client_get_client_by_id(client, conn, client_id);
1481     if (!client_entry)
1482       goto out;
1483
1484     /* Get channel entry */
1485     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1486                                 SILC_ID_CHANNEL);
1487     if (!channel_id)
1488       goto out;
1489     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1490                                      SILC_ID_CHANNEL, &id_cache))
1491       break;
1492
1493     channel = (SilcChannelEntry)id_cache->context;
1494
1495     /* Remove client from channel */
1496     silc_list_start(channel->clients);
1497     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1498       if (chu->client == client_entry) {
1499         silc_list_del(channel->clients, chu);
1500         silc_free(chu);
1501         break;
1502       }
1503     }
1504
1505     /* Notify application. The channel entry is sent last as this notify
1506        is for channel but application don't know it from the arguments
1507        sent by server. */
1508     client->ops->notify(client, conn, type, client_entry, channel);
1509     break;
1510
1511   case SILC_NOTIFY_TYPE_SIGNOFF:
1512     /*
1513      * Someone left SILC. We'll remove it from all channels and from cache.
1514      */
1515
1516     /* Get Client ID */
1517     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1518     if (!tmp)
1519       goto out;
1520
1521     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1522     if (!client_id)
1523       goto out;
1524
1525     /* Find Client entry */
1526     client_entry = 
1527       silc_client_get_client_by_id(client, conn, client_id);
1528     if (!client_entry)
1529       goto out;
1530
1531     /* Remove from all channels */
1532     silc_client_remove_from_channels(client, conn, client_entry);
1533
1534     /* Remove from cache */
1535     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1536                            client_entry->id);
1537
1538     /* Get signoff message */
1539     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1540     if (tmp_len > 128)
1541       tmp = NULL;
1542
1543     /* Notify application */
1544     client->ops->notify(client, conn, type, client_entry, tmp);
1545
1546     /* Free data */
1547     if (client_entry->nickname)
1548       silc_free(client_entry->nickname);
1549     if (client_entry->server)
1550       silc_free(client_entry->server);
1551     if (client_entry->id)
1552       silc_free(client_entry->id);
1553     if (client_entry->send_key)
1554       silc_cipher_free(client_entry->send_key);
1555     if (client_entry->receive_key)
1556       silc_cipher_free(client_entry->receive_key);
1557     break;
1558
1559   case SILC_NOTIFY_TYPE_TOPIC_SET:
1560     /*
1561      * Someone set the topic on a channel.
1562      */
1563
1564     /* Get Client ID */
1565     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1566     if (!tmp)
1567       goto out;
1568
1569     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1570     if (!client_id)
1571       goto out;
1572
1573     /* Find Client entry */
1574     client_entry = 
1575       silc_client_get_client_by_id(client, conn, client_id);
1576     if (!client_entry)
1577       goto out;
1578
1579     /* Get topic */
1580     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1581     if (!tmp)
1582       goto out;
1583
1584     /* Get channel entry */
1585     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1586                                 SILC_ID_CHANNEL);
1587     if (!channel_id)
1588       goto out;
1589     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1590                                      SILC_ID_CHANNEL, &id_cache))
1591       break;
1592
1593     channel = (SilcChannelEntry)id_cache->context;
1594
1595     /* Notify application. The channel entry is sent last as this notify
1596        is for channel but application don't know it from the arguments
1597        sent by server. */
1598     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1599     break;
1600
1601   case SILC_NOTIFY_TYPE_NICK_CHANGE:
1602     /*
1603      * Someone changed their nickname. If we don't have entry for the new
1604      * ID we will query it and return here after it's done. After we've
1605      * returned we fetch the old entry and free it and notify the 
1606      * application.
1607      */
1608
1609     /* Get new Client ID */
1610     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1611     if (!tmp)
1612       goto out;
1613
1614     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1615     if (!client_id)
1616       goto out;
1617
1618     /* Ignore my ID */
1619     if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1620       break;
1621
1622     /* Find Client entry and if not found query it */
1623     client_entry2 = 
1624       silc_client_get_client_by_id(client, conn, client_id);
1625     if (!client_entry2) {
1626       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1627       goto out;
1628     }
1629     silc_free(client_id);
1630
1631     /* Get old Client ID */
1632     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1633     if (!tmp)
1634       goto out;
1635
1636     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1637     if (!client_id)
1638       goto out;
1639
1640     /* Find old Client entry */
1641     client_entry = 
1642       silc_client_get_client_by_id(client, conn, client_id);
1643     if (!client_entry)
1644       goto out;
1645
1646     /* Remove the old from cache */
1647     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1648                            client_entry->id);
1649
1650     /* Replace old ID entry with new one on all channels. */
1651     silc_client_replace_from_channels(client, conn, client_entry,
1652                                       client_entry2);
1653
1654     /* Notify application */
1655     client->ops->notify(client, conn, type, client_entry, client_entry2);
1656
1657     /* Free data */
1658     if (client_entry->nickname)
1659       silc_free(client_entry->nickname);
1660     if (client_entry->server)
1661       silc_free(client_entry->server);
1662     if (client_entry->id)
1663       silc_free(client_entry->id);
1664     if (client_entry->send_key)
1665       silc_cipher_free(client_entry->send_key);
1666     if (client_entry->receive_key)
1667       silc_cipher_free(client_entry->receive_key);
1668     break;
1669
1670   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1671     /*
1672      * Someone changed a channel mode
1673      */
1674
1675     /* Get Client ID */
1676     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1677     if (!tmp)
1678       goto out;
1679
1680     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1681     if (!client_id)
1682       goto out;
1683
1684     /* Find Client entry */
1685     client_entry = 
1686       silc_client_get_client_by_id(client, conn, client_id);
1687     if (!client_entry)
1688       goto out;
1689
1690     /* Get the mode */
1691     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1692     if (!tmp)
1693       goto out;
1694
1695     SILC_GET32_MSB(mode, tmp);
1696
1697     /* Get channel entry */
1698     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1699                                 SILC_ID_CHANNEL);
1700     if (!channel_id)
1701       goto out;
1702     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1703                                      SILC_ID_CHANNEL, &id_cache))
1704       break;
1705
1706     channel = (SilcChannelEntry)id_cache->context;
1707
1708     /* Save the new mode */
1709     channel->mode = mode;
1710
1711     /* Notify application. The channel entry is sent last as this notify
1712        is for channel but application don't know it from the arguments
1713        sent by server. */
1714     client->ops->notify(client, conn, type, client_entry, mode, channel);
1715     break;
1716
1717   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1718     /*
1719      * Someone changed user's mode on a channel
1720      */
1721
1722     /* Get Client ID */
1723     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1724     if (!tmp)
1725       goto out;
1726
1727     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1728     if (!client_id)
1729       goto out;
1730
1731     /* Find Client entry */
1732     client_entry = 
1733       silc_client_get_client_by_id(client, conn, client_id);
1734     if (!client_entry)
1735       goto out;
1736
1737     /* Get the mode */
1738     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1739     if (!tmp)
1740       goto out;
1741
1742     SILC_GET32_MSB(mode, tmp);
1743
1744     /* Get target Client ID */
1745     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1746     if (!tmp)
1747       goto out;
1748
1749     silc_free(client_id);
1750     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1751     if (!client_id)
1752       goto out;
1753
1754     /* Find target Client entry */
1755     client_entry2 = 
1756       silc_client_get_client_by_id(client, conn, client_id);
1757     if (!client_entry2)
1758       goto out;
1759
1760     /* Get channel entry */
1761     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1762                                 SILC_ID_CHANNEL);
1763     if (!channel_id)
1764       goto out;
1765     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1766                                      SILC_ID_CHANNEL, &id_cache))
1767       break;
1768
1769     channel = (SilcChannelEntry)id_cache->context;
1770
1771     /* Save the mode */
1772     silc_list_start(channel->clients);
1773     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1774       if (chu->client == client_entry) {
1775         chu->mode = mode;
1776         break;
1777       }
1778     }
1779
1780     /* Notify application. The channel entry is sent last as this notify
1781        is for channel but application don't know it from the arguments
1782        sent by server. */
1783     client->ops->notify(client, conn, type, client_entry, mode, 
1784                         client_entry2, channel);
1785     break;
1786
1787   case SILC_NOTIFY_TYPE_MOTD:
1788     /*
1789      * Received Message of the day
1790      */
1791
1792     /* Get motd */
1793     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1794     if (!tmp)
1795       goto out;
1796     
1797     /* Notify application */
1798     client->ops->notify(client, conn, type, tmp);
1799     break;
1800
1801   case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1802     /*
1803      * Router has enforced a new ID to a channel. Let's change the old
1804      * ID to the one provided here.
1805      */
1806
1807     /* Get the old ID */
1808     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1809     if (!tmp)
1810       goto out;
1811     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1812     if (!channel_id)
1813       goto out;
1814     
1815     /* Get the channel entry */
1816     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1817                                      SILC_ID_CHANNEL, &id_cache))
1818       break;
1819
1820     channel = (SilcChannelEntry)id_cache->context;
1821
1822     /* Free the old ID */
1823     silc_free(channel_id);
1824     silc_free(channel->id);
1825
1826     /* Get the new ID */
1827     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1828     if (!tmp)
1829       goto out;
1830     channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1831     if (!channel->id)
1832       goto out;
1833
1834     id_cache->id = (void *)channel->id;
1835
1836     /* Notify application */
1837     client->ops->notify(client, conn, type, channel, channel);
1838     break;
1839
1840   case SILC_NOTIFY_TYPE_KICKED:
1841     /*
1842      * A client (maybe me) was kicked from a channel
1843      */
1844
1845     /* Get Client ID */
1846     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1847     if (!tmp)
1848       goto out;
1849
1850     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1851     if (!client_id)
1852       goto out;
1853
1854     /* Find Client entry */
1855     client_entry = 
1856       silc_client_get_client_by_id(client, conn, client_id);
1857     if (!client_entry)
1858       goto out;
1859
1860     /* Get channel entry */
1861     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1862                                 SILC_ID_CHANNEL);
1863     if (!channel_id)
1864       goto out;
1865     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1866                                      SILC_ID_CHANNEL, &id_cache))
1867       break;
1868
1869     channel = (SilcChannelEntry)id_cache->context;
1870
1871     /* Get comment */
1872     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1873
1874     /* Notify application. The channel entry is sent last as this notify
1875        is for channel but application don't know it from the arguments
1876        sent by server. */
1877     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1878
1879     /* If I was kicked from channel, remove the channel */
1880     if (client_entry == conn->local_entry) {
1881       if (conn->current_channel == channel)
1882         conn->current_channel = NULL;
1883       silc_idcache_del_by_id(conn->channel_cache, 
1884                              SILC_ID_CHANNEL, channel->id);
1885       silc_free(channel->channel_name);
1886       silc_free(channel->id);
1887       silc_free(channel->key);
1888       silc_cipher_free(channel->channel_key);
1889       silc_free(channel);
1890     }
1891     break;
1892     
1893   default:
1894     break;
1895   }
1896
1897  out:
1898   silc_notify_payload_free(payload);
1899   if (client_id)
1900     silc_free(client_id);
1901   if (channel_id)
1902     silc_free(channel_id);
1903 }
1904
1905 /* Processes the received new Client ID from server. Old Client ID is
1906    deleted from cache and new one is added. */
1907
1908 void silc_client_receive_new_id(SilcClient client,
1909                                 SilcSocketConnection sock,
1910                                 SilcIDPayload idp)
1911 {
1912   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1913   int connecting = FALSE;
1914
1915   if (!conn->local_entry)
1916     connecting = TRUE;
1917
1918   /* Delete old ID from ID cache */
1919   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1920   
1921   /* Save the new ID */
1922   if (conn->local_id)
1923     silc_free(conn->local_id);
1924   if (conn->local_id_data)
1925     silc_free(conn->local_id_data);
1926
1927   conn->local_id = silc_id_payload_get_id(idp);
1928   conn->local_id_data = silc_id_payload_get_data(idp);
1929   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1930
1931   if (!conn->local_entry)
1932     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1933
1934   conn->local_entry->nickname = conn->nickname;
1935   if (!conn->local_entry->username) {
1936     conn->local_entry->username = 
1937       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1938                   sizeof(conn->local_entry->username));
1939     sprintf(conn->local_entry->username, "%s@%s", client->username,
1940             client->hostname);
1941   }
1942   conn->local_entry->server = strdup(conn->remote_host);
1943   conn->local_entry->id = conn->local_id;
1944   
1945   /* Put it to the ID cache */
1946   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1947                    conn->local_id, (void *)conn->local_entry, TRUE);
1948
1949   /* Notify application of successful connection. We do it here now that
1950      we've received the Client ID and are allowed to send traffic. */
1951   if (connecting)
1952     client->ops->connect(client, conn, TRUE);
1953 }
1954
1955 /* Processed received Channel ID for a channel. This is called when client
1956    joins to channel and server replies with channel ID. The ID is cached. */
1957
1958 void silc_client_new_channel_id(SilcClient client,
1959                                 SilcSocketConnection sock,
1960                                 char *channel_name,
1961                                 unsigned int mode, SilcIDPayload idp)
1962 {
1963   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1964   SilcChannelEntry channel;
1965
1966   SILC_LOG_DEBUG(("New channel ID"));
1967
1968   channel = silc_calloc(1, sizeof(*channel));
1969   channel->channel_name = channel_name;
1970   channel->id = silc_id_payload_get_id(idp);
1971   channel->mode = mode;
1972   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1973
1974   conn->current_channel = channel;
1975
1976   /* Put it to the ID cache */
1977   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1978                    (void *)channel->id, (void *)channel, TRUE);
1979 }
1980
1981 /* Saves channel key from encoded `key_payload'. This is used when we
1982    receive Channel Key Payload and when we are processing JOIN command 
1983    reply. */
1984
1985 void silc_client_save_channel_key(SilcClientConnection conn,
1986                                   SilcBuffer key_payload, 
1987                                   SilcChannelEntry channel)
1988 {
1989   unsigned char *id_string, *key, *cipher;
1990   unsigned int tmp_len;
1991   SilcChannelID *id;
1992   SilcIDCacheEntry id_cache = NULL;
1993   SilcChannelKeyPayload payload;
1994
1995   payload = silc_channel_key_payload_parse(key_payload);
1996   if (!payload)
1997     return;
1998
1999   id_string = silc_channel_key_get_id(payload, &tmp_len);
2000   if (!id_string) {
2001     silc_channel_key_payload_free(payload);
2002     return;
2003   }
2004
2005   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
2006   if (!id) {
2007     silc_channel_key_payload_free(payload);
2008     return;
2009   }
2010
2011   /* Find channel. */
2012   if (!channel) {
2013     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2014                                      SILC_ID_CHANNEL, &id_cache))
2015       goto out;
2016     
2017     /* Get channel entry */
2018     channel = (SilcChannelEntry)id_cache->context;
2019   }
2020
2021   /* Save the key */
2022   key = silc_channel_key_get_key(payload, &tmp_len);
2023   cipher = silc_channel_key_get_cipher(payload, NULL);
2024   channel->key_len = tmp_len * 8;
2025   channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
2026   memcpy(channel->key, key, tmp_len);
2027
2028   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
2029     conn->client->ops->say(conn->client, conn,
2030                      "Cannot talk to channel: unsupported cipher %s", cipher);
2031     goto out;
2032   }
2033   channel->channel_key->cipher->set_key(channel->channel_key->context, 
2034                                         key, channel->key_len);
2035
2036   /* Client is now joined to the channel */
2037   channel->on_channel = TRUE;
2038
2039  out:
2040   silc_free(id);
2041   silc_channel_key_payload_free(payload);
2042 }
2043
2044 /* Processes received key for channel. The received key will be used
2045    to protect the traffic on the channel for now on. Client must receive
2046    the key to the channel before talking on the channel is possible. 
2047    This is the key that server has generated, this is not the channel
2048    private key, it is entirely local setting. */
2049
2050 void silc_client_receive_channel_key(SilcClient client,
2051                                      SilcSocketConnection sock,
2052                                      SilcBuffer packet)
2053 {
2054   SILC_LOG_DEBUG(("Received key for channel"));
2055
2056   /* Save the key */
2057   silc_client_save_channel_key(sock->user_data, packet, NULL);
2058 }
2059
2060 /* Process received message to a channel (or from a channel, really). This
2061    decrypts the channel message with channel specific key and parses the
2062    channel payload. Finally it displays the message on the screen. */
2063
2064 void silc_client_channel_message(SilcClient client, 
2065                                  SilcSocketConnection sock, 
2066                                  SilcPacketContext *packet)
2067 {
2068   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2069   SilcBuffer buffer = packet->buffer;
2070   SilcChannelPayload payload = NULL;
2071   SilcChannelID *id = NULL;
2072   SilcChannelEntry channel;
2073   SilcChannelUser chu;
2074   SilcIDCacheEntry id_cache = NULL;
2075   SilcClientID *client_id = NULL;
2076   int found = FALSE;
2077   unsigned int block_len;
2078
2079   /* Sanity checks */
2080   if (packet->dst_id_type != SILC_ID_CHANNEL)
2081     goto out;
2082
2083   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2084                              SILC_ID_CLIENT);
2085   if (!client_id)
2086     goto out;
2087   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2088   if (!id)
2089     goto out;
2090
2091   /* Find the channel entry from channels on this connection */
2092   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2093                                    SILC_ID_CHANNEL, &id_cache))
2094     goto out;
2095
2096   channel = (SilcChannelEntry)id_cache->context;
2097
2098   /* Decrypt the channel message payload. Push the IV out of the way,
2099      since it is not encrypted (after pushing buffer->tail has the IV). */
2100   block_len = silc_cipher_get_block_len(channel->channel_key);
2101   silc_buffer_push_tail(buffer, block_len);
2102   channel->channel_key->cipher->decrypt(channel->channel_key->context,
2103                                         buffer->data, buffer->data,
2104                                         buffer->len, buffer->tail);
2105   silc_buffer_pull_tail(buffer, block_len);
2106
2107   /* Parse the channel message payload */
2108   payload = silc_channel_payload_parse(buffer);
2109   if (!payload)
2110     goto out;
2111
2112   /* Find client entry */
2113   silc_list_start(channel->clients);
2114   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2115     if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2116       found = TRUE;
2117       break;
2118     }
2119   }
2120
2121   /* Pass the message to application */
2122   client->ops->channel_message(client, conn, found ? chu->client : NULL,
2123                                channel, silc_channel_get_data(payload, NULL));
2124
2125  out:
2126   if (id)
2127     silc_free(id);
2128   if (client_id)
2129     silc_free(client_id);
2130   if (payload)
2131     silc_channel_payload_free(payload);
2132 }
2133
2134 /* Private message received. This processes the private message and
2135    finally displays it on the screen. */
2136
2137 void silc_client_private_message(SilcClient client, 
2138                                  SilcSocketConnection sock, 
2139                                  SilcPacketContext *packet)
2140 {
2141   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2142   SilcBuffer buffer = packet->buffer;
2143   SilcIDCacheEntry id_cache;
2144   SilcClientID *remote_id = NULL;
2145   SilcClientEntry remote_client;
2146   unsigned short nick_len;
2147   unsigned char *nickname, *message = NULL;
2148   int ret;
2149
2150   if (packet->src_id_type != SILC_ID_CLIENT)
2151     goto out;
2152
2153   /* Get nickname */
2154   ret = silc_buffer_unformat(buffer, 
2155                              SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2156                              SILC_STR_END);
2157   if (ret == -1)
2158     return;
2159
2160   silc_buffer_pull(buffer, 2 + nick_len);
2161
2162   message = silc_calloc(buffer->len + 1, sizeof(char));
2163   memcpy(message, buffer->data, buffer->len);
2164
2165   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
2166                              SILC_ID_CLIENT);
2167   if (!remote_id)
2168     goto out;
2169
2170   /* Check whether we know this client already */
2171   if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2172                                    SILC_ID_CLIENT, &id_cache))
2173     {
2174       /* Allocate client entry */
2175       remote_client = silc_calloc(1, sizeof(*remote_client));
2176       remote_client->id = remote_id;
2177       silc_parse_nickname(nickname, &remote_client->nickname, 
2178                           &remote_client->server, &remote_client->num);
2179       
2180       /* Save the client to cache */
2181       silc_idcache_add(conn->client_cache, remote_client->nickname,
2182                        SILC_ID_CLIENT, remote_client->id, remote_client, 
2183                        TRUE);
2184     } else {
2185       remote_client = (SilcClientEntry)id_cache->context;
2186     }
2187
2188   /* Pass the private message to application */
2189   client->ops->private_message(client, conn, remote_client, message);
2190
2191   /* See if we are away (gone). If we are away we will reply to the
2192      sender with the set away message. */
2193   if (conn->away && conn->away->away) {
2194     /* If it's me, ignore */
2195     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2196       goto out;
2197
2198     /* Send the away message */
2199     silc_client_send_private_message(client, conn, remote_client,
2200                                      conn->away->away,
2201                                      strlen(conn->away->away), TRUE);
2202   }
2203
2204  out:
2205   if (remote_id)
2206     silc_free(remote_id);
2207
2208   if (message) {
2209     memset(message, 0, buffer->len);
2210     silc_free(message);
2211   }
2212   silc_free(nickname);
2213 }
2214
2215 /* Removes a client entry from all channel it has joined. This really is
2216    a performance killer (client_entry should have pointers to channel 
2217    entry list). */
2218
2219 void silc_client_remove_from_channels(SilcClient client,
2220                                       SilcClientConnection conn,
2221                                       SilcClientEntry client_entry)
2222 {
2223   SilcIDCacheEntry id_cache;
2224   SilcIDCacheList list;
2225   SilcChannelEntry channel;
2226   SilcChannelUser chu;
2227
2228   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2229                                SILC_ID_CHANNEL, &list))
2230     return;
2231
2232   silc_idcache_list_first(list, &id_cache);
2233   channel = (SilcChannelEntry)id_cache->context;
2234   
2235   while (channel) {
2236     
2237     /* Remove client from channel */
2238     silc_list_start(channel->clients);
2239     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2240       if (chu->client == client_entry) {
2241         silc_list_del(channel->clients, chu);
2242         silc_free(chu);
2243         break;
2244       }
2245     }
2246
2247     if (!silc_idcache_list_next(list, &id_cache))
2248       break;
2249     
2250     channel = (SilcChannelEntry)id_cache->context;
2251   }
2252
2253   silc_idcache_list_free(list);
2254 }
2255
2256 /* Replaces `old' client entries from all channels to `new' client entry.
2257    This can be called for example when nickname changes and old ID entry
2258    is replaced from ID cache with the new one. If the old ID entry is only
2259    updated, then this fucntion needs not to be called. */
2260
2261 void silc_client_replace_from_channels(SilcClient client, 
2262                                        SilcClientConnection conn,
2263                                        SilcClientEntry old,
2264                                        SilcClientEntry new)
2265 {
2266   SilcIDCacheEntry id_cache;
2267   SilcIDCacheList list;
2268   SilcChannelEntry channel;
2269   SilcChannelUser chu;
2270
2271   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2272                                SILC_ID_CHANNEL, &list))
2273     return;
2274
2275   silc_idcache_list_first(list, &id_cache);
2276   channel = (SilcChannelEntry)id_cache->context;
2277   
2278   while (channel) {
2279     
2280     /* Replace client entry */
2281     silc_list_start(channel->clients);
2282     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2283       if (chu->client == old) {
2284         chu->client = new;
2285         break;
2286       }
2287     }
2288
2289     if (!silc_idcache_list_next(list, &id_cache))
2290       break;
2291     
2292     channel = (SilcChannelEntry)id_cache->context;
2293   }
2294
2295   silc_idcache_list_free(list);
2296 }
2297
2298 /* Parses mode mask and returns the mode as string. */
2299
2300 char *silc_client_chmode(unsigned int mode)
2301 {
2302   char string[20];
2303
2304   if (!mode)
2305     return NULL;
2306
2307   memset(string, 0, sizeof(string));
2308
2309   if (mode & SILC_CHANNEL_MODE_PRIVATE)
2310     strncat(string, "p", 1);
2311
2312   if (mode & SILC_CHANNEL_MODE_SECRET)
2313     strncat(string, "s", 1);
2314
2315   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2316     strncat(string, "k", 1);
2317
2318   if (mode & SILC_CHANNEL_MODE_INVITE)
2319     strncat(string, "i", 1);
2320
2321   if (mode & SILC_CHANNEL_MODE_TOPIC)
2322     strncat(string, "t", 1);
2323
2324   if (mode & SILC_CHANNEL_MODE_ULIMIT)
2325     strncat(string, "l", 1);
2326
2327   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2328     strncat(string, "a", 1);
2329
2330   /* Rest of mode is ignored */
2331
2332   return strdup(string);
2333 }
2334
2335 /* Parses channel user mode mask and returns te mode as string */
2336
2337 char *silc_client_chumode(unsigned int mode)
2338 {
2339   char string[4];
2340
2341   if (!mode)
2342     return NULL;
2343
2344   memset(string, 0, sizeof(string));
2345
2346   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2347     strncat(string, "f", 1);
2348
2349   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2350     strncat(string, "o", 1);
2351
2352   return strdup(string);
2353 }
2354
2355 /* Parses channel user mode and returns it as special mode character. */
2356
2357 char *silc_client_chumode_char(unsigned int mode)
2358 {
2359   char string[4];
2360
2361   if (!mode)
2362     return NULL;
2363
2364   memset(string, 0, sizeof(string));
2365
2366   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2367     strncat(string, "*", 1);
2368
2369   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2370     strncat(string, "@", 1);
2371
2372   return strdup(string);
2373 }
2374
2375 /* Function that actually employes the received private message key */
2376
2377 static void silc_client_private_message_key_cb(SilcClient client,
2378                                                SilcClientConnection conn,
2379                                                SilcClientEntry *clients,
2380                                                unsigned int clients_count,
2381                                                void *context)
2382 {
2383   SilcPacketContext *packet = (SilcPacketContext *)context;
2384   unsigned char *key;
2385   unsigned short key_len;
2386   unsigned char *cipher;
2387   int ret;
2388
2389   if (!clients)
2390     goto out;
2391
2392   /* Parse the private message key payload */
2393   ret = silc_buffer_unformat(packet->buffer,
2394                              SILC_STR_UI16_NSTRING(&key, &key_len),
2395                              SILC_STR_UI16_STRING(&cipher),
2396                              SILC_STR_END);
2397   if (!ret)
2398     goto out;
2399
2400   if (key_len > packet->buffer->len)
2401     goto out;
2402
2403   /* Now take the key in use */
2404   if (!silc_client_add_private_message_key(client, conn, clients[0],
2405                                            cipher, key, key_len, FALSE))
2406     goto out;
2407
2408   /* Print some info for application */
2409   client->ops->say(client, conn, 
2410                    "Received private message key from %s%s%s %s%s%s", 
2411                    clients[0]->nickname,
2412                    clients[0]->server ? "@" : "",
2413                    clients[0]->server ? clients[0]->server : "",
2414                    clients[0]->username ? "(" : "",
2415                    clients[0]->username ? clients[0]->username : "",
2416                    clients[0]->username ? ")" : "");
2417
2418  out:
2419   silc_packet_context_free(packet);
2420 }
2421
2422 /* Processes incoming Private Message Key payload. The libary always
2423    accepts the key and takes it into use. */
2424
2425 void silc_client_private_message_key(SilcClient client,
2426                                      SilcSocketConnection sock,
2427                                      SilcPacketContext *packet)
2428 {
2429   SilcClientID *remote_id;
2430
2431   if (packet->src_id_type != SILC_ID_CLIENT)
2432     return;
2433
2434   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
2435                              SILC_ID_CLIENT);
2436   if (!remote_id)
2437     return;
2438
2439   silc_client_get_client_by_id_resolve(client, sock->user_data, remote_id,
2440                                        silc_client_private_message_key_cb,
2441                                        silc_packet_context_dup(packet));
2442   silc_free(remote_id);
2443 }
2444
2445 /* Adds private message key to the client library. The key will be used to
2446    encrypt all private message between the client and the remote client
2447    indicated by the `client_entry'. If the `key' is NULL and the boolean
2448    value `generate_key' is TRUE the library will generate random key.
2449    The `key' maybe for example pre-shared-key, passphrase or similar.
2450    The `cipher' MAY be provided but SHOULD be NULL to assure that the
2451    requirements of the SILC protocol are met. The API, however, allows
2452    to allocate any cipher.
2453
2454    It is not necessary to set key for normal private message usage. If the
2455    key is not set then the private messages are encrypted using normal
2456    session keys. Setting the private key, however, increases the security. 
2457
2458    Returns FALSE if the key is already set for the `client_entry', TRUE
2459    otherwise. */
2460
2461 int silc_client_add_private_message_key(SilcClient client,
2462                                         SilcClientConnection conn,
2463                                         SilcClientEntry client_entry,
2464                                         char *cipher,
2465                                         unsigned char *key,
2466                                         unsigned int key_len,
2467                                         int generate_key)
2468 {
2469   unsigned char private_key[32];
2470   unsigned int len;
2471   int i;
2472   SilcSKEKeyMaterial *keymat;
2473
2474   assert(client_entry);
2475
2476   /* Return FALSE if key already set */
2477   if (client_entry->send_key && client_entry->receive_key)
2478     return FALSE;
2479
2480   if (!cipher)
2481     cipher = "aes-256-cbc";
2482
2483   /* Check the requested cipher */
2484   if (!silc_cipher_is_supported(cipher))
2485     return FALSE;
2486
2487   /* Generate key if not provided */
2488   if (!key && generate_key == TRUE) {
2489     len = 32;
2490     for (i = 0; i < len; i++) private_key[i] = silc_rng_get_byte(client->rng);
2491     key = private_key;
2492     key_len = len;
2493     client_entry->generated = TRUE;
2494   }
2495
2496   /* Save the key */
2497   client_entry->key = silc_calloc(key_len, sizeof(*client_entry->key));
2498   memcpy(client_entry->key, key, key_len);
2499   client_entry->key_len = key_len;
2500
2501   /* Produce the key material as the protocol defines */
2502   keymat = silc_calloc(1, sizeof(*keymat));
2503   if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16, 
2504                                          client->md5hash, keymat) 
2505       != SILC_SKE_STATUS_OK)
2506     return FALSE;
2507
2508   /* Allocate the ciphers */
2509   silc_cipher_alloc(cipher, &client_entry->send_key);
2510   silc_cipher_alloc(cipher, &client_entry->receive_key);
2511
2512   /* Set the keys */
2513   silc_cipher_set_key(client_entry->send_key, keymat->send_enc_key,
2514                       keymat->enc_key_len);
2515   silc_cipher_set_iv(client_entry->send_key, keymat->send_iv);
2516   silc_cipher_set_key(client_entry->receive_key, keymat->receive_enc_key,
2517                       keymat->enc_key_len);
2518   silc_cipher_set_iv(client_entry->receive_key, keymat->receive_iv);
2519
2520   /* Free the key material */
2521   silc_ske_free_key_material(keymat);
2522
2523   return TRUE;
2524 }
2525
2526 /* Same as above but takes the key material from the SKE key material
2527    structure. This structure is received if the application uses the
2528    silc_client_send_key_agreement to negotiate the key material. The
2529    `cipher' SHOULD be provided as it is negotiated also in the SKE
2530    protocol. */
2531
2532 int silc_client_add_private_message_key_ske(SilcClient client,
2533                                             SilcClientConnection conn,
2534                                             SilcClientEntry client_entry,
2535                                             char *cipher,
2536                                             SilcSKEKeyMaterial *key)
2537 {
2538   assert(client_entry);
2539
2540   /* Return FALSE if key already set */
2541   if (client_entry->send_key && client_entry->receive_key)
2542     return FALSE;
2543
2544   if (!cipher)
2545     cipher = "aes-256-cbc";
2546
2547   /* Check the requested cipher */
2548   if (!silc_cipher_is_supported(cipher))
2549     return FALSE;
2550
2551   /* Allocate the ciphers */
2552   silc_cipher_alloc(cipher, &client_entry->send_key);
2553   silc_cipher_alloc(cipher, &client_entry->receive_key);
2554
2555   /* Set the keys */
2556   silc_cipher_set_key(client_entry->send_key, key->send_enc_key,
2557                       key->enc_key_len);
2558   silc_cipher_set_iv(client_entry->send_key, key->send_iv);
2559   silc_cipher_set_key(client_entry->receive_key, key->receive_enc_key,
2560                       key->enc_key_len);
2561   silc_cipher_set_iv(client_entry->receive_key, key->receive_iv);
2562
2563   return TRUE;
2564 }
2565
2566 /* Sends private message key payload to the remote client indicated by
2567    the `client_entry'. If the `force_send' is TRUE the packet is sent
2568    immediately. Returns FALSE if error occurs, TRUE otherwise. The
2569    application should call this function after setting the key to the
2570    client.
2571
2572    Note that the key sent using this function is sent to the remote client
2573    through the SILC network. The packet is protected using normal session
2574    keys. */
2575
2576 int silc_client_send_private_message_key(SilcClient client,
2577                                          SilcClientConnection conn,
2578                                          SilcClientEntry client_entry,
2579                                          int force_send)
2580 {
2581   SilcSocketConnection sock = conn->sock;
2582   SilcBuffer buffer;
2583   int cipher_len;
2584
2585   if (!client_entry->send_key || !client_entry->key)
2586     return FALSE;
2587
2588   SILC_LOG_DEBUG(("Sending private message key"));
2589
2590   cipher_len = strlen(client_entry->send_key->cipher->name);
2591
2592   /* Create private message key payload */
2593   buffer = silc_buffer_alloc(2 + client_entry->key_len);
2594   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
2595   silc_buffer_format(buffer,
2596                      SILC_STR_UI_SHORT(client_entry->key_len),
2597                      SILC_STR_UI_XNSTRING(client_entry->key, 
2598                                           client_entry->key_len),
2599                      SILC_STR_UI_SHORT(cipher_len),
2600                      SILC_STR_UI_XNSTRING(client_entry->send_key->cipher->name,
2601                                           cipher_len),
2602                      SILC_STR_END);
2603
2604   /* Send the packet */
2605   silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE_KEY,
2606                           client_entry->id, SILC_ID_CLIENT, NULL, NULL,
2607                           buffer->data, buffer->len, force_send);
2608   silc_free(buffer);
2609
2610   return TRUE;
2611 }
2612
2613 /* Removes the private message from the library. The key won't be used
2614    after this to protect the private messages with the remote `client_entry'
2615    client. Returns FALSE on error, TRUE otherwise. */
2616
2617 int silc_client_del_private_message_key(SilcClient client,
2618                                         SilcClientConnection conn,
2619                                         SilcClientEntry client_entry)
2620 {
2621   assert(client_entry);
2622
2623   if (!client_entry->send_key && !client_entry->receive_key)
2624     return FALSE;
2625
2626   silc_cipher_free(client_entry->send_key);
2627   silc_cipher_free(client_entry->receive_key);
2628
2629   if (client_entry->key) {
2630     memset(client_entry->key, 0, client_entry->key_len);
2631     silc_free(client_entry->key);
2632   }
2633
2634   client_entry->send_key = NULL;
2635   client_entry->receive_key = NULL;
2636   client_entry->key = NULL;
2637
2638   return TRUE;
2639 }
2640
2641 /* Returns array of set private message keys associated to the connection
2642    `conn'. Returns allocated SilcPrivateMessageKeys array and the array
2643    count to the `key_count' argument. The array must be freed by the caller
2644    by calling the silc_client_free_private_message_keys function. Note: 
2645    the keys returned in the array is in raw format. It might not be desired
2646    to show the keys as is. The application might choose not to show the keys
2647    at all or to show the fingerprints of the keys. */
2648
2649 SilcPrivateMessageKeys
2650 silc_client_list_private_message_keys(SilcClient client,
2651                                       SilcClientConnection conn,
2652                                       unsigned int *key_count)
2653 {
2654   SilcPrivateMessageKeys keys;
2655   unsigned int count = 0;
2656   SilcIDCacheEntry id_cache;
2657   SilcIDCacheList list;
2658   SilcClientEntry entry;
2659
2660   if (!silc_idcache_find_by_id(conn->client_cache, SILC_ID_CACHE_ANY, 
2661                                SILC_ID_CLIENT, &list))
2662     return NULL;
2663
2664   if (!silc_idcache_list_count(list)) {
2665     silc_idcache_list_free(list);
2666     return NULL;
2667   }
2668
2669   keys = silc_calloc(silc_idcache_list_count(list), sizeof(*keys));
2670
2671   silc_idcache_list_first(list, &id_cache);
2672   while (id_cache) {
2673     entry = (SilcClientEntry)id_cache->context;
2674
2675     if (entry->send_key) {
2676       keys[count].client_entry = entry;
2677       keys[count].cipher = entry->send_key->cipher->name;
2678       keys[count].key = entry->generated == FALSE ? entry->key : NULL;
2679       keys[count].key_len = entry->generated == FALSE ? entry->key_len : 0;
2680       count++;
2681     }
2682
2683     if (!silc_idcache_list_next(list, &id_cache))
2684       break;
2685   }
2686
2687   if (key_count)
2688     *key_count = count;
2689
2690   return keys;
2691 }
2692
2693 /* Frees the SilcPrivateMessageKeys array returned by the function
2694    silc_client_list_private_message_keys. */
2695
2696 void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
2697                                            unsigned int key_count)
2698 {
2699   silc_free(keys);
2700 }
2701
2702 /* Adds private key for channel. This may be set only if the channel's mode
2703    mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
2704    mode is not set. When channel has private key then the messages are
2705    encrypted using that key. All clients on the channel must also know the
2706    key in order to decrypt the messages. However, it is possible to have
2707    several private keys per one channel. In this case only some of the
2708    clients on the channel may now the one key and only some the other key.
2709
2710    The private key for channel is optional. If it is not set then the
2711    channel messages are encrypted using the channel key generated by the
2712    server. However, setting the private key (or keys) for the channel 
2713    significantly adds security. If more than one key is set the library
2714    will automatically try all keys at the message decryption phase. Note:
2715    setting many keys slows down the decryption phase as all keys has to
2716    be tried in order to find the correct decryption key. However, setting
2717    a few keys does not have big impact to the decryption performace. 
2718
2719    NOTE: that this is entirely local setting. The key set using this function
2720    is not sent to the network at any phase.
2721
2722    NOTE: If the key material was originated by the SKE protocol (using
2723    silc_client_send_key_agreement) then the `key' MUST be the
2724    key->send_enc_key as this is dictated by the SILC protocol. However,
2725    currently it is not expected that the SKE key material would be used
2726    as channel private key. However, this API allows it. */
2727
2728 int silc_client_add_channel_private_key(SilcClient client,
2729                                         SilcClientConnection conn,
2730                                         SilcChannelEntry channel,
2731                                         char *cipher,
2732                                         unsigned char *key,
2733                                         unsigned int key_len)
2734 {
2735
2736   return TRUE;
2737 }
2738
2739 /* Removes all private keys from the `channel'. The old channel key is used
2740    after calling this to protect the channel messages. Returns FALSE on
2741    on error, TRUE otherwise. */
2742
2743 int silc_client_del_channel_private_keys(SilcClient client,
2744                                          SilcClientConnection conn,
2745                                          SilcChannelEntry channel)
2746 {
2747
2748   return TRUE;
2749 }
2750
2751 /* Removes and frees private key `key' from the channel `channel'. The `key'
2752    is retrieved by calling the function silc_client_list_channel_private_keys.
2753    The key is not used after this. If the key was last private key then the
2754    old channel key is used hereafter to protect the channel messages. This
2755    returns FALSE on error, TRUE otherwise. */
2756
2757 int silc_client_del_channel_private_key(SilcClient client,
2758                                         SilcClientConnection conn,
2759                                         SilcChannelEntry channel,
2760                                         SilcChannelPrivateKey key)
2761 {
2762
2763   return TRUE;
2764 }
2765
2766 /* Returns array (pointers) of private keys associated to the `channel'.
2767    The caller must free the array by calling the function
2768    silc_client_free_channel_private_keys. The pointers in the array may be
2769    used to delete the specific key by giving the pointer as argument to the
2770    function silc_client_del_channel_private_key. */
2771
2772 SilcChannelPrivateKey *
2773 silc_client_list_channel_private_keys(SilcClient client,
2774                                       SilcClientConnection conn,
2775                                       SilcChannelEntry channel,
2776                                       unsigned int key_count)
2777 {
2778
2779   return NULL;
2780 }
2781
2782 /* Frees the SilcChannelPrivateKey array. */
2783
2784 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
2785                                            unsigned int key_count)
2786 {
2787
2788 }
2789
2790 /* Sends key agreement request to the remote client indicated by the
2791    `client_entry'. If the caller provides the `hostname' and the `port'
2792    arguments then the library will bind the client to that hostname and
2793    that port for the key agreement protocol. It also sends the `hostname'
2794    and the `port' in the key agreement packet to the remote client. This
2795    would indicate that the remote client may initiate the key agreement
2796    protocol to the `hostname' on the `port'.
2797
2798    If the `hostname' and `port' is not provided then empty key agreement
2799    packet is sent to the remote client. The remote client may reply with
2800    the same packet including its hostname and port. If the library receives
2801    the reply from the remote client the `key_agreement' client operation
2802    callback will be called to verify whether the user wants to perform the
2803    key agreement or not. 
2804
2805    NOTE: If the application provided the `hostname' and the `port' and the 
2806    remote side initiates the key agreement protocol it is not verified
2807    from the user anymore whether the protocol should be executed or not.
2808    By setting the `hostname' and `port' the user gives permission to
2809    perform the protocol (we are responder in this case).
2810
2811    NOTE: If the remote side decides not to initiate the key agreement
2812    or decides not to reply with the key agreement packet then we cannot
2813    perform the key agreement at all. If the key agreement protocol is
2814    performed the `completion' callback with the `context' will be called.
2815    If remote side decides to ignore the request the `completion' will never
2816    be called and the caller is responsible of freeing the `context' memory. 
2817    The application can do this by setting, for example, timeout. */
2818
2819 void silc_client_send_key_agreement(SilcClient client,
2820                                     SilcClientConnection conn,
2821                                     SilcClientEntry client_entry,
2822                                     char *hostname,
2823                                     int port,
2824                                     SilcKeyAgreementCallback completion,
2825                                     void *context)
2826 {
2827
2828 }
2829
2830 /* Performs the actual key agreement protocol. Application may use this
2831    to initiate the key agreement protocol. This can be called for example
2832    after the application has received the `key_agreement' client operation,
2833    and did not return TRUE from it.
2834
2835    The `hostname' is the remote hostname (or IP address) and the `port'
2836    is the remote port. The `completion' callblack with the `context' will
2837    be called after the key agreement protocol.
2838    
2839    NOTE: If the application returns TRUE in the `key_agreement' client
2840    operation the library will automatically start the key agreement. In this
2841    case the application must not call this function. However, application
2842    may choose to just ignore the `key_agreement' client operation (and
2843    merely just print information about it on the screen) and call this
2844    function when the user whishes to do so (by, for example, giving some
2845    specific command). Thus, the API provides both, automatic and manual
2846    initiation of the key agreement. Calling this function is the manual
2847    initiation and returning TRUE in the `key_agreement' client operation
2848    is the automatic initiation. */
2849
2850 void silc_client_perform_key_agreement(SilcClient client,
2851                                        SilcClientConnection conn,
2852                                        SilcClientEntry client_entry,
2853                                        char *hostname,
2854                                        int port,
2855                                        SilcKeyAgreementCallback completion,
2856                                        void *context)
2857 {
2858
2859 }
2860
2861 /* This function can be called to unbind the hostname and the port for
2862    the key agreement protocol. However, this function has effect only 
2863    before the key agreement protocol has been performed. After it has
2864    been performed the library will automatically unbind the port. The 
2865    `client_entry' is the client to which we sent the key agreement 
2866    request. */
2867
2868 void silc_client_abort_key_agreement(SilcClient client,
2869                                      SilcClientConnection conn,
2870                                      SilcClientEntry client_entry)
2871 {
2872
2873 }