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