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_final);
31 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
33 static void silc_client_packet_parse_type(SilcClient client,
34 SilcSocketConnection sock,
35 SilcPacketContext *packet);
36 void silc_client_resolve_auth_method(bool success,
37 SilcProtocolAuthMeth auth_meth,
38 const unsigned char *auth_data,
39 SilcUInt32 auth_data_len, void *context);
41 /* Allocates new client object. This has to be done before client may
42 work. After calling this one must call silc_client_init to initialize
43 the client. The `application' is application specific user data pointer
44 and caller must free it. */
46 SilcClient silc_client_alloc(SilcClientOperations *ops,
47 SilcClientParams *params,
49 const char *version_string)
51 SilcClient new_client;
53 new_client = silc_calloc(1, sizeof(*new_client));
54 new_client->application = application;
56 new_client->internal = silc_calloc(1, sizeof(*new_client->internal));
57 new_client->internal->ops = ops;
58 new_client->internal->params =
59 silc_calloc(1, sizeof(*new_client->internal->params));
61 version_string = silc_version_string;
62 new_client->internal->silc_client_version = strdup(version_string);
65 memcpy(new_client->internal->params, params, sizeof(*params));
67 if (!new_client->internal->params->task_max)
68 new_client->internal->params->task_max = 200;
70 if (!new_client->internal->params->rekey_secs)
71 new_client->internal->params->rekey_secs = 3600;
73 if (!new_client->internal->params->connauth_request_secs)
74 new_client->internal->params->connauth_request_secs = 2;
76 new_client->internal->params->
77 nickname_format[sizeof(new_client->internal->
78 params->nickname_format) - 1] = 0;
83 /* Frees client object and its internals. */
85 void silc_client_free(SilcClient client)
89 silc_rng_free(client->rng);
91 silc_free(client->internal->params);
92 silc_free(client->internal->silc_client_version);
93 silc_free(client->internal);
98 /* Initializes the client. This makes all the necessary steps to make
99 the client ready to be run. One must call silc_client_run to run the
100 client. Returns FALSE if error occured, TRUE otherwise. */
102 bool silc_client_init(SilcClient client)
104 SILC_LOG_DEBUG(("Initializing client"));
107 assert(client->username);
108 assert(client->hostname);
109 assert(client->realname);
111 /* Initialize the crypto library. If application has done this already
112 this has no effect. Also, we will not be overriding something
113 application might have registered earlier. */
114 silc_cipher_register_default();
115 silc_pkcs_register_default();
116 silc_hash_register_default();
117 silc_hmac_register_default();
119 /* Initialize hash functions for client to use */
120 silc_hash_alloc("md5", &client->md5hash);
121 silc_hash_alloc("sha1", &client->sha1hash);
123 /* Initialize none cipher */
124 silc_cipher_alloc("none", &client->internal->none_cipher);
126 /* Initialize random number generator */
127 client->rng = silc_rng_alloc();
128 silc_rng_init(client->rng);
129 silc_rng_global_init(client->rng);
131 /* Register protocols */
132 silc_client_protocols_register();
134 /* Initialize the scheduler */
136 silc_schedule_init(client->internal->params->task_max ?
137 client->internal->params->task_max : 200, client);
138 if (!client->schedule)
141 /* Register commands */
142 silc_client_commands_register(client);
147 /* Stops the client. This is called to stop the client and thus to stop
150 void silc_client_stop(SilcClient client)
152 SILC_LOG_DEBUG(("Stopping client"));
154 silc_schedule_stop(client->schedule);
155 silc_schedule_uninit(client->schedule);
157 silc_client_protocols_unregister();
158 silc_client_commands_unregister(client);
160 SILC_LOG_DEBUG(("Client stopped"));
163 /* Runs the client. This starts the scheduler from the utility library.
164 When this functions returns the execution of the appliation is over. */
166 void silc_client_run(SilcClient client)
168 SILC_LOG_DEBUG(("Running client"));
171 assert(client->pkcs);
172 assert(client->public_key);
173 assert(client->private_key);
175 /* Start the scheduler, the heart of the SILC client. When this returns
176 the program will be terminated. */
177 silc_schedule(client->schedule);
180 /* Runs the client and returns immeadiately. This function is used when
181 the SILC Client object indicated by the `client' is run under some
182 other scheduler, or event loop or main loop. On GUI applications,
183 for example this may be desired to use to run the client under the
184 GUI application's main loop. Typically the GUI application would
185 register an idle task that calls this function multiple times in
186 a second to quickly process the SILC specific data. */
188 void silc_client_run_one(SilcClient client)
190 /* Run the scheduler once. */
191 silc_schedule_one(client->schedule, 0);
194 static void silc_client_entry_destructor(SilcIDCache cache,
195 SilcIDCacheEntry entry)
197 silc_free(entry->name);
200 /* Allocates and adds new connection to the client. This adds the allocated
201 connection to the connection table and returns a pointer to it. A client
202 can have multiple connections to multiple servers. Every connection must
203 be added to the client using this function. User data `context' may
204 be sent as argument. This function is normally used only if the
205 application performed the connecting outside the library. The library
206 however may use this internally. */
209 silc_client_add_connection(SilcClient client,
210 SilcClientConnectionParams *params,
211 char *hostname, int port, void *context)
213 SilcClientConnection conn;
216 SILC_LOG_DEBUG(("Adding new connection to %s:%d", hostname, port));
218 conn = silc_calloc(1, sizeof(*conn));
219 conn->internal = silc_calloc(1, sizeof(*conn->internal));
221 /* Initialize ID caches */
222 conn->client = client;
223 conn->remote_host = strdup(hostname);
224 conn->remote_port = port;
225 conn->context = context;
226 conn->internal->client_cache =
227 silc_idcache_alloc(0, SILC_ID_CLIENT, silc_client_entry_destructor);
228 conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
229 conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
230 conn->internal->pending_commands = silc_dlist_init();
231 conn->internal->ftp_sessions = silc_dlist_init();
234 if (params->detach_data)
235 conn->internal->params.detach_data =
236 silc_memdup(params->detach_data,
237 params->detach_data_len);
238 conn->internal->params.detach_data_len = params->detach_data_len;
241 /* Add the connection to connections table */
242 for (i = 0; i < client->internal->conns_count; i++)
243 if (client->internal->conns && !client->internal->conns[i]) {
244 client->internal->conns[i] = conn;
248 client->internal->conns =
249 silc_realloc(client->internal->conns, sizeof(*client->internal->conns)
250 * (client->internal->conns_count + 1));
251 client->internal->conns[client->internal->conns_count] = conn;
252 client->internal->conns_count++;
257 /* Removes connection from client. Frees all memory. */
259 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
263 for (i = 0; i < client->internal->conns_count; i++)
264 if (client->internal->conns[i] == conn) {
265 /* Free all cache entries */
266 SilcIDCacheList list;
267 SilcIDCacheEntry entry;
268 SilcClientCommandPending *r;
271 if (silc_idcache_get_all(conn->internal->client_cache, &list)) {
272 ret = silc_idcache_list_first(list, &entry);
274 silc_client_del_client(client, conn, entry->context);
275 ret = silc_idcache_list_next(list, &entry);
277 silc_idcache_list_free(list);
280 if (silc_idcache_get_all(conn->internal->channel_cache, &list)) {
281 ret = silc_idcache_list_first(list, &entry);
283 silc_client_del_channel(client, conn, entry->context);
284 ret = silc_idcache_list_next(list, &entry);
286 silc_idcache_list_free(list);
289 if (silc_idcache_get_all(conn->internal->server_cache, &list)) {
290 ret = silc_idcache_list_first(list, &entry);
292 silc_client_del_server(client, conn, entry->context);
293 ret = silc_idcache_list_next(list, &entry);
295 silc_idcache_list_free(list);
298 /* Clear ID caches */
299 if (conn->internal->client_cache)
300 silc_idcache_free(conn->internal->client_cache);
301 if (conn->internal->channel_cache)
302 silc_idcache_free(conn->internal->channel_cache);
303 if (conn->internal->server_cache)
304 silc_idcache_free(conn->internal->server_cache);
306 /* Free data (my ID is freed in above silc_client_del_client).
307 conn->nickname is freed when freeing the local_entry->nickname. */
308 silc_free(conn->remote_host);
309 silc_free(conn->local_id_data);
310 if (conn->internal->send_key)
311 silc_cipher_free(conn->internal->send_key);
312 if (conn->internal->receive_key)
313 silc_cipher_free(conn->internal->receive_key);
314 if (conn->internal->hmac_send)
315 silc_hmac_free(conn->internal->hmac_send);
316 if (conn->internal->hmac_receive)
317 silc_hmac_free(conn->internal->hmac_receive);
318 silc_free(conn->internal->rekey);
320 if (conn->internal->active_session) {
321 conn->sock->user_data = NULL;
322 silc_client_ftp_session_free(conn->internal->active_session);
323 conn->internal->active_session = NULL;
326 silc_client_ftp_free_sessions(client, conn);
328 if (conn->internal->pending_commands) {
329 silc_dlist_start(conn->internal->pending_commands);
330 while ((r = silc_dlist_get(conn->internal->pending_commands))
332 silc_dlist_del(conn->internal->pending_commands, r);
333 silc_dlist_uninit(conn->internal->pending_commands);
336 silc_free(conn->internal);
337 memset(conn, 0, sizeof(*conn));
340 client->internal->conns[i] = NULL;
344 /* Adds listener socket to the listener sockets table. This function is
345 used to add socket objects that are listeners to the client. This should
346 not be used to add other connection objects. */
348 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
352 if (!client->internal->sockets) {
353 client->internal->sockets =
354 silc_calloc(1, sizeof(*client->internal->sockets));
355 client->internal->sockets[0] = silc_socket_dup(sock);
356 client->internal->sockets_count = 1;
360 for (i = 0; i < client->internal->sockets_count; i++) {
361 if (client->internal->sockets[i] == NULL) {
362 client->internal->sockets[i] = silc_socket_dup(sock);
367 client->internal->sockets =
368 silc_realloc(client->internal->sockets,
369 sizeof(*client->internal->sockets) *
370 (client->internal->sockets_count + 1));
371 client->internal->sockets[client->internal->sockets_count] =
372 silc_socket_dup(sock);
373 client->internal->sockets_count++;
376 /* Deletes listener socket from the listener sockets table. */
378 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
382 if (!client->internal->sockets)
385 for (i = 0; i < client->internal->sockets_count; i++) {
386 if (client->internal->sockets[i] == sock) {
387 silc_socket_free(sock);
388 client->internal->sockets[i] = NULL;
395 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
399 /* XXX In the future we should give up this non-blocking connect all
400 together and use threads instead. */
401 /* Create connection to server asynchronously */
402 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
406 /* Register task that will receive the async connect and will
408 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
409 silc_client_connect_to_server_start,
412 SILC_TASK_PRI_NORMAL);
413 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE,
421 /* Connects to remote server. This is the main routine used to connect
422 to SILC server. Returns -1 on error and the created socket otherwise.
423 The `context' is user context that is saved into the SilcClientConnection
424 that is created after the connection is created. Note that application
425 may handle the connecting process outside the library. If this is the
426 case then this function is not used at all. When the connecting is
427 done the `connect' client operation is called. */
429 bool silc_client_connect_to_server(SilcClient client,
430 SilcClientConnectionParams *params,
431 int port, char *host, void *context)
433 SilcClientInternalConnectContext *ctx;
434 SilcClientConnection conn;
437 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
440 conn = silc_client_add_connection(client, params, host, port, context);
442 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
443 "Connecting to port %d of server %s", port, host);
445 /* Allocate internal context for connection process. This is
446 needed as we are doing async connecting. */
447 ctx = silc_calloc(1, sizeof(*ctx));
448 ctx->client = client;
450 ctx->host = strdup(host);
451 ctx->port = port ? port : 706;
454 /* Do the actual connecting process */
455 sock = silc_client_connect_to_server_internal(ctx);
457 silc_client_del_connection(client, conn);
461 /* Socket hostname and IP lookup callback that is called before actually
462 starting the key exchange. The lookup is called from the function
463 silc_client_start_key_exchange. */
465 static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
468 SilcClientConnection conn = (SilcClientConnection)context;
469 SilcClient client = conn->client;
470 SilcProtocol protocol;
471 SilcClientKEInternalContext *proto_ctx;
473 SILC_LOG_DEBUG(("Start"));
475 if (conn->sock->hostname) {
476 silc_free(conn->remote_host);
477 conn->remote_host = strdup(conn->sock->hostname);
479 conn->sock->hostname = strdup(conn->remote_host);
482 conn->sock->ip = strdup(conn->sock->hostname);
483 conn->sock->port = conn->remote_port;
485 /* Allocate internal Key Exchange context. This is sent to the
486 protocol as context. */
487 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
488 proto_ctx->client = (void *)client;
489 proto_ctx->sock = silc_socket_dup(conn->sock);
490 proto_ctx->rng = client->rng;
491 proto_ctx->responder = FALSE;
492 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
493 proto_ctx->verify = silc_client_protocol_ke_verify_key;
495 /* Perform key exchange protocol. silc_client_connect_to_server_final
496 will be called after the protocol is finished. */
497 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
498 &protocol, (void *)proto_ctx,
499 silc_client_connect_to_server_second);
501 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
502 "Error: Could not start key exchange protocol");
503 silc_net_close_connection(conn->sock->sock);
504 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
507 conn->sock->protocol = protocol;
509 /* Register the connection for network input and output. This sets
510 that scheduler will listen for incoming packets for this connection
511 and sets that outgoing packets may be sent to this connection as well.
512 However, this doesn't set the scheduler for outgoing traffic, it will
513 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
514 later when outgoing data is available. */
515 context = (void *)client;
516 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(conn->sock->sock);
518 /* Execute the protocol */
519 silc_protocol_execute(protocol, client->schedule, 0, 0);
522 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
523 key material between client and server. This function can be called
524 directly if application is performing its own connecting and does not
525 use the connecting provided by this library. This function is normally
526 used only if the application performed the connecting outside the library.
527 The library however may use this internally. */
529 void silc_client_start_key_exchange(SilcClient client,
530 SilcClientConnection conn,
533 assert(client->pkcs);
534 assert(client->public_key);
535 assert(client->private_key);
537 /* Allocate new socket connection object */
538 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
540 /* Sometimes when doing quick reconnects the new socket may be same as
541 the old one and there might be pending stuff for the old socket.
542 If new one is same then those pending sutff might cause problems.
543 Make sure they do not do that. */
544 silc_schedule_task_del_by_fd(client->schedule, fd);
546 conn->nickname = (client->nickname ? strdup(client->nickname) :
547 strdup(client->username));
549 /* Resolve the remote hostname and IP address for our socket connection */
550 silc_socket_host_lookup(conn->sock, FALSE, silc_client_start_key_exchange_cb,
551 conn, client->schedule);
554 /* Callback called when error has occurred during connecting (KE) to
555 the server. The `connect' client operation will be called. */
557 SILC_TASK_CALLBACK(silc_client_connect_failure)
559 SilcClientKEInternalContext *ctx =
560 (SilcClientKEInternalContext *)context;
561 SilcClient client = (SilcClient)ctx->client;
563 client->internal->ops->connected(client, ctx->sock->user_data,
564 SILC_CLIENT_CONN_ERROR);
566 silc_packet_context_free(ctx->packet);
570 /* Callback called when error has occurred during connecting (auth) to
571 the server. The `connect' client operation will be called. */
573 SILC_TASK_CALLBACK(silc_client_connect_failure_auth)
575 SilcClientConnAuthInternalContext *ctx =
576 (SilcClientConnAuthInternalContext *)context;
577 SilcClient client = (SilcClient)ctx->client;
579 client->internal->ops->connected(client, ctx->sock->user_data,
580 SILC_CLIENT_CONN_ERROR);
584 /* Start of the connection to the remote server. This is called after
585 succesful TCP/IP connection has been established to the remote host. */
587 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
589 SilcClientInternalConnectContext *ctx =
590 (SilcClientInternalConnectContext *)context;
591 SilcClient client = ctx->client;
592 SilcClientConnection conn = ctx->conn;
593 int opt, opt_len = sizeof(opt);
595 SILC_LOG_DEBUG(("Start"));
597 /* Check the socket status as it might be in error */
598 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
600 if (ctx->tries < 2) {
601 /* Connection failed but lets try again */
602 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
603 "Could not connect to server %s: %s",
604 ctx->host, strerror(opt));
605 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
606 "Connecting to port %d of server %s resumed",
607 ctx->port, ctx->host);
609 /* Unregister old connection try */
610 silc_schedule_unset_listen_fd(client->schedule, fd);
611 silc_net_close_connection(fd);
612 silc_schedule_task_del(client->schedule, ctx->task);
615 silc_client_connect_to_server_internal(ctx);
618 /* Connection failed and we won't try anymore */
619 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
620 "Could not connect to server %s: %s",
621 ctx->host, strerror(opt));
622 silc_schedule_unset_listen_fd(client->schedule, fd);
623 silc_net_close_connection(fd);
624 silc_schedule_task_del(client->schedule, ctx->task);
627 /* Notify application of failure */
628 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
629 silc_client_del_connection(client, conn);
634 silc_schedule_unset_listen_fd(client->schedule, fd);
635 silc_schedule_task_del(client->schedule, ctx->task);
638 silc_client_start_key_exchange(client, conn, fd);
641 /* Second part of the connecting to the server. This executed
642 authentication protocol. */
644 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
646 SilcProtocol protocol = (SilcProtocol)context;
647 SilcClientKEInternalContext *ctx =
648 (SilcClientKEInternalContext *)protocol->context;
649 SilcClient client = (SilcClient)ctx->client;
650 SilcSocketConnection sock = NULL;
651 SilcClientConnAuthInternalContext *proto_ctx;
653 SILC_LOG_DEBUG(("Start"));
655 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
656 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
657 /* Error occured during protocol */
658 SILC_LOG_DEBUG(("Error during KE protocol"));
659 silc_protocol_free(protocol);
660 silc_ske_free_key_material(ctx->keymat);
662 silc_ske_free(ctx->ske);
664 silc_free(ctx->dest_id);
665 ctx->sock->protocol = NULL;
666 silc_socket_free(ctx->sock);
668 /* Notify application of failure */
669 silc_schedule_task_add(client->schedule, ctx->sock->sock,
670 silc_client_connect_failure, ctx,
671 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
675 /* We now have the key material as the result of the key exchange
676 protocol. Take the key material into use. Free the raw key material
677 as soon as we've set them into use. */
678 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
679 ctx->ske->prop->cipher,
680 ctx->ske->prop->pkcs,
681 ctx->ske->prop->hash,
682 ctx->ske->prop->hmac,
683 ctx->ske->prop->group,
685 silc_ske_free_key_material(ctx->keymat);
687 /* Allocate internal context for the authentication protocol. This
688 is sent as context for the protocol. */
689 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
690 proto_ctx->client = (void *)client;
691 proto_ctx->sock = sock = ctx->sock;
692 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
693 proto_ctx->dest_id_type = ctx->dest_id_type;
694 proto_ctx->dest_id = ctx->dest_id;
696 /* Free old protocol as it is finished now */
697 silc_protocol_free(protocol);
699 silc_packet_context_free(ctx->packet);
702 sock->protocol = NULL;
704 /* Resolve the authentication method to be used in this connection. The
705 completion callback is called after the application has resolved
706 the authentication method. */
707 client->internal->ops->get_auth_method(client, sock->user_data,
710 silc_client_resolve_auth_method,
714 /* Authentication method resolving callback. Application calls this function
715 after we've called the client->internal->ops->get_auth_method
716 client operation to resolve the authentication method. We will continue
717 the executiong of the protocol in this function. */
719 void silc_client_resolve_auth_method(bool success,
720 SilcProtocolAuthMeth auth_meth,
721 const unsigned char *auth_data,
722 SilcUInt32 auth_data_len, void *context)
724 SilcClientConnAuthInternalContext *proto_ctx =
725 (SilcClientConnAuthInternalContext *)context;
726 SilcClient client = (SilcClient)proto_ctx->client;
729 auth_meth = SILC_AUTH_NONE;
731 proto_ctx->auth_meth = auth_meth;
733 if (success && auth_data && auth_data_len) {
735 /* Passphrase must be UTF-8 encoded, if it isn't encode it */
736 if (auth_meth == SILC_AUTH_PASSWORD &&
737 !silc_utf8_valid(auth_data, auth_data_len)) {
739 unsigned char *autf8 = NULL;
740 payload_len = silc_utf8_encoded_len(auth_data, auth_data_len,
742 autf8 = silc_calloc(payload_len, sizeof(*autf8));
743 auth_data_len = silc_utf8_encode(auth_data, auth_data_len,
744 SILC_STRING_ASCII, autf8, payload_len);
748 proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
749 proto_ctx->auth_data_len = auth_data_len;
752 /* Allocate the authenteication protocol and execute it. */
753 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
754 &proto_ctx->sock->protocol, (void *)proto_ctx,
755 silc_client_connect_to_server_final);
757 /* Execute the protocol */
758 silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
761 /* Finalizes the connection to the remote SILC server. This is called
762 after authentication protocol has been completed. This send our
763 user information to the server to receive our client ID from
766 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
768 SilcProtocol protocol = (SilcProtocol)context;
769 SilcClientConnAuthInternalContext *ctx =
770 (SilcClientConnAuthInternalContext *)protocol->context;
771 SilcClient client = (SilcClient)ctx->client;
772 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
775 SILC_LOG_DEBUG(("Start"));
777 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
778 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
779 /* Error occured during protocol */
780 SILC_LOG_DEBUG(("Error during authentication protocol"));
784 if (conn->internal->params.detach_data) {
785 /* Send RESUME_CLIENT packet to the server, which is used to resume
786 old detached session back. */
788 SilcClientID *old_client_id;
789 unsigned char *old_id;
790 SilcUInt16 old_id_len;
792 if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len))
795 old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT);
796 if (!old_client_id) {
801 /* Generate authentication data that server will verify */
802 auth = silc_auth_public_key_auth_generate(client->public_key,
805 conn->internal->hash,
806 old_client_id, SILC_ID_CLIENT);
808 silc_free(old_client_id);
813 packet = silc_buffer_alloc_size(2 + old_id_len + auth->len);
814 silc_buffer_format(packet,
815 SILC_STR_UI_SHORT(old_id_len),
816 SILC_STR_UI_XNSTRING(old_id, old_id_len),
817 SILC_STR_UI_XNSTRING(auth->data, auth->len),
820 /* Send the packet */
821 silc_client_packet_send(client, ctx->sock, SILC_PACKET_RESUME_CLIENT,
823 packet->data, packet->len, TRUE);
824 silc_buffer_free(packet);
825 silc_buffer_free(auth);
826 silc_free(old_client_id);
829 /* Send NEW_CLIENT packet to the server. We will become registered
830 to the SILC network after sending this packet and we will receive
831 client ID from the server. */
832 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
833 strlen(client->realname));
834 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
835 silc_buffer_format(packet,
836 SILC_STR_UI_SHORT(strlen(client->username)),
837 SILC_STR_UI_XNSTRING(client->username,
838 strlen(client->username)),
839 SILC_STR_UI_SHORT(strlen(client->realname)),
840 SILC_STR_UI_XNSTRING(client->realname,
841 strlen(client->realname)),
844 /* Send the packet */
845 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
847 packet->data, packet->len, TRUE);
848 silc_buffer_free(packet);
851 /* Save remote ID. */
852 conn->remote_id = ctx->dest_id;
853 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
854 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
856 /* Register re-key timeout */
857 conn->internal->rekey->timeout = client->internal->params->rekey_secs;
858 conn->internal->rekey->context = (void *)client;
859 silc_schedule_task_add(client->schedule, conn->sock->sock,
860 silc_client_rekey_callback,
861 (void *)conn->sock, conn->internal->rekey->timeout, 0,
862 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
864 silc_protocol_free(protocol);
865 silc_free(ctx->auth_data);
867 silc_ske_free(ctx->ske);
868 silc_socket_free(ctx->sock);
870 conn->sock->protocol = NULL;
874 silc_protocol_free(protocol);
875 silc_free(ctx->auth_data);
876 silc_free(ctx->dest_id);
878 silc_ske_free(ctx->ske);
879 conn->sock->protocol = NULL;
880 silc_socket_free(ctx->sock);
882 /* Notify application of failure */
883 silc_schedule_task_add(client->schedule, ctx->sock->sock,
884 silc_client_connect_failure_auth, ctx,
885 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
888 /* Internal routine that sends packet or marks packet to be sent. This
889 is used directly only in special cases. Normal cases should use
890 silc_server_packet_send. Returns < 0 on error. */
892 bool silc_client_packet_send_real(SilcClient client,
893 SilcSocketConnection sock,
898 /* If rekey protocol is active we must assure that all packets are
899 sent through packet queue. */
900 if (SILC_CLIENT_IS_REKEY(sock))
903 /* If outbound data is already pending do not force send */
904 if (SILC_IS_OUTBUF_PENDING(sock))
907 /* Send the packet */
908 ret = silc_packet_send(sock, force_send);
912 /* Mark that there is some outgoing data available for this connection.
913 This call sets the connection both for input and output (the input
914 is set always and this call keeps the input setting, actually).
915 Actual data sending is performed by silc_client_packet_process. */
916 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
918 /* Mark to socket that data is pending in outgoing buffer. This flag
919 is needed if new data is added to the buffer before the earlier
920 put data is sent to the network. */
921 SILC_SET_OUTBUF_PENDING(sock);
926 /* Packet processing callback. This is used to send and receive packets
927 from network. This is generic task. */
929 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
931 SilcClient client = (SilcClient)context;
932 SilcSocketConnection sock = NULL;
933 SilcClientConnection conn;
936 SILC_LOG_DEBUG(("Processing packet"));
938 SILC_CLIENT_GET_SOCK(client, fd, sock);
942 conn = (SilcClientConnection)sock->user_data;
945 if (type == SILC_TASK_WRITE) {
946 /* Do not send data to disconnected connection */
947 if (SILC_IS_DISCONNECTED(sock))
950 ret = silc_packet_send(sock, TRUE);
952 /* If returned -2 could not write to connection now, will do
961 /* The packet has been sent and now it is time to set the connection
962 back to only for input. When there is again some outgoing data
963 available for this connection it will be set for output as well.
964 This call clears the output setting and sets it only for input. */
965 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
966 SILC_UNSET_OUTBUF_PENDING(sock);
968 silc_buffer_clear(sock->outbuf);
972 /* Packet receiving */
973 if (type == SILC_TASK_READ) {
974 /* Read data from network */
975 ret = silc_packet_receive(sock);
981 SILC_LOG_DEBUG(("Read EOF"));
983 /* If connection is disconnecting already we will finally
984 close the connection */
985 if (SILC_IS_DISCONNECTING(sock)) {
986 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
987 client->internal->ops->disconnected(client, conn, 0, NULL);
988 silc_client_close_connection_real(client, sock, conn);
992 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
993 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
994 client->internal->ops->disconnected(client, conn, 0, NULL);
995 silc_client_close_connection_real(client, sock, conn);
999 /* Process the packet. This will call the parser that will then
1000 decrypt and parse the packet. */
1001 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
1002 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
1003 conn->internal->hmac_receive,
1004 conn->internal->psn_receive,
1005 silc_client_packet_parse, client);
1007 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
1008 silc_client_packet_parse, client);
1012 /* Parser callback called by silc_packet_receive_process. Thie merely
1013 registers timeout that will handle the actual parsing when appropriate. */
1015 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
1018 SilcClient client = (SilcClient)context;
1019 SilcSocketConnection sock = parser_context->sock;
1020 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1021 SilcPacketContext *packet = parser_context->packet;
1024 if (conn && conn->internal->hmac_receive && conn->sock == sock)
1025 conn->internal->psn_receive = parser_context->packet->sequence + 1;
1027 /* Parse the packet immediately */
1028 if (parser_context->normal)
1029 ret = silc_packet_parse(packet, conn->internal->receive_key);
1031 ret = silc_packet_parse_special(packet, conn->internal->receive_key);
1033 if (ret == SILC_PACKET_NONE) {
1034 silc_packet_context_free(packet);
1035 silc_free(parser_context);
1039 /* If protocol for this connection is key exchange or rekey then we'll
1040 process all packets synchronously, since there might be packets in
1041 queue that we are not able to decrypt without first processing the
1042 packets before them. */
1043 if ((ret == SILC_PACKET_REKEY || ret == SILC_PACKET_REKEY_DONE) ||
1044 (sock->protocol && sock->protocol->protocol &&
1045 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1046 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY))) {
1048 /* Parse the incoming packet type */
1049 silc_client_packet_parse_type(client, sock, packet);
1050 silc_packet_context_free(packet);
1051 silc_free(parser_context);
1053 /* Reprocess the buffer since we'll return FALSE. This is because
1054 the `conn->internal->receive_key' might have become valid by processing
1055 the previous packet */
1056 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
1057 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
1058 conn->internal->hmac_receive,
1059 conn->internal->psn_receive,
1060 silc_client_packet_parse, client);
1062 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
1063 silc_client_packet_parse, client);
1068 /* Parse the incoming packet type */
1069 silc_client_packet_parse_type(client, sock, packet);
1070 silc_packet_context_free(packet);
1071 silc_free(parser_context);
1075 /* Parses the packet type and calls what ever routines the packet type
1076 requires. This is done for all incoming packets. */
1078 void silc_client_packet_parse_type(SilcClient client,
1079 SilcSocketConnection sock,
1080 SilcPacketContext *packet)
1082 SilcBuffer buffer = packet->buffer;
1083 SilcPacketType type = packet->type;
1085 SILC_LOG_DEBUG(("Parsing %s packet", silc_get_packet_name(type)));
1087 /* Parse the packet type */
1090 case SILC_PACKET_DISCONNECT:
1091 silc_client_disconnected_by_server(client, sock, buffer);
1094 case SILC_PACKET_SUCCESS:
1096 * Success received for something. For now we can have only
1097 * one protocol for connection executing at once hence this
1098 * success message is for whatever protocol is executing currently.
1101 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1104 case SILC_PACKET_FAILURE:
1106 * Failure received for some protocol. Set the protocol state to
1107 * error and call the protocol callback. This fill cause error on
1108 * protocol and it will call the final callback.
1110 silc_client_process_failure(client, sock, packet);
1113 case SILC_PACKET_REJECT:
1116 case SILC_PACKET_NOTIFY:
1118 * Received notify message
1120 silc_client_notify_by_server(client, sock, packet);
1123 case SILC_PACKET_ERROR:
1125 * Received error message
1127 silc_client_error_by_server(client, sock, buffer);
1130 case SILC_PACKET_CHANNEL_MESSAGE:
1132 * Received message to (from, actually) a channel
1134 silc_client_channel_message(client, sock, packet);
1137 case SILC_PACKET_CHANNEL_KEY:
1139 * Received key for a channel. By receiving this key the client will be
1140 * able to talk to the channel it has just joined. This can also be
1141 * a new key for existing channel as keys expire peridiocally.
1143 silc_client_receive_channel_key(client, sock, buffer);
1146 case SILC_PACKET_PRIVATE_MESSAGE:
1148 * Received private message
1150 silc_client_private_message(client, sock, packet);
1153 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1155 * Received private message key
1159 case SILC_PACKET_COMMAND:
1161 * Received command packet, a special case since normally client
1162 * does not receive commands.
1164 silc_client_command_process(client, sock, packet);
1167 case SILC_PACKET_COMMAND_REPLY:
1169 * Recived reply for a command
1171 silc_client_command_reply_process(client, sock, packet);
1174 case SILC_PACKET_KEY_EXCHANGE:
1175 if (sock->protocol && sock->protocol->protocol &&
1176 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
1177 SilcClientKEInternalContext *proto_ctx =
1178 (SilcClientKEInternalContext *)sock->protocol->context;
1180 proto_ctx->packet = silc_packet_context_dup(packet);
1181 proto_ctx->dest_id_type = packet->src_id_type;
1182 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1183 packet->src_id_type);
1184 if (!proto_ctx->dest_id)
1187 /* Let the protocol handle the packet */
1188 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1190 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1191 "protocol active, packet dropped."));
1195 case SILC_PACKET_KEY_EXCHANGE_1:
1196 if (sock->protocol && sock->protocol->protocol &&
1197 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1198 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1200 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1201 SilcClientRekeyInternalContext *proto_ctx =
1202 (SilcClientRekeyInternalContext *)sock->protocol->context;
1204 if (proto_ctx->packet)
1205 silc_packet_context_free(proto_ctx->packet);
1207 proto_ctx->packet = silc_packet_context_dup(packet);
1209 /* Let the protocol handle the packet */
1210 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1212 SilcClientKEInternalContext *proto_ctx =
1213 (SilcClientKEInternalContext *)sock->protocol->context;
1215 if (proto_ctx->packet)
1216 silc_packet_context_free(proto_ctx->packet);
1218 proto_ctx->packet = silc_packet_context_dup(packet);
1219 proto_ctx->dest_id_type = packet->src_id_type;
1220 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1221 packet->src_id_type);
1222 if (!proto_ctx->dest_id)
1225 /* Let the protocol handle the packet */
1226 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1229 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1230 "protocol active, packet dropped."));
1234 case SILC_PACKET_KEY_EXCHANGE_2:
1235 if (sock->protocol && sock->protocol->protocol &&
1236 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1237 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1239 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1240 SilcClientRekeyInternalContext *proto_ctx =
1241 (SilcClientRekeyInternalContext *)sock->protocol->context;
1243 if (proto_ctx->packet)
1244 silc_packet_context_free(proto_ctx->packet);
1246 proto_ctx->packet = silc_packet_context_dup(packet);
1248 /* Let the protocol handle the packet */
1249 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1251 SilcClientKEInternalContext *proto_ctx =
1252 (SilcClientKEInternalContext *)sock->protocol->context;
1254 if (proto_ctx->packet)
1255 silc_packet_context_free(proto_ctx->packet);
1256 if (proto_ctx->dest_id)
1257 silc_free(proto_ctx->dest_id);
1258 proto_ctx->packet = silc_packet_context_dup(packet);
1259 proto_ctx->dest_id_type = packet->src_id_type;
1260 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1261 packet->src_id_type);
1262 if (!proto_ctx->dest_id)
1265 /* Let the protocol handle the packet */
1266 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1269 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1270 "protocol active, packet dropped."));
1274 case SILC_PACKET_NEW_ID:
1277 * Received new ID from server. This packet is received at
1278 * the connection to the server. New ID is also received when
1279 * user changes nickname but in that case the new ID is received
1280 * as command reply and not as this packet type.
1284 idp = silc_id_payload_parse(buffer->data, buffer->len);
1287 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1290 silc_client_receive_new_id(client, sock, idp);
1291 silc_id_payload_free(idp);
1295 case SILC_PACKET_HEARTBEAT:
1297 * Received heartbeat packet
1299 SILC_LOG_DEBUG(("Heartbeat packet"));
1302 case SILC_PACKET_KEY_AGREEMENT:
1304 * Received key agreement packet
1306 SILC_LOG_DEBUG(("Key agreement packet"));
1307 silc_client_key_agreement(client, sock, packet);
1310 case SILC_PACKET_REKEY:
1311 SILC_LOG_DEBUG(("Re-key packet"));
1312 /* We ignore this for now */
1315 case SILC_PACKET_REKEY_DONE:
1316 SILC_LOG_DEBUG(("Re-key done packet"));
1318 if (sock->protocol && sock->protocol->protocol &&
1319 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1321 SilcClientRekeyInternalContext *proto_ctx =
1322 (SilcClientRekeyInternalContext *)sock->protocol->context;
1324 if (proto_ctx->packet)
1325 silc_packet_context_free(proto_ctx->packet);
1327 proto_ctx->packet = silc_packet_context_dup(packet);
1329 /* Let the protocol handle the packet */
1330 if (proto_ctx->responder == FALSE)
1331 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1333 /* Let the protocol handle the packet */
1334 silc_protocol_execute(sock->protocol, client->schedule,
1337 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1338 "protocol active, packet dropped."));
1342 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1344 * Reveived reply to our connection authentication method request
1345 * packet. This is used to resolve the authentication method for the
1346 * current session from the server if the client does not know it.
1348 silc_client_connection_auth_request(client, sock, packet);
1351 case SILC_PACKET_FTP:
1352 /* Received file transfer packet. */
1353 silc_client_ftp(client, sock, packet);
1357 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1362 /* Sends packet. This doesn't actually send the packet instead it assembles
1363 it and marks it to be sent. However, if force_send is TRUE the packet
1364 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1365 will be derived from sock argument. Otherwise the valid arguments sent
1368 void silc_client_packet_send(SilcClient client,
1369 SilcSocketConnection sock,
1370 SilcPacketType type,
1372 SilcIdType dst_id_type,
1375 unsigned char *data,
1376 SilcUInt32 data_len,
1379 SilcPacketContext packetdata;
1380 const SilcBufferStruct packet;
1382 SilcUInt32 sequence = 0;
1387 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1389 /* Get data used in the packet sending, keys and stuff */
1390 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1391 if (!cipher && ((SilcClientConnection)sock->user_data)->internal->send_key)
1392 cipher = ((SilcClientConnection)sock->user_data)->internal->send_key;
1394 if (!hmac && ((SilcClientConnection)sock->user_data)->internal->hmac_send)
1395 hmac = ((SilcClientConnection)sock->user_data)->internal->hmac_send;
1397 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1398 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1399 dst_id_type = SILC_ID_SERVER;
1403 sequence = ((SilcClientConnection)sock->user_data)->internal->psn_send++;
1405 /* Check for mandatory rekey */
1406 if (sequence == SILC_CLIENT_REKEY_THRESHOLD)
1407 silc_schedule_task_add(client->schedule, sock->sock,
1408 silc_client_rekey_callback, sock, 0, 1,
1409 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1412 block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1414 /* Set the packet context pointers */
1415 packetdata.flags = 0;
1416 packetdata.type = type;
1417 if (sock->user_data &&
1418 ((SilcClientConnection)sock->user_data)->local_id_data) {
1419 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1420 packetdata.src_id_len =
1421 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1424 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1425 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1427 packetdata.src_id_type = SILC_ID_CLIENT;
1429 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1430 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1431 packetdata.dst_id_type = dst_id_type;
1433 packetdata.dst_id = NULL;
1434 packetdata.dst_id_len = 0;
1435 packetdata.dst_id_type = SILC_ID_NONE;
1437 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1438 packetdata.src_id_len +
1439 packetdata.dst_id_len));
1440 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1441 packetdata.src_id_len + packetdata.dst_id_len;
1442 if (type == SILC_PACKET_CONNECTION_AUTH)
1443 SILC_PACKET_PADLEN_MAX(packetdata.truelen, block_len, packetdata.padlen);
1445 SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
1447 /* Create the outgoing packet */
1448 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
1449 data, data_len, (const SilcBuffer)&packet)) {
1450 SILC_LOG_ERROR(("Error assembling packet"));
1454 /* Encrypt the packet */
1456 silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet,
1459 SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
1460 packet.data, packet.len);
1462 /* Now actually send the packet */
1463 silc_client_packet_send_real(client, sock, force_send);
1466 /* Packet sending routine for application. This is the only routine that
1467 is provided for application to send SILC packets. */
1469 bool silc_client_send_packet(SilcClient client,
1470 SilcClientConnection conn,
1471 SilcPacketType type,
1472 const unsigned char *data,
1473 SilcUInt32 data_len)
1480 silc_client_packet_send(client, conn->sock, type, NULL, 0, NULL, NULL,
1481 (unsigned char *)data, data_len, TRUE);
1485 void silc_client_packet_queue_purge(SilcClient client,
1486 SilcSocketConnection sock)
1488 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1489 (SILC_IS_DISCONNECTED(sock) == FALSE)) {
1490 silc_packet_send(sock, TRUE);
1491 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1492 SILC_UNSET_OUTBUF_PENDING(sock);
1493 silc_buffer_clear(sock->outbuf);
1497 /* Closes connection to remote end. Free's all allocated data except
1498 for some information such as nickname etc. that are valid at all time.
1499 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1500 provided it will be checked whether the sock and `conn->sock' are the
1501 same (they can be different, ie. a socket can use `conn' as its
1502 connection but `conn->sock' might be actually a different connection
1503 than the `sock'). */
1505 void silc_client_close_connection_real(SilcClient client,
1506 SilcSocketConnection sock,
1507 SilcClientConnection conn)
1511 SILC_LOG_DEBUG(("Start"));
1516 if (!sock || (sock && conn->sock == sock))
1521 /* We won't listen for this connection anymore */
1522 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1524 /* Unregister all tasks */
1525 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1527 /* Close the actual connection */
1528 silc_net_close_connection(sock->sock);
1530 /* Cancel any active protocol */
1531 if (sock->protocol) {
1532 if (sock->protocol->protocol->type ==
1533 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1534 sock->protocol->protocol->type ==
1535 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1536 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1537 silc_protocol_execute_final(sock->protocol, client->schedule);
1538 /* The application will recall this function with these protocols
1539 (the ops->connected client operation). */
1542 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1543 silc_protocol_execute_final(sock->protocol, client->schedule);
1544 sock->protocol = NULL;
1548 /* Free everything */
1549 if (del && sock->user_data)
1550 silc_client_del_connection(client, conn);
1552 silc_socket_free(sock);
1555 /* Closes the connection to the remote end */
1557 void silc_client_close_connection(SilcClient client,
1558 SilcClientConnection conn)
1560 silc_client_close_connection_real(client, NULL, conn);
1563 /* Called when we receive disconnection packet from server. This
1564 closes our end properly and displays the reason of the disconnection
1567 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1569 SilcClient client = (SilcClient)context;
1570 SilcSocketConnection sock;
1572 SILC_CLIENT_GET_SOCK(client, fd, sock);
1576 silc_client_close_connection_real(client, sock, sock->user_data);
1579 /* Called when we receive disconnection packet from server. This
1580 closes our end properly and displays the reason of the disconnection
1583 void silc_client_disconnected_by_server(SilcClient client,
1584 SilcSocketConnection sock,
1587 SilcClientConnection conn;
1589 char *message = NULL;
1591 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1593 if (packet->len < 1)
1596 status = (SilcStatus)packet->data[0];
1598 if (packet->len > 1 &&
1599 silc_utf8_valid(packet->data + 1, packet->len - 1))
1600 message = silc_memdup(packet->data + 1, packet->len - 1);
1602 conn = (SilcClientConnection)sock->user_data;
1603 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1604 client->internal->ops->disconnected(client, conn, status, message);
1608 SILC_SET_DISCONNECTED(sock);
1610 /* Close connection through scheduler. */
1611 silc_schedule_task_add(client->schedule, sock->sock,
1612 silc_client_disconnected_by_server_later,
1613 client, 0, 1, SILC_TASK_TIMEOUT,
1614 SILC_TASK_PRI_NORMAL);
1617 /* Received error message from server. Display it on the screen.
1618 We don't take any action what so ever of the error message. */
1620 void silc_client_error_by_server(SilcClient client,
1621 SilcSocketConnection sock,
1626 msg = silc_memdup(message->data, message->len);
1627 client->internal->ops->say(client, sock->user_data,
1628 SILC_CLIENT_MESSAGE_AUDIT, msg);
1632 /* Auto-nicking callback to send NICK command to server. */
1634 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1636 SilcClientConnection conn = (SilcClientConnection)context;
1637 SilcClient client = conn->client;
1639 silc_client_command_send(client, conn, SILC_COMMAND_NICK,
1640 ++conn->cmd_ident, 1, 1,
1641 client->nickname, strlen(client->nickname));
1644 /* Client session resuming callback. If the session was resumed
1645 this callback is called after the resuming is completed. This
1646 will call the `connect' client operation to the application
1647 since it has not been called yet. */
1649 static void silc_client_resume_session_cb(SilcClient client,
1650 SilcClientConnection conn,
1656 /* Notify application that connection is created to server */
1657 client->internal->ops->connected(client, conn, success ?
1658 SILC_CLIENT_CONN_SUCCESS_RESUME :
1659 SILC_CLIENT_CONN_ERROR);
1662 /* Issue INFO command to fetch the real server name and server
1663 information and other stuff. */
1664 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1665 silc_client_command_reply_info_i, 0,
1667 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1668 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1669 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1670 silc_buffer_free(sidp);
1674 /* Processes the received new Client ID from server. Old Client ID is
1675 deleted from cache and new one is added. */
1677 void silc_client_receive_new_id(SilcClient client,
1678 SilcSocketConnection sock,
1681 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1682 int connecting = FALSE;
1683 SilcClientID *client_id = silc_id_payload_get_id(idp);
1685 if (!conn->local_entry)
1688 /* Delete old ID from ID cache */
1689 if (conn->local_id) {
1690 /* Check whether they are different */
1691 if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1692 silc_free(client_id);
1696 silc_idcache_del_by_context(conn->internal->client_cache,
1698 silc_free(conn->local_id);
1701 /* Save the new ID */
1703 if (conn->local_id_data)
1704 silc_free(conn->local_id_data);
1706 conn->local_id = client_id;
1707 conn->local_id_data = silc_id_payload_get_data(idp);
1708 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1710 if (!conn->local_entry)
1711 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1713 conn->local_entry->nickname = conn->nickname;
1714 if (!conn->local_entry->username)
1715 conn->local_entry->username = strdup(client->username);
1716 if (!conn->local_entry->server)
1717 conn->local_entry->server = strdup(conn->remote_host);
1718 conn->local_entry->id = conn->local_id;
1719 conn->local_entry->valid = TRUE;
1720 if (!conn->local_entry->channels)
1721 conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
1726 /* Put it to the ID cache */
1727 silc_idcache_add(conn->internal->client_cache,
1728 strdup(conn->nickname), conn->local_id,
1729 (void *)conn->local_entry, 0, NULL);
1734 /* Issue IDENTIFY command for itself to get resolved hostname
1735 correctly from server. */
1736 silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
1737 silc_client_command_reply_identify_i, 0,
1739 sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT);
1740 silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
1741 conn->cmd_ident, 1, 5, sidp->data, sidp->len);
1742 silc_buffer_free(sidp);
1744 if (!conn->internal->params.detach_data) {
1745 /* Send NICK command if the nickname was set by the application (and is
1746 not same as the username). Send this with little timeout. */
1747 if (client->nickname && strcmp(client->nickname, client->username))
1748 silc_schedule_task_add(client->schedule, 0,
1749 silc_client_send_auto_nick, conn,
1750 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1752 /* Notify application of successful connection. We do it here now that
1753 we've received the Client ID and are allowed to send traffic. */
1754 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_SUCCESS);
1756 /* Issue INFO command to fetch the real server name and server
1757 information and other stuff. */
1758 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1759 silc_client_command_reply_info_i, 0,
1761 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1762 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1763 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1764 silc_buffer_free(sidp);
1766 /* We are resuming session. Start resolving informations from the
1767 server we need to set the client libary in the state before
1768 detaching the session. The connect client operation is called
1769 after this is successfully completed */
1770 silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1776 /* Removes a client entry from all channels it has joined. */
1778 void silc_client_remove_from_channels(SilcClient client,
1779 SilcClientConnection conn,
1780 SilcClientEntry client_entry)
1782 SilcHashTableList htl;
1783 SilcChannelUser chu;
1785 silc_hash_table_list(client_entry->channels, &htl);
1786 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1787 silc_hash_table_del(chu->client->channels, chu->channel);
1788 silc_hash_table_del(chu->channel->user_list, chu->client);
1792 silc_hash_table_list_reset(&htl);
1795 /* Replaces `old' client entries from all channels to `new' client entry.
1796 This can be called for example when nickname changes and old ID entry
1797 is replaced from ID cache with the new one. If the old ID entry is only
1798 updated, then this fucntion needs not to be called. */
1800 void silc_client_replace_from_channels(SilcClient client,
1801 SilcClientConnection conn,
1802 SilcClientEntry old,
1803 SilcClientEntry new)
1805 SilcHashTableList htl;
1806 SilcChannelUser chu;
1808 silc_hash_table_list(old->channels, &htl);
1809 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1810 /* Replace client entry */
1811 silc_hash_table_del(chu->client->channels, chu->channel);
1812 silc_hash_table_del(chu->channel->user_list, chu->client);
1815 silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1816 silc_hash_table_add(chu->client->channels, chu->channel, chu);
1818 silc_hash_table_list_reset(&htl);
1821 /* Registers failure timeout to process the received failure packet
1824 void silc_client_process_failure(SilcClient client,
1825 SilcSocketConnection sock,
1826 SilcPacketContext *packet)
1828 SilcUInt32 failure = 0;
1830 if (sock->protocol) {
1831 if (packet->buffer->len >= 4)
1832 SILC_GET32_MSB(failure, packet->buffer->data);
1834 /* Notify application */
1835 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1840 /* A timeout callback for the re-key. We will be the initiator of the
1843 SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback)
1845 SilcSocketConnection sock = (SilcSocketConnection)context;
1846 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1847 SilcClient client = (SilcClient)conn->internal->rekey->context;
1848 SilcProtocol protocol;
1849 SilcClientRekeyInternalContext *proto_ctx;
1851 SILC_LOG_DEBUG(("Start"));
1853 /* Allocate internal protocol context. This is sent as context
1855 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1856 proto_ctx->client = (void *)client;
1857 proto_ctx->sock = silc_socket_dup(sock);
1858 proto_ctx->responder = FALSE;
1859 proto_ctx->pfs = conn->internal->rekey->pfs;
1861 /* Perform rekey protocol. Will call the final callback after the
1862 protocol is over. */
1863 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1864 &protocol, proto_ctx, silc_client_rekey_final);
1865 sock->protocol = protocol;
1867 /* Run the protocol */
1868 silc_protocol_execute(protocol, client->schedule, 0, 0);
1870 /* Re-register re-key timeout */
1871 silc_schedule_task_add(client->schedule, sock->sock,
1872 silc_client_rekey_callback,
1873 context, conn->internal->rekey->timeout, 0,
1874 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1877 /* The final callback for the REKEY protocol. This will actually take the
1878 new key material into use. */
1880 SILC_TASK_CALLBACK(silc_client_rekey_final)
1882 SilcProtocol protocol = (SilcProtocol)context;
1883 SilcClientRekeyInternalContext *ctx =
1884 (SilcClientRekeyInternalContext *)protocol->context;
1885 SilcClient client = (SilcClient)ctx->client;
1886 SilcSocketConnection sock = ctx->sock;
1888 SILC_LOG_DEBUG(("Start"));
1890 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1891 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1892 /* Error occured during protocol */
1893 silc_protocol_cancel(protocol, client->schedule);
1894 silc_protocol_free(protocol);
1895 sock->protocol = NULL;
1897 silc_packet_context_free(ctx->packet);
1899 silc_ske_free(ctx->ske);
1900 silc_socket_free(ctx->sock);
1905 /* Purge the outgoing data queue to assure that all rekey packets really
1906 go to the network before we quit the protocol. */
1907 silc_client_packet_queue_purge(client, sock);
1910 silc_protocol_free(protocol);
1911 sock->protocol = NULL;
1913 silc_packet_context_free(ctx->packet);
1915 silc_ske_free(ctx->ske);
1916 silc_socket_free(ctx->sock);
1920 /* Processes incoming connection authentication method request packet.
1921 It is a reply to our previously sent request. The packet can be used
1922 to resolve the authentication method for the current session if the
1923 client does not know it beforehand. */
1925 void silc_client_connection_auth_request(SilcClient client,
1926 SilcSocketConnection sock,
1927 SilcPacketContext *packet)
1929 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1930 SilcUInt16 conn_type, auth_meth;
1933 /* If we haven't send our request then ignore this one. */
1934 if (!conn->internal->connauth)
1937 /* Parse the payload */
1938 ret = silc_buffer_unformat(packet->buffer,
1939 SILC_STR_UI_SHORT(&conn_type),
1940 SILC_STR_UI_SHORT(&auth_meth),
1943 auth_meth = SILC_AUTH_NONE;
1945 /* Call the request callback to notify application for received
1946 authentication method information. */
1947 if (conn->internal->connauth->callback)
1948 (*conn->internal->connauth->callback)(client, conn, auth_meth,
1949 conn->internal->connauth->context);
1951 silc_schedule_task_del(client->schedule, conn->internal->connauth->timeout);
1953 silc_free(conn->internal->connauth);
1954 conn->internal->connauth = NULL;
1957 /* Timeout task callback called if the server does not reply to our
1958 connection authentication method request in the specified time interval. */
1960 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1962 SilcClientConnection conn = (SilcClientConnection)context;
1963 SilcClient client = conn->client;
1965 if (!conn->internal->connauth)
1968 /* Call the request callback to notify application */
1969 if (conn->internal->connauth->callback)
1970 (*conn->internal->connauth->callback)(client, conn, SILC_AUTH_NONE,
1971 conn->internal->connauth->context);
1973 silc_free(conn->internal->connauth);
1974 conn->internal->connauth = NULL;
1977 /* This function can be used to request the current authentication method
1978 from the server. This may be called when connecting to the server
1979 and the client library requests the authentication data from the
1980 application. If the application does not know the current authentication
1981 method it can request it from the server using this function.
1982 The `callback' with `context' will be called after the server has
1983 replied back with the current authentication method. */
1986 silc_client_request_authentication_method(SilcClient client,
1987 SilcClientConnection conn,
1988 SilcConnectionAuthRequest callback,
1991 SilcClientConnAuthRequest connauth;
1994 assert(client && conn);
1995 connauth = silc_calloc(1, sizeof(*connauth));
1996 connauth->callback = callback;
1997 connauth->context = context;
1999 if (conn->internal->connauth)
2000 silc_free(conn->internal->connauth);
2002 conn->internal->connauth = connauth;
2004 /* Assemble the request packet and send it to the server */
2005 packet = silc_buffer_alloc(4);
2006 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
2007 silc_buffer_format(packet,
2008 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
2009 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
2011 silc_client_packet_send(client, conn->sock,
2012 SILC_PACKET_CONNECTION_AUTH_REQUEST,
2013 NULL, 0, NULL, NULL,
2014 packet->data, packet->len, FALSE);
2015 silc_buffer_free(packet);
2017 /* Register a timeout in case server does not reply anything back. */
2019 silc_schedule_task_add(client->schedule, conn->sock->sock,
2020 silc_client_request_authentication_method_timeout,
2022 client->internal->params->connauth_request_secs, 0,
2023 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);