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