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 *silc_version)
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));
61 new_client->internal->silc_client_version = strdup(silc_version);
64 memcpy(new_client->internal->params, params, sizeof(*params));
66 if (!new_client->internal->params->task_max)
67 new_client->internal->params->task_max = 200;
69 if (!new_client->internal->params->rekey_secs)
70 new_client->internal->params->rekey_secs = 3600;
72 if (!new_client->internal->params->connauth_request_secs)
73 new_client->internal->params->connauth_request_secs = 2;
75 new_client->internal->params->
76 nickname_format[sizeof(new_client->internal->
77 params->nickname_format) - 1] = 0;
82 /* Frees client object and its internals. */
84 void silc_client_free(SilcClient client)
88 silc_rng_free(client->rng);
90 silc_free(client->internal->params);
91 silc_free(client->internal->silc_client_version);
92 silc_free(client->internal);
97 /* Initializes the client. This makes all the necessary steps to make
98 the client ready to be run. One must call silc_client_run to run the
99 client. Returns FALSE if error occured, TRUE otherwise. */
101 int silc_client_init(SilcClient client)
103 SILC_LOG_DEBUG(("Initializing client"));
105 /* Initialize hash functions for client to use */
106 silc_hash_alloc("md5", &client->internal->md5hash);
107 silc_hash_alloc("sha1", &client->internal->sha1hash);
109 /* Initialize none cipher */
110 silc_cipher_alloc("none", &client->internal->none_cipher);
112 /* Initialize random number generator */
113 client->rng = silc_rng_alloc();
114 silc_rng_init(client->rng);
115 silc_rng_global_init(client->rng);
117 /* Register protocols */
118 silc_client_protocols_register();
120 /* Initialize the scheduler */
122 silc_schedule_init(client->internal->params->task_max ?
123 client->internal->params->task_max : 200, client);
124 if (!client->schedule)
127 /* Register commands */
128 silc_client_commands_register(client);
133 /* Stops the client. This is called to stop the client and thus to stop
136 void silc_client_stop(SilcClient client)
138 SILC_LOG_DEBUG(("Stopping client"));
140 silc_schedule_stop(client->schedule);
141 silc_schedule_uninit(client->schedule);
143 silc_client_protocols_unregister();
144 silc_client_commands_unregister(client);
146 SILC_LOG_DEBUG(("Client stopped"));
149 /* Runs the client. This starts the scheduler from the utility library.
150 When this functions returns the execution of the appliation is over. */
152 void silc_client_run(SilcClient client)
154 SILC_LOG_DEBUG(("Running client"));
156 /* Start the scheduler, the heart of the SILC client. When this returns
157 the program will be terminated. */
158 silc_schedule(client->schedule);
161 /* Runs the client and returns immeadiately. This function is used when
162 the SILC Client object indicated by the `client' is run under some
163 other scheduler, or event loop or main loop. On GUI applications,
164 for example this may be desired to use to run the client under the
165 GUI application's main loop. Typically the GUI application would
166 register an idle task that calls this function multiple times in
167 a second to quickly process the SILC specific data. */
169 void silc_client_run_one(SilcClient client)
171 /* Run the scheduler once. */
172 silc_schedule_one(client->schedule, 0);
175 static void silc_client_entry_destructor(SilcIDCache cache,
176 SilcIDCacheEntry entry)
178 silc_free(entry->name);
181 /* Allocates and adds new connection to the client. This adds the allocated
182 connection to the connection table and returns a pointer to it. A client
183 can have multiple connections to multiple servers. Every connection must
184 be added to the client using this function. User data `context' may
185 be sent as argument. This function is normally used only if the
186 application performed the connecting outside the library. The library
187 however may use this internally. */
190 silc_client_add_connection(SilcClient client,
191 SilcClientConnectionParams *params,
192 char *hostname, int port, void *context)
194 SilcClientConnection conn;
197 SILC_LOG_DEBUG(("Adding new connection to %s:%d", hostname, port));
199 conn = silc_calloc(1, sizeof(*conn));
201 /* Initialize ID caches */
202 conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT,
203 silc_client_entry_destructor);
204 conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
205 conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
206 conn->client = client;
207 conn->remote_host = strdup(hostname);
208 conn->remote_port = port;
209 conn->context = context;
210 conn->pending_commands = silc_dlist_init();
211 conn->ftp_sessions = silc_dlist_init();
214 if (params->detach_data)
215 conn->params.detach_data = silc_memdup(params->detach_data,
216 params->detach_data_len);
217 conn->params.detach_data_len = params->detach_data_len;
220 /* Add the connection to connections table */
221 for (i = 0; i < client->internal->conns_count; i++)
222 if (client->internal->conns && !client->internal->conns[i]) {
223 client->internal->conns[i] = conn;
227 client->internal->conns =
228 silc_realloc(client->internal->conns, sizeof(*client->internal->conns)
229 * (client->internal->conns_count + 1));
230 client->internal->conns[client->internal->conns_count] = conn;
231 client->internal->conns_count++;
236 /* Removes connection from client. Frees all memory. */
238 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
242 for (i = 0; i < client->internal->conns_count; i++)
243 if (client->internal->conns[i] == conn) {
245 silc_idcache_free(conn->client_cache);
246 silc_idcache_free(conn->channel_cache);
247 silc_idcache_free(conn->server_cache);
248 if (conn->pending_commands)
249 silc_dlist_uninit(conn->pending_commands);
250 silc_free(conn->remote_host);
251 if (conn->ftp_sessions)
252 silc_dlist_uninit(conn->ftp_sessions);
255 client->internal->conns[i] = NULL;
259 /* Adds listener socket to the listener sockets table. This function is
260 used to add socket objects that are listeners to the client. This should
261 not be used to add other connection objects. */
263 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
267 if (!client->internal->sockets) {
268 client->internal->sockets =
269 silc_calloc(1, sizeof(*client->internal->sockets));
270 client->internal->sockets[0] = silc_socket_dup(sock);
271 client->internal->sockets_count = 1;
275 for (i = 0; i < client->internal->sockets_count; i++) {
276 if (client->internal->sockets[i] == NULL) {
277 client->internal->sockets[i] = silc_socket_dup(sock);
282 client->internal->sockets =
283 silc_realloc(client->internal->sockets,
284 sizeof(*client->internal->sockets) *
285 (client->internal->sockets_count + 1));
286 client->internal->sockets[client->internal->sockets_count] =
287 silc_socket_dup(sock);
288 client->internal->sockets_count++;
291 /* Deletes listener socket from the listener sockets table. */
293 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
297 if (!client->internal->sockets)
300 for (i = 0; i < client->internal->sockets_count; i++) {
301 if (client->internal->sockets[i] == sock) {
302 silc_socket_free(sock);
303 client->internal->sockets[i] = NULL;
310 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
314 /* XXX In the future we should give up this non-blocking connect all
315 together and use threads instead. */
316 /* Create connection to server asynchronously */
317 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
321 /* Register task that will receive the async connect and will
323 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
324 silc_client_connect_to_server_start,
327 SILC_TASK_PRI_NORMAL);
328 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
335 /* Connects to remote server. This is the main routine used to connect
336 to SILC server. Returns -1 on error and the created socket otherwise.
337 The `context' is user context that is saved into the SilcClientConnection
338 that is created after the connection is created. Note that application
339 may handle the connecting process outside the library. If this is the
340 case then this function is not used at all. When the connecting is
341 done the `connect' client operation is called. */
343 int silc_client_connect_to_server(SilcClient client,
344 SilcClientConnectionParams *params,
345 int port, char *host, void *context)
347 SilcClientInternalConnectContext *ctx;
348 SilcClientConnection conn;
351 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
354 conn = silc_client_add_connection(client, params, host, port, context);
356 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
357 "Connecting to port %d of server %s", port, host);
359 /* Allocate internal context for connection process. This is
360 needed as we are doing async connecting. */
361 ctx = silc_calloc(1, sizeof(*ctx));
362 ctx->client = client;
364 ctx->host = strdup(host);
368 /* Do the actual connecting process */
369 sock = silc_client_connect_to_server_internal(ctx);
371 silc_client_del_connection(client, conn);
375 /* Socket hostname and IP lookup callback that is called before actually
376 starting the key exchange. The lookup is called from the function
377 silc_client_start_key_exchange. */
379 static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
382 SilcClientConnection conn = (SilcClientConnection)context;
383 SilcClient client = conn->client;
384 SilcProtocol protocol;
385 SilcClientKEInternalContext *proto_ctx;
387 SILC_LOG_DEBUG(("Start"));
389 if (conn->sock->hostname) {
390 silc_free(conn->remote_host);
391 conn->remote_host = strdup(conn->sock->hostname);
393 conn->sock->hostname = strdup(conn->remote_host);
396 conn->sock->ip = strdup(conn->sock->hostname);
397 conn->sock->port = conn->remote_port;
399 /* Allocate internal Key Exchange context. This is sent to the
400 protocol as context. */
401 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
402 proto_ctx->client = (void *)client;
403 proto_ctx->sock = silc_socket_dup(conn->sock);
404 proto_ctx->rng = client->rng;
405 proto_ctx->responder = FALSE;
406 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
407 proto_ctx->verify = silc_client_protocol_ke_verify_key;
409 /* Perform key exchange protocol. silc_client_connect_to_server_final
410 will be called after the protocol is finished. */
411 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
412 &protocol, (void *)proto_ctx,
413 silc_client_connect_to_server_second);
415 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
416 "Error: Could not start key exchange protocol");
417 silc_net_close_connection(conn->sock->sock);
418 client->internal->ops->connect(client, conn, SILC_CLIENT_CONN_ERROR);
421 conn->sock->protocol = protocol;
423 /* Register the connection for network input and output. This sets
424 that scheduler will listen for incoming packets for this connection
425 and sets that outgoing packets may be sent to this connection as well.
426 However, this doesn't set the scheduler for outgoing traffic, it will
427 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
428 later when outgoing data is available. */
429 context = (void *)client;
430 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(conn->sock->sock);
432 /* Execute the protocol */
433 silc_protocol_execute(protocol, client->schedule, 0, 0);
436 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
437 key material between client and server. This function can be called
438 directly if application is performing its own connecting and does not
439 use the connecting provided by this library. This function is normally
440 used only if the application performed the connecting outside the library.
441 The library however may use this internally. */
443 void silc_client_start_key_exchange(SilcClient client,
444 SilcClientConnection conn,
447 /* Allocate new socket connection object */
448 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
450 /* Sometimes when doing quick reconnects the new socket may be same as
451 the old one and there might be pending stuff for the old socket.
452 If new one is same then those pending sutff might cause problems.
453 Make sure they do not do that. */
454 silc_schedule_task_del_by_fd(client->schedule, fd);
456 conn->nickname = (client->nickname ? strdup(client->nickname) :
457 strdup(client->username));
459 /* Resolve the remote hostname and IP address for our socket connection */
460 silc_socket_host_lookup(conn->sock, FALSE, silc_client_start_key_exchange_cb,
461 conn, client->schedule);
464 /* Callback called when error has occurred during connecting to the server.
465 The `connect' client operation will be called. */
467 SILC_TASK_CALLBACK(silc_client_connect_failure)
469 SilcClientKEInternalContext *ctx =
470 (SilcClientKEInternalContext *)context;
471 SilcClient client = (SilcClient)ctx->client;
473 client->internal->ops->connect(client, ctx->sock->user_data,
474 SILC_CLIENT_CONN_ERROR);
476 silc_packet_context_free(ctx->packet);
480 /* Start of the connection to the remote server. This is called after
481 succesful TCP/IP connection has been established to the remote host. */
483 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
485 SilcClientInternalConnectContext *ctx =
486 (SilcClientInternalConnectContext *)context;
487 SilcClient client = ctx->client;
488 SilcClientConnection conn = ctx->conn;
489 int opt, opt_len = sizeof(opt);
491 SILC_LOG_DEBUG(("Start"));
493 /* Check the socket status as it might be in error */
494 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
496 if (ctx->tries < 2) {
497 /* Connection failed but lets try again */
498 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
499 "Could not connect to server %s: %s",
500 ctx->host, strerror(opt));
501 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
502 "Connecting to port %d of server %s resumed",
503 ctx->port, ctx->host);
505 /* Unregister old connection try */
506 silc_schedule_unset_listen_fd(client->schedule, fd);
507 silc_net_close_connection(fd);
508 silc_schedule_task_del(client->schedule, ctx->task);
511 silc_client_connect_to_server_internal(ctx);
514 /* Connection failed and we won't try anymore */
515 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
516 "Could not connect to server %s: %s",
517 ctx->host, strerror(opt));
518 silc_schedule_unset_listen_fd(client->schedule, fd);
519 silc_net_close_connection(fd);
520 silc_schedule_task_del(client->schedule, ctx->task);
523 /* Notify application of failure */
524 client->internal->ops->connect(client, conn, SILC_CLIENT_CONN_ERROR);
525 silc_client_del_connection(client, conn);
530 silc_schedule_unset_listen_fd(client->schedule, fd);
531 silc_schedule_task_del(client->schedule, ctx->task);
534 silc_client_start_key_exchange(client, conn, fd);
537 /* Second part of the connecting to the server. This executed
538 authentication protocol. */
540 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
542 SilcProtocol protocol = (SilcProtocol)context;
543 SilcClientKEInternalContext *ctx =
544 (SilcClientKEInternalContext *)protocol->context;
545 SilcClient client = (SilcClient)ctx->client;
546 SilcSocketConnection sock = NULL;
547 SilcClientConnAuthInternalContext *proto_ctx;
549 SILC_LOG_DEBUG(("Start"));
551 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
552 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
553 /* Error occured during protocol */
554 SILC_LOG_DEBUG(("Error during KE protocol"));
555 silc_protocol_free(protocol);
556 silc_ske_free_key_material(ctx->keymat);
558 silc_ske_free(ctx->ske);
560 silc_free(ctx->dest_id);
561 ctx->sock->protocol = NULL;
562 silc_socket_free(ctx->sock);
564 /* Notify application of failure */
565 silc_schedule_task_add(client->schedule, ctx->sock->sock,
566 silc_client_connect_failure, ctx,
567 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
571 /* We now have the key material as the result of the key exchange
572 protocol. Take the key material into use. Free the raw key material
573 as soon as we've set them into use. */
574 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
575 ctx->ske->prop->cipher,
576 ctx->ske->prop->pkcs,
577 ctx->ske->prop->hash,
578 ctx->ske->prop->hmac,
579 ctx->ske->prop->group,
581 silc_ske_free_key_material(ctx->keymat);
583 /* Allocate internal context for the authentication protocol. This
584 is sent as context for the protocol. */
585 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
586 proto_ctx->client = (void *)client;
587 proto_ctx->sock = sock = ctx->sock;
588 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
589 proto_ctx->dest_id_type = ctx->dest_id_type;
590 proto_ctx->dest_id = ctx->dest_id;
592 /* Free old protocol as it is finished now */
593 silc_protocol_free(protocol);
595 silc_packet_context_free(ctx->packet);
597 sock->protocol = NULL;
599 /* Resolve the authentication method to be used in this connection. The
600 completion callback is called after the application has resolved
601 the authentication method. */
602 client->internal->ops->get_auth_method(client, sock->user_data,
605 silc_client_resolve_auth_method,
609 /* Authentication method resolving callback. Application calls this function
610 after we've called the client->internal->ops->get_auth_method
611 client operation to resolve the authentication method. We will continue
612 the executiong of the protocol in this function. */
614 void silc_client_resolve_auth_method(bool success,
615 SilcProtocolAuthMeth auth_meth,
616 const unsigned char *auth_data,
617 SilcUInt32 auth_data_len, void *context)
619 SilcClientConnAuthInternalContext *proto_ctx =
620 (SilcClientConnAuthInternalContext *)context;
621 SilcClient client = (SilcClient)proto_ctx->client;
624 auth_meth = SILC_AUTH_NONE;
626 proto_ctx->auth_meth = auth_meth;
628 if (auth_data && auth_data_len) {
629 proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
630 proto_ctx->auth_data_len = auth_data_len;
633 /* Allocate the authenteication protocol and execute it. */
634 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
635 &proto_ctx->sock->protocol, (void *)proto_ctx,
636 silc_client_connect_to_server_final);
638 /* Execute the protocol */
639 silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
642 /* Finalizes the connection to the remote SILC server. This is called
643 after authentication protocol has been completed. This send our
644 user information to the server to receive our client ID from
647 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
649 SilcProtocol protocol = (SilcProtocol)context;
650 SilcClientConnAuthInternalContext *ctx =
651 (SilcClientConnAuthInternalContext *)protocol->context;
652 SilcClient client = (SilcClient)ctx->client;
653 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
656 SILC_LOG_DEBUG(("Start"));
658 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
659 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
660 /* Error occured during protocol */
661 SILC_LOG_DEBUG(("Error during authentication protocol"));
665 if (conn->params.detach_data) {
666 /* Send RESUME_CLIENT packet to the server, which is used to resume
667 old detached session back. */
669 SilcClientID *old_client_id;
670 unsigned char *old_id;
671 SilcUInt16 old_id_len;
673 if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len))
676 old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT);
677 if (!old_client_id) {
682 /* Generate authentication data that server will verify */
683 auth = silc_auth_public_key_auth_generate(client->public_key,
685 client->rng, conn->hash,
686 old_client_id, SILC_ID_CLIENT);
688 silc_free(old_client_id);
693 packet = silc_buffer_alloc_size(2 + old_id_len + auth->len);
694 silc_buffer_format(packet,
695 SILC_STR_UI_SHORT(old_id_len),
696 SILC_STR_UI_XNSTRING(old_id, old_id_len),
697 SILC_STR_UI_XNSTRING(auth->data, auth->len),
700 /* Send the packet */
701 silc_client_packet_send(client, ctx->sock, SILC_PACKET_RESUME_CLIENT,
703 packet->data, packet->len, TRUE);
704 silc_buffer_free(packet);
705 silc_buffer_free(auth);
706 silc_free(old_client_id);
709 /* Send NEW_CLIENT packet to the server. We will become registered
710 to the SILC network after sending this packet and we will receive
711 client ID from the server. */
712 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
713 strlen(client->realname));
714 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
715 silc_buffer_format(packet,
716 SILC_STR_UI_SHORT(strlen(client->username)),
717 SILC_STR_UI_XNSTRING(client->username,
718 strlen(client->username)),
719 SILC_STR_UI_SHORT(strlen(client->realname)),
720 SILC_STR_UI_XNSTRING(client->realname,
721 strlen(client->realname)),
724 /* Send the packet */
725 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
727 packet->data, packet->len, TRUE);
728 silc_buffer_free(packet);
731 /* Save remote ID. */
732 conn->remote_id = ctx->dest_id;
733 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
734 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
736 /* Register re-key timeout */
737 conn->rekey->timeout = client->internal->params->rekey_secs;
738 conn->rekey->context = (void *)client;
739 silc_schedule_task_add(client->schedule, conn->sock->sock,
740 silc_client_rekey_callback,
741 (void *)conn->sock, conn->rekey->timeout, 0,
742 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
744 silc_protocol_free(protocol);
745 silc_free(ctx->auth_data);
747 silc_ske_free(ctx->ske);
748 silc_socket_free(ctx->sock);
750 conn->sock->protocol = NULL;
754 silc_protocol_free(protocol);
755 silc_free(ctx->auth_data);
756 silc_free(ctx->dest_id);
758 silc_ske_free(ctx->ske);
759 conn->sock->protocol = NULL;
760 silc_socket_free(ctx->sock);
762 /* Notify application of failure */
763 silc_schedule_task_add(client->schedule, ctx->sock->sock,
764 silc_client_connect_failure, ctx,
765 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
768 /* Internal routine that sends packet or marks packet to be sent. This
769 is used directly only in special cases. Normal cases should use
770 silc_server_packet_send. Returns < 0 on error. */
772 int silc_client_packet_send_real(SilcClient client,
773 SilcSocketConnection sock,
778 /* If rekey protocol is active we must assure that all packets are
779 sent through packet queue. */
780 if (SILC_CLIENT_IS_REKEY(sock))
783 /* If outbound data is already pending do not force send */
784 if (SILC_IS_OUTBUF_PENDING(sock))
787 /* Send the packet */
788 ret = silc_packet_send(sock, force_send);
792 /* Mark that there is some outgoing data available for this connection.
793 This call sets the connection both for input and output (the input
794 is set always and this call keeps the input setting, actually).
795 Actual data sending is performed by silc_client_packet_process. */
796 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
798 /* Mark to socket that data is pending in outgoing buffer. This flag
799 is needed if new data is added to the buffer before the earlier
800 put data is sent to the network. */
801 SILC_SET_OUTBUF_PENDING(sock);
806 /* Packet processing callback. This is used to send and receive packets
807 from network. This is generic task. */
809 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
811 SilcClient client = (SilcClient)context;
812 SilcSocketConnection sock = NULL;
813 SilcClientConnection conn;
816 SILC_LOG_DEBUG(("Processing packet"));
818 SILC_CLIENT_GET_SOCK(client, fd, sock);
822 conn = (SilcClientConnection)sock->user_data;
825 if (type == SILC_TASK_WRITE) {
826 /* Do not send data to disconnected connection */
827 if (SILC_IS_DISCONNECTED(sock))
830 ret = silc_packet_send(sock, TRUE);
832 /* If returned -2 could not write to connection now, will do
841 /* The packet has been sent and now it is time to set the connection
842 back to only for input. When there is again some outgoing data
843 available for this connection it will be set for output as well.
844 This call clears the output setting and sets it only for input. */
845 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
846 SILC_UNSET_OUTBUF_PENDING(sock);
848 silc_buffer_clear(sock->outbuf);
852 /* Packet receiving */
853 if (type == SILC_TASK_READ) {
854 /* Read data from network */
855 ret = silc_packet_receive(sock);
861 SILC_LOG_DEBUG(("Read EOF"));
863 /* If connection is disconnecting already we will finally
864 close the connection */
865 if (SILC_IS_DISCONNECTING(sock)) {
866 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
867 client->internal->ops->disconnect(client, conn, 0, NULL);
868 silc_client_close_connection_real(client, sock, conn);
872 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
873 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
874 client->internal->ops->disconnect(client, conn, 0, NULL);
875 silc_client_close_connection_real(client, sock, conn);
879 /* Process the packet. This will call the parser that will then
880 decrypt and parse the packet. */
881 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
882 silc_packet_receive_process(sock, FALSE, conn->receive_key,
883 conn->hmac_receive, conn->psn_receive,
884 silc_client_packet_parse, client);
886 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
887 silc_client_packet_parse, client);
891 /* Parser callback called by silc_packet_receive_process. Thie merely
892 registers timeout that will handle the actual parsing when appropriate. */
894 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
897 SilcClient client = (SilcClient)context;
898 SilcSocketConnection sock = parser_context->sock;
899 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
900 SilcPacketContext *packet = parser_context->packet;
903 if (conn && conn->hmac_receive && conn->sock == sock)
904 conn->psn_receive = parser_context->packet->sequence + 1;
906 /* Parse the packet immediately */
907 if (parser_context->normal)
908 ret = silc_packet_parse(packet, conn->receive_key);
910 ret = silc_packet_parse_special(packet, conn->receive_key);
912 if (ret == SILC_PACKET_NONE) {
913 silc_packet_context_free(packet);
914 silc_free(parser_context);
918 /* If protocol for this connection is key exchange or rekey then we'll
919 process all packets synchronously, since there might be packets in
920 queue that we are not able to decrypt without first processing the
921 packets before them. */
922 if ((ret == SILC_PACKET_REKEY || ret == SILC_PACKET_REKEY_DONE) ||
923 (sock->protocol && sock->protocol->protocol &&
924 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
925 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY))) {
927 /* Parse the incoming packet type */
928 silc_client_packet_parse_type(client, sock, packet);
929 silc_packet_context_free(packet);
930 silc_free(parser_context);
932 /* Reprocess the buffer since we'll return FALSE. This is because
933 the `conn->receive_key' might have become valid by processing
934 the previous packet */
935 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
936 silc_packet_receive_process(sock, FALSE, conn->receive_key,
937 conn->hmac_receive, conn->psn_receive,
938 silc_client_packet_parse, client);
940 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
941 silc_client_packet_parse, client);
946 /* Parse the incoming packet type */
947 silc_client_packet_parse_type(client, sock, packet);
948 silc_packet_context_free(packet);
949 silc_free(parser_context);
953 /* Parses the packet type and calls what ever routines the packet type
954 requires. This is done for all incoming packets. */
956 void silc_client_packet_parse_type(SilcClient client,
957 SilcSocketConnection sock,
958 SilcPacketContext *packet)
960 SilcBuffer buffer = packet->buffer;
961 SilcPacketType type = packet->type;
963 SILC_LOG_DEBUG(("Parsing %s packet", silc_get_packet_name(type)));
965 /* Parse the packet type */
968 case SILC_PACKET_DISCONNECT:
969 silc_client_disconnected_by_server(client, sock, buffer);
972 case SILC_PACKET_SUCCESS:
974 * Success received for something. For now we can have only
975 * one protocol for connection executing at once hence this
976 * success message is for whatever protocol is executing currently.
979 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
982 case SILC_PACKET_FAILURE:
984 * Failure received for some protocol. Set the protocol state to
985 * error and call the protocol callback. This fill cause error on
986 * protocol and it will call the final callback.
988 silc_client_process_failure(client, sock, packet);
991 case SILC_PACKET_REJECT:
994 case SILC_PACKET_NOTIFY:
996 * Received notify message
998 silc_client_notify_by_server(client, sock, packet);
1001 case SILC_PACKET_ERROR:
1003 * Received error message
1005 silc_client_error_by_server(client, sock, buffer);
1008 case SILC_PACKET_CHANNEL_MESSAGE:
1010 * Received message to (from, actually) a channel
1012 silc_client_channel_message(client, sock, packet);
1015 case SILC_PACKET_CHANNEL_KEY:
1017 * Received key for a channel. By receiving this key the client will be
1018 * able to talk to the channel it has just joined. This can also be
1019 * a new key for existing channel as keys expire peridiocally.
1021 silc_client_receive_channel_key(client, sock, buffer);
1024 case SILC_PACKET_PRIVATE_MESSAGE:
1026 * Received private message
1028 silc_client_private_message(client, sock, packet);
1031 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1033 * Received private message key
1037 case SILC_PACKET_COMMAND:
1039 * Received command packet, a special case since normally client
1040 * does not receive commands.
1042 silc_client_command_process(client, sock, packet);
1045 case SILC_PACKET_COMMAND_REPLY:
1047 * Recived reply for a command
1049 silc_client_command_reply_process(client, sock, packet);
1052 case SILC_PACKET_KEY_EXCHANGE:
1053 if (sock->protocol && sock->protocol->protocol &&
1054 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
1055 SilcClientKEInternalContext *proto_ctx =
1056 (SilcClientKEInternalContext *)sock->protocol->context;
1058 proto_ctx->packet = silc_packet_context_dup(packet);
1059 proto_ctx->dest_id_type = packet->src_id_type;
1060 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1061 packet->src_id_type);
1062 if (!proto_ctx->dest_id)
1065 /* Let the protocol handle the packet */
1066 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1068 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1069 "protocol active, packet dropped."));
1073 case SILC_PACKET_KEY_EXCHANGE_1:
1074 if (sock->protocol && sock->protocol->protocol &&
1075 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1076 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1078 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1079 SilcClientRekeyInternalContext *proto_ctx =
1080 (SilcClientRekeyInternalContext *)sock->protocol->context;
1082 if (proto_ctx->packet)
1083 silc_packet_context_free(proto_ctx->packet);
1085 proto_ctx->packet = silc_packet_context_dup(packet);
1087 /* Let the protocol handle the packet */
1088 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1090 SilcClientKEInternalContext *proto_ctx =
1091 (SilcClientKEInternalContext *)sock->protocol->context;
1093 if (proto_ctx->packet)
1094 silc_packet_context_free(proto_ctx->packet);
1096 proto_ctx->packet = silc_packet_context_dup(packet);
1097 proto_ctx->dest_id_type = packet->src_id_type;
1098 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1099 packet->src_id_type);
1100 if (!proto_ctx->dest_id)
1103 /* Let the protocol handle the packet */
1104 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1107 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1108 "protocol active, packet dropped."));
1112 case SILC_PACKET_KEY_EXCHANGE_2:
1113 if (sock->protocol && sock->protocol->protocol &&
1114 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1115 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1117 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1118 SilcClientRekeyInternalContext *proto_ctx =
1119 (SilcClientRekeyInternalContext *)sock->protocol->context;
1121 if (proto_ctx->packet)
1122 silc_packet_context_free(proto_ctx->packet);
1124 proto_ctx->packet = silc_packet_context_dup(packet);
1126 /* Let the protocol handle the packet */
1127 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1129 SilcClientKEInternalContext *proto_ctx =
1130 (SilcClientKEInternalContext *)sock->protocol->context;
1132 if (proto_ctx->packet)
1133 silc_packet_context_free(proto_ctx->packet);
1134 if (proto_ctx->dest_id)
1135 silc_free(proto_ctx->dest_id);
1136 proto_ctx->packet = silc_packet_context_dup(packet);
1137 proto_ctx->dest_id_type = packet->src_id_type;
1138 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1139 packet->src_id_type);
1140 if (!proto_ctx->dest_id)
1143 /* Let the protocol handle the packet */
1144 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1147 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1148 "protocol active, packet dropped."));
1152 case SILC_PACKET_NEW_ID:
1155 * Received new ID from server. This packet is received at
1156 * the connection to the server. New ID is also received when
1157 * user changes nickname but in that case the new ID is received
1158 * as command reply and not as this packet type.
1162 idp = silc_id_payload_parse(buffer->data, buffer->len);
1165 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1168 silc_client_receive_new_id(client, sock, idp);
1169 silc_id_payload_free(idp);
1173 case SILC_PACKET_HEARTBEAT:
1175 * Received heartbeat packet
1177 SILC_LOG_DEBUG(("Heartbeat packet"));
1180 case SILC_PACKET_KEY_AGREEMENT:
1182 * Received key agreement packet
1184 SILC_LOG_DEBUG(("Key agreement packet"));
1185 silc_client_key_agreement(client, sock, packet);
1188 case SILC_PACKET_REKEY:
1189 SILC_LOG_DEBUG(("Re-key packet"));
1190 /* We ignore this for now */
1193 case SILC_PACKET_REKEY_DONE:
1194 SILC_LOG_DEBUG(("Re-key done packet"));
1196 if (sock->protocol && sock->protocol->protocol &&
1197 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1199 SilcClientRekeyInternalContext *proto_ctx =
1200 (SilcClientRekeyInternalContext *)sock->protocol->context;
1202 if (proto_ctx->packet)
1203 silc_packet_context_free(proto_ctx->packet);
1205 proto_ctx->packet = silc_packet_context_dup(packet);
1207 /* Let the protocol handle the packet */
1208 if (proto_ctx->responder == FALSE)
1209 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1211 /* Let the protocol handle the packet */
1212 silc_protocol_execute(sock->protocol, client->schedule,
1215 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1216 "protocol active, packet dropped."));
1220 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1222 * Reveived reply to our connection authentication method request
1223 * packet. This is used to resolve the authentication method for the
1224 * current session from the server if the client does not know it.
1226 silc_client_connection_auth_request(client, sock, packet);
1229 case SILC_PACKET_FTP:
1230 /* Received file transfer packet. */
1231 silc_client_ftp(client, sock, packet);
1235 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1240 /* Sends packet. This doesn't actually send the packet instead it assembles
1241 it and marks it to be sent. However, if force_send is TRUE the packet
1242 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1243 will be derived from sock argument. Otherwise the valid arguments sent
1246 void silc_client_packet_send(SilcClient client,
1247 SilcSocketConnection sock,
1248 SilcPacketType type,
1250 SilcIdType dst_id_type,
1253 unsigned char *data,
1254 SilcUInt32 data_len,
1257 SilcPacketContext packetdata;
1258 const SilcBufferStruct packet;
1260 SilcUInt32 sequence = 0;
1265 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1267 /* Get data used in the packet sending, keys and stuff */
1268 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1269 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1270 cipher = ((SilcClientConnection)sock->user_data)->send_key;
1272 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1273 hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1275 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1276 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1277 dst_id_type = SILC_ID_SERVER;
1281 sequence = ((SilcClientConnection)sock->user_data)->psn_send++;
1284 block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1286 /* Set the packet context pointers */
1287 packetdata.flags = 0;
1288 packetdata.type = type;
1289 if (sock->user_data &&
1290 ((SilcClientConnection)sock->user_data)->local_id_data) {
1291 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1292 packetdata.src_id_len =
1293 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1296 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1297 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1299 packetdata.src_id_type = SILC_ID_CLIENT;
1301 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1302 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1303 packetdata.dst_id_type = dst_id_type;
1305 packetdata.dst_id = NULL;
1306 packetdata.dst_id_len = 0;
1307 packetdata.dst_id_type = SILC_ID_NONE;
1309 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1310 packetdata.src_id_len +
1311 packetdata.dst_id_len));
1312 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1313 packetdata.src_id_len + packetdata.dst_id_len;
1314 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
1316 /* Create the outgoing packet */
1317 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
1318 data, data_len, (const SilcBuffer)&packet)) {
1319 SILC_LOG_ERROR(("Error assembling packet"));
1323 /* Encrypt the packet */
1325 silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet,
1328 SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
1329 packet.data, packet.len);
1331 /* Now actually send the packet */
1332 silc_client_packet_send_real(client, sock, force_send);
1335 void silc_client_packet_queue_purge(SilcClient client,
1336 SilcSocketConnection sock)
1338 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1339 (SILC_IS_DISCONNECTED(sock) == FALSE)) {
1340 silc_packet_send(sock, TRUE);
1341 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1342 SILC_UNSET_OUTBUF_PENDING(sock);
1343 silc_buffer_clear(sock->outbuf);
1347 /* Closes connection to remote end. Free's all allocated data except
1348 for some information such as nickname etc. that are valid at all time.
1349 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1350 provided it will be checked whether the sock and `conn->sock' are the
1351 same (they can be different, ie. a socket can use `conn' as its
1352 connection but `conn->sock' might be actually a different connection
1353 than the `sock'). */
1355 void silc_client_close_connection_real(SilcClient client,
1356 SilcSocketConnection sock,
1357 SilcClientConnection conn)
1361 SILC_LOG_DEBUG(("Start"));
1366 if (!sock || (sock && conn->sock == sock))
1371 /* We won't listen for this connection anymore */
1372 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1374 /* Unregister all tasks */
1375 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1377 /* Close the actual connection */
1378 silc_net_close_connection(sock->sock);
1380 /* Cancel any active protocol */
1381 if (sock->protocol) {
1382 if (sock->protocol->protocol->type ==
1383 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1384 sock->protocol->protocol->type ==
1385 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1386 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1387 silc_protocol_execute_final(sock->protocol, client->schedule);
1388 /* The application will recall this function with these protocols
1389 (the ops->connect client operation). */
1392 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1393 silc_protocol_execute_final(sock->protocol, client->schedule);
1394 sock->protocol = NULL;
1398 /* Free everything */
1399 if (del && sock->user_data) {
1400 /* Free all cache entries */
1401 SilcIDCacheList list;
1402 SilcIDCacheEntry entry;
1403 SilcClientCommandPending *r;
1406 if (silc_idcache_get_all(conn->client_cache, &list)) {
1407 ret = silc_idcache_list_first(list, &entry);
1409 silc_client_del_client(client, conn, entry->context);
1410 ret = silc_idcache_list_next(list, &entry);
1412 silc_idcache_list_free(list);
1415 if (silc_idcache_get_all(conn->channel_cache, &list)) {
1416 ret = silc_idcache_list_first(list, &entry);
1418 silc_client_del_channel(client, conn, entry->context);
1419 ret = silc_idcache_list_next(list, &entry);
1421 silc_idcache_list_free(list);
1424 if (silc_idcache_get_all(conn->server_cache, &list)) {
1425 ret = silc_idcache_list_first(list, &entry);
1427 silc_client_del_server(client, conn, entry->context);
1428 ret = silc_idcache_list_next(list, &entry);
1430 silc_idcache_list_free(list);
1433 /* Clear ID caches */
1434 if (conn->client_cache)
1435 silc_idcache_free(conn->client_cache);
1436 if (conn->channel_cache)
1437 silc_idcache_free(conn->channel_cache);
1438 if (conn->server_cache)
1439 silc_idcache_free(conn->server_cache);
1441 /* Free data (my ID is freed in above silc_client_del_client).
1442 conn->nickname is freed when freeing the local_entry->nickname. */
1443 if (conn->remote_host)
1444 silc_free(conn->remote_host);
1445 if (conn->local_id_data)
1446 silc_free(conn->local_id_data);
1448 silc_cipher_free(conn->send_key);
1449 if (conn->receive_key)
1450 silc_cipher_free(conn->receive_key);
1451 if (conn->hmac_send)
1452 silc_hmac_free(conn->hmac_send);
1453 if (conn->hmac_receive)
1454 silc_hmac_free(conn->hmac_receive);
1456 silc_free(conn->rekey);
1458 if (conn->active_session) {
1459 sock->user_data = NULL;
1460 silc_client_ftp_session_free(conn->active_session);
1461 conn->active_session = NULL;
1464 silc_client_ftp_free_sessions(client, conn);
1466 silc_dlist_start(conn->pending_commands);
1467 while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END)
1468 silc_dlist_del(conn->pending_commands, r);
1469 if (conn->pending_commands)
1470 silc_dlist_uninit(conn->pending_commands);
1472 memset(conn, 0, sizeof(*conn));
1473 silc_client_del_connection(client, conn);
1476 silc_socket_free(sock);
1479 /* Closes the connection to the remote end */
1481 void silc_client_close_connection(SilcClient client,
1482 SilcClientConnection conn)
1484 silc_client_close_connection_real(client, NULL, conn);
1487 /* Called when we receive disconnection packet from server. This
1488 closes our end properly and displays the reason of the disconnection
1491 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1493 SilcClient client = (SilcClient)context;
1494 SilcSocketConnection sock;
1496 SILC_CLIENT_GET_SOCK(client, fd, sock);
1500 silc_client_close_connection_real(client, sock, sock->user_data);
1503 /* Called when we receive disconnection packet from server. This
1504 closes our end properly and displays the reason of the disconnection
1507 void silc_client_disconnected_by_server(SilcClient client,
1508 SilcSocketConnection sock,
1511 SilcClientConnection conn;
1513 char *message = NULL;
1515 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1517 if (packet->len < 1)
1520 status = (SilcStatus)packet->data[0];
1522 if (packet->len > 1 &&
1523 silc_utf8_valid(packet->data + 1, packet->len - 1))
1524 message = silc_memdup(packet->data + 1, packet->len - 1);
1526 conn = (SilcClientConnection)sock->user_data;
1527 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1528 client->internal->ops->disconnect(client, conn, status, message);
1532 SILC_SET_DISCONNECTED(sock);
1534 /* Close connection through scheduler. */
1535 silc_schedule_task_add(client->schedule, sock->sock,
1536 silc_client_disconnected_by_server_later,
1537 client, 0, 1, SILC_TASK_TIMEOUT,
1538 SILC_TASK_PRI_NORMAL);
1541 /* Received error message from server. Display it on the screen.
1542 We don't take any action what so ever of the error message. */
1544 void silc_client_error_by_server(SilcClient client,
1545 SilcSocketConnection sock,
1550 msg = silc_memdup(message->data, message->len);
1551 client->internal->ops->say(client, sock->user_data,
1552 SILC_CLIENT_MESSAGE_AUDIT, msg);
1556 /* Auto-nicking callback to send NICK command to server. */
1558 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1560 SilcClientConnection conn = (SilcClientConnection)context;
1561 SilcClient client = conn->client;
1563 silc_client_command_send(client, conn, SILC_COMMAND_NICK,
1564 ++conn->cmd_ident, 1, 1,
1565 client->nickname, strlen(client->nickname));
1568 /* Client session resuming callback. If the session was resumed
1569 this callback is called after the resuming is completed. This
1570 will call the `connect' client operation to the application
1571 since it has not been called yet. */
1573 static void silc_client_resume_session_cb(SilcClient client,
1574 SilcClientConnection conn,
1580 /* Notify application that connection is created to server */
1581 client->internal->ops->connect(client, conn, success ?
1582 SILC_CLIENT_CONN_SUCCESS_RESUME :
1583 SILC_CLIENT_CONN_ERROR);
1586 /* Issue INFO command to fetch the real server name and server
1587 information and other stuff. */
1588 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1589 silc_client_command_reply_info_i, 0,
1591 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1592 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1593 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1594 silc_buffer_free(sidp);
1598 /* Processes the received new Client ID from server. Old Client ID is
1599 deleted from cache and new one is added. */
1601 void silc_client_receive_new_id(SilcClient client,
1602 SilcSocketConnection sock,
1605 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1606 int connecting = FALSE;
1607 SilcClientID *client_id = silc_id_payload_get_id(idp);
1609 if (!conn->local_entry)
1612 /* Delete old ID from ID cache */
1613 if (conn->local_id) {
1614 /* Check whether they are different */
1615 if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1616 silc_free(client_id);
1620 silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1621 silc_free(conn->local_id);
1624 /* Save the new ID */
1626 if (conn->local_id_data)
1627 silc_free(conn->local_id_data);
1629 conn->local_id = client_id;
1630 conn->local_id_data = silc_id_payload_get_data(idp);
1631 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1633 if (!conn->local_entry)
1634 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1636 conn->local_entry->nickname = conn->nickname;
1637 if (!conn->local_entry->username)
1638 conn->local_entry->username = strdup(client->username);
1639 if (!conn->local_entry->server)
1640 conn->local_entry->server = strdup(conn->remote_host);
1641 conn->local_entry->id = conn->local_id;
1642 conn->local_entry->valid = TRUE;
1643 if (!conn->local_entry->channels)
1644 conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
1649 /* Put it to the ID cache */
1650 silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id,
1651 (void *)conn->local_entry, 0, NULL);
1656 /* Issue IDENTIFY command for itself to get resolved hostname
1657 correctly from server. */
1658 silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
1659 silc_client_command_reply_identify_i, 0,
1661 sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT);
1662 silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
1663 conn->cmd_ident, 1, 5, sidp->data, sidp->len);
1664 silc_buffer_free(sidp);
1666 if (!conn->params.detach_data) {
1667 /* Send NICK command if the nickname was set by the application (and is
1668 not same as the username). Send this with little timeout. */
1669 if (client->nickname && strcmp(client->nickname, client->username))
1670 silc_schedule_task_add(client->schedule, 0,
1671 silc_client_send_auto_nick, conn,
1672 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1674 /* Notify application of successful connection. We do it here now that
1675 we've received the Client ID and are allowed to send traffic. */
1676 client->internal->ops->connect(client, conn, SILC_CLIENT_CONN_SUCCESS);
1678 /* Issue INFO command to fetch the real server name and server
1679 information and other stuff. */
1680 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1681 silc_client_command_reply_info_i, 0,
1683 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1684 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1685 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1686 silc_buffer_free(sidp);
1688 /* We are resuming session. Start resolving informations from the
1689 server we need to set the client libary in the state before
1690 detaching the session. The connect client operation is called
1691 after this is successfully completed */
1692 silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1698 /* Removes a client entry from all channels it has joined. */
1700 void silc_client_remove_from_channels(SilcClient client,
1701 SilcClientConnection conn,
1702 SilcClientEntry client_entry)
1704 SilcHashTableList htl;
1705 SilcChannelUser chu;
1707 silc_hash_table_list(client_entry->channels, &htl);
1708 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1709 silc_hash_table_del(chu->client->channels, chu->channel);
1710 silc_hash_table_del(chu->channel->user_list, chu->client);
1714 silc_hash_table_list_reset(&htl);
1717 /* Replaces `old' client entries from all channels to `new' client entry.
1718 This can be called for example when nickname changes and old ID entry
1719 is replaced from ID cache with the new one. If the old ID entry is only
1720 updated, then this fucntion needs not to be called. */
1722 void silc_client_replace_from_channels(SilcClient client,
1723 SilcClientConnection conn,
1724 SilcClientEntry old,
1725 SilcClientEntry new)
1727 SilcHashTableList htl;
1728 SilcChannelUser chu;
1730 silc_hash_table_list(old->channels, &htl);
1731 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1732 /* Replace client entry */
1733 silc_hash_table_del(chu->client->channels, chu->channel);
1734 silc_hash_table_del(chu->channel->user_list, chu->client);
1737 silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1738 silc_hash_table_add(chu->client->channels, chu->channel, chu);
1740 silc_hash_table_list_reset(&htl);
1743 /* Registers failure timeout to process the received failure packet
1746 void silc_client_process_failure(SilcClient client,
1747 SilcSocketConnection sock,
1748 SilcPacketContext *packet)
1750 SilcUInt32 failure = 0;
1752 if (sock->protocol) {
1753 if (packet->buffer->len >= 4)
1754 SILC_GET32_MSB(failure, packet->buffer->data);
1756 /* Notify application */
1757 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1762 /* A timeout callback for the re-key. We will be the initiator of the
1765 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1767 SilcSocketConnection sock = (SilcSocketConnection)context;
1768 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1769 SilcClient client = (SilcClient)conn->rekey->context;
1770 SilcProtocol protocol;
1771 SilcClientRekeyInternalContext *proto_ctx;
1773 SILC_LOG_DEBUG(("Start"));
1775 /* Allocate internal protocol context. This is sent as context
1777 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1778 proto_ctx->client = (void *)client;
1779 proto_ctx->sock = silc_socket_dup(sock);
1780 proto_ctx->responder = FALSE;
1781 proto_ctx->pfs = conn->rekey->pfs;
1783 /* Perform rekey protocol. Will call the final callback after the
1784 protocol is over. */
1785 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1786 &protocol, proto_ctx, silc_client_rekey_final);
1787 sock->protocol = protocol;
1789 /* Run the protocol */
1790 silc_protocol_execute(protocol, client->schedule, 0, 0);
1792 /* Re-register re-key timeout */
1793 silc_schedule_task_add(client->schedule, sock->sock,
1794 silc_client_rekey_callback,
1795 context, conn->rekey->timeout, 0,
1796 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1799 /* The final callback for the REKEY protocol. This will actually take the
1800 new key material into use. */
1802 SILC_TASK_CALLBACK(silc_client_rekey_final)
1804 SilcProtocol protocol = (SilcProtocol)context;
1805 SilcClientRekeyInternalContext *ctx =
1806 (SilcClientRekeyInternalContext *)protocol->context;
1807 SilcClient client = (SilcClient)ctx->client;
1808 SilcSocketConnection sock = ctx->sock;
1810 SILC_LOG_DEBUG(("Start"));
1812 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1813 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1814 /* Error occured during protocol */
1815 silc_protocol_cancel(protocol, client->schedule);
1816 silc_protocol_free(protocol);
1817 sock->protocol = NULL;
1819 silc_packet_context_free(ctx->packet);
1821 silc_ske_free(ctx->ske);
1822 silc_socket_free(ctx->sock);
1827 /* Purge the outgoing data queue to assure that all rekey packets really
1828 go to the network before we quit the protocol. */
1829 silc_client_packet_queue_purge(client, sock);
1832 silc_protocol_free(protocol);
1833 sock->protocol = NULL;
1835 silc_packet_context_free(ctx->packet);
1837 silc_ske_free(ctx->ske);
1838 silc_socket_free(ctx->sock);
1842 /* Processes incoming connection authentication method request packet.
1843 It is a reply to our previously sent request. The packet can be used
1844 to resolve the authentication method for the current session if the
1845 client does not know it beforehand. */
1847 void silc_client_connection_auth_request(SilcClient client,
1848 SilcSocketConnection sock,
1849 SilcPacketContext *packet)
1851 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1852 SilcUInt16 conn_type, auth_meth;
1855 /* If we haven't send our request then ignore this one. */
1856 if (!conn->connauth)
1859 /* Parse the payload */
1860 ret = silc_buffer_unformat(packet->buffer,
1861 SILC_STR_UI_SHORT(&conn_type),
1862 SILC_STR_UI_SHORT(&auth_meth),
1865 auth_meth = SILC_AUTH_NONE;
1867 /* Call the request callback to notify application for received
1868 authentication method information. */
1869 if (conn->connauth->callback)
1870 (*conn->connauth->callback)(client, conn, auth_meth,
1871 conn->connauth->context);
1873 silc_schedule_task_del(client->schedule, conn->connauth->timeout);
1875 silc_free(conn->connauth);
1876 conn->connauth = NULL;
1879 /* Timeout task callback called if the server does not reply to our
1880 connection authentication method request in the specified time interval. */
1882 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1884 SilcClientConnection conn = (SilcClientConnection)context;
1885 SilcClient client = conn->client;
1887 if (!conn->connauth)
1890 /* Call the request callback to notify application */
1891 if (conn->connauth->callback)
1892 (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE,
1893 conn->connauth->context);
1895 silc_free(conn->connauth);
1896 conn->connauth = NULL;
1899 /* This function can be used to request the current authentication method
1900 from the server. This may be called when connecting to the server
1901 and the client library requests the authentication data from the
1902 application. If the application does not know the current authentication
1903 method it can request it from the server using this function.
1904 The `callback' with `context' will be called after the server has
1905 replied back with the current authentication method. */
1908 silc_client_request_authentication_method(SilcClient client,
1909 SilcClientConnection conn,
1910 SilcConnectionAuthRequest callback,
1913 SilcClientConnAuthRequest connauth;
1916 connauth = silc_calloc(1, sizeof(*connauth));
1917 connauth->callback = callback;
1918 connauth->context = context;
1921 silc_free(conn->connauth);
1923 conn->connauth = connauth;
1925 /* Assemble the request packet and send it to the server */
1926 packet = silc_buffer_alloc(4);
1927 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1928 silc_buffer_format(packet,
1929 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
1930 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
1932 silc_client_packet_send(client, conn->sock,
1933 SILC_PACKET_CONNECTION_AUTH_REQUEST,
1934 NULL, 0, NULL, NULL,
1935 packet->data, packet->len, FALSE);
1936 silc_buffer_free(packet);
1938 /* Register a timeout in case server does not reply anything back. */
1940 silc_schedule_task_add(client->schedule, conn->sock->sock,
1941 silc_client_request_authentication_method_timeout,
1943 client->internal->params->connauth_request_secs, 0,
1944 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);