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   if (ctx->packet)
461     silc_packet_context_free(ctx->packet);
462   silc_free(ctx);
463 }
464
465 /* Start of the connection to the remote server. This is called after
466    succesful TCP/IP connection has been established to the remote host. */
467
468 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
469 {
470   SilcClientInternalConnectContext *ctx =
471     (SilcClientInternalConnectContext *)context;
472   SilcClient client = ctx->client;
473   SilcClientConnection conn = ctx->conn;
474   int opt, opt_len = sizeof(opt);
475
476   SILC_LOG_DEBUG(("Start"));
477
478   /* Check the socket status as it might be in error */
479   silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
480   if (opt != 0) {
481     if (ctx->tries < 2) {
482       /* Connection failed but lets try again */
483       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
484                                  "Could not connect to server %s: %s",
485                                  ctx->host, strerror(opt));
486       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
487                                  "Connecting to port %d of server %s resumed", 
488                                  ctx->port, ctx->host);
489
490       /* Unregister old connection try */
491       silc_schedule_unset_listen_fd(client->schedule, fd);
492       silc_net_close_connection(fd);
493       silc_schedule_task_del(client->schedule, ctx->task);
494
495       /* Try again */
496       silc_client_connect_to_server_internal(ctx);
497       ctx->tries++;
498     } else {
499       /* Connection failed and we won't try anymore */
500       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
501                                  "Could not connect to server %s: %s",
502                                  ctx->host, strerror(opt));
503       silc_schedule_unset_listen_fd(client->schedule, fd);
504       silc_net_close_connection(fd);
505       silc_schedule_task_del(client->schedule, ctx->task);
506       silc_free(ctx);
507
508       /* Notify application of failure */
509       client->internal->ops->connect(client, conn, FALSE);
510       silc_client_del_connection(client, conn);
511     }
512     return;
513   }
514
515   silc_schedule_unset_listen_fd(client->schedule, fd);
516   silc_schedule_task_del(client->schedule, ctx->task);
517   silc_free(ctx);
518
519   silc_client_start_key_exchange(client, conn, fd);
520 }
521
522 /* Second part of the connecting to the server. This executed 
523    authentication protocol. */
524
525 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
526 {
527   SilcProtocol protocol = (SilcProtocol)context;
528   SilcClientKEInternalContext *ctx = 
529     (SilcClientKEInternalContext *)protocol->context;
530   SilcClient client = (SilcClient)ctx->client;
531   SilcSocketConnection sock = NULL;
532   SilcClientConnAuthInternalContext *proto_ctx;
533
534   SILC_LOG_DEBUG(("Start"));
535
536   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
537       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
538     /* Error occured during protocol */
539     SILC_LOG_DEBUG(("Error during KE protocol"));
540     silc_protocol_free(protocol);
541     silc_ske_free_key_material(ctx->keymat);
542     if (ctx->ske)
543       silc_ske_free(ctx->ske);
544     if (ctx->dest_id)
545       silc_free(ctx->dest_id);
546     ctx->sock->protocol = NULL;
547     silc_socket_free(ctx->sock);
548
549     /* Notify application of failure */
550     silc_schedule_task_add(client->schedule, ctx->sock->sock,
551                            silc_client_connect_failure, ctx,
552                            0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
553     return;
554   }
555
556   /* We now have the key material as the result of the key exchange
557      protocol. Take the key material into use. Free the raw key material
558      as soon as we've set them into use. */
559   silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
560                                    ctx->ske->prop->cipher,
561                                    ctx->ske->prop->pkcs,
562                                    ctx->ske->prop->hash,
563                                    ctx->ske->prop->hmac,
564                                    ctx->ske->prop->group,
565                                    ctx->responder);
566   silc_ske_free_key_material(ctx->keymat);
567
568   /* Allocate internal context for the authentication protocol. This
569      is sent as context for the protocol. */
570   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
571   proto_ctx->client = (void *)client;
572   proto_ctx->sock = sock = ctx->sock;
573   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
574   proto_ctx->dest_id_type = ctx->dest_id_type;
575   proto_ctx->dest_id = ctx->dest_id;
576
577   /* Free old protocol as it is finished now */
578   silc_protocol_free(protocol);
579   if (ctx->packet)
580     silc_packet_context_free(ctx->packet);
581   silc_free(ctx);
582   sock->protocol = NULL;
583
584   /* Resolve the authentication method to be used in this connection. The
585      completion callback is called after the application has resolved
586      the authentication method. */
587   client->internal->ops->get_auth_method(client, sock->user_data, 
588                                          sock->hostname,
589                                          sock->port, 
590                                          silc_client_resolve_auth_method,
591                                          proto_ctx);
592 }
593
594 /* Authentication method resolving callback. Application calls this function
595    after we've called the client->internal->ops->get_auth_method 
596    client operation to resolve the authentication method. We will continue
597    the executiong of the protocol in this function. */
598
599 void silc_client_resolve_auth_method(bool success,
600                                      SilcProtocolAuthMeth auth_meth,
601                                      const unsigned char *auth_data,
602                                      uint32 auth_data_len, void *context)
603 {
604   SilcClientConnAuthInternalContext *proto_ctx =
605     (SilcClientConnAuthInternalContext *)context;
606   SilcClient client = (SilcClient)proto_ctx->client;
607
608   if (!success)
609     auth_meth = SILC_AUTH_NONE;
610
611   proto_ctx->auth_meth = auth_meth;
612
613   if (auth_data && auth_data_len) {
614     proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
615     proto_ctx->auth_data_len = auth_data_len;
616   }
617
618   /* Allocate the authenteication protocol and execute it. */
619   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
620                       &proto_ctx->sock->protocol, (void *)proto_ctx, 
621                       silc_client_connect_to_server_final);
622
623   /* Execute the protocol */
624   silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
625 }
626
627 /* Finalizes the connection to the remote SILC server. This is called
628    after authentication protocol has been completed. This send our
629    user information to the server to receive our client ID from
630    server. */
631
632 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
633 {
634   SilcProtocol protocol = (SilcProtocol)context;
635   SilcClientConnAuthInternalContext *ctx = 
636     (SilcClientConnAuthInternalContext *)protocol->context;
637   SilcClient client = (SilcClient)ctx->client;
638   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
639   SilcBuffer packet;
640
641   SILC_LOG_DEBUG(("Start"));
642
643   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
644       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
645     /* Error occured during protocol */
646     SILC_LOG_DEBUG(("Error during authentication protocol"));
647     silc_protocol_free(protocol);
648     if (ctx->auth_data)
649       silc_free(ctx->auth_data);
650     if (ctx->ske)
651       silc_ske_free(ctx->ske);
652     if (ctx->dest_id)
653       silc_free(ctx->dest_id);
654     conn->sock->protocol = NULL;
655     silc_socket_free(ctx->sock);
656
657     /* Notify application of failure */
658     silc_schedule_task_add(client->schedule, ctx->sock->sock,
659                            silc_client_connect_failure, ctx,
660                            0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
661     return;
662   }
663
664   /* Send NEW_CLIENT packet to the server. We will become registered
665      to the SILC network after sending this packet and we will receive
666      client ID from the server. */
667   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
668                              strlen(client->realname));
669   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
670   silc_buffer_format(packet,
671                      SILC_STR_UI_SHORT(strlen(client->username)),
672                      SILC_STR_UI_XNSTRING(client->username,
673                                           strlen(client->username)),
674                      SILC_STR_UI_SHORT(strlen(client->realname)),
675                      SILC_STR_UI_XNSTRING(client->realname,
676                                           strlen(client->realname)),
677                      SILC_STR_END);
678
679   /* Send the packet */
680   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
681                           NULL, 0, NULL, NULL, 
682                           packet->data, packet->len, TRUE);
683   silc_buffer_free(packet);
684
685   /* Save remote ID. */
686   conn->remote_id = ctx->dest_id;
687   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
688   conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
689
690   /* Register re-key timeout */
691   conn->rekey->timeout = client->internal->params->rekey_secs;
692   conn->rekey->context = (void *)client;
693   silc_schedule_task_add(client->schedule, conn->sock->sock, 
694                          silc_client_rekey_callback,
695                          (void *)conn->sock, conn->rekey->timeout, 0,
696                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
697
698   silc_protocol_free(protocol);
699   if (ctx->auth_data)
700     silc_free(ctx->auth_data);
701   if (ctx->ske)
702     silc_ske_free(ctx->ske);
703   silc_socket_free(ctx->sock);
704   silc_free(ctx);
705   conn->sock->protocol = NULL;
706 }
707
708 /* Internal routine that sends packet or marks packet to be sent. This
709    is used directly only in special cases. Normal cases should use
710    silc_server_packet_send. Returns < 0 on error. */
711
712 int silc_client_packet_send_real(SilcClient client,
713                                  SilcSocketConnection sock,
714                                  bool force_send)
715 {
716   int ret;
717
718   /* If rekey protocol is active we must assure that all packets are
719      sent through packet queue. */
720   if (SILC_CLIENT_IS_REKEY(sock))
721     force_send = FALSE;
722
723   /* If outbound data is already pending do not force send */
724   if (SILC_IS_OUTBUF_PENDING(sock))
725     force_send = FALSE;
726
727   /* Send the packet */
728   ret = silc_packet_send(sock, force_send);
729   if (ret != -2)
730     return ret;
731
732   /* Mark that there is some outgoing data available for this connection. 
733      This call sets the connection both for input and output (the input
734      is set always and this call keeps the input setting, actually). 
735      Actual data sending is performed by silc_client_packet_process. */
736   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
737
738   /* Mark to socket that data is pending in outgoing buffer. This flag
739      is needed if new data is added to the buffer before the earlier
740      put data is sent to the network. */
741   SILC_SET_OUTBUF_PENDING(sock);
742
743   return 0;
744 }
745
746 /* Packet processing callback. This is used to send and receive packets
747    from network. This is generic task. */
748
749 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
750 {
751   SilcClient client = (SilcClient)context;
752   SilcSocketConnection sock = NULL;
753   SilcClientConnection conn;
754   int ret;
755
756   SILC_LOG_DEBUG(("Processing packet"));
757
758   SILC_CLIENT_GET_SOCK(client, fd, sock);
759   if (sock == NULL)
760     return;
761
762   conn = (SilcClientConnection)sock->user_data;
763
764   /* Packet sending */
765   if (type == SILC_TASK_WRITE) {
766     /* Do not send data to disconnected connection */
767     if (SILC_IS_DISCONNECTED(sock))
768       return;
769
770     if (sock->outbuf->data - sock->outbuf->head)
771       silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
772
773     ret = silc_packet_send(sock, TRUE);
774
775     /* If returned -2 could not write to connection now, will do
776        it later. */
777     if (ret == -2)
778       return;
779
780     /* Error */
781     if (ret == -1)
782       return;
783     
784     /* The packet has been sent and now it is time to set the connection
785        back to only for input. When there is again some outgoing data 
786        available for this connection it will be set for output as well. 
787        This call clears the output setting and sets it only for input. */
788     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
789     SILC_UNSET_OUTBUF_PENDING(sock);
790
791     silc_buffer_clear(sock->outbuf);
792     return;
793   }
794
795   /* Packet receiving */
796   if (type == SILC_TASK_READ) {
797     /* Read data from network */
798     ret = silc_packet_receive(sock);
799     if (ret < 0)
800       return;
801     
802     /* EOF */
803     if (ret == 0) {
804       SILC_LOG_DEBUG(("Read EOF"));
805
806       /* If connection is disconnecting already we will finally
807          close the connection */
808       if (SILC_IS_DISCONNECTING(sock)) {
809         if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
810           client->internal->ops->disconnect(client, conn);
811         silc_client_close_connection(client, sock, conn);
812         return;
813       }
814       
815       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
816       if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
817         client->internal->ops->disconnect(client, conn);
818       silc_client_close_connection(client, sock, conn);
819       return;
820     }
821
822     /* Process the packet. This will call the parser that will then
823        decrypt and parse the packet. */
824     if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
825       silc_packet_receive_process(sock, FALSE, conn->receive_key, 
826                                   conn->hmac_receive, conn->psn_receive,
827                                   silc_client_packet_parse, client);
828     else
829       silc_packet_receive_process(sock, FALSE, NULL, NULL, 0, 
830                                   silc_client_packet_parse, client);
831   }
832 }
833
834 /* Parser callback called by silc_packet_receive_process. Thie merely
835    registers timeout that will handle the actual parsing when appropriate. */
836
837 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
838                                      void *context)
839 {
840   SilcClient client = (SilcClient)context;
841   SilcSocketConnection sock = parser_context->sock;
842   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
843   SilcPacketContext *packet = parser_context->packet;
844   SilcPacketType ret;
845
846   if (conn && conn->hmac_receive && conn->sock == sock)
847     conn->psn_receive = parser_context->packet->sequence + 1;
848
849   /* Parse the packet immediately */
850   if (parser_context->normal)
851     ret = silc_packet_parse(packet, conn->receive_key);
852   else
853     ret = silc_packet_parse_special(packet, conn->receive_key);
854
855   if (ret == SILC_PACKET_NONE) {
856     silc_packet_context_free(packet);
857     silc_free(parser_context);
858     return FALSE;
859   }
860   
861   /* If protocol for this connection is key exchange or rekey then we'll
862      process all packets synchronously, since there might be packets in
863      queue that we are not able to decrypt without first processing the
864      packets before them. */
865   if ((ret == SILC_PACKET_REKEY || ret == SILC_PACKET_REKEY_DONE) ||
866       (sock->protocol && sock->protocol->protocol && 
867        (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
868         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY))) {
869
870     /* Parse the incoming packet type */
871     silc_client_packet_parse_type(client, sock, packet);
872     silc_packet_context_free(packet);
873     silc_free(parser_context);
874
875     /* Reprocess the buffer since we'll return FALSE. This is because
876        the `conn->receive_key' might have become valid by processing
877        the previous packet */
878     if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
879       silc_packet_receive_process(sock, FALSE, conn->receive_key, 
880                                   conn->hmac_receive, conn->psn_receive,
881                                   silc_client_packet_parse, client);
882     else
883       silc_packet_receive_process(sock, FALSE, NULL, NULL, 0, 
884                                   silc_client_packet_parse, client);
885     
886     return FALSE;
887   }
888
889   /* Parse the incoming packet type */
890   silc_client_packet_parse_type(client, sock, packet);
891   silc_packet_context_free(packet);
892   silc_free(parser_context);
893   return TRUE;
894 }
895
896 /* Parses the packet type and calls what ever routines the packet type
897    requires. This is done for all incoming packets. */
898
899 void silc_client_packet_parse_type(SilcClient client, 
900                                    SilcSocketConnection sock,
901                                    SilcPacketContext *packet)
902 {
903   SilcBuffer buffer = packet->buffer;
904   SilcPacketType type = packet->type;
905
906   SILC_LOG_DEBUG(("Parsing packet type %d", type));
907
908   /* Parse the packet type */
909   switch(type) {
910   case SILC_PACKET_DISCONNECT:
911     silc_client_disconnected_by_server(client, sock, buffer);
912     break;
913   case SILC_PACKET_SUCCESS:
914     /*
915      * Success received for something. For now we can have only
916      * one protocol for connection executing at once hence this
917      * success message is for whatever protocol is executing currently.
918      */
919     if (sock->protocol)
920       silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
921     break;
922   case SILC_PACKET_FAILURE:
923     /*
924      * Failure received for some protocol. Set the protocol state to 
925      * error and call the protocol callback. This fill cause error on
926      * protocol and it will call the final callback.
927      */
928     silc_client_process_failure(client, sock, packet);
929     break;
930   case SILC_PACKET_REJECT:
931     break;
932
933   case SILC_PACKET_NOTIFY:
934     /*
935      * Received notify message 
936      */
937     silc_client_notify_by_server(client, sock, packet);
938     break;
939
940   case SILC_PACKET_ERROR:
941     /*
942      * Received error message
943      */
944     silc_client_error_by_server(client, sock, buffer);
945     break;
946
947   case SILC_PACKET_CHANNEL_MESSAGE:
948     /*
949      * Received message to (from, actually) a channel
950      */
951     silc_client_channel_message(client, sock, packet);
952     break;
953   case SILC_PACKET_CHANNEL_KEY:
954     /*
955      * Received key for a channel. By receiving this key the client will be
956      * able to talk to the channel it has just joined. This can also be
957      * a new key for existing channel as keys expire peridiocally.
958      */
959     silc_client_receive_channel_key(client, sock, buffer);
960     break;
961
962   case SILC_PACKET_PRIVATE_MESSAGE:
963     /*
964      * Received private message
965      */
966     silc_client_private_message(client, sock, packet);
967     break;
968   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
969     /*
970      * Received private message key
971      */
972     break;
973
974   case SILC_PACKET_COMMAND_REPLY:
975     /*
976      * Recived reply for a command
977      */
978     silc_client_command_reply_process(client, sock, packet);
979     break;
980
981   case SILC_PACKET_KEY_EXCHANGE:
982     if (sock->protocol && sock->protocol->protocol && 
983         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
984       SilcClientKEInternalContext *proto_ctx = 
985         (SilcClientKEInternalContext *)sock->protocol->context;
986
987       proto_ctx->packet = silc_packet_context_dup(packet);
988       proto_ctx->dest_id_type = packet->src_id_type;
989       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
990                                           packet->src_id_type);
991       if (!proto_ctx->dest_id)
992         break;
993
994       /* Let the protocol handle the packet */
995       silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
996     } else {
997       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
998                       "protocol active, packet dropped."));
999     }
1000     break;
1001
1002   case SILC_PACKET_KEY_EXCHANGE_1:
1003     if (sock->protocol && sock->protocol->protocol && 
1004         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1005          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1006
1007       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1008         SilcClientRekeyInternalContext *proto_ctx = 
1009           (SilcClientRekeyInternalContext *)sock->protocol->context;
1010         
1011         if (proto_ctx->packet)
1012           silc_packet_context_free(proto_ctx->packet);
1013         
1014         proto_ctx->packet = silc_packet_context_dup(packet);
1015
1016         /* Let the protocol handle the packet */
1017         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1018       } else {
1019         SilcClientKEInternalContext *proto_ctx = 
1020           (SilcClientKEInternalContext *)sock->protocol->context;
1021         
1022         if (proto_ctx->packet)
1023           silc_packet_context_free(proto_ctx->packet);
1024         
1025         proto_ctx->packet = silc_packet_context_dup(packet);
1026         proto_ctx->dest_id_type = packet->src_id_type;
1027         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1028                                             packet->src_id_type);
1029         if (!proto_ctx->dest_id)
1030           break;
1031         
1032         /* Let the protocol handle the packet */
1033         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1034       }
1035     } else {
1036       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1037                       "protocol active, packet dropped."));
1038     }
1039     break;
1040   case SILC_PACKET_KEY_EXCHANGE_2:
1041     if (sock->protocol && sock->protocol->protocol && 
1042         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1043          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1044
1045       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1046         SilcClientRekeyInternalContext *proto_ctx = 
1047           (SilcClientRekeyInternalContext *)sock->protocol->context;
1048         
1049         if (proto_ctx->packet)
1050           silc_packet_context_free(proto_ctx->packet);
1051         
1052         proto_ctx->packet = silc_packet_context_dup(packet);
1053
1054         /* Let the protocol handle the packet */
1055         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1056       } else {
1057         SilcClientKEInternalContext *proto_ctx = 
1058           (SilcClientKEInternalContext *)sock->protocol->context;
1059         
1060         if (proto_ctx->packet)
1061           silc_packet_context_free(proto_ctx->packet);
1062         if (proto_ctx->dest_id)
1063           silc_free(proto_ctx->dest_id);
1064         proto_ctx->packet = silc_packet_context_dup(packet);
1065         proto_ctx->dest_id_type = packet->src_id_type;
1066         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1067                                             packet->src_id_type);
1068         if (!proto_ctx->dest_id)
1069           break;
1070         
1071         /* Let the protocol handle the packet */
1072         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1073       }
1074     } else {
1075       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1076                       "protocol active, packet dropped."));
1077     }
1078     break;
1079
1080   case SILC_PACKET_NEW_ID:
1081     {
1082       /*
1083        * Received new ID from server. This packet is received at
1084        * the connection to the server.  New ID is also received when 
1085        * user changes nickname but in that case the new ID is received
1086        * as command reply and not as this packet type.
1087        */
1088       SilcIDPayload idp;
1089
1090       idp = silc_id_payload_parse(buffer->data, buffer->len);
1091       if (!idp)
1092         break;
1093       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1094         break;
1095
1096       silc_client_receive_new_id(client, sock, idp);
1097       silc_id_payload_free(idp);
1098       break;
1099     }
1100
1101   case SILC_PACKET_HEARTBEAT:
1102     /*
1103      * Received heartbeat packet
1104      */
1105     SILC_LOG_DEBUG(("Heartbeat packet"));
1106     break;
1107
1108   case SILC_PACKET_KEY_AGREEMENT:
1109     /*
1110      * Received key agreement packet
1111      */
1112     SILC_LOG_DEBUG(("Key agreement packet"));
1113     silc_client_key_agreement(client, sock, packet);
1114     break;
1115
1116   case SILC_PACKET_REKEY:
1117     SILC_LOG_DEBUG(("Re-key packet"));
1118     /* We ignore this for now */
1119     break;
1120
1121   case SILC_PACKET_REKEY_DONE:
1122     SILC_LOG_DEBUG(("Re-key done packet"));
1123
1124     if (sock->protocol && sock->protocol->protocol && 
1125         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1126
1127       SilcClientRekeyInternalContext *proto_ctx = 
1128         (SilcClientRekeyInternalContext *)sock->protocol->context;
1129       
1130       if (proto_ctx->packet)
1131         silc_packet_context_free(proto_ctx->packet);
1132       
1133       proto_ctx->packet = silc_packet_context_dup(packet);
1134
1135       /* Let the protocol handle the packet */
1136       if (proto_ctx->responder == FALSE)
1137         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1138       else
1139         /* Let the protocol handle the packet */
1140         silc_protocol_execute(sock->protocol, client->schedule, 
1141                               0, 100000);
1142     } else {
1143       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1144                       "protocol active, packet dropped."));
1145     }
1146     break;
1147
1148   case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1149     /*
1150      * Reveived reply to our connection authentication method request
1151      * packet. This is used to resolve the authentication method for the
1152      * current session from the server if the client does not know it.
1153      */
1154     silc_client_connection_auth_request(client, sock, packet);
1155     break;
1156
1157   case SILC_PACKET_FTP:
1158     /* Received file transfer packet. */
1159     silc_client_ftp(client, sock, packet);
1160     break;
1161
1162   default:
1163     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1164     break;
1165   }
1166 }
1167
1168 /* Sends packet. This doesn't actually send the packet instead it assembles
1169    it and marks it to be sent. However, if force_send is TRUE the packet
1170    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1171    will be derived from sock argument. Otherwise the valid arguments sent
1172    are used. */
1173
1174 void silc_client_packet_send(SilcClient client, 
1175                              SilcSocketConnection sock,
1176                              SilcPacketType type, 
1177                              void *dst_id,
1178                              SilcIdType dst_id_type,
1179                              SilcCipher cipher,
1180                              SilcHmac hmac,
1181                              unsigned char *data, 
1182                              uint32 data_len, 
1183                              int force_send)
1184 {
1185   SilcPacketContext packetdata;
1186   int block_len;
1187   uint32 sequence = 0;
1188
1189   if (!sock)
1190     return;
1191
1192   SILC_LOG_DEBUG(("Sending packet, type %d", type));
1193
1194   /* Get data used in the packet sending, keys and stuff */
1195   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1196     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1197       cipher = ((SilcClientConnection)sock->user_data)->send_key;
1198
1199     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1200       hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1201
1202     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1203       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1204       dst_id_type = SILC_ID_SERVER;
1205     }
1206
1207     if (hmac)
1208       sequence = ((SilcClientConnection)sock->user_data)->psn_send++;
1209   }
1210
1211   block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1212
1213   /* Set the packet context pointers */
1214   packetdata.flags = 0;
1215   packetdata.type = type;
1216   if (sock->user_data && 
1217       ((SilcClientConnection)sock->user_data)->local_id_data) {
1218     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1219     packetdata.src_id_len = 
1220       silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1221                       SILC_ID_CLIENT);
1222   } else { 
1223     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1224     packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1225   }
1226   packetdata.src_id_type = SILC_ID_CLIENT;
1227   if (dst_id) {
1228     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1229     packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1230     packetdata.dst_id_type = dst_id_type;
1231   } else {
1232     packetdata.dst_id = NULL;
1233     packetdata.dst_id_len = 0;
1234     packetdata.dst_id_type = SILC_ID_NONE;
1235   }
1236   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
1237     packetdata.src_id_len + packetdata.dst_id_len;
1238   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
1239
1240   /* Prepare outgoing data buffer for packet sending */
1241   silc_packet_send_prepare(sock, 
1242                            SILC_PACKET_HEADER_LEN +
1243                            packetdata.src_id_len + 
1244                            packetdata.dst_id_len,
1245                            packetdata.padlen,
1246                            data_len);
1247
1248   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1249
1250   packetdata.buffer = sock->outbuf;
1251
1252   /* Put the data to the buffer */
1253   if (data && data_len)
1254     silc_buffer_put(sock->outbuf, data, data_len);
1255
1256   /* Create the outgoing packet */
1257   silc_packet_assemble(&packetdata, cipher);
1258
1259   /* Encrypt the packet */
1260   if (cipher)
1261     silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, 
1262                         sock->outbuf->len);
1263
1264   SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, sock->outbuf->len),
1265                    sock->outbuf->data, sock->outbuf->len);
1266
1267   /* Now actually send the packet */
1268   silc_client_packet_send_real(client, sock, force_send);
1269 }
1270
1271 void silc_client_packet_queue_purge(SilcClient client,
1272                                     SilcSocketConnection sock)
1273 {
1274   if (sock && SILC_IS_OUTBUF_PENDING(sock) && 
1275       (SILC_IS_DISCONNECTED(sock) == FALSE)) {
1276     if (sock->outbuf->data - sock->outbuf->head)
1277       silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
1278
1279     silc_packet_send(sock, TRUE);
1280
1281     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1282     SILC_UNSET_OUTBUF_PENDING(sock);
1283     silc_buffer_clear(sock->outbuf);
1284   }
1285 }
1286
1287 /* Closes connection to remote end. Free's all allocated data except
1288    for some information such as nickname etc. that are valid at all time. 
1289    If the `sock' is NULL then the conn->sock will be used.  If `sock' is
1290    provided it will be checked whether the sock and `conn->sock' are the
1291    same (they can be different, ie. a socket can use `conn' as its
1292    connection but `conn->sock' might be actually a different connection
1293    than the `sock'). */
1294
1295 void silc_client_close_connection(SilcClient client,
1296                                   SilcSocketConnection sock,
1297                                   SilcClientConnection conn)
1298 {
1299   int del = FALSE;
1300
1301   SILC_LOG_DEBUG(("Start"));
1302
1303   if (!sock || (sock && conn->sock == sock))
1304     del = TRUE;
1305   if (!sock)
1306     sock = conn->sock;
1307
1308   /* We won't listen for this connection anymore */
1309   silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1310
1311   /* Unregister all tasks */
1312   silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1313   silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1314
1315   /* Close the actual connection */
1316   silc_net_close_connection(sock->sock);
1317
1318   /* Cancel any active protocol */
1319   if (sock->protocol) {
1320     if (sock->protocol->protocol->type == 
1321         SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1322         sock->protocol->protocol->type == 
1323         SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1324       sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1325       silc_protocol_execute_final(sock->protocol, client->schedule);
1326       /* The application will recall this function with these protocols
1327          (the ops->connect client operation). */
1328       return;
1329     } else {
1330       sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1331       silc_protocol_execute_final(sock->protocol, client->schedule);
1332       sock->protocol = NULL;
1333     }
1334   }
1335
1336   /* Free everything */
1337   if (del && sock->user_data) {
1338     /* Free all cache entries */
1339     SilcIDCacheList list;
1340     SilcIDCacheEntry entry;
1341     bool ret;
1342
1343     if (silc_idcache_get_all(conn->client_cache, &list)) {
1344       ret = silc_idcache_list_first(list, &entry);
1345       while (ret) {
1346         silc_client_del_client(client, conn, entry->context);
1347         ret = silc_idcache_list_next(list, &entry);
1348       }
1349       silc_idcache_list_free(list);
1350     }
1351
1352     if (silc_idcache_get_all(conn->channel_cache, &list)) {
1353       ret = silc_idcache_list_first(list, &entry);
1354       while (ret) {
1355         silc_client_del_channel(client, conn, entry->context);
1356         ret = silc_idcache_list_next(list, &entry);
1357       }
1358       silc_idcache_list_free(list);
1359     }
1360
1361     if (silc_idcache_get_all(conn->server_cache, &list)) {
1362       ret = silc_idcache_list_first(list, &entry);
1363       while (ret) {
1364         silc_client_del_server(client, conn, entry->context);
1365         ret = silc_idcache_list_next(list, &entry);
1366       }
1367       silc_idcache_list_free(list);
1368     }
1369
1370     /* Clear ID caches */
1371     if (conn->client_cache)
1372       silc_idcache_free(conn->client_cache);
1373     if (conn->channel_cache)
1374       silc_idcache_free(conn->channel_cache);
1375     if (conn->server_cache)
1376       silc_idcache_free(conn->server_cache);
1377
1378     /* Free data (my ID is freed in above silc_client_del_client).
1379        conn->nickname is freed when freeing the local_entry->nickname. */
1380     if (conn->remote_host)
1381       silc_free(conn->remote_host);
1382     if (conn->local_id_data)
1383       silc_free(conn->local_id_data);
1384     if (conn->send_key)
1385       silc_cipher_free(conn->send_key);
1386     if (conn->receive_key)
1387       silc_cipher_free(conn->receive_key);
1388     if (conn->hmac_send)
1389       silc_hmac_free(conn->hmac_send);
1390     if (conn->hmac_receive)
1391       silc_hmac_free(conn->hmac_receive);
1392     if (conn->pending_commands)
1393       silc_dlist_uninit(conn->pending_commands);
1394     if (conn->rekey)
1395       silc_free(conn->rekey);
1396
1397     if (conn->active_session) {
1398       sock->user_data = NULL;
1399       silc_client_ftp_session_free(conn->active_session);
1400       conn->active_session = NULL;
1401     }
1402
1403     silc_client_ftp_free_sessions(client, conn);
1404
1405     memset(conn, 0, sizeof(*conn));
1406     silc_client_del_connection(client, conn);
1407   }
1408
1409   silc_socket_free(sock);
1410 }
1411
1412 /* Called when we receive disconnection packet from server. This 
1413    closes our end properly and displays the reason of the disconnection
1414    on the screen. */
1415
1416 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1417 {
1418   SilcClient client = (SilcClient)context;
1419   SilcSocketConnection sock;
1420
1421   SILC_CLIENT_GET_SOCK(client, fd, sock);
1422   if (sock == NULL)
1423     return;
1424
1425   silc_client_close_connection(client, sock, sock->user_data);
1426 }
1427
1428 /* Called when we receive disconnection packet from server. This 
1429    closes our end properly and displays the reason of the disconnection
1430    on the screen. */
1431
1432 void silc_client_disconnected_by_server(SilcClient client,
1433                                         SilcSocketConnection sock,
1434                                         SilcBuffer message)
1435 {
1436   char *msg;
1437
1438   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1439
1440   msg = silc_memdup(message->data, message->len);
1441   client->internal->ops->say(client, sock->user_data, 
1442                              SILC_CLIENT_MESSAGE_AUDIT, msg);
1443   silc_free(msg);
1444
1445   SILC_SET_DISCONNECTED(sock);
1446
1447   /* Close connection through scheduler. */
1448   silc_schedule_task_add(client->schedule, sock->sock, 
1449                          silc_client_disconnected_by_server_later,
1450                          client, 0, 1, SILC_TASK_TIMEOUT, 
1451                          SILC_TASK_PRI_NORMAL);
1452 }
1453
1454 /* Received error message from server. Display it on the screen. 
1455    We don't take any action what so ever of the error message. */
1456
1457 void silc_client_error_by_server(SilcClient client,
1458                                  SilcSocketConnection sock,
1459                                  SilcBuffer message)
1460 {
1461   char *msg;
1462
1463   msg = silc_memdup(message->data, message->len);
1464   client->internal->ops->say(client, sock->user_data, 
1465                              SILC_CLIENT_MESSAGE_AUDIT, msg);
1466   silc_free(msg);
1467 }
1468
1469 /* Auto-nicking callback to send NICK command to server. */
1470
1471 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1472 {
1473   SilcClientConnection conn = (SilcClientConnection)context;
1474   SilcClient client = conn->client;
1475
1476   silc_client_command_send(client, conn, SILC_COMMAND_NICK, 
1477                            ++conn->cmd_ident, 1, 1, 
1478                            client->nickname, strlen(client->nickname));
1479 }
1480
1481 /* Processes the received new Client ID from server. Old Client ID is
1482    deleted from cache and new one is added. */
1483
1484 void silc_client_receive_new_id(SilcClient client,
1485                                 SilcSocketConnection sock,
1486                                 SilcIDPayload idp)
1487 {
1488   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1489   int connecting = FALSE;
1490   SilcClientID *client_id = silc_id_payload_get_id(idp);
1491   SilcBuffer sidp;
1492
1493   if (!conn->local_entry)
1494     connecting = TRUE;
1495
1496   /* Delete old ID from ID cache */
1497   if (conn->local_id) {
1498     /* Check whether they are different */
1499     if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1500       silc_free(client_id);
1501       return;
1502     }
1503
1504     silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1505     silc_free(conn->local_id);
1506   }
1507   
1508   /* Save the new ID */
1509
1510   if (conn->local_id_data)
1511     silc_free(conn->local_id_data);
1512
1513   conn->local_id = client_id;
1514   conn->local_id_data = silc_id_payload_get_data(idp);
1515   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1516
1517   if (!conn->local_entry)
1518     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1519
1520   conn->local_entry->nickname = conn->nickname;
1521   if (!conn->local_entry->username)
1522     conn->local_entry->username = strdup(client->username);
1523   if (!conn->local_entry->hostname)
1524     conn->local_entry->hostname = strdup(client->hostname);
1525   if (!conn->local_entry->server)
1526     conn->local_entry->server = strdup(conn->remote_host);
1527   conn->local_entry->id = conn->local_id;
1528   conn->local_entry->valid = TRUE;
1529   if (!conn->local_entry->channels)
1530     conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr, 
1531                                                         NULL, NULL,
1532                                                         NULL, NULL, NULL, 
1533                                                         TRUE);
1534
1535   /* Put it to the ID cache */
1536   silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id, 
1537                    (void *)conn->local_entry, 0, NULL);
1538
1539   if (connecting) {
1540     /* Send NICK command if the nickname was set by the application (and is
1541        not same as the username). Send this with little timeout. */
1542     if (client->nickname && strcmp(client->nickname, client->username))
1543       silc_schedule_task_add(client->schedule, 0,
1544                              silc_client_send_auto_nick, conn,
1545                              1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1546
1547     /* Issue INFO command to fetch the real server name and server information
1548        and other stuff. */
1549     silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1550                                  silc_client_command_reply_info_i, 0, 
1551                                  ++conn->cmd_ident);
1552     sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1553     silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1554                              conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1555     silc_buffer_free(sidp);
1556
1557     /* Notify application of successful connection. We do it here now that
1558        we've received the Client ID and are allowed to send traffic. */
1559     client->internal->ops->connect(client, conn, TRUE);
1560   }
1561 }
1562
1563 /* Removes a client entry from all channels it has joined. */
1564
1565 void silc_client_remove_from_channels(SilcClient client,
1566                                       SilcClientConnection conn,
1567                                       SilcClientEntry client_entry)
1568 {
1569   SilcHashTableList htl;
1570   SilcChannelUser chu;
1571
1572   silc_hash_table_list(client_entry->channels, &htl);
1573   while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1574     silc_hash_table_del(chu->client->channels, chu->channel);
1575     silc_hash_table_del(chu->channel->user_list, chu->client);
1576     silc_free(chu);
1577   }
1578
1579   silc_hash_table_list_reset(&htl);
1580 }
1581
1582 /* Replaces `old' client entries from all channels to `new' client entry.
1583    This can be called for example when nickname changes and old ID entry
1584    is replaced from ID cache with the new one. If the old ID entry is only
1585    updated, then this fucntion needs not to be called. */
1586
1587 void silc_client_replace_from_channels(SilcClient client, 
1588                                        SilcClientConnection conn,
1589                                        SilcClientEntry old,
1590                                        SilcClientEntry new)
1591 {
1592   SilcHashTableList htl;
1593   SilcChannelUser chu;
1594
1595   silc_hash_table_list(old->channels, &htl);
1596   while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1597     /* Replace client entry */
1598     silc_hash_table_del(chu->client->channels, chu->channel);
1599     silc_hash_table_del(chu->channel->user_list, chu->client);
1600     
1601     chu->client = new;
1602     silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1603     silc_hash_table_add(chu->client->channels, chu->channel, chu);
1604   }
1605   silc_hash_table_list_reset(&htl);
1606 }
1607
1608 /* Registers failure timeout to process the received failure packet
1609    with timeout. */
1610
1611 void silc_client_process_failure(SilcClient client,
1612                                  SilcSocketConnection sock,
1613                                  SilcPacketContext *packet)
1614 {
1615   uint32 failure = 0;
1616
1617   if (sock->protocol) {
1618     if (packet->buffer->len >= 4)
1619       SILC_GET32_MSB(failure, packet->buffer->data);
1620
1621     /* Notify application */
1622     client->internal->ops->failure(client, sock->user_data, sock->protocol,
1623                                    (void *)failure);
1624   }
1625 }
1626
1627 /* A timeout callback for the re-key. We will be the initiator of the
1628    re-key protocol. */
1629
1630 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1631 {
1632   SilcSocketConnection sock = (SilcSocketConnection)context;
1633   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1634   SilcClient client = (SilcClient)conn->rekey->context;
1635   SilcProtocol protocol;
1636   SilcClientRekeyInternalContext *proto_ctx;
1637
1638   SILC_LOG_DEBUG(("Start"));
1639
1640   /* Allocate internal protocol context. This is sent as context
1641      to the protocol. */
1642   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1643   proto_ctx->client = (void *)client;
1644   proto_ctx->sock = silc_socket_dup(sock);
1645   proto_ctx->responder = FALSE;
1646   proto_ctx->pfs = conn->rekey->pfs;
1647       
1648   /* Perform rekey protocol. Will call the final callback after the
1649      protocol is over. */
1650   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY, 
1651                       &protocol, proto_ctx, silc_client_rekey_final);
1652   sock->protocol = protocol;
1653       
1654   /* Run the protocol */
1655   silc_protocol_execute(protocol, client->schedule, 0, 0);
1656
1657   /* Re-register re-key timeout */
1658   silc_schedule_task_add(client->schedule, sock->sock, 
1659                          silc_client_rekey_callback,
1660                          context, conn->rekey->timeout, 0,
1661                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1662 }
1663
1664 /* The final callback for the REKEY protocol. This will actually take the
1665    new key material into use. */
1666
1667 SILC_TASK_CALLBACK(silc_client_rekey_final)
1668 {
1669   SilcProtocol protocol = (SilcProtocol)context;
1670   SilcClientRekeyInternalContext *ctx =
1671     (SilcClientRekeyInternalContext *)protocol->context;
1672   SilcClient client = (SilcClient)ctx->client;
1673   SilcSocketConnection sock = ctx->sock;
1674
1675   SILC_LOG_DEBUG(("Start"));
1676
1677   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1678       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1679     /* Error occured during protocol */
1680     silc_protocol_cancel(protocol, client->schedule);
1681     silc_protocol_free(protocol);
1682     sock->protocol = NULL;
1683     if (ctx->packet)
1684       silc_packet_context_free(ctx->packet);
1685     if (ctx->ske)
1686       silc_ske_free(ctx->ske);
1687     silc_socket_free(ctx->sock);
1688     silc_free(ctx);
1689     return;
1690   }
1691
1692   /* Purge the outgoing data queue to assure that all rekey packets really
1693      go to the network before we quit the protocol. */
1694   silc_client_packet_queue_purge(client, sock);
1695
1696   /* Cleanup */
1697   silc_protocol_free(protocol);
1698   sock->protocol = NULL;
1699   if (ctx->packet)
1700     silc_packet_context_free(ctx->packet);
1701   if (ctx->ske)
1702     silc_ske_free(ctx->ske);
1703   silc_socket_free(ctx->sock);
1704   silc_free(ctx);
1705 }
1706
1707 /* Processes incoming connection authentication method request packet.
1708    It is a reply to our previously sent request. The packet can be used
1709    to resolve the authentication method for the current session if the
1710    client does not know it beforehand. */
1711
1712 void silc_client_connection_auth_request(SilcClient client,
1713                                          SilcSocketConnection sock,
1714                                          SilcPacketContext *packet)
1715 {
1716   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1717   uint16 conn_type, auth_meth;
1718   int ret;
1719
1720   /* If we haven't send our request then ignore this one. */
1721   if (!conn->connauth)
1722     return;
1723
1724   /* Parse the payload */
1725   ret = silc_buffer_unformat(packet->buffer,
1726                              SILC_STR_UI_SHORT(&conn_type),
1727                              SILC_STR_UI_SHORT(&auth_meth),
1728                              SILC_STR_END);
1729   if (ret == -1)
1730     auth_meth = SILC_AUTH_NONE;
1731
1732   /* Call the request callback to notify application for received 
1733      authentication method information. */
1734   if (conn->connauth->callback)
1735     (*conn->connauth->callback)(client, conn, auth_meth,
1736                                 conn->connauth->context);
1737
1738   silc_schedule_task_del(client->schedule, conn->connauth->timeout);
1739
1740   silc_free(conn->connauth);
1741   conn->connauth = NULL;
1742 }
1743
1744 /* Timeout task callback called if the server does not reply to our 
1745    connection authentication method request in the specified time interval. */
1746
1747 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1748 {
1749   SilcClientConnection conn = (SilcClientConnection)context;
1750   SilcClient client = conn->client;
1751
1752   if (!conn->connauth)
1753     return;
1754
1755   /* Call the request callback to notify application */
1756   if (conn->connauth->callback)
1757     (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE,
1758                                 conn->connauth->context);
1759
1760   silc_free(conn->connauth);
1761   conn->connauth = NULL;
1762 }
1763
1764 /* This function can be used to request the current authentication method
1765    from the server. This may be called when connecting to the server
1766    and the client library requests the authentication data from the
1767    application. If the application does not know the current authentication
1768    method it can request it from the server using this function.
1769    The `callback' with `context' will be called after the server has
1770    replied back with the current authentication method. */
1771
1772 void 
1773 silc_client_request_authentication_method(SilcClient client,
1774                                           SilcClientConnection conn,
1775                                           SilcConnectionAuthRequest callback,
1776                                           void *context)
1777 {
1778   SilcClientConnAuthRequest connauth;
1779   SilcBuffer packet;
1780
1781   connauth = silc_calloc(1, sizeof(*connauth));
1782   connauth->callback = callback;
1783   connauth->context = context;
1784
1785   if (conn->connauth)
1786     silc_free(conn->connauth);
1787
1788   conn->connauth = connauth;
1789
1790   /* Assemble the request packet and send it to the server */
1791   packet = silc_buffer_alloc(4);
1792   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1793   silc_buffer_format(packet,
1794                      SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
1795                      SILC_STR_UI_SHORT(SILC_AUTH_NONE),
1796                      SILC_STR_END);
1797   silc_client_packet_send(client, conn->sock, 
1798                           SILC_PACKET_CONNECTION_AUTH_REQUEST,
1799                           NULL, 0, NULL, NULL, 
1800                           packet->data, packet->len, FALSE);
1801   silc_buffer_free(packet);
1802
1803   /* Register a timeout in case server does not reply anything back. */
1804   connauth->timeout =
1805     silc_schedule_task_add(client->schedule, conn->sock->sock, 
1806                            silc_client_request_authentication_method_timeout,
1807                            conn, 
1808                            client->internal->params->connauth_request_secs, 0,
1809                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1810 }