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