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