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