Added new function silc_client_start_key_exchange and changed that
[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 - 2000 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 /* Free's client object */
53
54 void silc_client_free(SilcClient client)
55 {
56   if (client) {
57     silc_free(client);
58   }
59 }
60
61 /* Initializes the client. This makes all the necessary steps to make
62    the client ready to be run. One must call silc_client_run to run the
63    client. */
64
65 int silc_client_init(SilcClient client)
66 {
67   SILC_LOG_DEBUG(("Initializing client"));
68
69   /* Initialize hash functions for client to use */
70   silc_hash_alloc("md5", &client->md5hash);
71   silc_hash_alloc("sha1", &client->sha1hash);
72
73   /* Initialize none cipher */
74   silc_cipher_alloc("none", &client->none_cipher);
75
76   /* Initialize random number generator */
77   client->rng = silc_rng_alloc();
78   silc_rng_init(client->rng);
79   silc_math_primegen_init(); /* XXX */
80
81   /* Register protocols */
82   silc_client_protocols_register();
83
84   /* Initialize the scheduler */
85   silc_schedule_init(&client->io_queue, &client->timeout_queue, 
86                      &client->generic_queue, 5000);
87
88   return TRUE;
89 }
90
91 /* Stops the client. This is called to stop the client and thus to stop
92    the program. */
93
94 void silc_client_stop(SilcClient client)
95 {
96   SILC_LOG_DEBUG(("Stopping client"));
97
98   /* Stop the scheduler, although it might be already stopped. This
99      doesn't hurt anyone. This removes all the tasks and task queues,
100      as well. */
101   silc_schedule_stop();
102   silc_schedule_uninit();
103
104   silc_client_protocols_unregister();
105
106   SILC_LOG_DEBUG(("Client stopped"));
107 }
108
109 /* Runs the client. */
110
111 void silc_client_run(SilcClient client)
112 {
113   SILC_LOG_DEBUG(("Running client"));
114
115   /* Start the scheduler, the heart of the SILC client. When this returns
116      the program will be terminated. */
117   silc_schedule();
118 }
119
120 /* Allocates and adds new connection to the client. This adds the allocated
121    connection to the connection table and returns a pointer to it. A client
122    can have multiple connections to multiple servers. Every connection must
123    be added to the client using this function. User data `context' may
124    be sent as argument. */
125
126 SilcClientConnection silc_client_add_connection(SilcClient client,
127                                                 void *context)
128 {
129   SilcClientConnection conn;
130   int i;
131
132   conn = silc_calloc(1, sizeof(*conn));
133
134   /* Initialize ID caches */
135   conn->client_cache = silc_idcache_alloc(0);
136   conn->channel_cache = silc_idcache_alloc(0);
137   conn->server_cache = silc_idcache_alloc(0);
138   conn->client = client;
139   conn->context = context;
140
141   /* Add the connection to connections table */
142   for (i = 0; i < client->conns_count; i++)
143     if (client->conns && !client->conns[i]) {
144       client->conns[i] = conn;
145       return conn;
146     }
147
148   client->conns = silc_realloc(client->conns, sizeof(*client->conns)
149                                * (client->conns_count + 1));
150   client->conns[client->conns_count] = conn;
151   client->conns_count++;
152
153   return conn;
154 }
155
156 /* Removes connection from client. */
157
158 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
159 {
160   int i;
161
162   for (i = 0; i < client->conns_count; i++)
163     if (client->conns[i] == conn) {
164       silc_free(conn);
165       client->conns[i] = NULL;
166     }
167 }
168
169 /* Internal context for connection process. This is needed as we
170    doing asynchronous connecting. */
171 typedef struct {
172   SilcClient client;
173   SilcClientConnection conn;
174   SilcTask task;
175   int sock;
176   char *host;
177   int port;
178   int tries;
179 } SilcClientInternalConnectContext;
180
181 static int 
182 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
183 {
184   int sock;
185
186   /* XXX In the future we should give up this non-blocking connect all
187      together and use threads instead. */
188   /* Create connection to server asynchronously */
189   sock = silc_net_create_connection_async(ctx->port, ctx->host);
190   if (sock < 0)
191     return -1;
192
193   /* Register task that will receive the async connect and will
194      read the result. */
195   ctx->task = silc_task_register(ctx->client->io_queue, sock, 
196                                  silc_client_connect_to_server_start,
197                                  (void *)ctx, 0, 0, 
198                                  SILC_TASK_FD,
199                                  SILC_TASK_PRI_NORMAL);
200   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
201   silc_schedule_set_listen_fd(sock, ctx->task->iomask);
202
203   ctx->sock = sock;
204
205   return sock;
206 }
207
208 /* Connects to remote server. This is the main routine used to connect
209    to SILC server. Returns -1 on error and the created socket otherwise. 
210    The `context' is user context that is saved into the SilcClientConnection
211    that is created after the connection is created. */
212
213 int silc_client_connect_to_server(SilcClient client, int port,
214                                   char *host, void *context)
215 {
216   SilcClientInternalConnectContext *ctx;
217   SilcClientConnection conn;
218   int sock;
219
220   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
221                   port, host));
222
223   conn = silc_client_add_connection(client, context);
224   conn->remote_host = strdup(host);
225   conn->remote_port = port;
226
227   client->ops->say(client, conn, 
228                    "Connecting to port %d of server %s", port, host);
229
230   /* Allocate internal context for connection process. This is
231      needed as we are doing async connecting. */
232   ctx = silc_calloc(1, sizeof(*ctx));
233   ctx->client = client;
234   ctx->conn = conn;
235   ctx->host = strdup(host);
236   ctx->port = port;
237   ctx->tries = 0;
238
239   /* Do the actual connecting process */
240   sock = silc_client_connect_to_server_internal(ctx);
241   if (sock == -1)
242     silc_client_del_connection(client, conn);
243   return sock;
244 }
245
246 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
247    key material between client and server.  This function can be called
248    directly if application is performing its own connecting and does not
249    use the connecting provided by this library. */
250
251 int silc_client_start_key_exchange(SilcClient client,
252                                    SilcClientConnection conn,
253                                    int fd)
254 {
255   SilcProtocol protocol;
256   SilcClientKEInternalContext *proto_ctx;
257   void *context;
258
259   /* Allocate new socket connection object */
260   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
261   if (conn->sock == NULL) {
262     client->ops->say(client, conn, 
263                      "Error: Could not allocate connection socket");
264     return FALSE;
265   }
266
267   conn->nickname = strdup(client->username);
268   conn->sock->hostname = conn->remote_host;
269   conn->sock->port = conn->remote_port;
270
271   /* Allocate internal Key Exchange context. This is sent to the
272      protocol as context. */
273   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
274   proto_ctx->client = (void *)client;
275   proto_ctx->sock = conn->sock;
276   proto_ctx->rng = client->rng;
277   proto_ctx->responder = FALSE;
278
279   /* Perform key exchange protocol. silc_client_connect_to_server_final
280      will be called after the protocol is finished. */
281   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
282                       &protocol, (void *)proto_ctx,
283                       silc_client_connect_to_server_second);
284   if (!protocol) {
285     client->ops->say(client, conn, 
286                      "Error: Could not start authentication protocol");
287     return FALSE;
288   }
289   conn->sock->protocol = protocol;
290
291   /* Register the connection for network input and output. This sets
292      that scheduler will listen for incoming packets for this connection 
293      and sets that outgoing packets may be sent to this connection as well.
294      However, this doesn't set the scheduler for outgoing traffic, it will 
295      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
296      later when outgoing data is available. */
297   context = (void *)client;
298   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
299
300   /* Execute the protocol */
301   protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
302   return TRUE;
303 }
304
305 /* Start of the connection to the remote server. This is called after
306    succesful TCP/IP connection has been established to the remote host. */
307
308 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
309 {
310   SilcClientInternalConnectContext *ctx =
311     (SilcClientInternalConnectContext *)context;
312   SilcClient client = ctx->client;
313   SilcClientConnection conn = ctx->conn;
314   int opt, opt_len = sizeof(opt);
315
316   SILC_LOG_DEBUG(("Start"));
317
318   /* Check the socket status as it might be in error */
319   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
320   if (opt != 0) {
321     if (ctx->tries < 2) {
322       /* Connection failed but lets try again */
323       client->ops->say(client, conn, "Could not connect to server %s: %s",
324                        ctx->host, strerror(opt));
325       client->ops->say(client, conn, 
326                        "Connecting to port %d of server %s resumed", 
327                        ctx->port, ctx->host);
328
329       /* Unregister old connection try */
330       silc_schedule_unset_listen_fd(fd);
331       silc_net_close_connection(fd);
332       silc_task_unregister(client->io_queue, ctx->task);
333
334       /* Try again */
335       silc_client_connect_to_server_internal(ctx);
336       ctx->tries++;
337     } else {
338       /* Connection failed and we won't try anymore */
339       client->ops->say(client, conn, "Could not connect to server %s: %s",
340                        ctx->host, strerror(opt));
341       silc_schedule_unset_listen_fd(fd);
342       silc_net_close_connection(fd);
343       silc_task_unregister(client->io_queue, ctx->task);
344       silc_free(ctx);
345
346       /* Notify application of failure */
347       client->ops->connect(client, conn, FALSE);
348       silc_client_del_connection(client, conn);
349     }
350     return;
351   }
352
353   silc_schedule_unset_listen_fd(fd);
354   silc_task_unregister(client->io_queue, ctx->task);
355   silc_free(ctx);
356
357   if (!silc_client_start_key_exchange(client, conn, fd)) {
358     silc_net_close_connection(fd);
359     client->ops->connect(client, conn, FALSE);
360   }
361 }
362
363 /* Second part of the connecting to the server. This executed 
364    authentication protocol. */
365
366 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
367 {
368   SilcProtocol protocol = (SilcProtocol)context;
369   SilcClientKEInternalContext *ctx = 
370     (SilcClientKEInternalContext *)protocol->context;
371   SilcClient client = (SilcClient)ctx->client;
372   SilcSocketConnection sock = NULL;
373   SilcClientConnAuthInternalContext *proto_ctx;
374
375   SILC_LOG_DEBUG(("Start"));
376
377   if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
378     /* Error occured during protocol */
379     SILC_LOG_DEBUG(("Error during KE protocol"));
380     silc_protocol_free(protocol);
381     if (ctx->ske)
382       silc_ske_free(ctx->ske);
383     if (ctx->dest_id)
384       silc_free(ctx->dest_id);
385     ctx->sock->protocol = NULL;
386     silc_free(ctx);
387
388     /* Notify application of failure */
389     client->ops->connect(client, ctx->sock->user_data, FALSE);
390     return;
391   }
392
393   /* Allocate internal context for the authentication protocol. This
394      is sent as context for the protocol. */
395   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
396   proto_ctx->client = (void *)client;
397   proto_ctx->sock = sock = ctx->sock;
398   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
399   proto_ctx->dest_id_type = ctx->dest_id_type;
400   proto_ctx->dest_id = ctx->dest_id;
401
402   /* Resolve the authentication method to be used in this connection */
403   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
404                                     sock->port, &proto_ctx->auth_meth,
405                                     &proto_ctx->auth_data, 
406                                     &proto_ctx->auth_data_len))
407     {
408       /* XXX do AUTH_REQUEST resolcing with server */
409       proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
410     }
411
412   /* Free old protocol as it is finished now */
413   silc_protocol_free(protocol);
414   if (ctx->packet)
415     silc_buffer_free(ctx->packet);
416   silc_free(ctx);
417   /* silc_free(ctx->keymat....); */
418   sock->protocol = NULL;
419
420   /* Allocate the authentication protocol. This is allocated here
421      but we won't start it yet. We will be receiving party of this
422      protocol thus we will wait that connecting party will make
423      their first move. */
424   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
425                       &sock->protocol, (void *)proto_ctx, 
426                       silc_client_connect_to_server_final);
427
428   /* Execute the protocol */
429   sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
430 }
431
432 /* Finalizes the connection to the remote SILC server. This is called
433    after authentication protocol has been completed. This send our
434    user information to the server to receive our client ID from
435    server. */
436
437 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
438 {
439   SilcProtocol protocol = (SilcProtocol)context;
440   SilcClientConnAuthInternalContext *ctx = 
441     (SilcClientConnAuthInternalContext *)protocol->context;
442   SilcClient client = (SilcClient)ctx->client;
443   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
444   SilcBuffer packet;
445
446   SILC_LOG_DEBUG(("Start"));
447
448   if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
449     /* Error occured during protocol */
450     SILC_LOG_DEBUG(("Error during authentication protocol"));
451     silc_protocol_free(protocol);
452     if (ctx->auth_data)
453       silc_free(ctx->auth_data);
454     if (ctx->ske)
455       silc_ske_free(ctx->ske);
456     if (ctx->dest_id)
457       silc_free(ctx->dest_id);
458     silc_free(ctx);
459     conn->sock->protocol = NULL;
460
461     /* Notify application of failure */
462     client->ops->connect(client, ctx->sock->user_data, FALSE);
463     return;
464   }
465
466   /* Send NEW_CLIENT packet to the server. We will become registered
467      to the SILC network after sending this packet and we will receive
468      client ID from the server. */
469   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
470                              strlen(client->realname));
471   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
472   silc_buffer_format(packet,
473                      SILC_STR_UI_SHORT(strlen(client->username)),
474                      SILC_STR_UI_XNSTRING(client->username,
475                                           strlen(client->username)),
476                      SILC_STR_UI_SHORT(strlen(client->realname)),
477                      SILC_STR_UI_XNSTRING(client->realname,
478                                           strlen(client->realname)),
479                      SILC_STR_END);
480
481   /* Send the packet */
482   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
483                           NULL, 0, NULL, NULL, 
484                           packet->data, packet->len, TRUE);
485   silc_buffer_free(packet);
486
487   /* Save remote ID. */
488   conn->remote_id = ctx->dest_id;
489   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
490   conn->remote_id_data_len = SILC_ID_SERVER_LEN;
491
492   /* Notify application of successful connection */
493   client->ops->connect(client, conn, TRUE);
494
495   silc_protocol_free(protocol);
496   if (ctx->auth_data)
497     silc_free(ctx->auth_data);
498   if (ctx->ske)
499     silc_ske_free(ctx->ske);
500   if (ctx->dest_id)
501     silc_free(ctx->dest_id);
502   silc_free(ctx);
503   conn->sock->protocol = NULL;
504 }
505
506 /* Internal routine that sends packet or marks packet to be sent. This
507    is used directly only in special cases. Normal cases should use
508    silc_server_packet_send. Returns < 0 on error. */
509
510 static int silc_client_packet_send_real(SilcClient client,
511                                         SilcSocketConnection sock,
512                                         int force_send)
513 {
514   int ret;
515
516   /* Send the packet */
517   ret = silc_packet_send(sock, force_send);
518   if (ret != -2)
519     return ret;
520
521   /* Mark that there is some outgoing data available for this connection. 
522      This call sets the connection both for input and output (the input
523      is set always and this call keeps the input setting, actually). 
524      Actual data sending is performed by silc_client_packet_process. */
525   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
526
527   /* Mark to socket that data is pending in outgoing buffer. This flag
528      is needed if new data is added to the buffer before the earlier
529      put data is sent to the network. */
530   SILC_SET_OUTBUF_PENDING(sock);
531
532   return 0;
533 }
534
535 /* Packet processing callback. This is used to send and receive packets
536    from network. This is generic task. */
537
538 SILC_TASK_CALLBACK(silc_client_packet_process)
539 {
540   SilcClient client = (SilcClient)context;
541   SilcSocketConnection sock = NULL;
542   SilcClientConnection conn;
543   int ret;
544
545   SILC_LOG_DEBUG(("Processing packet"));
546
547   SILC_CLIENT_GET_SOCK(client, fd, sock);
548   if (sock == NULL)
549     return;
550
551   conn = (SilcClientConnection)sock->user_data;
552
553   /* Packet sending */
554   if (type == SILC_TASK_WRITE) {
555     SILC_LOG_DEBUG(("Writing data to connection"));
556
557     if (sock->outbuf->data - sock->outbuf->head)
558       silc_buffer_push(sock->outbuf, 
559                        sock->outbuf->data - sock->outbuf->head);
560
561     ret = silc_client_packet_send_real(client, sock, TRUE);
562
563     /* If returned -2 could not write to connection now, will do
564        it later. */
565     if (ret == -2)
566       return;
567     
568     /* The packet has been sent and now it is time to set the connection
569        back to only for input. When there is again some outgoing data 
570        available for this connection it will be set for output as well. 
571        This call clears the output setting and sets it only for input. */
572     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
573     SILC_UNSET_OUTBUF_PENDING(sock);
574
575     silc_buffer_clear(sock->outbuf);
576     return;
577   }
578
579   /* Packet receiving */
580   if (type == SILC_TASK_READ) {
581     SILC_LOG_DEBUG(("Reading data from connection"));
582
583     /* Read data from network */
584     ret = silc_packet_receive(sock);
585     if (ret < 0)
586       return;
587     
588     /* EOF */
589     if (ret == 0) {
590       SILC_LOG_DEBUG(("Read EOF"));
591
592       /* If connection is disconnecting already we will finally
593          close the connection */
594       if (SILC_IS_DISCONNECTING(sock)) {
595         client->ops->disconnect(client, conn);
596         silc_client_close_connection(client, sock);
597         return;
598       }
599       
600       client->ops->say(client, conn, "Connection closed: premature EOF");
601       SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
602       client->ops->disconnect(client, conn);
603       silc_client_close_connection(client, sock);
604       return;
605     }
606
607     /* Process the packet. This will call the parser that will then
608        decrypt and parse the packet. */
609     if (!silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
610                                      silc_client_packet_parse, client)) {
611       silc_buffer_clear(sock->inbuf);
612       return;
613     }
614   }
615 }
616
617 /* Parses whole packet, received earlier. */
618
619 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
620 {
621   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
622   SilcClient client = (SilcClient)parse_ctx->context;
623   SilcPacketContext *packet = parse_ctx->packet;
624   SilcBuffer buffer = packet->buffer;
625   SilcSocketConnection sock = parse_ctx->sock;
626   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
627   int ret;
628
629   SILC_LOG_DEBUG(("Start"));
630
631   /* Decrypt the received packet */
632   ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
633   if (ret < 0)
634     goto out;
635
636   if (ret == 0) {
637     /* Parse the packet. Packet type is returned. */
638     ret = silc_packet_parse(packet);
639   } else {
640     /* Parse the packet header in special way as this is "special"
641        packet type. */
642     ret = silc_packet_parse_special(packet);
643   }
644
645   if (ret == SILC_PACKET_NONE)
646     goto out;
647
648   /* Parse the incoming packet type */
649   silc_client_packet_parse_type(client, sock, packet);
650
651  out:
652   silc_buffer_clear(buffer);
653   silc_free(packet);
654   silc_free(parse_ctx);
655 }
656
657 /* Parser callback called by silc_packet_receive_process. Thie merely
658    registers timeout that will handle the actual parsing when appropriate. */
659
660 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
661 {
662   SilcClient client = (SilcClient)parser_context->context;
663
664   /* Parse the packet */
665   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
666                      silc_client_packet_parse_real,
667                      (void *)parser_context, 0, 1, 
668                      SILC_TASK_TIMEOUT,
669                      SILC_TASK_PRI_NORMAL);
670 }
671   
672 /* Parses the packet type and calls what ever routines the packet type
673    requires. This is done for all incoming packets. */
674
675 void silc_client_packet_parse_type(SilcClient client, 
676                                    SilcSocketConnection sock,
677                                    SilcPacketContext *packet)
678 {
679   SilcBuffer buffer = packet->buffer;
680   SilcPacketType type = packet->type;
681
682   SILC_LOG_DEBUG(("Parsing packet type %d", type));
683
684   /* Parse the packet type */
685   switch(type) {
686   case SILC_PACKET_DISCONNECT:
687     silc_client_disconnected_by_server(client, sock, buffer);
688     break;
689   case SILC_PACKET_SUCCESS:
690     /*
691      * Success received for something. For now we can have only
692      * one protocol for connection executing at once hence this
693      * success message is for whatever protocol is executing currently.
694      */
695     if (sock->protocol) {
696       sock->protocol->execute(client->timeout_queue, 0,
697                               sock->protocol, sock->sock, 0, 0);
698     }
699     break;
700   case SILC_PACKET_FAILURE:
701     /*
702      * Failure received for some protocol. Set the protocol state to 
703      * error and call the protocol callback. This fill cause error on
704      * protocol and it will call the final callback.
705      */
706     if (sock->protocol) {
707       sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
708       sock->protocol->execute(client->timeout_queue, 0,
709                               sock->protocol, sock->sock, 0, 0);
710     }
711     break;
712   case SILC_PACKET_REJECT:
713     break;
714
715   case SILC_PACKET_NOTIFY:
716     /*
717      * Received notify message 
718      */
719     silc_client_notify_by_server(client, sock, buffer);
720     break;
721
722   case SILC_PACKET_ERROR:
723     /*
724      * Received error message
725      */
726     silc_client_error_by_server(client, sock, buffer);
727     break;
728
729   case SILC_PACKET_CHANNEL_MESSAGE:
730     /*
731      * Received message to (from, actually) a channel
732      */
733     silc_client_channel_message(client, sock, packet);
734     break;
735   case SILC_PACKET_CHANNEL_KEY:
736     /*
737      * Received key for a channel. By receiving this key the client will be
738      * able to talk to the channel it has just joined. This can also be
739      * a new key for existing channel as keys expire peridiocally.
740      */
741     silc_client_receive_channel_key(client, sock, buffer);
742     break;
743
744   case SILC_PACKET_PRIVATE_MESSAGE:
745     /*
746      * Received private message
747      */
748     silc_client_private_message(client, sock, packet);
749     break;
750   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
751     /*
752      * Received private message key
753      */
754     break;
755
756   case SILC_PACKET_COMMAND_REPLY:
757     /*
758      * Recived reply for a command
759      */
760     silc_client_command_reply_process(client, sock, packet);
761     break;
762
763   case SILC_PACKET_KEY_EXCHANGE:
764     if (sock->protocol) {
765       SilcClientKEInternalContext *proto_ctx = 
766         (SilcClientKEInternalContext *)sock->protocol->context;
767
768       proto_ctx->packet = buffer;
769       proto_ctx->dest_id_type = packet->src_id_type;
770       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
771
772       /* Let the protocol handle the packet */
773       sock->protocol->execute(client->timeout_queue, 0,
774                               sock->protocol, sock->sock, 0, 0);
775     } else {
776       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
777                       "protocol active, packet dropped."));
778
779       /* XXX Trigger KE protocol?? Rekey actually! */
780     }
781     break;
782
783   case SILC_PACKET_KEY_EXCHANGE_1:
784     if (sock->protocol) {
785
786     } else {
787       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
788                       "protocol active, packet dropped."));
789     }
790     break;
791   case SILC_PACKET_KEY_EXCHANGE_2:
792     if (sock->protocol) {
793       SilcClientKEInternalContext *proto_ctx = 
794         (SilcClientKEInternalContext *)sock->protocol->context;
795
796       if (proto_ctx->packet)
797         silc_buffer_free(proto_ctx->packet);
798
799       proto_ctx->packet = buffer;
800       proto_ctx->dest_id_type = packet->src_id_type;
801       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
802
803       /* Let the protocol handle the packet */
804       sock->protocol->execute(client->timeout_queue, 0,
805                               sock->protocol, sock->sock, 0, 0);
806     } else {
807       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
808                       "protocol active, packet dropped."));
809     }
810     break;
811
812   case SILC_PACKET_NEW_ID:
813     {
814       /*
815        * Received new ID from server. This packet is received at
816        * the connection to the server.  New ID is also received when 
817        * user changes nickname but in that case the new ID is received
818        * as command reply and not as this packet type.
819        */
820       unsigned char *id_string;
821       unsigned short id_type;
822       
823       silc_buffer_unformat(buffer,
824                            SILC_STR_UI_SHORT(&id_type),
825                            SILC_STR_UI16_STRING_ALLOC(&id_string),
826                            SILC_STR_END);
827       
828       if ((SilcIdType)id_type != SILC_ID_CLIENT)
829         break;
830
831       silc_client_receive_new_id(client, sock, id_string);
832       silc_free(id_string);
833       break;
834     }
835
836   default:
837     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
838     break;
839   }
840 }
841
842 /* Sends packet. This doesn't actually send the packet instead it assembles
843    it and marks it to be sent. However, if force_send is TRUE the packet
844    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
845    will be derived from sock argument. Otherwise the valid arguments sent
846    are used. */
847
848 void silc_client_packet_send(SilcClient client, 
849                              SilcSocketConnection sock,
850                              SilcPacketType type, 
851                              void *dst_id,
852                              SilcIdType dst_id_type,
853                              SilcCipher cipher,
854                              SilcHmac hmac,
855                              unsigned char *data, 
856                              unsigned int data_len, 
857                              int force_send)
858 {
859   SilcPacketContext packetdata;
860
861   SILC_LOG_DEBUG(("Sending packet, type %d", type));
862
863   /* Get data used in the packet sending, keys and stuff */
864   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
865     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
866       cipher = ((SilcClientConnection)sock->user_data)->send_key;
867
868     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
869       hmac = ((SilcClientConnection)sock->user_data)->hmac;
870
871     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
872       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
873       dst_id_type = SILC_ID_SERVER;
874     }
875   }
876
877   /* Set the packet context pointers */
878   packetdata.flags = 0;
879   packetdata.type = type;
880   if (((SilcClientConnection)sock->user_data)->local_id_data)
881     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
882   else 
883     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
884   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
885   packetdata.src_id_type = SILC_ID_CLIENT;
886   if (dst_id) {
887     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
888     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
889     packetdata.dst_id_type = dst_id_type;
890   } else {
891     packetdata.dst_id = NULL;
892     packetdata.dst_id_len = 0;
893     packetdata.dst_id_type = SILC_ID_NONE;
894   }
895   packetdata.rng = client->rng;
896   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
897     packetdata.src_id_len + packetdata.dst_id_len;
898   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
899
900   /* Prepare outgoing data buffer for packet sending */
901   silc_packet_send_prepare(sock, 
902                            SILC_PACKET_HEADER_LEN +
903                            packetdata.src_id_len + 
904                            packetdata.dst_id_len,
905                            packetdata.padlen,
906                            data_len);
907
908   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
909
910   packetdata.buffer = sock->outbuf;
911
912   /* Put the data to the buffer */
913   if (data && data_len)
914     silc_buffer_put(sock->outbuf, data, data_len);
915
916   /* Create the outgoing packet */
917   silc_packet_assemble(&packetdata);
918
919   /* Encrypt the packet */
920   if (cipher)
921     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
922
923   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
924                    sock->outbuf->data, sock->outbuf->len);
925
926   /* Now actually send the packet */
927   silc_client_packet_send_real(client, sock, force_send);
928 }
929
930 /* Sends packet to a channel. Packet to channel is always encrypted
931    differently from "normal" packets. SILC header of the packet is 
932    encrypted with the next receiver's key and the rest of the packet is
933    encrypted with the channel specific key. Padding and HMAC is computed
934    with the next receiver's key. */
935
936 void silc_client_packet_send_to_channel(SilcClient client, 
937                                         SilcSocketConnection sock,
938                                         SilcChannelEntry channel,
939                                         unsigned char *data, 
940                                         unsigned int data_len, 
941                                         int force_send)
942 {
943   int i;
944   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
945   SilcBuffer payload;
946   SilcPacketContext packetdata;
947   SilcCipher cipher;
948   SilcHmac hmac;
949   unsigned char *id_string;
950
951   SILC_LOG_DEBUG(("Sending packet to channel"));
952
953   if (!channel || !channel->key) {
954     client->ops->say(client, conn, 
955                      "Cannot talk to channel: key does not exist");
956     return;
957   }
958
959   /* Generate IV */
960   if (!channel->iv)
961     for (i = 0; i < 16; i++)
962       channel->iv[i] = silc_rng_get_byte(client->rng);
963   else
964     silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
965
966   /* Encode the channel payload */
967   payload = silc_channel_encode_payload(strlen(conn->nickname), conn->nickname,
968                                         data_len, data, 16, channel->iv, 
969                                         client->rng);
970   if (!payload) {
971     client->ops->say(client, conn, 
972                      "Error: Could not create packet to be sent to channel");
973     return;
974   }
975
976   /* Get data used in packet header encryption, keys and stuff. Rest
977      of the packet (the payload) is, however, encrypted with the 
978      specified channel key. */
979   cipher = conn->send_key;
980   hmac = conn->hmac;
981   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
982
983   /* Set the packet context pointers. The destination ID is always
984      the Channel ID of the channel. Server and router will handle the
985      distribution of the packet. */
986   packetdata.flags = 0;
987   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
988   packetdata.src_id = conn->local_id_data;
989   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
990   packetdata.src_id_type = SILC_ID_CLIENT;
991   packetdata.dst_id = id_string;
992   packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
993   packetdata.dst_id_type = SILC_ID_CHANNEL;
994   packetdata.rng = client->rng;
995   packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN + 
996     packetdata.src_id_len + packetdata.dst_id_len;
997   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
998                                           packetdata.src_id_len +
999                                           packetdata.dst_id_len));
1000
1001   /* Prepare outgoing data buffer for packet sending */
1002   silc_packet_send_prepare(sock, 
1003                            SILC_PACKET_HEADER_LEN +
1004                            packetdata.src_id_len + 
1005                            packetdata.dst_id_len,
1006                            packetdata.padlen,
1007                            payload->len);
1008
1009   packetdata.buffer = sock->outbuf;
1010
1011   /* Encrypt payload of the packet. This is encrypted with the channel key. */
1012   channel->channel_key->cipher->encrypt(channel->channel_key->context,
1013                                         payload->data, payload->data,
1014                                         payload->len - 16, /* -IV_LEN */
1015                                         channel->iv);
1016
1017   /* Put the actual encrypted payload data into the buffer. */
1018   silc_buffer_put(sock->outbuf, payload->data, payload->len);
1019
1020   /* Create the outgoing packet */
1021   silc_packet_assemble(&packetdata);
1022
1023   /* Encrypt the header and padding of the packet. This is encrypted 
1024      with normal session key shared with our server. */
1025   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1026                       packetdata.src_id_len + packetdata.dst_id_len +
1027                       packetdata.padlen);
1028
1029   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1030                    sock->outbuf->data, sock->outbuf->len);
1031
1032   /* Now actually send the packet */
1033   silc_client_packet_send_real(client, sock, force_send);
1034   silc_buffer_free(payload);
1035   silc_free(id_string);
1036 }
1037
1038 /* Sends private message to remote client. If private message key has
1039    not been set with this client then the message will be encrypted using
1040    normal session keys. Private messages are special packets in SILC
1041    network hence we need this own function for them. This is similiar
1042    to silc_client_packet_send_to_channel except that we send private
1043    message. */
1044
1045 void silc_client_packet_send_private_message(SilcClient client,
1046                                              SilcSocketConnection sock,
1047                                              SilcClientEntry client_entry,
1048                                              unsigned char *data, 
1049                                              unsigned int data_len, 
1050                                              int force_send)
1051 {
1052   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1053   SilcBuffer buffer;
1054   SilcPacketContext packetdata;
1055   unsigned int nick_len;
1056   SilcCipher cipher;
1057   SilcHmac hmac;
1058
1059   SILC_LOG_DEBUG(("Sending private message"));
1060
1061   /* Create private message payload */
1062   nick_len = strlen(conn->nickname);
1063   buffer = silc_buffer_alloc(2 + nick_len + data_len);
1064   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1065   silc_buffer_format(buffer,
1066                      SILC_STR_UI_SHORT(nick_len),
1067                      SILC_STR_UI_XNSTRING(conn->nickname,
1068                                           nick_len),
1069                      SILC_STR_UI_XNSTRING(data, data_len),
1070                      SILC_STR_END);
1071
1072   /* If we don't have private message specific key then private messages
1073      are just as any normal packet thus call normal packet sending.  If
1074      the key exist then the encryption process is a bit different and
1075      will be done in the rest of this function. */
1076   if (!client_entry->send_key) {
1077     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1078                             client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1079                             buffer->data, buffer->len, force_send);
1080     goto out;
1081   }
1082
1083   /* We have private message specific key */
1084
1085   /* Get data used in the encryption */
1086   cipher = client_entry->send_key;
1087   hmac = conn->hmac;
1088
1089   /* Set the packet context pointers. */
1090   packetdata.flags = 0;
1091   packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1092   packetdata.src_id = conn->local_id_data;
1093   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1094   packetdata.src_id_type = SILC_ID_CLIENT;
1095   if (client_entry)
1096     packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1097   else
1098     packetdata.dst_id = conn->local_id_data;
1099   packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1100   packetdata.dst_id_type = SILC_ID_CLIENT;
1101   packetdata.rng = client->rng;
1102   packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN + 
1103     packetdata.src_id_len + packetdata.dst_id_len;
1104   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1105                                           packetdata.src_id_len +
1106                                           packetdata.dst_id_len));
1107
1108   /* Prepare outgoing data buffer for packet sending */
1109   silc_packet_send_prepare(sock, 
1110                            SILC_PACKET_HEADER_LEN +
1111                            packetdata.src_id_len + 
1112                            packetdata.dst_id_len,
1113                            packetdata.padlen,
1114                            buffer->len);
1115   
1116   packetdata.buffer = sock->outbuf;
1117
1118   /* Encrypt payload of the packet. Encrypt with private message specific
1119      key if it exist, otherwise with session key. */
1120   cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1121                           buffer->len, cipher->iv);
1122       
1123   /* Put the actual encrypted payload data into the buffer. */
1124   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1125
1126   /* Create the outgoing packet */
1127   silc_packet_assemble(&packetdata);
1128
1129   /* Encrypt the header and padding of the packet. */
1130   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1131                       packetdata.src_id_len + packetdata.dst_id_len +
1132                       packetdata.padlen);
1133
1134   SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1135                    sock->outbuf->data, sock->outbuf->len);
1136
1137   /* Now actually send the packet */
1138   silc_client_packet_send_real(client, sock, force_send);
1139   silc_free(packetdata.dst_id);
1140
1141  out:
1142   silc_free(buffer);
1143 }     
1144
1145 /* Closes connection to remote end. Free's all allocated data except
1146    for some information such as nickname etc. that are valid at all time. */
1147
1148 void silc_client_close_connection(SilcClient client,
1149                                   SilcSocketConnection sock)
1150 {
1151   SilcClientConnection conn;
1152
1153   /* We won't listen for this connection anymore */
1154   silc_schedule_unset_listen_fd(sock->sock);
1155
1156   /* Unregister all tasks */
1157   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1158   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1159
1160   /* Close the actual connection */
1161   silc_net_close_connection(sock->sock);
1162
1163   client->ops->say(client, sock->user_data,
1164                    "Closed connection to host %s", sock->hostname ?
1165                    sock->hostname : sock->ip);
1166
1167   /* Free everything */
1168   if (sock->user_data) {
1169     conn = (SilcClientConnection)sock->user_data;
1170
1171     /* XXX Free all client entries and channel entries. */
1172
1173     /* Clear ID caches */
1174     silc_idcache_del_all(conn->client_cache);
1175     silc_idcache_del_all(conn->channel_cache);
1176
1177     /* Free data */
1178     if (conn->remote_host)
1179       silc_free(conn->remote_host);
1180     if (conn->local_id)
1181       silc_free(conn->local_id);
1182     if (conn->local_id_data)
1183       silc_free(conn->local_id_data);
1184     if (conn->send_key)
1185       silc_cipher_free(conn->send_key);
1186     if (conn->receive_key)
1187       silc_cipher_free(conn->receive_key);
1188     if (conn->hmac)
1189       silc_hmac_free(conn->hmac);
1190     if (conn->hmac_key) {
1191       memset(conn->hmac_key, 0, conn->hmac_key_len);
1192       silc_free(conn->hmac_key);
1193     }
1194
1195     conn->sock = NULL;
1196     conn->remote_port = 0;
1197     conn->remote_type = 0;
1198     conn->send_key = NULL;
1199     conn->receive_key = NULL;
1200     conn->hmac = NULL;
1201     conn->hmac_key = NULL;
1202     conn->hmac_key_len = 0;
1203     conn->local_id = NULL;
1204     conn->local_id_data = NULL;
1205     conn->remote_host = NULL;
1206     conn->current_channel = NULL;
1207
1208     silc_client_del_connection(client, conn);
1209   }
1210
1211   if (sock->protocol) {
1212     silc_protocol_free(sock->protocol);
1213     sock->protocol = NULL;
1214   }
1215   silc_socket_free(sock);
1216 }
1217
1218 /* Called when we receive disconnection packet from server. This 
1219    closes our end properly and displays the reason of the disconnection
1220    on the screen. */
1221
1222 void silc_client_disconnected_by_server(SilcClient client,
1223                                         SilcSocketConnection sock,
1224                                         SilcBuffer message)
1225 {
1226   char *msg;
1227
1228   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1229
1230   msg = silc_calloc(message->len + 1, sizeof(char));
1231   memcpy(msg, message->data, message->len);
1232   client->ops->say(client, sock->user_data, msg);
1233   silc_free(msg);
1234
1235   SILC_SET_DISCONNECTED(sock);
1236   silc_client_close_connection(client, sock);
1237 }
1238
1239 /* Received error message from server. Display it on the screen. 
1240    We don't take any action what so ever of the error message. */
1241
1242 void silc_client_error_by_server(SilcClient client,
1243                                  SilcSocketConnection sock,
1244                                  SilcBuffer message)
1245 {
1246   char *msg;
1247
1248   msg = silc_calloc(message->len + 1, sizeof(char));
1249   memcpy(msg, message->data, message->len);
1250   client->ops->say(client, sock->user_data, msg);
1251   silc_free(msg);
1252 }
1253
1254 /* Received notify message from server */
1255
1256 void silc_client_notify_by_server(SilcClient client,
1257                                   SilcSocketConnection sock,
1258                                   SilcBuffer message)
1259 {
1260   char *msg;
1261   SilcNotifyType type;
1262
1263   SILC_GET16_MSB(type, message->data);
1264   silc_buffer_pull(message, 2);
1265
1266   msg = silc_calloc(message->len + 1, sizeof(char));
1267   memcpy(msg, message->data, message->len);
1268   client->ops->notify(client, sock->user_data, type, msg);
1269   silc_free(msg);
1270 }
1271
1272 /* Processes the received new Client ID from server. Old Client ID is
1273    deleted from cache and new one is added. */
1274
1275 void silc_client_receive_new_id(SilcClient client,
1276                                 SilcSocketConnection sock,
1277                                 unsigned char *id_string)
1278 {
1279   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1280
1281   /* Delete old ID from ID cache */
1282   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1283   
1284   /* Save the new ID */
1285   if (conn->local_id)
1286     silc_free(conn->local_id);
1287   conn->local_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
1288   if (conn->local_id_data)
1289     silc_free(conn->local_id_data);
1290   conn->local_id_data = 
1291     silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1292   memcpy(conn->local_id_data, id_string, SILC_ID_CLIENT_LEN);
1293   conn->local_id_data_len = SILC_ID_CLIENT_LEN;
1294   if (!conn->local_entry)
1295     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1296   conn->local_entry->nickname = conn->nickname;
1297   conn->local_entry->id = conn->local_id;
1298   
1299   /* Put it to the ID cache */
1300   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1301                    conn->local_id, (void *)conn->local_entry, TRUE);
1302 }
1303
1304 /* Processed received Channel ID for a channel. This is called when client
1305    joins to channel and server replies with channel ID. The ID is cached. */
1306
1307 void silc_client_new_channel_id(SilcClient client,
1308                                 SilcSocketConnection sock,
1309                                 char *channel_name,
1310                                 unsigned int mode,
1311                                 unsigned char *id_string)
1312 {
1313   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1314   SilcChannelID *id;
1315   SilcChannelEntry channel;
1316
1317   SILC_LOG_DEBUG(("New channel ID"));
1318
1319   id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1320   channel = silc_calloc(1, sizeof(*channel));
1321   channel->channel_name = channel_name;
1322   channel->id = id;
1323   channel->mode = mode;
1324   conn->current_channel = channel;
1325   
1326   /* Put it to the ID cache */
1327   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1328                    (void *)id, (void *)channel, TRUE);
1329 }
1330
1331 /* Processes received key for channel. The received key will be used
1332    to protect the traffic on the channel for now on. Client must receive
1333    the key to the channel before talking on the channel is possible. 
1334    This is the key that server has generated, this is not the channel
1335    private key, it is entirely local setting. */
1336
1337 void silc_client_receive_channel_key(SilcClient client,
1338                                      SilcSocketConnection sock,
1339                                      SilcBuffer packet)
1340 {
1341   unsigned char *id_string, *key, *cipher;
1342   unsigned int key_len;
1343   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1344   SilcChannelID *id;
1345   SilcIDCacheEntry id_cache = NULL;
1346   SilcChannelEntry channel;
1347   SilcChannelKeyPayload payload;
1348
1349   SILC_LOG_DEBUG(("Received key for channel"));
1350   
1351   payload = silc_channel_key_parse_payload(packet);
1352   if (!payload)
1353     return;
1354
1355   id_string = silc_channel_key_get_id(payload, NULL);
1356   if (!id_string) {
1357     silc_channel_key_free_payload(payload);
1358     return;
1359   }
1360   id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1361
1362   /* Find channel. */
1363   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1364                                    SILC_ID_CHANNEL, &id_cache))
1365     goto out;
1366   
1367   /* Save the key */
1368   key = silc_channel_key_get_key(payload, &key_len);
1369   cipher = silc_channel_key_get_cipher(payload, NULL);
1370
1371   channel = (SilcChannelEntry)id_cache->context;
1372   channel->key_len = key_len;
1373   channel->key = silc_calloc(key_len, sizeof(*channel->key));
1374   memcpy(channel->key, key, key_len);
1375
1376   silc_cipher_alloc(cipher, &channel->channel_key);
1377   if (!channel->channel_key) {
1378     client->ops->say(client, conn,
1379                      "Cannot talk to channel: unsupported cipher %s", cipher);
1380     goto out;
1381   }
1382   channel->channel_key->cipher->set_key(channel->channel_key->context, 
1383                                         key, key_len);
1384
1385   /* Client is now joined to the channel */
1386   channel->on_channel = TRUE;
1387
1388  out:
1389   silc_free(id);
1390   silc_channel_key_free_payload(payload);
1391 }
1392
1393 /* Process received message to a channel (or from a channel, really). This
1394    decrypts the channel message with channel specific key and parses the
1395    channel payload. Finally it displays the message on the screen. */
1396
1397 void silc_client_channel_message(SilcClient client, 
1398                                  SilcSocketConnection sock, 
1399                                  SilcPacketContext *packet)
1400 {
1401   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1402   SilcBuffer buffer = packet->buffer;
1403   SilcChannelPayload payload = NULL;
1404   SilcChannelID *id = NULL;
1405   SilcChannelEntry channel;
1406   SilcIDCacheEntry id_cache = NULL;
1407
1408   /* Sanity checks */
1409   if (packet->dst_id_type != SILC_ID_CHANNEL)
1410     goto out;
1411
1412   id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1413
1414   /* Find the channel entry from channels on this connection */
1415   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1416                                    SILC_ID_CHANNEL, &id_cache))
1417     goto out;
1418
1419   channel = (SilcChannelEntry)id_cache->context;
1420
1421   /* Decrypt the channel message payload. Push the IV out of the way,
1422      since it is not encrypted (after pushing buffer->tail has the IV). */
1423   silc_buffer_push_tail(buffer, 16);
1424   channel->channel_key->cipher->decrypt(channel->channel_key->context,
1425                                         buffer->data, buffer->data,
1426                                         buffer->len, buffer->tail);
1427   silc_buffer_pull_tail(buffer, 16);
1428
1429   /* Parse the channel message payload */
1430   payload = silc_channel_parse_payload(buffer);
1431   if (!payload)
1432     goto out;
1433
1434   /* Pass the message to application */
1435   if (packet->src_id_type == SILC_ID_CLIENT) {
1436     client->ops->channel_message(client, conn, 
1437                                  silc_channel_get_nickname(payload, NULL),
1438                                  channel->channel_name,
1439                                  silc_channel_get_data(payload, NULL));
1440   } else {
1441     /* Message from server */
1442     /* XXX maybe this should be passed to app... */
1443     client->ops->say(client, conn, "%s", silc_channel_get_data(payload, NULL));
1444   }
1445
1446  out:
1447   if (id)
1448     silc_free(id);
1449   if (payload)
1450     silc_channel_free_payload(payload);
1451 }
1452
1453 /* Private message received. This processes the private message and
1454    finally displays it on the screen. */
1455
1456 void silc_client_private_message(SilcClient client, 
1457                                  SilcSocketConnection sock, 
1458                                  SilcPacketContext *packet)
1459 {
1460   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1461   SilcBuffer buffer = packet->buffer;
1462   unsigned short nick_len;
1463   unsigned char *nickname, *message;
1464
1465   /* Get nickname */
1466   silc_buffer_unformat(buffer, 
1467                        SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
1468                        SILC_STR_END);
1469   silc_buffer_pull(buffer, 2 + nick_len);
1470      
1471   message = silc_calloc(buffer->len + 1, sizeof(char));
1472   memcpy(message, buffer->data, buffer->len);
1473
1474   /* Pass the private message to application */
1475   client->ops->private_message(client, conn, nickname, message);
1476
1477   /* See if we are away (gone). If we are away we will reply to the
1478      sender with the set away message. */
1479   if (conn->away && conn->away->away) {
1480     SilcClientID *remote_id;
1481     SilcClientEntry remote_client;
1482     SilcIDCacheEntry id_cache;
1483
1484     if (packet->src_id_type != SILC_ID_CLIENT)
1485       goto out;
1486
1487     remote_id = silc_id_str2id(packet->src_id, SILC_ID_CLIENT);
1488     if (!remote_id)
1489       goto out;
1490
1491     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
1492       goto out;
1493
1494     /* Check whether we know this client already */
1495     if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
1496                                      SILC_ID_CLIENT, &id_cache))
1497       {
1498         /* Allocate client entry */
1499         remote_client = silc_calloc(1, sizeof(*remote_client));
1500         remote_client->id = remote_id;
1501         remote_client->nickname = strdup(nickname);
1502
1503         /* Save the client to cache */
1504         silc_idcache_add(conn->client_cache, remote_client->nickname,
1505                          SILC_ID_CLIENT, remote_client->id, remote_client, 
1506                          TRUE);
1507       } else {
1508         silc_free(remote_id);
1509         remote_client = (SilcClientEntry)id_cache->context;
1510       }
1511
1512     /* Send the away message */
1513     silc_client_packet_send_private_message(client, sock, remote_client,
1514                                             conn->away->away,
1515                                             strlen(conn->away->away), TRUE);
1516   }
1517
1518  out:
1519   memset(message, 0, buffer->len);
1520   silc_free(message);
1521   silc_free(nickname);
1522 }