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