5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
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.
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.
21 #include "silcincludes.h"
22 #include "silcclient.h"
23 #include "client_internal.h"
25 /* Static task callback prototypes */
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
28 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
29 SILC_TASK_CALLBACK(silc_client_rekey_callback);
30 SILC_TASK_CALLBACK(silc_client_rekey_final);
32 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
34 static void silc_client_packet_parse_type(SilcClient client,
35 SilcSocketConnection sock,
36 SilcPacketContext *packet);
37 void silc_client_resolve_auth_method(bool success,
38 SilcProtocolAuthMeth auth_meth,
39 const unsigned char *auth_data,
40 SilcUInt32 auth_data_len, void *context);
42 /* Allocates new client object. This has to be done before client may
43 work. After calling this one must call silc_client_init to initialize
44 the client. The `application' is application specific user data pointer
45 and caller must free it. */
47 SilcClient silc_client_alloc(SilcClientOperations *ops,
48 SilcClientParams *params,
50 const char *version_string)
52 SilcClient new_client;
54 new_client = silc_calloc(1, sizeof(*new_client));
55 new_client->application = application;
57 new_client->internal = silc_calloc(1, sizeof(*new_client->internal));
58 new_client->internal->ops = ops;
59 new_client->internal->params =
60 silc_calloc(1, sizeof(*new_client->internal->params));
62 version_string = silc_version_string;
63 new_client->internal->silc_client_version = strdup(version_string);
66 memcpy(new_client->internal->params, params, sizeof(*params));
68 if (!new_client->internal->params->task_max)
69 new_client->internal->params->task_max = 200;
71 if (!new_client->internal->params->rekey_secs)
72 new_client->internal->params->rekey_secs = 3600;
74 if (!new_client->internal->params->connauth_request_secs)
75 new_client->internal->params->connauth_request_secs = 2;
77 new_client->internal->params->
78 nickname_format[sizeof(new_client->internal->
79 params->nickname_format) - 1] = 0;
84 /* Frees client object and its internals. */
86 void silc_client_free(SilcClient client)
90 silc_rng_free(client->rng);
92 silc_free(client->internal->params);
93 silc_free(client->internal->silc_client_version);
94 silc_free(client->internal);
99 /* Initializes the client. This makes all the necessary steps to make
100 the client ready to be run. One must call silc_client_run to run the
101 client. Returns FALSE if error occured, TRUE otherwise. */
103 int silc_client_init(SilcClient client)
105 SILC_LOG_DEBUG(("Initializing client"));
107 /* Initialize the crypto library. If application has done this already
108 this has no effect. Also, we will not be overriding something
109 application might have registered earlier. */
110 silc_cipher_register_default();
111 silc_pkcs_register_default();
112 silc_hash_register_default();
113 silc_hmac_register_default();
115 /* Initialize hash functions for client to use */
116 silc_hash_alloc("md5", &client->md5hash);
117 silc_hash_alloc("sha1", &client->sha1hash);
119 /* Initialize none cipher */
120 silc_cipher_alloc("none", &client->internal->none_cipher);
122 /* Initialize random number generator */
123 client->rng = silc_rng_alloc();
124 silc_rng_init(client->rng);
125 silc_rng_global_init(client->rng);
127 /* Register protocols */
128 silc_client_protocols_register();
130 /* Initialize the scheduler */
132 silc_schedule_init(client->internal->params->task_max ?
133 client->internal->params->task_max : 200, client);
134 if (!client->schedule)
137 /* Register commands */
138 silc_client_commands_register(client);
143 /* Stops the client. This is called to stop the client and thus to stop
146 void silc_client_stop(SilcClient client)
148 SILC_LOG_DEBUG(("Stopping client"));
150 silc_schedule_stop(client->schedule);
151 silc_schedule_uninit(client->schedule);
153 silc_client_protocols_unregister();
154 silc_client_commands_unregister(client);
156 SILC_LOG_DEBUG(("Client stopped"));
159 /* Runs the client. This starts the scheduler from the utility library.
160 When this functions returns the execution of the appliation is over. */
162 void silc_client_run(SilcClient client)
164 SILC_LOG_DEBUG(("Running client"));
166 /* Start the scheduler, the heart of the SILC client. When this returns
167 the program will be terminated. */
168 silc_schedule(client->schedule);
171 /* Runs the client and returns immeadiately. This function is used when
172 the SILC Client object indicated by the `client' is run under some
173 other scheduler, or event loop or main loop. On GUI applications,
174 for example this may be desired to use to run the client under the
175 GUI application's main loop. Typically the GUI application would
176 register an idle task that calls this function multiple times in
177 a second to quickly process the SILC specific data. */
179 void silc_client_run_one(SilcClient client)
181 /* Run the scheduler once. */
182 silc_schedule_one(client->schedule, 0);
185 static void silc_client_entry_destructor(SilcIDCache cache,
186 SilcIDCacheEntry entry)
188 silc_free(entry->name);
191 /* Allocates and adds new connection to the client. This adds the allocated
192 connection to the connection table and returns a pointer to it. A client
193 can have multiple connections to multiple servers. Every connection must
194 be added to the client using this function. User data `context' may
195 be sent as argument. This function is normally used only if the
196 application performed the connecting outside the library. The library
197 however may use this internally. */
200 silc_client_add_connection(SilcClient client,
201 SilcClientConnectionParams *params,
202 char *hostname, int port, void *context)
204 SilcClientConnection conn;
207 SILC_LOG_DEBUG(("Adding new connection to %s:%d", hostname, port));
209 conn = silc_calloc(1, sizeof(*conn));
210 conn->internal = silc_calloc(1, sizeof(*conn->internal));
212 /* Initialize ID caches */
213 conn->client = client;
214 conn->remote_host = strdup(hostname);
215 conn->remote_port = port;
216 conn->context = context;
217 conn->internal->client_cache =
218 silc_idcache_alloc(0, SILC_ID_CLIENT, silc_client_entry_destructor);
219 conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
220 conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
221 conn->internal->pending_commands = silc_dlist_init();
222 conn->internal->ftp_sessions = silc_dlist_init();
225 if (params->detach_data)
226 conn->internal->params.detach_data =
227 silc_memdup(params->detach_data,
228 params->detach_data_len);
229 conn->internal->params.detach_data_len = params->detach_data_len;
232 /* Add the connection to connections table */
233 for (i = 0; i < client->internal->conns_count; i++)
234 if (client->internal->conns && !client->internal->conns[i]) {
235 client->internal->conns[i] = conn;
239 client->internal->conns =
240 silc_realloc(client->internal->conns, sizeof(*client->internal->conns)
241 * (client->internal->conns_count + 1));
242 client->internal->conns[client->internal->conns_count] = conn;
243 client->internal->conns_count++;
248 /* Removes connection from client. Frees all memory. */
250 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
254 for (i = 0; i < client->internal->conns_count; i++)
255 if (client->internal->conns[i] == conn) {
257 silc_idcache_free(conn->internal->client_cache);
258 silc_idcache_free(conn->internal->channel_cache);
259 silc_idcache_free(conn->internal->server_cache);
260 if (conn->internal->pending_commands)
261 silc_dlist_uninit(conn->internal->pending_commands);
262 silc_free(conn->remote_host);
263 if (conn->internal->ftp_sessions)
264 silc_dlist_uninit(conn->internal->ftp_sessions);
265 silc_free(conn->internal);
268 client->internal->conns[i] = NULL;
272 /* Adds listener socket to the listener sockets table. This function is
273 used to add socket objects that are listeners to the client. This should
274 not be used to add other connection objects. */
276 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
280 if (!client->internal->sockets) {
281 client->internal->sockets =
282 silc_calloc(1, sizeof(*client->internal->sockets));
283 client->internal->sockets[0] = silc_socket_dup(sock);
284 client->internal->sockets_count = 1;
288 for (i = 0; i < client->internal->sockets_count; i++) {
289 if (client->internal->sockets[i] == NULL) {
290 client->internal->sockets[i] = silc_socket_dup(sock);
295 client->internal->sockets =
296 silc_realloc(client->internal->sockets,
297 sizeof(*client->internal->sockets) *
298 (client->internal->sockets_count + 1));
299 client->internal->sockets[client->internal->sockets_count] =
300 silc_socket_dup(sock);
301 client->internal->sockets_count++;
304 /* Deletes listener socket from the listener sockets table. */
306 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
310 if (!client->internal->sockets)
313 for (i = 0; i < client->internal->sockets_count; i++) {
314 if (client->internal->sockets[i] == sock) {
315 silc_socket_free(sock);
316 client->internal->sockets[i] = NULL;
323 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
327 /* XXX In the future we should give up this non-blocking connect all
328 together and use threads instead. */
329 /* Create connection to server asynchronously */
330 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
334 /* Register task that will receive the async connect and will
336 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
337 silc_client_connect_to_server_start,
340 SILC_TASK_PRI_NORMAL);
341 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE,
349 /* Connects to remote server. This is the main routine used to connect
350 to SILC server. Returns -1 on error and the created socket otherwise.
351 The `context' is user context that is saved into the SilcClientConnection
352 that is created after the connection is created. Note that application
353 may handle the connecting process outside the library. If this is the
354 case then this function is not used at all. When the connecting is
355 done the `connect' client operation is called. */
357 int silc_client_connect_to_server(SilcClient client,
358 SilcClientConnectionParams *params,
359 int port, char *host, void *context)
361 SilcClientInternalConnectContext *ctx;
362 SilcClientConnection conn;
365 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
368 conn = silc_client_add_connection(client, params, host, port, context);
370 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
371 "Connecting to port %d of server %s", port, host);
373 /* Allocate internal context for connection process. This is
374 needed as we are doing async connecting. */
375 ctx = silc_calloc(1, sizeof(*ctx));
376 ctx->client = client;
378 ctx->host = strdup(host);
379 ctx->port = port ? port : 706;
382 /* Do the actual connecting process */
383 sock = silc_client_connect_to_server_internal(ctx);
385 silc_client_del_connection(client, conn);
389 /* Socket hostname and IP lookup callback that is called before actually
390 starting the key exchange. The lookup is called from the function
391 silc_client_start_key_exchange. */
393 static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
396 SilcClientConnection conn = (SilcClientConnection)context;
397 SilcClient client = conn->client;
398 SilcProtocol protocol;
399 SilcClientKEInternalContext *proto_ctx;
401 SILC_LOG_DEBUG(("Start"));
403 if (conn->sock->hostname) {
404 silc_free(conn->remote_host);
405 conn->remote_host = strdup(conn->sock->hostname);
407 conn->sock->hostname = strdup(conn->remote_host);
410 conn->sock->ip = strdup(conn->sock->hostname);
411 conn->sock->port = conn->remote_port;
413 /* Allocate internal Key Exchange context. This is sent to the
414 protocol as context. */
415 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
416 proto_ctx->client = (void *)client;
417 proto_ctx->sock = silc_socket_dup(conn->sock);
418 proto_ctx->rng = client->rng;
419 proto_ctx->responder = FALSE;
420 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
421 proto_ctx->verify = silc_client_protocol_ke_verify_key;
423 /* Perform key exchange protocol. silc_client_connect_to_server_final
424 will be called after the protocol is finished. */
425 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
426 &protocol, (void *)proto_ctx,
427 silc_client_connect_to_server_second);
429 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
430 "Error: Could not start key exchange protocol");
431 silc_net_close_connection(conn->sock->sock);
432 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
435 conn->sock->protocol = protocol;
437 /* Register the connection for network input and output. This sets
438 that scheduler will listen for incoming packets for this connection
439 and sets that outgoing packets may be sent to this connection as well.
440 However, this doesn't set the scheduler for outgoing traffic, it will
441 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
442 later when outgoing data is available. */
443 context = (void *)client;
444 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(conn->sock->sock);
446 /* Execute the protocol */
447 silc_protocol_execute(protocol, client->schedule, 0, 0);
450 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
451 key material between client and server. This function can be called
452 directly if application is performing its own connecting and does not
453 use the connecting provided by this library. This function is normally
454 used only if the application performed the connecting outside the library.
455 The library however may use this internally. */
457 void silc_client_start_key_exchange(SilcClient client,
458 SilcClientConnection conn,
461 /* Allocate new socket connection object */
462 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
464 /* Sometimes when doing quick reconnects the new socket may be same as
465 the old one and there might be pending stuff for the old socket.
466 If new one is same then those pending sutff might cause problems.
467 Make sure they do not do that. */
468 silc_schedule_task_del_by_fd(client->schedule, fd);
470 conn->nickname = (client->nickname ? strdup(client->nickname) :
471 strdup(client->username));
473 /* Resolve the remote hostname and IP address for our socket connection */
474 silc_socket_host_lookup(conn->sock, FALSE, silc_client_start_key_exchange_cb,
475 conn, client->schedule);
478 /* Callback called when error has occurred during connecting (KE) to
479 the server. The `connect' client operation will be called. */
481 SILC_TASK_CALLBACK(silc_client_connect_failure)
483 SilcClientKEInternalContext *ctx =
484 (SilcClientKEInternalContext *)context;
485 SilcClient client = (SilcClient)ctx->client;
487 client->internal->ops->connected(client, ctx->sock->user_data,
488 SILC_CLIENT_CONN_ERROR);
490 silc_packet_context_free(ctx->packet);
494 /* Callback called when error has occurred during connecting (auth) to
495 the server. The `connect' client operation will be called. */
497 SILC_TASK_CALLBACK(silc_client_connect_failure_auth)
499 SilcClientConnAuthInternalContext *ctx =
500 (SilcClientConnAuthInternalContext *)context;
501 SilcClient client = (SilcClient)ctx->client;
503 client->internal->ops->connected(client, ctx->sock->user_data,
504 SILC_CLIENT_CONN_ERROR);
508 /* Start of the connection to the remote server. This is called after
509 succesful TCP/IP connection has been established to the remote host. */
511 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
513 SilcClientInternalConnectContext *ctx =
514 (SilcClientInternalConnectContext *)context;
515 SilcClient client = ctx->client;
516 SilcClientConnection conn = ctx->conn;
517 int opt, opt_len = sizeof(opt);
519 SILC_LOG_DEBUG(("Start"));
521 /* Check the socket status as it might be in error */
522 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
524 if (ctx->tries < 2) {
525 /* Connection failed but lets try again */
526 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
527 "Could not connect to server %s: %s",
528 ctx->host, strerror(opt));
529 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
530 "Connecting to port %d of server %s resumed",
531 ctx->port, ctx->host);
533 /* Unregister old connection try */
534 silc_schedule_unset_listen_fd(client->schedule, fd);
535 silc_net_close_connection(fd);
536 silc_schedule_task_del(client->schedule, ctx->task);
539 silc_client_connect_to_server_internal(ctx);
542 /* Connection failed and we won't try anymore */
543 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
544 "Could not connect to server %s: %s",
545 ctx->host, strerror(opt));
546 silc_schedule_unset_listen_fd(client->schedule, fd);
547 silc_net_close_connection(fd);
548 silc_schedule_task_del(client->schedule, ctx->task);
551 /* Notify application of failure */
552 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
553 silc_client_del_connection(client, conn);
558 silc_schedule_unset_listen_fd(client->schedule, fd);
559 silc_schedule_task_del(client->schedule, ctx->task);
562 silc_client_start_key_exchange(client, conn, fd);
565 /* Second part of the connecting to the server. This executed
566 authentication protocol. */
568 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
570 SilcProtocol protocol = (SilcProtocol)context;
571 SilcClientKEInternalContext *ctx =
572 (SilcClientKEInternalContext *)protocol->context;
573 SilcClient client = (SilcClient)ctx->client;
574 SilcSocketConnection sock = NULL;
575 SilcClientConnAuthInternalContext *proto_ctx;
577 SILC_LOG_DEBUG(("Start"));
579 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
580 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
581 /* Error occured during protocol */
582 SILC_LOG_DEBUG(("Error during KE protocol"));
583 silc_protocol_free(protocol);
584 silc_ske_free_key_material(ctx->keymat);
586 silc_ske_free(ctx->ske);
588 silc_free(ctx->dest_id);
589 ctx->sock->protocol = NULL;
590 silc_socket_free(ctx->sock);
592 /* Notify application of failure */
593 silc_schedule_task_add(client->schedule, ctx->sock->sock,
594 silc_client_connect_failure, ctx,
595 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
599 /* We now have the key material as the result of the key exchange
600 protocol. Take the key material into use. Free the raw key material
601 as soon as we've set them into use. */
602 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
603 ctx->ske->prop->cipher,
604 ctx->ske->prop->pkcs,
605 ctx->ske->prop->hash,
606 ctx->ske->prop->hmac,
607 ctx->ske->prop->group,
609 silc_ske_free_key_material(ctx->keymat);
611 /* Allocate internal context for the authentication protocol. This
612 is sent as context for the protocol. */
613 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
614 proto_ctx->client = (void *)client;
615 proto_ctx->sock = sock = ctx->sock;
616 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
617 proto_ctx->dest_id_type = ctx->dest_id_type;
618 proto_ctx->dest_id = ctx->dest_id;
620 /* Free old protocol as it is finished now */
621 silc_protocol_free(protocol);
623 silc_packet_context_free(ctx->packet);
626 sock->protocol = NULL;
628 /* Resolve the authentication method to be used in this connection. The
629 completion callback is called after the application has resolved
630 the authentication method. */
631 client->internal->ops->get_auth_method(client, sock->user_data,
634 silc_client_resolve_auth_method,
638 /* Authentication method resolving callback. Application calls this function
639 after we've called the client->internal->ops->get_auth_method
640 client operation to resolve the authentication method. We will continue
641 the executiong of the protocol in this function. */
643 void silc_client_resolve_auth_method(bool success,
644 SilcProtocolAuthMeth auth_meth,
645 const unsigned char *auth_data,
646 SilcUInt32 auth_data_len, void *context)
648 SilcClientConnAuthInternalContext *proto_ctx =
649 (SilcClientConnAuthInternalContext *)context;
650 SilcClient client = (SilcClient)proto_ctx->client;
653 auth_meth = SILC_AUTH_NONE;
655 proto_ctx->auth_meth = auth_meth;
657 if (success && auth_data && auth_data_len) {
659 /* Passphrase must be UTF-8 encoded, if it isn't encode it */
660 if (auth_meth == SILC_AUTH_PASSWORD &&
661 !silc_utf8_valid(auth_data, auth_data_len)) {
663 unsigned char *autf8 = NULL;
664 payload_len = silc_utf8_encoded_len(auth_data, auth_data_len,
666 autf8 = silc_calloc(payload_len, sizeof(*autf8));
667 auth_data_len = silc_utf8_encode(auth_data, auth_data_len,
668 SILC_STRING_ASCII, autf8, payload_len);
672 proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
673 proto_ctx->auth_data_len = auth_data_len;
676 /* Allocate the authenteication protocol and execute it. */
677 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
678 &proto_ctx->sock->protocol, (void *)proto_ctx,
679 silc_client_connect_to_server_final);
681 /* Execute the protocol */
682 silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
685 /* Finalizes the connection to the remote SILC server. This is called
686 after authentication protocol has been completed. This send our
687 user information to the server to receive our client ID from
690 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
692 SilcProtocol protocol = (SilcProtocol)context;
693 SilcClientConnAuthInternalContext *ctx =
694 (SilcClientConnAuthInternalContext *)protocol->context;
695 SilcClient client = (SilcClient)ctx->client;
696 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
699 SILC_LOG_DEBUG(("Start"));
701 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
702 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
703 /* Error occured during protocol */
704 SILC_LOG_DEBUG(("Error during authentication protocol"));
708 if (conn->internal->params.detach_data) {
709 /* Send RESUME_CLIENT packet to the server, which is used to resume
710 old detached session back. */
712 SilcClientID *old_client_id;
713 unsigned char *old_id;
714 SilcUInt16 old_id_len;
716 if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len))
719 old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT);
720 if (!old_client_id) {
725 /* Generate authentication data that server will verify */
726 auth = silc_auth_public_key_auth_generate(client->public_key,
729 conn->internal->hash,
730 old_client_id, SILC_ID_CLIENT);
732 silc_free(old_client_id);
737 packet = silc_buffer_alloc_size(2 + old_id_len + auth->len);
738 silc_buffer_format(packet,
739 SILC_STR_UI_SHORT(old_id_len),
740 SILC_STR_UI_XNSTRING(old_id, old_id_len),
741 SILC_STR_UI_XNSTRING(auth->data, auth->len),
744 /* Send the packet */
745 silc_client_packet_send(client, ctx->sock, SILC_PACKET_RESUME_CLIENT,
747 packet->data, packet->len, TRUE);
748 silc_buffer_free(packet);
749 silc_buffer_free(auth);
750 silc_free(old_client_id);
753 /* Send NEW_CLIENT packet to the server. We will become registered
754 to the SILC network after sending this packet and we will receive
755 client ID from the server. */
756 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
757 strlen(client->realname));
758 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
759 silc_buffer_format(packet,
760 SILC_STR_UI_SHORT(strlen(client->username)),
761 SILC_STR_UI_XNSTRING(client->username,
762 strlen(client->username)),
763 SILC_STR_UI_SHORT(strlen(client->realname)),
764 SILC_STR_UI_XNSTRING(client->realname,
765 strlen(client->realname)),
768 /* Send the packet */
769 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
771 packet->data, packet->len, TRUE);
772 silc_buffer_free(packet);
775 /* Save remote ID. */
776 conn->remote_id = ctx->dest_id;
777 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
778 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
780 /* Register re-key timeout */
781 conn->internal->rekey->timeout = client->internal->params->rekey_secs;
782 conn->internal->rekey->context = (void *)client;
783 silc_schedule_task_add(client->schedule, conn->sock->sock,
784 silc_client_rekey_callback,
785 (void *)conn->sock, conn->internal->rekey->timeout, 0,
786 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
788 silc_protocol_free(protocol);
789 silc_free(ctx->auth_data);
791 silc_ske_free(ctx->ske);
792 silc_socket_free(ctx->sock);
794 conn->sock->protocol = NULL;
798 silc_protocol_free(protocol);
799 silc_free(ctx->auth_data);
800 silc_free(ctx->dest_id);
802 silc_ske_free(ctx->ske);
803 conn->sock->protocol = NULL;
804 silc_socket_free(ctx->sock);
806 /* Notify application of failure */
807 silc_schedule_task_add(client->schedule, ctx->sock->sock,
808 silc_client_connect_failure_auth, ctx,
809 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
812 /* Internal routine that sends packet or marks packet to be sent. This
813 is used directly only in special cases. Normal cases should use
814 silc_server_packet_send. Returns < 0 on error. */
816 int silc_client_packet_send_real(SilcClient client,
817 SilcSocketConnection sock,
822 /* If rekey protocol is active we must assure that all packets are
823 sent through packet queue. */
824 if (SILC_CLIENT_IS_REKEY(sock))
827 /* If outbound data is already pending do not force send */
828 if (SILC_IS_OUTBUF_PENDING(sock))
831 /* Send the packet */
832 ret = silc_packet_send(sock, force_send);
836 /* Mark that there is some outgoing data available for this connection.
837 This call sets the connection both for input and output (the input
838 is set always and this call keeps the input setting, actually).
839 Actual data sending is performed by silc_client_packet_process. */
840 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
842 /* Mark to socket that data is pending in outgoing buffer. This flag
843 is needed if new data is added to the buffer before the earlier
844 put data is sent to the network. */
845 SILC_SET_OUTBUF_PENDING(sock);
850 /* Packet processing callback. This is used to send and receive packets
851 from network. This is generic task. */
853 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
855 SilcClient client = (SilcClient)context;
856 SilcSocketConnection sock = NULL;
857 SilcClientConnection conn;
860 SILC_LOG_DEBUG(("Processing packet"));
862 SILC_CLIENT_GET_SOCK(client, fd, sock);
866 conn = (SilcClientConnection)sock->user_data;
869 if (type == SILC_TASK_WRITE) {
870 /* Do not send data to disconnected connection */
871 if (SILC_IS_DISCONNECTED(sock))
874 ret = silc_packet_send(sock, TRUE);
876 /* If returned -2 could not write to connection now, will do
885 /* The packet has been sent and now it is time to set the connection
886 back to only for input. When there is again some outgoing data
887 available for this connection it will be set for output as well.
888 This call clears the output setting and sets it only for input. */
889 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
890 SILC_UNSET_OUTBUF_PENDING(sock);
892 silc_buffer_clear(sock->outbuf);
896 /* Packet receiving */
897 if (type == SILC_TASK_READ) {
898 /* Read data from network */
899 ret = silc_packet_receive(sock);
905 SILC_LOG_DEBUG(("Read EOF"));
907 /* If connection is disconnecting already we will finally
908 close the connection */
909 if (SILC_IS_DISCONNECTING(sock)) {
910 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
911 client->internal->ops->disconnected(client, conn, 0, NULL);
912 silc_client_close_connection_real(client, sock, conn);
916 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
917 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
918 client->internal->ops->disconnected(client, conn, 0, NULL);
919 silc_client_close_connection_real(client, sock, conn);
923 /* Process the packet. This will call the parser that will then
924 decrypt and parse the packet. */
925 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
926 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
927 conn->internal->hmac_receive,
928 conn->internal->psn_receive,
929 silc_client_packet_parse, client);
931 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
932 silc_client_packet_parse, client);
936 /* Parser callback called by silc_packet_receive_process. Thie merely
937 registers timeout that will handle the actual parsing when appropriate. */
939 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
942 SilcClient client = (SilcClient)context;
943 SilcSocketConnection sock = parser_context->sock;
944 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
945 SilcPacketContext *packet = parser_context->packet;
948 if (conn && conn->internal->hmac_receive && conn->sock == sock)
949 conn->internal->psn_receive = parser_context->packet->sequence + 1;
951 /* Parse the packet immediately */
952 if (parser_context->normal)
953 ret = silc_packet_parse(packet, conn->internal->receive_key);
955 ret = silc_packet_parse_special(packet, conn->internal->receive_key);
957 if (ret == SILC_PACKET_NONE) {
958 silc_packet_context_free(packet);
959 silc_free(parser_context);
963 /* If protocol for this connection is key exchange or rekey then we'll
964 process all packets synchronously, since there might be packets in
965 queue that we are not able to decrypt without first processing the
966 packets before them. */
967 if ((ret == SILC_PACKET_REKEY || ret == SILC_PACKET_REKEY_DONE) ||
968 (sock->protocol && sock->protocol->protocol &&
969 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
970 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY))) {
972 /* Parse the incoming packet type */
973 silc_client_packet_parse_type(client, sock, packet);
974 silc_packet_context_free(packet);
975 silc_free(parser_context);
977 /* Reprocess the buffer since we'll return FALSE. This is because
978 the `conn->internal->receive_key' might have become valid by processing
979 the previous packet */
980 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
981 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
982 conn->internal->hmac_receive,
983 conn->internal->psn_receive,
984 silc_client_packet_parse, client);
986 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
987 silc_client_packet_parse, client);
992 /* Parse the incoming packet type */
993 silc_client_packet_parse_type(client, sock, packet);
994 silc_packet_context_free(packet);
995 silc_free(parser_context);
999 /* Parses the packet type and calls what ever routines the packet type
1000 requires. This is done for all incoming packets. */
1002 void silc_client_packet_parse_type(SilcClient client,
1003 SilcSocketConnection sock,
1004 SilcPacketContext *packet)
1006 SilcBuffer buffer = packet->buffer;
1007 SilcPacketType type = packet->type;
1009 SILC_LOG_DEBUG(("Parsing %s packet", silc_get_packet_name(type)));
1011 /* Parse the packet type */
1014 case SILC_PACKET_DISCONNECT:
1015 silc_client_disconnected_by_server(client, sock, buffer);
1018 case SILC_PACKET_SUCCESS:
1020 * Success received for something. For now we can have only
1021 * one protocol for connection executing at once hence this
1022 * success message is for whatever protocol is executing currently.
1025 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1028 case SILC_PACKET_FAILURE:
1030 * Failure received for some protocol. Set the protocol state to
1031 * error and call the protocol callback. This fill cause error on
1032 * protocol and it will call the final callback.
1034 silc_client_process_failure(client, sock, packet);
1037 case SILC_PACKET_REJECT:
1040 case SILC_PACKET_NOTIFY:
1042 * Received notify message
1044 silc_client_notify_by_server(client, sock, packet);
1047 case SILC_PACKET_ERROR:
1049 * Received error message
1051 silc_client_error_by_server(client, sock, buffer);
1054 case SILC_PACKET_CHANNEL_MESSAGE:
1056 * Received message to (from, actually) a channel
1058 silc_client_channel_message(client, sock, packet);
1061 case SILC_PACKET_CHANNEL_KEY:
1063 * Received key for a channel. By receiving this key the client will be
1064 * able to talk to the channel it has just joined. This can also be
1065 * a new key for existing channel as keys expire peridiocally.
1067 silc_client_receive_channel_key(client, sock, buffer);
1070 case SILC_PACKET_PRIVATE_MESSAGE:
1072 * Received private message
1074 silc_client_private_message(client, sock, packet);
1077 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1079 * Received private message key
1083 case SILC_PACKET_COMMAND:
1085 * Received command packet, a special case since normally client
1086 * does not receive commands.
1088 silc_client_command_process(client, sock, packet);
1091 case SILC_PACKET_COMMAND_REPLY:
1093 * Recived reply for a command
1095 silc_client_command_reply_process(client, sock, packet);
1098 case SILC_PACKET_KEY_EXCHANGE:
1099 if (sock->protocol && sock->protocol->protocol &&
1100 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
1101 SilcClientKEInternalContext *proto_ctx =
1102 (SilcClientKEInternalContext *)sock->protocol->context;
1104 proto_ctx->packet = silc_packet_context_dup(packet);
1105 proto_ctx->dest_id_type = packet->src_id_type;
1106 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1107 packet->src_id_type);
1108 if (!proto_ctx->dest_id)
1111 /* Let the protocol handle the packet */
1112 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1114 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1115 "protocol active, packet dropped."));
1119 case SILC_PACKET_KEY_EXCHANGE_1:
1120 if (sock->protocol && sock->protocol->protocol &&
1121 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1122 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1124 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1125 SilcClientRekeyInternalContext *proto_ctx =
1126 (SilcClientRekeyInternalContext *)sock->protocol->context;
1128 if (proto_ctx->packet)
1129 silc_packet_context_free(proto_ctx->packet);
1131 proto_ctx->packet = silc_packet_context_dup(packet);
1133 /* Let the protocol handle the packet */
1134 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1136 SilcClientKEInternalContext *proto_ctx =
1137 (SilcClientKEInternalContext *)sock->protocol->context;
1139 if (proto_ctx->packet)
1140 silc_packet_context_free(proto_ctx->packet);
1142 proto_ctx->packet = silc_packet_context_dup(packet);
1143 proto_ctx->dest_id_type = packet->src_id_type;
1144 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1145 packet->src_id_type);
1146 if (!proto_ctx->dest_id)
1149 /* Let the protocol handle the packet */
1150 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1153 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1154 "protocol active, packet dropped."));
1158 case SILC_PACKET_KEY_EXCHANGE_2:
1159 if (sock->protocol && sock->protocol->protocol &&
1160 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1161 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1163 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1164 SilcClientRekeyInternalContext *proto_ctx =
1165 (SilcClientRekeyInternalContext *)sock->protocol->context;
1167 if (proto_ctx->packet)
1168 silc_packet_context_free(proto_ctx->packet);
1170 proto_ctx->packet = silc_packet_context_dup(packet);
1172 /* Let the protocol handle the packet */
1173 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1175 SilcClientKEInternalContext *proto_ctx =
1176 (SilcClientKEInternalContext *)sock->protocol->context;
1178 if (proto_ctx->packet)
1179 silc_packet_context_free(proto_ctx->packet);
1180 if (proto_ctx->dest_id)
1181 silc_free(proto_ctx->dest_id);
1182 proto_ctx->packet = silc_packet_context_dup(packet);
1183 proto_ctx->dest_id_type = packet->src_id_type;
1184 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1185 packet->src_id_type);
1186 if (!proto_ctx->dest_id)
1189 /* Let the protocol handle the packet */
1190 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1193 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1194 "protocol active, packet dropped."));
1198 case SILC_PACKET_NEW_ID:
1201 * Received new ID from server. This packet is received at
1202 * the connection to the server. New ID is also received when
1203 * user changes nickname but in that case the new ID is received
1204 * as command reply and not as this packet type.
1208 idp = silc_id_payload_parse(buffer->data, buffer->len);
1211 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1214 silc_client_receive_new_id(client, sock, idp);
1215 silc_id_payload_free(idp);
1219 case SILC_PACKET_HEARTBEAT:
1221 * Received heartbeat packet
1223 SILC_LOG_DEBUG(("Heartbeat packet"));
1226 case SILC_PACKET_KEY_AGREEMENT:
1228 * Received key agreement packet
1230 SILC_LOG_DEBUG(("Key agreement packet"));
1231 silc_client_key_agreement(client, sock, packet);
1234 case SILC_PACKET_REKEY:
1235 SILC_LOG_DEBUG(("Re-key packet"));
1236 /* We ignore this for now */
1239 case SILC_PACKET_REKEY_DONE:
1240 SILC_LOG_DEBUG(("Re-key done packet"));
1242 if (sock->protocol && sock->protocol->protocol &&
1243 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1245 SilcClientRekeyInternalContext *proto_ctx =
1246 (SilcClientRekeyInternalContext *)sock->protocol->context;
1248 if (proto_ctx->packet)
1249 silc_packet_context_free(proto_ctx->packet);
1251 proto_ctx->packet = silc_packet_context_dup(packet);
1253 /* Let the protocol handle the packet */
1254 if (proto_ctx->responder == FALSE)
1255 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1257 /* Let the protocol handle the packet */
1258 silc_protocol_execute(sock->protocol, client->schedule,
1261 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1262 "protocol active, packet dropped."));
1266 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1268 * Reveived reply to our connection authentication method request
1269 * packet. This is used to resolve the authentication method for the
1270 * current session from the server if the client does not know it.
1272 silc_client_connection_auth_request(client, sock, packet);
1275 case SILC_PACKET_FTP:
1276 /* Received file transfer packet. */
1277 silc_client_ftp(client, sock, packet);
1281 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1286 /* Sends packet. This doesn't actually send the packet instead it assembles
1287 it and marks it to be sent. However, if force_send is TRUE the packet
1288 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1289 will be derived from sock argument. Otherwise the valid arguments sent
1292 void silc_client_packet_send(SilcClient client,
1293 SilcSocketConnection sock,
1294 SilcPacketType type,
1296 SilcIdType dst_id_type,
1299 unsigned char *data,
1300 SilcUInt32 data_len,
1303 SilcPacketContext packetdata;
1304 const SilcBufferStruct packet;
1306 SilcUInt32 sequence = 0;
1311 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1313 /* Get data used in the packet sending, keys and stuff */
1314 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1315 if (!cipher && ((SilcClientConnection)sock->user_data)->internal->send_key)
1316 cipher = ((SilcClientConnection)sock->user_data)->internal->send_key;
1318 if (!hmac && ((SilcClientConnection)sock->user_data)->internal->hmac_send)
1319 hmac = ((SilcClientConnection)sock->user_data)->internal->hmac_send;
1321 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1322 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1323 dst_id_type = SILC_ID_SERVER;
1327 sequence = ((SilcClientConnection)sock->user_data)->internal->psn_send++;
1330 block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1332 /* Set the packet context pointers */
1333 packetdata.flags = 0;
1334 packetdata.type = type;
1335 if (sock->user_data &&
1336 ((SilcClientConnection)sock->user_data)->local_id_data) {
1337 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1338 packetdata.src_id_len =
1339 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1342 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1343 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1345 packetdata.src_id_type = SILC_ID_CLIENT;
1347 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1348 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1349 packetdata.dst_id_type = dst_id_type;
1351 packetdata.dst_id = NULL;
1352 packetdata.dst_id_len = 0;
1353 packetdata.dst_id_type = SILC_ID_NONE;
1355 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1356 packetdata.src_id_len +
1357 packetdata.dst_id_len));
1358 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1359 packetdata.src_id_len + packetdata.dst_id_len;
1360 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
1362 /* Create the outgoing packet */
1363 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
1364 data, data_len, (const SilcBuffer)&packet)) {
1365 SILC_LOG_ERROR(("Error assembling packet"));
1369 /* Encrypt the packet */
1371 silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet,
1374 SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
1375 packet.data, packet.len);
1377 /* Now actually send the packet */
1378 silc_client_packet_send_real(client, sock, force_send);
1381 void silc_client_packet_queue_purge(SilcClient client,
1382 SilcSocketConnection sock)
1384 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1385 (SILC_IS_DISCONNECTED(sock) == FALSE)) {
1386 silc_packet_send(sock, TRUE);
1387 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1388 SILC_UNSET_OUTBUF_PENDING(sock);
1389 silc_buffer_clear(sock->outbuf);
1393 /* Closes connection to remote end. Free's all allocated data except
1394 for some information such as nickname etc. that are valid at all time.
1395 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1396 provided it will be checked whether the sock and `conn->sock' are the
1397 same (they can be different, ie. a socket can use `conn' as its
1398 connection but `conn->sock' might be actually a different connection
1399 than the `sock'). */
1401 void silc_client_close_connection_real(SilcClient client,
1402 SilcSocketConnection sock,
1403 SilcClientConnection conn)
1407 SILC_LOG_DEBUG(("Start"));
1412 if (!sock || (sock && conn->sock == sock))
1417 /* We won't listen for this connection anymore */
1418 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1420 /* Unregister all tasks */
1421 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1423 /* Close the actual connection */
1424 silc_net_close_connection(sock->sock);
1426 /* Cancel any active protocol */
1427 if (sock->protocol) {
1428 if (sock->protocol->protocol->type ==
1429 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1430 sock->protocol->protocol->type ==
1431 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1432 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1433 silc_protocol_execute_final(sock->protocol, client->schedule);
1434 /* The application will recall this function with these protocols
1435 (the ops->connected client operation). */
1438 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1439 silc_protocol_execute_final(sock->protocol, client->schedule);
1440 sock->protocol = NULL;
1444 /* Free everything */
1445 if (del && sock->user_data) {
1446 /* Free all cache entries */
1447 SilcIDCacheList list;
1448 SilcIDCacheEntry entry;
1449 SilcClientCommandPending *r;
1452 if (silc_idcache_get_all(conn->internal->client_cache, &list)) {
1453 ret = silc_idcache_list_first(list, &entry);
1455 silc_client_del_client(client, conn, entry->context);
1456 ret = silc_idcache_list_next(list, &entry);
1458 silc_idcache_list_free(list);
1461 if (silc_idcache_get_all(conn->internal->channel_cache, &list)) {
1462 ret = silc_idcache_list_first(list, &entry);
1464 silc_client_del_channel(client, conn, entry->context);
1465 ret = silc_idcache_list_next(list, &entry);
1467 silc_idcache_list_free(list);
1470 if (silc_idcache_get_all(conn->internal->server_cache, &list)) {
1471 ret = silc_idcache_list_first(list, &entry);
1473 silc_client_del_server(client, conn, entry->context);
1474 ret = silc_idcache_list_next(list, &entry);
1476 silc_idcache_list_free(list);
1479 /* Clear ID caches */
1480 if (conn->internal->client_cache)
1481 silc_idcache_free(conn->internal->client_cache);
1482 if (conn->internal->channel_cache)
1483 silc_idcache_free(conn->internal->channel_cache);
1484 if (conn->internal->server_cache)
1485 silc_idcache_free(conn->internal->server_cache);
1487 /* Free data (my ID is freed in above silc_client_del_client).
1488 conn->nickname is freed when freeing the local_entry->nickname. */
1489 if (conn->remote_host)
1490 silc_free(conn->remote_host);
1491 if (conn->local_id_data)
1492 silc_free(conn->local_id_data);
1493 if (conn->internal->send_key)
1494 silc_cipher_free(conn->internal->send_key);
1495 if (conn->internal->receive_key)
1496 silc_cipher_free(conn->internal->receive_key);
1497 if (conn->internal->hmac_send)
1498 silc_hmac_free(conn->internal->hmac_send);
1499 if (conn->internal->hmac_receive)
1500 silc_hmac_free(conn->internal->hmac_receive);
1501 if (conn->internal->rekey)
1502 silc_free(conn->internal->rekey);
1504 if (conn->internal->active_session) {
1505 sock->user_data = NULL;
1506 silc_client_ftp_session_free(conn->internal->active_session);
1507 conn->internal->active_session = NULL;
1510 silc_client_ftp_free_sessions(client, conn);
1512 silc_dlist_start(conn->internal->pending_commands);
1513 while ((r = silc_dlist_get(conn->internal->pending_commands))
1515 silc_dlist_del(conn->internal->pending_commands, r);
1516 if (conn->internal->pending_commands)
1517 silc_dlist_uninit(conn->internal->pending_commands);
1519 memset(conn, 0, sizeof(*conn));
1520 silc_client_del_connection(client, conn);
1523 silc_socket_free(sock);
1526 /* Closes the connection to the remote end */
1528 void silc_client_close_connection(SilcClient client,
1529 SilcClientConnection conn)
1531 silc_client_close_connection_real(client, NULL, conn);
1534 /* Called when we receive disconnection packet from server. This
1535 closes our end properly and displays the reason of the disconnection
1538 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1540 SilcClient client = (SilcClient)context;
1541 SilcSocketConnection sock;
1543 SILC_CLIENT_GET_SOCK(client, fd, sock);
1547 silc_client_close_connection_real(client, sock, sock->user_data);
1550 /* Called when we receive disconnection packet from server. This
1551 closes our end properly and displays the reason of the disconnection
1554 void silc_client_disconnected_by_server(SilcClient client,
1555 SilcSocketConnection sock,
1558 SilcClientConnection conn;
1560 char *message = NULL;
1562 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1564 if (packet->len < 1)
1567 status = (SilcStatus)packet->data[0];
1569 if (packet->len > 1 &&
1570 silc_utf8_valid(packet->data + 1, packet->len - 1))
1571 message = silc_memdup(packet->data + 1, packet->len - 1);
1573 conn = (SilcClientConnection)sock->user_data;
1574 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1575 client->internal->ops->disconnected(client, conn, status, message);
1579 SILC_SET_DISCONNECTED(sock);
1581 /* Close connection through scheduler. */
1582 silc_schedule_task_add(client->schedule, sock->sock,
1583 silc_client_disconnected_by_server_later,
1584 client, 0, 1, SILC_TASK_TIMEOUT,
1585 SILC_TASK_PRI_NORMAL);
1588 /* Received error message from server. Display it on the screen.
1589 We don't take any action what so ever of the error message. */
1591 void silc_client_error_by_server(SilcClient client,
1592 SilcSocketConnection sock,
1597 msg = silc_memdup(message->data, message->len);
1598 client->internal->ops->say(client, sock->user_data,
1599 SILC_CLIENT_MESSAGE_AUDIT, msg);
1603 /* Auto-nicking callback to send NICK command to server. */
1605 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1607 SilcClientConnection conn = (SilcClientConnection)context;
1608 SilcClient client = conn->client;
1610 silc_client_command_send(client, conn, SILC_COMMAND_NICK,
1611 ++conn->cmd_ident, 1, 1,
1612 client->nickname, strlen(client->nickname));
1615 /* Client session resuming callback. If the session was resumed
1616 this callback is called after the resuming is completed. This
1617 will call the `connect' client operation to the application
1618 since it has not been called yet. */
1620 static void silc_client_resume_session_cb(SilcClient client,
1621 SilcClientConnection conn,
1627 /* Notify application that connection is created to server */
1628 client->internal->ops->connected(client, conn, success ?
1629 SILC_CLIENT_CONN_SUCCESS_RESUME :
1630 SILC_CLIENT_CONN_ERROR);
1633 /* Issue INFO command to fetch the real server name and server
1634 information and other stuff. */
1635 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1636 silc_client_command_reply_info_i, 0,
1638 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1639 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1640 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1641 silc_buffer_free(sidp);
1645 /* Processes the received new Client ID from server. Old Client ID is
1646 deleted from cache and new one is added. */
1648 void silc_client_receive_new_id(SilcClient client,
1649 SilcSocketConnection sock,
1652 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1653 int connecting = FALSE;
1654 SilcClientID *client_id = silc_id_payload_get_id(idp);
1656 if (!conn->local_entry)
1659 /* Delete old ID from ID cache */
1660 if (conn->local_id) {
1661 /* Check whether they are different */
1662 if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1663 silc_free(client_id);
1667 silc_idcache_del_by_context(conn->internal->client_cache,
1669 silc_free(conn->local_id);
1672 /* Save the new ID */
1674 if (conn->local_id_data)
1675 silc_free(conn->local_id_data);
1677 conn->local_id = client_id;
1678 conn->local_id_data = silc_id_payload_get_data(idp);
1679 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1681 if (!conn->local_entry)
1682 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1684 conn->local_entry->nickname = conn->nickname;
1685 if (!conn->local_entry->username)
1686 conn->local_entry->username = strdup(client->username);
1687 if (!conn->local_entry->server)
1688 conn->local_entry->server = strdup(conn->remote_host);
1689 conn->local_entry->id = conn->local_id;
1690 conn->local_entry->valid = TRUE;
1691 if (!conn->local_entry->channels)
1692 conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
1697 /* Put it to the ID cache */
1698 silc_idcache_add(conn->internal->client_cache,
1699 strdup(conn->nickname), conn->local_id,
1700 (void *)conn->local_entry, 0, NULL);
1705 /* Issue IDENTIFY command for itself to get resolved hostname
1706 correctly from server. */
1707 silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
1708 silc_client_command_reply_identify_i, 0,
1710 sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT);
1711 silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
1712 conn->cmd_ident, 1, 5, sidp->data, sidp->len);
1713 silc_buffer_free(sidp);
1715 if (!conn->internal->params.detach_data) {
1716 /* Send NICK command if the nickname was set by the application (and is
1717 not same as the username). Send this with little timeout. */
1718 if (client->nickname && strcmp(client->nickname, client->username))
1719 silc_schedule_task_add(client->schedule, 0,
1720 silc_client_send_auto_nick, conn,
1721 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1723 /* Notify application of successful connection. We do it here now that
1724 we've received the Client ID and are allowed to send traffic. */
1725 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_SUCCESS);
1727 /* Issue INFO command to fetch the real server name and server
1728 information and other stuff. */
1729 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1730 silc_client_command_reply_info_i, 0,
1732 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1733 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1734 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1735 silc_buffer_free(sidp);
1737 /* We are resuming session. Start resolving informations from the
1738 server we need to set the client libary in the state before
1739 detaching the session. The connect client operation is called
1740 after this is successfully completed */
1741 silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1747 /* Removes a client entry from all channels it has joined. */
1749 void silc_client_remove_from_channels(SilcClient client,
1750 SilcClientConnection conn,
1751 SilcClientEntry client_entry)
1753 SilcHashTableList htl;
1754 SilcChannelUser chu;
1756 silc_hash_table_list(client_entry->channels, &htl);
1757 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1758 silc_hash_table_del(chu->client->channels, chu->channel);
1759 silc_hash_table_del(chu->channel->user_list, chu->client);
1763 silc_hash_table_list_reset(&htl);
1766 /* Replaces `old' client entries from all channels to `new' client entry.
1767 This can be called for example when nickname changes and old ID entry
1768 is replaced from ID cache with the new one. If the old ID entry is only
1769 updated, then this fucntion needs not to be called. */
1771 void silc_client_replace_from_channels(SilcClient client,
1772 SilcClientConnection conn,
1773 SilcClientEntry old,
1774 SilcClientEntry new)
1776 SilcHashTableList htl;
1777 SilcChannelUser chu;
1779 silc_hash_table_list(old->channels, &htl);
1780 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1781 /* Replace client entry */
1782 silc_hash_table_del(chu->client->channels, chu->channel);
1783 silc_hash_table_del(chu->channel->user_list, chu->client);
1786 silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1787 silc_hash_table_add(chu->client->channels, chu->channel, chu);
1789 silc_hash_table_list_reset(&htl);
1792 /* Registers failure timeout to process the received failure packet
1795 void silc_client_process_failure(SilcClient client,
1796 SilcSocketConnection sock,
1797 SilcPacketContext *packet)
1799 SilcUInt32 failure = 0;
1801 if (sock->protocol) {
1802 if (packet->buffer->len >= 4)
1803 SILC_GET32_MSB(failure, packet->buffer->data);
1805 /* Notify application */
1806 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1811 /* A timeout callback for the re-key. We will be the initiator of the
1814 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1816 SilcSocketConnection sock = (SilcSocketConnection)context;
1817 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1818 SilcClient client = (SilcClient)conn->internal->rekey->context;
1819 SilcProtocol protocol;
1820 SilcClientRekeyInternalContext *proto_ctx;
1822 SILC_LOG_DEBUG(("Start"));
1824 /* Allocate internal protocol context. This is sent as context
1826 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1827 proto_ctx->client = (void *)client;
1828 proto_ctx->sock = silc_socket_dup(sock);
1829 proto_ctx->responder = FALSE;
1830 proto_ctx->pfs = conn->internal->rekey->pfs;
1832 /* Perform rekey protocol. Will call the final callback after the
1833 protocol is over. */
1834 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1835 &protocol, proto_ctx, silc_client_rekey_final);
1836 sock->protocol = protocol;
1838 /* Run the protocol */
1839 silc_protocol_execute(protocol, client->schedule, 0, 0);
1841 /* Re-register re-key timeout */
1842 silc_schedule_task_add(client->schedule, sock->sock,
1843 silc_client_rekey_callback,
1844 context, conn->internal->rekey->timeout, 0,
1845 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1848 /* The final callback for the REKEY protocol. This will actually take the
1849 new key material into use. */
1851 SILC_TASK_CALLBACK(silc_client_rekey_final)
1853 SilcProtocol protocol = (SilcProtocol)context;
1854 SilcClientRekeyInternalContext *ctx =
1855 (SilcClientRekeyInternalContext *)protocol->context;
1856 SilcClient client = (SilcClient)ctx->client;
1857 SilcSocketConnection sock = ctx->sock;
1859 SILC_LOG_DEBUG(("Start"));
1861 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1862 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1863 /* Error occured during protocol */
1864 silc_protocol_cancel(protocol, client->schedule);
1865 silc_protocol_free(protocol);
1866 sock->protocol = NULL;
1868 silc_packet_context_free(ctx->packet);
1870 silc_ske_free(ctx->ske);
1871 silc_socket_free(ctx->sock);
1876 /* Purge the outgoing data queue to assure that all rekey packets really
1877 go to the network before we quit the protocol. */
1878 silc_client_packet_queue_purge(client, sock);
1881 silc_protocol_free(protocol);
1882 sock->protocol = NULL;
1884 silc_packet_context_free(ctx->packet);
1886 silc_ske_free(ctx->ske);
1887 silc_socket_free(ctx->sock);
1891 /* Processes incoming connection authentication method request packet.
1892 It is a reply to our previously sent request. The packet can be used
1893 to resolve the authentication method for the current session if the
1894 client does not know it beforehand. */
1896 void silc_client_connection_auth_request(SilcClient client,
1897 SilcSocketConnection sock,
1898 SilcPacketContext *packet)
1900 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1901 SilcUInt16 conn_type, auth_meth;
1904 /* If we haven't send our request then ignore this one. */
1905 if (!conn->internal->connauth)
1908 /* Parse the payload */
1909 ret = silc_buffer_unformat(packet->buffer,
1910 SILC_STR_UI_SHORT(&conn_type),
1911 SILC_STR_UI_SHORT(&auth_meth),
1914 auth_meth = SILC_AUTH_NONE;
1916 /* Call the request callback to notify application for received
1917 authentication method information. */
1918 if (conn->internal->connauth->callback)
1919 (*conn->internal->connauth->callback)(client, conn, auth_meth,
1920 conn->internal->connauth->context);
1922 silc_schedule_task_del(client->schedule, conn->internal->connauth->timeout);
1924 silc_free(conn->internal->connauth);
1925 conn->internal->connauth = NULL;
1928 /* Timeout task callback called if the server does not reply to our
1929 connection authentication method request in the specified time interval. */
1931 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1933 SilcClientConnection conn = (SilcClientConnection)context;
1934 SilcClient client = conn->client;
1936 if (!conn->internal->connauth)
1939 /* Call the request callback to notify application */
1940 if (conn->internal->connauth->callback)
1941 (*conn->internal->connauth->callback)(client, conn, SILC_AUTH_NONE,
1942 conn->internal->connauth->context);
1944 silc_free(conn->internal->connauth);
1945 conn->internal->connauth = NULL;
1948 /* This function can be used to request the current authentication method
1949 from the server. This may be called when connecting to the server
1950 and the client library requests the authentication data from the
1951 application. If the application does not know the current authentication
1952 method it can request it from the server using this function.
1953 The `callback' with `context' will be called after the server has
1954 replied back with the current authentication method. */
1957 silc_client_request_authentication_method(SilcClient client,
1958 SilcClientConnection conn,
1959 SilcConnectionAuthRequest callback,
1962 SilcClientConnAuthRequest connauth;
1965 connauth = silc_calloc(1, sizeof(*connauth));
1966 connauth->callback = callback;
1967 connauth->context = context;
1969 if (conn->internal->connauth)
1970 silc_free(conn->internal->connauth);
1972 conn->internal->connauth = connauth;
1974 /* Assemble the request packet and send it to the server */
1975 packet = silc_buffer_alloc(4);
1976 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1977 silc_buffer_format(packet,
1978 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
1979 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
1981 silc_client_packet_send(client, conn->sock,
1982 SILC_PACKET_CONNECTION_AUTH_REQUEST,
1983 NULL, 0, NULL, NULL,
1984 packet->data, packet->len, FALSE);
1985 silc_buffer_free(packet);
1987 /* Register a timeout in case server does not reply anything back. */
1989 silc_schedule_task_add(client->schedule, conn->sock->sock,
1990 silc_client_request_authentication_method_timeout,
1992 client->internal->params->connauth_request_secs, 0,
1993 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);