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