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