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