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