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