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);
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 SILC_LOG_DEBUG(("Deleting connection %s%d", conn->remote_host,
245 for (i = 0; i < client->internal->conns_count; i++)
246 if (client->internal->conns[i] == conn) {
248 silc_idcache_free(conn->client_cache);
249 silc_idcache_free(conn->channel_cache);
250 silc_idcache_free(conn->server_cache);
251 if (conn->pending_commands)
252 silc_dlist_uninit(conn->pending_commands);
253 silc_free(conn->remote_host);
254 silc_dlist_uninit(conn->ftp_sessions);
257 client->internal->conns[i] = NULL;
261 /* Adds listener socket to the listener sockets table. This function is
262 used to add socket objects that are listeners to the client. This should
263 not be used to add other connection objects. */
265 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
269 if (!client->internal->sockets) {
270 client->internal->sockets =
271 silc_calloc(1, sizeof(*client->internal->sockets));
272 client->internal->sockets[0] = silc_socket_dup(sock);
273 client->internal->sockets_count = 1;
277 for (i = 0; i < client->internal->sockets_count; i++) {
278 if (client->internal->sockets[i] == NULL) {
279 client->internal->sockets[i] = silc_socket_dup(sock);
284 client->internal->sockets =
285 silc_realloc(client->internal->sockets,
286 sizeof(*client->internal->sockets) *
287 (client->internal->sockets_count + 1));
288 client->internal->sockets[client->internal->sockets_count] =
289 silc_socket_dup(sock);
290 client->internal->sockets_count++;
293 /* Deletes listener socket from the listener sockets table. */
295 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
299 if (!client->internal->sockets)
302 for (i = 0; i < client->internal->sockets_count; i++) {
303 if (client->internal->sockets[i] == sock) {
304 silc_socket_free(sock);
305 client->internal->sockets[i] = NULL;
312 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
316 /* XXX In the future we should give up this non-blocking connect all
317 together and use threads instead. */
318 /* Create connection to server asynchronously */
319 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
323 /* Register task that will receive the async connect and will
325 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
326 silc_client_connect_to_server_start,
329 SILC_TASK_PRI_NORMAL);
330 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
337 /* Connects to remote server. This is the main routine used to connect
338 to SILC server. Returns -1 on error and the created socket otherwise.
339 The `context' is user context that is saved into the SilcClientConnection
340 that is created after the connection is created. Note that application
341 may handle the connecting process outside the library. If this is the
342 case then this function is not used at all. When the connecting is
343 done the `connect' client operation is called. */
345 int silc_client_connect_to_server(SilcClient client,
346 SilcClientConnectionParams *params,
347 int port, char *host, void *context)
349 SilcClientInternalConnectContext *ctx;
350 SilcClientConnection conn;
353 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
356 conn = silc_client_add_connection(client, params, host, port, context);
358 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
359 "Connecting to port %d of server %s", port, host);
361 /* Allocate internal context for connection process. This is
362 needed as we are doing async connecting. */
363 ctx = silc_calloc(1, sizeof(*ctx));
364 ctx->client = client;
366 ctx->host = strdup(host);
370 /* Do the actual connecting process */
371 sock = silc_client_connect_to_server_internal(ctx);
373 silc_client_del_connection(client, conn);
377 /* Socket hostname and IP lookup callback that is called before actually
378 starting the key exchange. The lookup is called from the function
379 silc_client_start_key_exchange. */
381 static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
384 SilcClientConnection conn = (SilcClientConnection)context;
385 SilcClient client = conn->client;
386 SilcProtocol protocol;
387 SilcClientKEInternalContext *proto_ctx;
389 SILC_LOG_DEBUG(("Start"));
391 /* XXX We should most likely use the resolved host name instead of the
392 one user provided for us. */
393 silc_free(conn->sock->hostname);
394 conn->sock->hostname = strdup(conn->remote_host);
396 conn->sock->ip = strdup(conn->remote_host);
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 packet type %d", type));
965 /* Parse the packet type */
967 case SILC_PACKET_DISCONNECT:
968 silc_client_disconnected_by_server(client, sock, buffer);
970 case SILC_PACKET_SUCCESS:
972 * Success received for something. For now we can have only
973 * one protocol for connection executing at once hence this
974 * success message is for whatever protocol is executing currently.
977 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
979 case SILC_PACKET_FAILURE:
981 * Failure received for some protocol. Set the protocol state to
982 * error and call the protocol callback. This fill cause error on
983 * protocol and it will call the final callback.
985 silc_client_process_failure(client, sock, packet);
987 case SILC_PACKET_REJECT:
990 case SILC_PACKET_NOTIFY:
992 * Received notify message
994 silc_client_notify_by_server(client, sock, packet);
997 case SILC_PACKET_ERROR:
999 * Received error message
1001 silc_client_error_by_server(client, sock, buffer);
1004 case SILC_PACKET_CHANNEL_MESSAGE:
1006 * Received message to (from, actually) a channel
1008 silc_client_channel_message(client, sock, packet);
1010 case SILC_PACKET_CHANNEL_KEY:
1012 * Received key for a channel. By receiving this key the client will be
1013 * able to talk to the channel it has just joined. This can also be
1014 * a new key for existing channel as keys expire peridiocally.
1016 silc_client_receive_channel_key(client, sock, buffer);
1019 case SILC_PACKET_PRIVATE_MESSAGE:
1021 * Received private message
1023 silc_client_private_message(client, sock, packet);
1025 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1027 * Received private message key
1031 case SILC_PACKET_COMMAND_REPLY:
1033 * Recived reply for a command
1035 silc_client_command_reply_process(client, sock, packet);
1038 case SILC_PACKET_KEY_EXCHANGE:
1039 if (sock->protocol && sock->protocol->protocol &&
1040 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
1041 SilcClientKEInternalContext *proto_ctx =
1042 (SilcClientKEInternalContext *)sock->protocol->context;
1044 proto_ctx->packet = silc_packet_context_dup(packet);
1045 proto_ctx->dest_id_type = packet->src_id_type;
1046 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1047 packet->src_id_type);
1048 if (!proto_ctx->dest_id)
1051 /* Let the protocol handle the packet */
1052 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1054 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1055 "protocol active, packet dropped."));
1059 case SILC_PACKET_KEY_EXCHANGE_1:
1060 if (sock->protocol && sock->protocol->protocol &&
1061 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1062 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1064 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1065 SilcClientRekeyInternalContext *proto_ctx =
1066 (SilcClientRekeyInternalContext *)sock->protocol->context;
1068 if (proto_ctx->packet)
1069 silc_packet_context_free(proto_ctx->packet);
1071 proto_ctx->packet = silc_packet_context_dup(packet);
1073 /* Let the protocol handle the packet */
1074 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1076 SilcClientKEInternalContext *proto_ctx =
1077 (SilcClientKEInternalContext *)sock->protocol->context;
1079 if (proto_ctx->packet)
1080 silc_packet_context_free(proto_ctx->packet);
1082 proto_ctx->packet = silc_packet_context_dup(packet);
1083 proto_ctx->dest_id_type = packet->src_id_type;
1084 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1085 packet->src_id_type);
1086 if (!proto_ctx->dest_id)
1089 /* Let the protocol handle the packet */
1090 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1093 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1094 "protocol active, packet dropped."));
1097 case SILC_PACKET_KEY_EXCHANGE_2:
1098 if (sock->protocol && sock->protocol->protocol &&
1099 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1100 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1102 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1103 SilcClientRekeyInternalContext *proto_ctx =
1104 (SilcClientRekeyInternalContext *)sock->protocol->context;
1106 if (proto_ctx->packet)
1107 silc_packet_context_free(proto_ctx->packet);
1109 proto_ctx->packet = silc_packet_context_dup(packet);
1111 /* Let the protocol handle the packet */
1112 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1114 SilcClientKEInternalContext *proto_ctx =
1115 (SilcClientKEInternalContext *)sock->protocol->context;
1117 if (proto_ctx->packet)
1118 silc_packet_context_free(proto_ctx->packet);
1119 if (proto_ctx->dest_id)
1120 silc_free(proto_ctx->dest_id);
1121 proto_ctx->packet = silc_packet_context_dup(packet);
1122 proto_ctx->dest_id_type = packet->src_id_type;
1123 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1124 packet->src_id_type);
1125 if (!proto_ctx->dest_id)
1128 /* Let the protocol handle the packet */
1129 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1132 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1133 "protocol active, packet dropped."));
1137 case SILC_PACKET_NEW_ID:
1140 * Received new ID from server. This packet is received at
1141 * the connection to the server. New ID is also received when
1142 * user changes nickname but in that case the new ID is received
1143 * as command reply and not as this packet type.
1147 idp = silc_id_payload_parse(buffer->data, buffer->len);
1150 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1153 silc_client_receive_new_id(client, sock, idp);
1154 silc_id_payload_free(idp);
1158 case SILC_PACKET_HEARTBEAT:
1160 * Received heartbeat packet
1162 SILC_LOG_DEBUG(("Heartbeat packet"));
1165 case SILC_PACKET_KEY_AGREEMENT:
1167 * Received key agreement packet
1169 SILC_LOG_DEBUG(("Key agreement packet"));
1170 silc_client_key_agreement(client, sock, packet);
1173 case SILC_PACKET_REKEY:
1174 SILC_LOG_DEBUG(("Re-key packet"));
1175 /* We ignore this for now */
1178 case SILC_PACKET_REKEY_DONE:
1179 SILC_LOG_DEBUG(("Re-key done packet"));
1181 if (sock->protocol && sock->protocol->protocol &&
1182 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1184 SilcClientRekeyInternalContext *proto_ctx =
1185 (SilcClientRekeyInternalContext *)sock->protocol->context;
1187 if (proto_ctx->packet)
1188 silc_packet_context_free(proto_ctx->packet);
1190 proto_ctx->packet = silc_packet_context_dup(packet);
1192 /* Let the protocol handle the packet */
1193 if (proto_ctx->responder == FALSE)
1194 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1196 /* Let the protocol handle the packet */
1197 silc_protocol_execute(sock->protocol, client->schedule,
1200 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1201 "protocol active, packet dropped."));
1205 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1207 * Reveived reply to our connection authentication method request
1208 * packet. This is used to resolve the authentication method for the
1209 * current session from the server if the client does not know it.
1211 silc_client_connection_auth_request(client, sock, packet);
1214 case SILC_PACKET_FTP:
1215 /* Received file transfer packet. */
1216 silc_client_ftp(client, sock, packet);
1220 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1225 /* Sends packet. This doesn't actually send the packet instead it assembles
1226 it and marks it to be sent. However, if force_send is TRUE the packet
1227 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1228 will be derived from sock argument. Otherwise the valid arguments sent
1231 void silc_client_packet_send(SilcClient client,
1232 SilcSocketConnection sock,
1233 SilcPacketType type,
1235 SilcIdType dst_id_type,
1238 unsigned char *data,
1239 SilcUInt32 data_len,
1242 SilcPacketContext packetdata;
1243 const SilcBufferStruct packet;
1245 SilcUInt32 sequence = 0;
1250 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1252 /* Get data used in the packet sending, keys and stuff */
1253 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1254 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1255 cipher = ((SilcClientConnection)sock->user_data)->send_key;
1257 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1258 hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1260 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1261 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1262 dst_id_type = SILC_ID_SERVER;
1266 sequence = ((SilcClientConnection)sock->user_data)->psn_send++;
1269 block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1271 /* Set the packet context pointers */
1272 packetdata.flags = 0;
1273 packetdata.type = type;
1274 if (sock->user_data &&
1275 ((SilcClientConnection)sock->user_data)->local_id_data) {
1276 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1277 packetdata.src_id_len =
1278 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1281 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1282 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1284 packetdata.src_id_type = SILC_ID_CLIENT;
1286 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1287 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1288 packetdata.dst_id_type = dst_id_type;
1290 packetdata.dst_id = NULL;
1291 packetdata.dst_id_len = 0;
1292 packetdata.dst_id_type = SILC_ID_NONE;
1294 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1295 packetdata.src_id_len +
1296 packetdata.dst_id_len));
1297 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1298 packetdata.src_id_len + packetdata.dst_id_len;
1299 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
1301 /* Create the outgoing packet */
1302 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
1303 data, data_len, (const SilcBuffer)&packet)) {
1304 SILC_LOG_ERROR(("Error assembling packet"));
1308 /* Encrypt the packet */
1310 silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet,
1313 SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
1314 packet.data, packet.len);
1316 /* Now actually send the packet */
1317 silc_client_packet_send_real(client, sock, force_send);
1320 void silc_client_packet_queue_purge(SilcClient client,
1321 SilcSocketConnection sock)
1323 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1324 (SILC_IS_DISCONNECTED(sock) == FALSE)) {
1325 silc_packet_send(sock, TRUE);
1326 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1327 SILC_UNSET_OUTBUF_PENDING(sock);
1328 silc_buffer_clear(sock->outbuf);
1332 /* Closes connection to remote end. Free's all allocated data except
1333 for some information such as nickname etc. that are valid at all time.
1334 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1335 provided it will be checked whether the sock and `conn->sock' are the
1336 same (they can be different, ie. a socket can use `conn' as its
1337 connection but `conn->sock' might be actually a different connection
1338 than the `sock'). */
1340 void silc_client_close_connection_real(SilcClient client,
1341 SilcSocketConnection sock,
1342 SilcClientConnection conn)
1346 SILC_LOG_DEBUG(("Start"));
1351 if (!sock || (sock && conn->sock == sock))
1356 /* We won't listen for this connection anymore */
1357 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1359 /* Unregister all tasks */
1360 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1362 /* Close the actual connection */
1363 silc_net_close_connection(sock->sock);
1365 /* Cancel any active protocol */
1366 if (sock->protocol) {
1367 if (sock->protocol->protocol->type ==
1368 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1369 sock->protocol->protocol->type ==
1370 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1371 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1372 silc_protocol_execute_final(sock->protocol, client->schedule);
1373 /* The application will recall this function with these protocols
1374 (the ops->connect client operation). */
1377 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1378 silc_protocol_execute_final(sock->protocol, client->schedule);
1379 sock->protocol = NULL;
1383 /* Free everything */
1384 if (del && sock->user_data) {
1385 /* Free all cache entries */
1386 SilcIDCacheList list;
1387 SilcIDCacheEntry entry;
1388 SilcClientCommandPending *r;
1391 if (silc_idcache_get_all(conn->client_cache, &list)) {
1392 ret = silc_idcache_list_first(list, &entry);
1394 silc_client_del_client(client, conn, entry->context);
1395 ret = silc_idcache_list_next(list, &entry);
1397 silc_idcache_list_free(list);
1400 if (silc_idcache_get_all(conn->channel_cache, &list)) {
1401 ret = silc_idcache_list_first(list, &entry);
1403 silc_client_del_channel(client, conn, entry->context);
1404 ret = silc_idcache_list_next(list, &entry);
1406 silc_idcache_list_free(list);
1409 if (silc_idcache_get_all(conn->server_cache, &list)) {
1410 ret = silc_idcache_list_first(list, &entry);
1412 silc_client_del_server(client, conn, entry->context);
1413 ret = silc_idcache_list_next(list, &entry);
1415 silc_idcache_list_free(list);
1418 /* Clear ID caches */
1419 if (conn->client_cache)
1420 silc_idcache_free(conn->client_cache);
1421 if (conn->channel_cache)
1422 silc_idcache_free(conn->channel_cache);
1423 if (conn->server_cache)
1424 silc_idcache_free(conn->server_cache);
1426 /* Free data (my ID is freed in above silc_client_del_client).
1427 conn->nickname is freed when freeing the local_entry->nickname. */
1428 if (conn->remote_host)
1429 silc_free(conn->remote_host);
1430 if (conn->local_id_data)
1431 silc_free(conn->local_id_data);
1433 silc_cipher_free(conn->send_key);
1434 if (conn->receive_key)
1435 silc_cipher_free(conn->receive_key);
1436 if (conn->hmac_send)
1437 silc_hmac_free(conn->hmac_send);
1438 if (conn->hmac_receive)
1439 silc_hmac_free(conn->hmac_receive);
1441 silc_free(conn->rekey);
1443 if (conn->active_session) {
1444 sock->user_data = NULL;
1445 silc_client_ftp_session_free(conn->active_session);
1446 conn->active_session = NULL;
1449 silc_client_ftp_free_sessions(client, conn);
1451 silc_dlist_start(conn->pending_commands);
1452 while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END)
1453 silc_dlist_del(conn->pending_commands, r);
1454 if (conn->pending_commands)
1455 silc_dlist_uninit(conn->pending_commands);
1457 memset(conn, 0, sizeof(*conn));
1458 silc_client_del_connection(client, conn);
1461 silc_socket_free(sock);
1464 /* Closes the connection to the remote end */
1466 void silc_client_close_connection(SilcClient client,
1467 SilcClientConnection conn)
1469 silc_client_close_connection_real(client, NULL, conn);
1472 /* Called when we receive disconnection packet from server. This
1473 closes our end properly and displays the reason of the disconnection
1476 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1478 SilcClient client = (SilcClient)context;
1479 SilcSocketConnection sock;
1481 SILC_CLIENT_GET_SOCK(client, fd, sock);
1485 silc_client_close_connection_real(client, sock, sock->user_data);
1488 /* Called when we receive disconnection packet from server. This
1489 closes our end properly and displays the reason of the disconnection
1492 void silc_client_disconnected_by_server(SilcClient client,
1493 SilcSocketConnection sock,
1496 SilcClientConnection conn;
1498 char *message = NULL;
1500 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1502 if (packet->len < 1)
1505 status = (SilcStatus)packet->data[0];
1507 if (packet->len > 1 &&
1508 silc_utf8_valid(packet->data + 1, packet->len - 1))
1509 message = silc_memdup(packet->data + 1, packet->len - 1);
1511 conn = (SilcClientConnection)sock->user_data;
1512 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1513 client->internal->ops->disconnect(client, conn, status, message);
1517 SILC_SET_DISCONNECTED(sock);
1519 /* Close connection through scheduler. */
1520 silc_schedule_task_add(client->schedule, sock->sock,
1521 silc_client_disconnected_by_server_later,
1522 client, 0, 1, SILC_TASK_TIMEOUT,
1523 SILC_TASK_PRI_NORMAL);
1526 /* Received error message from server. Display it on the screen.
1527 We don't take any action what so ever of the error message. */
1529 void silc_client_error_by_server(SilcClient client,
1530 SilcSocketConnection sock,
1535 msg = silc_memdup(message->data, message->len);
1536 client->internal->ops->say(client, sock->user_data,
1537 SILC_CLIENT_MESSAGE_AUDIT, msg);
1541 /* Auto-nicking callback to send NICK command to server. */
1543 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1545 SilcClientConnection conn = (SilcClientConnection)context;
1546 SilcClient client = conn->client;
1548 silc_client_command_send(client, conn, SILC_COMMAND_NICK,
1549 ++conn->cmd_ident, 1, 1,
1550 client->nickname, strlen(client->nickname));
1553 /* Client session resuming callback. If the session was resumed
1554 this callback is called after the resuming is completed. This
1555 will call the `connect' client operation to the application
1556 since it has not been called yet. */
1558 static void silc_client_resume_session_cb(SilcClient client,
1559 SilcClientConnection conn,
1565 /* Notify application that connection is created to server */
1566 client->internal->ops->connect(client, conn, success ?
1567 SILC_CLIENT_CONN_SUCCESS_RESUME :
1568 SILC_CLIENT_CONN_ERROR);
1571 /* Issue INFO command to fetch the real server name and server
1572 information and other stuff. */
1573 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1574 silc_client_command_reply_info_i, 0,
1576 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1577 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1578 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1579 silc_buffer_free(sidp);
1583 /* Processes the received new Client ID from server. Old Client ID is
1584 deleted from cache and new one is added. */
1586 void silc_client_receive_new_id(SilcClient client,
1587 SilcSocketConnection sock,
1590 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1591 int connecting = FALSE;
1592 SilcClientID *client_id = silc_id_payload_get_id(idp);
1594 if (!conn->local_entry)
1597 /* Delete old ID from ID cache */
1598 if (conn->local_id) {
1599 /* Check whether they are different */
1600 if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1601 silc_free(client_id);
1605 silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1606 silc_free(conn->local_id);
1609 /* Save the new ID */
1611 if (conn->local_id_data)
1612 silc_free(conn->local_id_data);
1614 conn->local_id = client_id;
1615 conn->local_id_data = silc_id_payload_get_data(idp);
1616 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1618 if (!conn->local_entry)
1619 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1621 conn->local_entry->nickname = conn->nickname;
1622 if (!conn->local_entry->username)
1623 conn->local_entry->username = strdup(client->username);
1624 if (!conn->local_entry->hostname)
1625 conn->local_entry->hostname = strdup(client->hostname);
1626 if (!conn->local_entry->server)
1627 conn->local_entry->server = strdup(conn->remote_host);
1628 conn->local_entry->id = conn->local_id;
1629 conn->local_entry->valid = TRUE;
1630 if (!conn->local_entry->channels)
1631 conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
1636 /* Put it to the ID cache */
1637 silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id,
1638 (void *)conn->local_entry, 0, NULL);
1641 if (!conn->params.detach_data) {
1644 /* Send NICK command if the nickname was set by the application (and is
1645 not same as the username). Send this with little timeout. */
1646 if (client->nickname && strcmp(client->nickname, client->username))
1647 silc_schedule_task_add(client->schedule, 0,
1648 silc_client_send_auto_nick, conn,
1649 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1651 /* Notify application of successful connection. We do it here now that
1652 we've received the Client ID and are allowed to send traffic. */
1653 client->internal->ops->connect(client, conn, SILC_CLIENT_CONN_SUCCESS);
1655 /* Issue INFO command to fetch the real server name and server
1656 information and other stuff. */
1657 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1658 silc_client_command_reply_info_i, 0,
1660 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1661 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1662 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1663 silc_buffer_free(sidp);
1665 /* We are resuming session. Start resolving informations from the
1666 server we need to set the client libary in the state before
1667 detaching the session. The connect client operation is called
1668 after this is successfully completed */
1669 silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1675 /* Removes a client entry from all channels it has joined. */
1677 void silc_client_remove_from_channels(SilcClient client,
1678 SilcClientConnection conn,
1679 SilcClientEntry client_entry)
1681 SilcHashTableList htl;
1682 SilcChannelUser chu;
1684 silc_hash_table_list(client_entry->channels, &htl);
1685 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1686 silc_hash_table_del(chu->client->channels, chu->channel);
1687 silc_hash_table_del(chu->channel->user_list, chu->client);
1691 silc_hash_table_list_reset(&htl);
1694 /* Replaces `old' client entries from all channels to `new' client entry.
1695 This can be called for example when nickname changes and old ID entry
1696 is replaced from ID cache with the new one. If the old ID entry is only
1697 updated, then this fucntion needs not to be called. */
1699 void silc_client_replace_from_channels(SilcClient client,
1700 SilcClientConnection conn,
1701 SilcClientEntry old,
1702 SilcClientEntry new)
1704 SilcHashTableList htl;
1705 SilcChannelUser chu;
1707 silc_hash_table_list(old->channels, &htl);
1708 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1709 /* Replace client entry */
1710 silc_hash_table_del(chu->client->channels, chu->channel);
1711 silc_hash_table_del(chu->channel->user_list, chu->client);
1714 silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1715 silc_hash_table_add(chu->client->channels, chu->channel, chu);
1717 silc_hash_table_list_reset(&htl);
1720 /* Registers failure timeout to process the received failure packet
1723 void silc_client_process_failure(SilcClient client,
1724 SilcSocketConnection sock,
1725 SilcPacketContext *packet)
1727 SilcUInt32 failure = 0;
1729 if (sock->protocol) {
1730 if (packet->buffer->len >= 4)
1731 SILC_GET32_MSB(failure, packet->buffer->data);
1733 /* Notify application */
1734 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1739 /* A timeout callback for the re-key. We will be the initiator of the
1742 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1744 SilcSocketConnection sock = (SilcSocketConnection)context;
1745 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1746 SilcClient client = (SilcClient)conn->rekey->context;
1747 SilcProtocol protocol;
1748 SilcClientRekeyInternalContext *proto_ctx;
1750 SILC_LOG_DEBUG(("Start"));
1752 /* Allocate internal protocol context. This is sent as context
1754 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1755 proto_ctx->client = (void *)client;
1756 proto_ctx->sock = silc_socket_dup(sock);
1757 proto_ctx->responder = FALSE;
1758 proto_ctx->pfs = conn->rekey->pfs;
1760 /* Perform rekey protocol. Will call the final callback after the
1761 protocol is over. */
1762 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1763 &protocol, proto_ctx, silc_client_rekey_final);
1764 sock->protocol = protocol;
1766 /* Run the protocol */
1767 silc_protocol_execute(protocol, client->schedule, 0, 0);
1769 /* Re-register re-key timeout */
1770 silc_schedule_task_add(client->schedule, sock->sock,
1771 silc_client_rekey_callback,
1772 context, conn->rekey->timeout, 0,
1773 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1776 /* The final callback for the REKEY protocol. This will actually take the
1777 new key material into use. */
1779 SILC_TASK_CALLBACK(silc_client_rekey_final)
1781 SilcProtocol protocol = (SilcProtocol)context;
1782 SilcClientRekeyInternalContext *ctx =
1783 (SilcClientRekeyInternalContext *)protocol->context;
1784 SilcClient client = (SilcClient)ctx->client;
1785 SilcSocketConnection sock = ctx->sock;
1787 SILC_LOG_DEBUG(("Start"));
1789 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1790 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1791 /* Error occured during protocol */
1792 silc_protocol_cancel(protocol, client->schedule);
1793 silc_protocol_free(protocol);
1794 sock->protocol = NULL;
1796 silc_packet_context_free(ctx->packet);
1798 silc_ske_free(ctx->ske);
1799 silc_socket_free(ctx->sock);
1804 /* Purge the outgoing data queue to assure that all rekey packets really
1805 go to the network before we quit the protocol. */
1806 silc_client_packet_queue_purge(client, sock);
1809 silc_protocol_free(protocol);
1810 sock->protocol = NULL;
1812 silc_packet_context_free(ctx->packet);
1814 silc_ske_free(ctx->ske);
1815 silc_socket_free(ctx->sock);
1819 /* Processes incoming connection authentication method request packet.
1820 It is a reply to our previously sent request. The packet can be used
1821 to resolve the authentication method for the current session if the
1822 client does not know it beforehand. */
1824 void silc_client_connection_auth_request(SilcClient client,
1825 SilcSocketConnection sock,
1826 SilcPacketContext *packet)
1828 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1829 SilcUInt16 conn_type, auth_meth;
1832 /* If we haven't send our request then ignore this one. */
1833 if (!conn->connauth)
1836 /* Parse the payload */
1837 ret = silc_buffer_unformat(packet->buffer,
1838 SILC_STR_UI_SHORT(&conn_type),
1839 SILC_STR_UI_SHORT(&auth_meth),
1842 auth_meth = SILC_AUTH_NONE;
1844 /* Call the request callback to notify application for received
1845 authentication method information. */
1846 if (conn->connauth->callback)
1847 (*conn->connauth->callback)(client, conn, auth_meth,
1848 conn->connauth->context);
1850 silc_schedule_task_del(client->schedule, conn->connauth->timeout);
1852 silc_free(conn->connauth);
1853 conn->connauth = NULL;
1856 /* Timeout task callback called if the server does not reply to our
1857 connection authentication method request in the specified time interval. */
1859 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1861 SilcClientConnection conn = (SilcClientConnection)context;
1862 SilcClient client = conn->client;
1864 if (!conn->connauth)
1867 /* Call the request callback to notify application */
1868 if (conn->connauth->callback)
1869 (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE,
1870 conn->connauth->context);
1872 silc_free(conn->connauth);
1873 conn->connauth = NULL;
1876 /* This function can be used to request the current authentication method
1877 from the server. This may be called when connecting to the server
1878 and the client library requests the authentication data from the
1879 application. If the application does not know the current authentication
1880 method it can request it from the server using this function.
1881 The `callback' with `context' will be called after the server has
1882 replied back with the current authentication method. */
1885 silc_client_request_authentication_method(SilcClient client,
1886 SilcClientConnection conn,
1887 SilcConnectionAuthRequest callback,
1890 SilcClientConnAuthRequest connauth;
1893 connauth = silc_calloc(1, sizeof(*connauth));
1894 connauth->callback = callback;
1895 connauth->context = context;
1898 silc_free(conn->connauth);
1900 conn->connauth = connauth;
1902 /* Assemble the request packet and send it to the server */
1903 packet = silc_buffer_alloc(4);
1904 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1905 silc_buffer_format(packet,
1906 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
1907 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
1909 silc_client_packet_send(client, conn->sock,
1910 SILC_PACKET_CONNECTION_AUTH_REQUEST,
1911 NULL, 0, NULL, NULL,
1912 packet->data, packet->len, FALSE);
1913 silc_buffer_free(packet);
1915 /* Register a timeout in case server does not reply anything back. */
1917 silc_schedule_task_add(client->schedule, conn->sock->sock,
1918 silc_client_request_authentication_method_timeout,
1920 client->internal->params->connauth_request_secs, 0,
1921 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);