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