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