5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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 if (!client->internal->params->dont_register_crypto_library) {
92 silc_cipher_unregister_all();
93 silc_pkcs_unregister_all();
94 silc_hash_unregister_all();
95 silc_hmac_unregister_all();
98 silc_hash_free(client->md5hash);
99 silc_hash_free(client->sha1hash);
100 silc_hmac_free(client->internal->md5hmac);
101 silc_hmac_free(client->internal->sha1hmac);
102 silc_cipher_free(client->internal->none_cipher);
103 silc_free(client->internal->params);
104 silc_free(client->internal->silc_client_version);
105 silc_free(client->internal);
110 /* Initializes the client. This makes all the necessary steps to make
111 the client ready to be run. One must call silc_client_run to run the
112 client. Returns FALSE if error occured, TRUE otherwise. */
114 bool silc_client_init(SilcClient client)
116 SILC_LOG_DEBUG(("Initializing client"));
119 assert(client->username);
120 assert(client->hostname);
121 assert(client->realname);
123 /* Validate essential strings */
124 if (client->nickname)
125 if (!silc_identifier_verify(client->nickname, strlen(client->nickname),
126 SILC_STRING_UTF8, 128)) {
127 SILC_LOG_ERROR(("Malformed nickname '%s'", client->nickname));
130 if (!silc_identifier_verify(client->username, strlen(client->username),
131 SILC_STRING_UTF8, 128)) {
132 SILC_LOG_ERROR(("Malformed username '%s'", client->username));
135 if (!silc_identifier_verify(client->hostname, strlen(client->hostname),
136 SILC_STRING_UTF8, 256)) {
137 SILC_LOG_ERROR(("Malformed hostname '%s'", client->hostname));
140 if (!silc_utf8_valid(client->realname, strlen(client->realname))) {
141 SILC_LOG_ERROR(("Malformed realname '%s'", client->realname));
145 if (!client->internal->params->dont_register_crypto_library) {
146 /* Initialize the crypto library. If application has done this already
147 this has no effect. Also, we will not be overriding something
148 application might have registered earlier. */
149 silc_cipher_register_default();
150 silc_pkcs_register_default();
151 silc_hash_register_default();
152 silc_hmac_register_default();
155 /* Initialize hash functions for client to use */
156 silc_hash_alloc("md5", &client->md5hash);
157 silc_hash_alloc("sha1", &client->sha1hash);
159 /* Initialize none cipher */
160 silc_cipher_alloc("none", &client->internal->none_cipher);
162 /* Initialize random number generator */
163 client->rng = silc_rng_alloc();
164 silc_rng_init(client->rng);
165 silc_rng_global_init(client->rng);
167 /* Register protocols */
168 silc_client_protocols_register();
170 /* Initialize the scheduler */
172 silc_schedule_init(client->internal->params->task_max ?
173 client->internal->params->task_max : 200, client);
174 if (!client->schedule)
177 /* Register commands */
178 silc_client_commands_register(client);
183 /* Stops the client. This is called to stop the client and thus to stop
186 void silc_client_stop(SilcClient client)
188 SILC_LOG_DEBUG(("Stopping client"));
190 silc_schedule_stop(client->schedule);
191 silc_schedule_uninit(client->schedule);
193 silc_client_protocols_unregister();
194 silc_client_commands_unregister(client);
196 SILC_LOG_DEBUG(("Client stopped"));
199 /* Runs the client. This starts the scheduler from the utility library.
200 When this functions returns the execution of the appliation is over. */
202 void silc_client_run(SilcClient client)
204 SILC_LOG_DEBUG(("Running client"));
207 assert(client->pkcs);
208 assert(client->public_key);
209 assert(client->private_key);
211 /* Start the scheduler, the heart of the SILC client. When this returns
212 the program will be terminated. */
213 silc_schedule(client->schedule);
216 /* Runs the client and returns immeadiately. This function is used when
217 the SILC Client object indicated by the `client' is run under some
218 other scheduler, or event loop or main loop. On GUI applications,
219 for example this may be desired to use to run the client under the
220 GUI application's main loop. Typically the GUI application would
221 register an idle task that calls this function multiple times in
222 a second to quickly process the SILC specific data. */
224 void silc_client_run_one(SilcClient client)
226 /* Run the scheduler once. */
227 silc_schedule_one(client->schedule, 0);
230 static void silc_client_entry_destructor(SilcIDCache cache,
231 SilcIDCacheEntry entry)
233 silc_free(entry->name);
236 /* Allocates and adds new connection to the client. This adds the allocated
237 connection to the connection table and returns a pointer to it. A client
238 can have multiple connections to multiple servers. Every connection must
239 be added to the client using this function. User data `context' may
240 be sent as argument. This function is normally used only if the
241 application performed the connecting outside the library. The library
242 however may use this internally. */
245 silc_client_add_connection(SilcClient client,
246 SilcClientConnectionParams *params,
247 char *hostname, int port, void *context)
249 SilcClientConnection conn;
252 SILC_LOG_DEBUG(("Adding new connection to %s:%d", hostname, port));
254 conn = silc_calloc(1, sizeof(*conn));
255 conn->internal = silc_calloc(1, sizeof(*conn->internal));
257 /* Initialize ID caches */
258 conn->client = client;
259 conn->remote_host = strdup(hostname);
260 conn->remote_port = port;
261 conn->context = context;
262 conn->internal->client_cache =
263 silc_idcache_alloc(0, SILC_ID_CLIENT, silc_client_entry_destructor,
265 conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL,
267 conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL,
269 conn->internal->pending_commands = silc_dlist_init();
270 conn->internal->ftp_sessions = silc_dlist_init();
273 if (params->detach_data)
274 conn->internal->params.detach_data =
275 silc_memdup(params->detach_data,
276 params->detach_data_len);
277 conn->internal->params.detach_data_len = params->detach_data_len;
280 /* Add the connection to connections table */
281 for (i = 0; i < client->internal->conns_count; i++)
282 if (client->internal->conns && !client->internal->conns[i]) {
283 client->internal->conns[i] = conn;
287 client->internal->conns =
288 silc_realloc(client->internal->conns, sizeof(*client->internal->conns)
289 * (client->internal->conns_count + 1));
290 client->internal->conns[client->internal->conns_count] = conn;
291 client->internal->conns_count++;
296 /* Removes connection from client. Frees all memory. */
298 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
302 for (i = 0; i < client->internal->conns_count; i++)
303 if (client->internal->conns[i] == conn) {
304 /* Free all cache entries */
305 SilcIDCacheList list;
306 SilcIDCacheEntry entry;
307 SilcClientCommandPending *r;
310 if (silc_idcache_get_all(conn->internal->client_cache, &list)) {
311 ret = silc_idcache_list_first(list, &entry);
313 silc_client_del_client(client, conn, entry->context);
314 ret = silc_idcache_list_next(list, &entry);
316 silc_idcache_list_free(list);
319 if (silc_idcache_get_all(conn->internal->channel_cache, &list)) {
320 ret = silc_idcache_list_first(list, &entry);
322 silc_client_del_channel(client, conn, entry->context);
323 ret = silc_idcache_list_next(list, &entry);
325 silc_idcache_list_free(list);
328 if (silc_idcache_get_all(conn->internal->server_cache, &list)) {
329 ret = silc_idcache_list_first(list, &entry);
331 silc_client_del_server(client, conn, entry->context);
332 ret = silc_idcache_list_next(list, &entry);
334 silc_idcache_list_free(list);
337 /* Clear ID caches */
338 if (conn->internal->client_cache)
339 silc_idcache_free(conn->internal->client_cache);
340 if (conn->internal->channel_cache)
341 silc_idcache_free(conn->internal->channel_cache);
342 if (conn->internal->server_cache)
343 silc_idcache_free(conn->internal->server_cache);
345 /* Free data (my ID is freed in above silc_client_del_client).
346 conn->nickname is freed when freeing the local_entry->nickname. */
347 silc_free(conn->remote_host);
348 silc_free(conn->local_id_data);
349 if (conn->internal->send_key)
350 silc_cipher_free(conn->internal->send_key);
351 if (conn->internal->receive_key)
352 silc_cipher_free(conn->internal->receive_key);
353 if (conn->internal->hmac_send)
354 silc_hmac_free(conn->internal->hmac_send);
355 if (conn->internal->hmac_receive)
356 silc_hmac_free(conn->internal->hmac_receive);
357 silc_free(conn->internal->rekey);
359 if (conn->internal->active_session) {
361 conn->sock->user_data = NULL;
362 silc_client_ftp_session_free(conn->internal->active_session);
363 conn->internal->active_session = NULL;
366 silc_client_ftp_free_sessions(client, conn);
368 if (conn->internal->pending_commands) {
369 silc_dlist_start(conn->internal->pending_commands);
370 while ((r = silc_dlist_get(conn->internal->pending_commands))
372 silc_dlist_del(conn->internal->pending_commands, r);
373 silc_dlist_uninit(conn->internal->pending_commands);
376 silc_free(conn->internal);
377 memset(conn, 0, sizeof(*conn));
380 client->internal->conns[i] = NULL;
384 /* Adds listener socket to the listener sockets table. This function is
385 used to add socket objects that are listeners to the client. This should
386 not be used to add other connection objects. */
388 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
392 if (!client->internal->sockets) {
393 client->internal->sockets =
394 silc_calloc(1, sizeof(*client->internal->sockets));
395 client->internal->sockets[0] = silc_socket_dup(sock);
396 client->internal->sockets_count = 1;
400 for (i = 0; i < client->internal->sockets_count; i++) {
401 if (client->internal->sockets[i] == NULL) {
402 client->internal->sockets[i] = silc_socket_dup(sock);
407 client->internal->sockets =
408 silc_realloc(client->internal->sockets,
409 sizeof(*client->internal->sockets) *
410 (client->internal->sockets_count + 1));
411 client->internal->sockets[client->internal->sockets_count] =
412 silc_socket_dup(sock);
413 client->internal->sockets_count++;
416 /* Deletes listener socket from the listener sockets table. */
418 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
422 if (!client->internal->sockets)
425 for (i = 0; i < client->internal->sockets_count; i++) {
426 if (client->internal->sockets[i] == sock) {
427 silc_socket_free(sock);
428 client->internal->sockets[i] = NULL;
435 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
439 /* XXX In the future we should give up this non-blocking connect all
440 together and use threads instead. */
441 /* Create connection to server asynchronously */
442 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
446 /* Register task that will receive the async connect and will
448 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
449 silc_client_connect_to_server_start,
452 SILC_TASK_PRI_NORMAL);
453 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE,
461 /* Connects to remote server. This is the main routine used to connect
462 to SILC server. Returns -1 on error and the created socket otherwise.
463 The `context' is user context that is saved into the SilcClientConnection
464 that is created after the connection is created. Note that application
465 may handle the connecting process outside the library. If this is the
466 case then this function is not used at all. When the connecting is
467 done the `connect' client operation is called. */
469 int silc_client_connect_to_server(SilcClient client,
470 SilcClientConnectionParams *params,
471 int port, char *host, void *context)
473 SilcClientInternalConnectContext *ctx;
474 SilcClientConnection conn;
477 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
480 conn = silc_client_add_connection(client, params, host, port, context);
482 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
483 "Connecting to port %d of server %s", port, host);
485 /* Allocate internal context for connection process. This is
486 needed as we are doing async connecting. */
487 ctx = silc_calloc(1, sizeof(*ctx));
488 ctx->client = client;
490 ctx->host = strdup(host);
491 ctx->port = port ? port : 706;
494 /* Do the actual connecting process */
495 sock = silc_client_connect_to_server_internal(ctx);
497 silc_client_del_connection(client, conn);
501 /* Socket hostname and IP lookup callback that is called before actually
502 starting the key exchange. The lookup is called from the function
503 silc_client_start_key_exchange. */
505 static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
508 SilcClientConnection conn = (SilcClientConnection)context;
509 SilcClient client = conn->client;
510 SilcProtocol protocol;
511 SilcClientKEInternalContext *proto_ctx;
513 SILC_LOG_DEBUG(("Start"));
515 if (conn->sock->hostname) {
516 silc_free(conn->remote_host);
517 conn->remote_host = strdup(conn->sock->hostname);
519 conn->sock->hostname = strdup(conn->remote_host);
522 conn->sock->ip = strdup(conn->sock->hostname);
523 conn->sock->port = conn->remote_port;
525 /* Allocate internal Key Exchange context. This is sent to the
526 protocol as context. */
527 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
528 proto_ctx->client = (void *)client;
529 proto_ctx->sock = silc_socket_dup(conn->sock);
530 proto_ctx->rng = client->rng;
531 proto_ctx->responder = FALSE;
532 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
533 proto_ctx->verify = silc_client_protocol_ke_verify_key;
535 /* Perform key exchange protocol. silc_client_connect_to_server_final
536 will be called after the protocol is finished. */
537 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
538 &protocol, (void *)proto_ctx,
539 silc_client_connect_to_server_second);
541 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
542 "Error: Could not start key exchange protocol");
543 silc_net_close_connection(conn->sock->sock);
544 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
547 conn->sock->protocol = protocol;
549 /* Register the connection for network input and output. This sets
550 that scheduler will listen for incoming packets for this connection
551 and sets that outgoing packets may be sent to this connection as well.
552 However, this doesn't set the scheduler for outgoing traffic, it will
553 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
554 later when outgoing data is available. */
555 context = (void *)client;
556 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(conn->sock->sock);
558 /* Execute the protocol */
559 silc_protocol_execute(protocol, client->schedule, 0, 0);
562 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
563 key material between client and server. This function can be called
564 directly if application is performing its own connecting and does not
565 use the connecting provided by this library. This function is normally
566 used only if the application performed the connecting outside the library.
567 The library however may use this internally. */
569 void silc_client_start_key_exchange(SilcClient client,
570 SilcClientConnection conn,
573 assert(client->pkcs);
574 assert(client->public_key);
575 assert(client->private_key);
577 /* Allocate new socket connection object */
578 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
580 /* Sometimes when doing quick reconnects the new socket may be same as
581 the old one and there might be pending stuff for the old socket.
582 If new one is same then those pending sutff might cause problems.
583 Make sure they do not do that. */
584 silc_schedule_task_del_by_fd(client->schedule, fd);
586 conn->nickname = (client->nickname ? strdup(client->nickname) :
587 strdup(client->username));
589 /* Resolve the remote hostname and IP address for our socket connection */
590 silc_socket_host_lookup(conn->sock, FALSE, silc_client_start_key_exchange_cb,
591 conn, client->schedule);
594 /* Callback called when error has occurred during connecting (KE) to
595 the server. The `connect' client operation will be called. */
597 SILC_TASK_CALLBACK(silc_client_connect_failure)
599 SilcClientKEInternalContext *ctx =
600 (SilcClientKEInternalContext *)context;
601 SilcClient client = (SilcClient)ctx->client;
603 client->internal->ops->connected(client, ctx->sock->user_data,
604 SILC_CLIENT_CONN_ERROR_KE);
606 silc_packet_context_free(ctx->packet);
610 /* Callback called when error has occurred during connecting (auth) to
611 the server. The `connect' client operation will be called. */
613 SILC_TASK_CALLBACK(silc_client_connect_failure_auth)
615 SilcClientConnAuthInternalContext *ctx =
616 (SilcClientConnAuthInternalContext *)context;
617 SilcClient client = (SilcClient)ctx->client;
619 client->internal->ops->connected(client, ctx->sock->user_data, ctx->status);
623 /* Start of the connection to the remote server. This is called after
624 succesful TCP/IP connection has been established to the remote host. */
626 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
628 SilcClientInternalConnectContext *ctx =
629 (SilcClientInternalConnectContext *)context;
630 SilcClient client = ctx->client;
631 SilcClientConnection conn = ctx->conn;
632 int opt, opt_len = sizeof(opt);
634 SILC_LOG_DEBUG(("Start"));
636 /* Check the socket status as it might be in error */
637 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
639 if (ctx->tries < 2) {
640 /* Connection failed but lets try again */
641 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
642 "Could not connect to server %s: %s",
643 ctx->host, strerror(opt));
644 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
645 "Connecting to port %d of server %s resumed",
646 ctx->port, ctx->host);
648 /* Unregister old connection try */
649 silc_schedule_unset_listen_fd(client->schedule, fd);
650 silc_net_close_connection(fd);
651 silc_schedule_task_del(client->schedule, ctx->task);
654 silc_client_connect_to_server_internal(ctx);
657 /* Connection failed and we won't try anymore */
658 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
659 "Could not connect to server %s: %s",
660 ctx->host, strerror(opt));
661 silc_schedule_unset_listen_fd(client->schedule, fd);
662 silc_net_close_connection(fd);
663 silc_schedule_task_del(client->schedule, ctx->task);
666 /* Notify application of failure */
667 client->internal->ops->connected(client, conn,
668 SILC_CLIENT_CONN_ERROR_TIMEOUT);
673 silc_schedule_unset_listen_fd(client->schedule, fd);
674 silc_schedule_task_del(client->schedule, ctx->task);
677 silc_client_start_key_exchange(client, conn, fd);
680 /* Second part of the connecting to the server. This executed
681 authentication protocol. */
683 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
685 SilcProtocol protocol = (SilcProtocol)context;
686 SilcClientKEInternalContext *ctx =
687 (SilcClientKEInternalContext *)protocol->context;
688 SilcClient client = (SilcClient)ctx->client;
689 SilcSocketConnection sock = NULL;
690 SilcClientConnAuthInternalContext *proto_ctx;
692 SILC_LOG_DEBUG(("Start"));
694 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
695 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
696 /* Error occured during protocol */
697 SILC_LOG_DEBUG(("Error during KE protocol"));
698 silc_protocol_free(protocol);
699 silc_ske_free_key_material(ctx->keymat);
701 silc_ske_free(ctx->ske);
703 silc_free(ctx->dest_id);
704 ctx->sock->protocol = NULL;
705 silc_socket_free(ctx->sock);
707 /* Notify application of failure */
708 silc_schedule_task_add(client->schedule, ctx->sock->sock,
709 silc_client_connect_failure, ctx,
710 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
714 /* We now have the key material as the result of the key exchange
715 protocol. Take the key material into use. Free the raw key material
716 as soon as we've set them into use. */
717 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
718 ctx->ske->prop->cipher,
719 ctx->ske->prop->pkcs,
720 ctx->ske->prop->hash,
721 ctx->ske->prop->hmac,
722 ctx->ske->prop->group,
724 silc_ske_free_key_material(ctx->keymat);
726 /* Allocate internal context for the authentication protocol. This
727 is sent as context for the protocol. */
728 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
729 proto_ctx->client = (void *)client;
730 proto_ctx->sock = sock = ctx->sock;
731 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
732 proto_ctx->dest_id_type = ctx->dest_id_type;
733 proto_ctx->dest_id = ctx->dest_id;
735 /* Free old protocol as it is finished now */
736 silc_protocol_free(protocol);
738 silc_packet_context_free(ctx->packet);
741 sock->protocol = NULL;
743 /* Resolve the authentication method to be used in this connection. The
744 completion callback is called after the application has resolved
745 the authentication method. */
746 client->internal->ops->get_auth_method(client, sock->user_data,
749 silc_client_resolve_auth_method,
753 /* Authentication method resolving callback. Application calls this function
754 after we've called the client->internal->ops->get_auth_method
755 client operation to resolve the authentication method. We will continue
756 the executiong of the protocol in this function. */
758 void silc_client_resolve_auth_method(bool success,
759 SilcProtocolAuthMeth auth_meth,
760 const unsigned char *auth_data,
761 SilcUInt32 auth_data_len, void *context)
763 SilcClientConnAuthInternalContext *proto_ctx =
764 (SilcClientConnAuthInternalContext *)context;
765 SilcClient client = (SilcClient)proto_ctx->client;
768 auth_meth = SILC_AUTH_NONE;
770 proto_ctx->auth_meth = auth_meth;
772 if (success && auth_data && auth_data_len) {
774 /* Passphrase must be UTF-8 encoded, if it isn't encode it */
775 if (auth_meth == SILC_AUTH_PASSWORD &&
776 !silc_utf8_valid(auth_data, auth_data_len)) {
778 unsigned char *autf8 = NULL;
779 payload_len = silc_utf8_encoded_len(auth_data, auth_data_len,
781 autf8 = silc_calloc(payload_len, sizeof(*autf8));
782 auth_data_len = silc_utf8_encode(auth_data, auth_data_len,
783 SILC_STRING_ASCII, autf8, payload_len);
787 proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
788 proto_ctx->auth_data_len = auth_data_len;
791 /* Allocate the authenteication protocol and execute it. */
792 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
793 &proto_ctx->sock->protocol, (void *)proto_ctx,
794 silc_client_connect_to_server_final);
796 /* Execute the protocol */
797 silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
800 /* Finalizes the connection to the remote SILC server. This is called
801 after authentication protocol has been completed. This send our
802 user information to the server to receive our client ID from
805 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
807 SilcProtocol protocol = (SilcProtocol)context;
808 SilcClientConnAuthInternalContext *ctx =
809 (SilcClientConnAuthInternalContext *)protocol->context;
810 SilcClient client = (SilcClient)ctx->client;
811 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
814 SILC_LOG_DEBUG(("Start"));
816 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
817 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
818 /* Error occured during protocol */
819 SILC_LOG_DEBUG(("Error during authentication protocol"));
820 ctx->status = SILC_CLIENT_CONN_ERROR_AUTH;
824 if (conn->internal->params.detach_data) {
825 /* Send RESUME_CLIENT packet to the server, which is used to resume
826 old detached session back. */
828 SilcClientID *old_client_id;
829 unsigned char *old_id;
830 SilcUInt16 old_id_len;
832 if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len)) {
833 ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
837 old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT);
838 if (!old_client_id) {
840 ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
844 /* Generate authentication data that server will verify */
845 auth = silc_auth_public_key_auth_generate(client->public_key,
848 conn->internal->hash,
849 old_client_id, SILC_ID_CLIENT);
851 silc_free(old_client_id);
853 ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
857 packet = silc_buffer_alloc_size(2 + old_id_len + auth->len);
858 silc_buffer_format(packet,
859 SILC_STR_UI_SHORT(old_id_len),
860 SILC_STR_UI_XNSTRING(old_id, old_id_len),
861 SILC_STR_UI_XNSTRING(auth->data, auth->len),
864 /* Send the packet */
865 silc_client_packet_send(client, ctx->sock, SILC_PACKET_RESUME_CLIENT,
867 packet->data, packet->len, TRUE);
868 silc_buffer_free(packet);
869 silc_buffer_free(auth);
870 silc_free(old_client_id);
873 /* Send NEW_CLIENT packet to the server. We will become registered
874 to the SILC network after sending this packet and we will receive
875 client ID from the server. */
876 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
877 strlen(client->realname));
878 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
879 silc_buffer_format(packet,
880 SILC_STR_UI_SHORT(strlen(client->username)),
881 SILC_STR_UI_XNSTRING(client->username,
882 strlen(client->username)),
883 SILC_STR_UI_SHORT(strlen(client->realname)),
884 SILC_STR_UI_XNSTRING(client->realname,
885 strlen(client->realname)),
888 /* Send the packet */
889 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
891 packet->data, packet->len, TRUE);
892 silc_buffer_free(packet);
895 /* Save remote ID. */
896 conn->remote_id = ctx->dest_id;
897 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
898 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
900 /* Register re-key timeout */
901 conn->internal->rekey->timeout = client->internal->params->rekey_secs;
902 conn->internal->rekey->context = (void *)client;
903 silc_schedule_task_add(client->schedule, conn->sock->sock,
904 silc_client_rekey_callback,
905 (void *)conn->sock, conn->internal->rekey->timeout, 0,
906 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
908 silc_protocol_free(protocol);
909 silc_free(ctx->auth_data);
911 silc_ske_free(ctx->ske);
912 silc_socket_free(ctx->sock);
914 conn->sock->protocol = NULL;
918 silc_protocol_free(protocol);
919 silc_free(ctx->auth_data);
920 silc_free(ctx->dest_id);
922 silc_ske_free(ctx->ske);
923 conn->sock->protocol = NULL;
924 silc_socket_free(ctx->sock);
926 /* Notify application of failure */
927 silc_schedule_task_add(client->schedule, ctx->sock->sock,
928 silc_client_connect_failure_auth, ctx,
929 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
932 /* Internal routine that sends packet or marks packet to be sent. This
933 is used directly only in special cases. Normal cases should use
934 silc_server_packet_send. Returns < 0 on error. */
936 int silc_client_packet_send_real(SilcClient client,
937 SilcSocketConnection sock,
942 /* If rekey protocol is active we must assure that all packets are
943 sent through packet queue. */
944 if (SILC_CLIENT_IS_REKEY(sock))
947 /* If outbound data is already pending do not force send */
948 if (SILC_IS_OUTBUF_PENDING(sock))
951 /* Send the packet */
952 ret = silc_packet_send(sock, force_send);
956 /* Mark that there is some outgoing data available for this connection.
957 This call sets the connection both for input and output (the input
958 is set always and this call keeps the input setting, actually).
959 Actual data sending is performed by silc_client_packet_process. */
960 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
962 /* Mark to socket that data is pending in outgoing buffer. This flag
963 is needed if new data is added to the buffer before the earlier
964 put data is sent to the network. */
965 SILC_SET_OUTBUF_PENDING(sock);
970 /* Packet processing callback. This is used to send and receive packets
971 from network. This is generic task. */
973 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
975 SilcClient client = (SilcClient)context;
976 SilcSocketConnection sock = NULL;
977 SilcClientConnection conn;
980 SILC_LOG_DEBUG(("Processing packet"));
982 SILC_CLIENT_GET_SOCK(client, fd, sock);
986 conn = (SilcClientConnection)sock->user_data;
989 if (type == SILC_TASK_WRITE) {
990 /* Do not send data to disconnected connection */
991 if (SILC_IS_DISCONNECTED(sock))
994 ret = silc_packet_send(sock, TRUE);
996 /* If returned -2 could not write to connection now, will do
1005 /* The packet has been sent and now it is time to set the connection
1006 back to only for input. When there is again some outgoing data
1007 available for this connection it will be set for output as well.
1008 This call clears the output setting and sets it only for input. */
1009 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
1010 SILC_UNSET_OUTBUF_PENDING(sock);
1012 silc_buffer_clear(sock->outbuf);
1016 /* Packet receiving */
1017 if (type == SILC_TASK_READ) {
1018 /* Read data from network */
1019 ret = silc_packet_receive(sock);
1025 SILC_LOG_DEBUG(("Read EOF"));
1027 /* If connection is disconnecting already we will finally
1028 close the connection */
1029 if (SILC_IS_DISCONNECTING(sock)) {
1030 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1031 client->internal->ops->disconnected(client, conn, 0, NULL);
1032 silc_client_close_connection_real(client, sock, conn);
1036 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
1037 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1038 client->internal->ops->disconnected(client, conn, 0, NULL);
1039 silc_client_close_connection_real(client, sock, conn);
1043 /* Process the packet. This will call the parser that will then
1044 decrypt and parse the packet. */
1045 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
1046 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
1047 conn->internal->hmac_receive,
1048 conn->internal->psn_receive,
1049 silc_client_packet_parse, client);
1051 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
1052 silc_client_packet_parse, client);
1056 /* Parser callback called by silc_packet_receive_process. Thie merely
1057 registers timeout that will handle the actual parsing when appropriate. */
1059 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
1062 SilcClient client = (SilcClient)context;
1063 SilcSocketConnection sock = parser_context->sock;
1064 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1065 SilcPacketContext *packet = parser_context->packet;
1068 if (conn && conn->internal->hmac_receive && conn->sock == sock)
1069 conn->internal->psn_receive = parser_context->packet->sequence + 1;
1071 /* Parse the packet immediately */
1072 if (parser_context->normal)
1073 ret = silc_packet_parse(packet, conn->internal->receive_key);
1075 ret = silc_packet_parse_special(packet, conn->internal->receive_key);
1077 if (ret == SILC_PACKET_NONE) {
1078 silc_packet_context_free(packet);
1079 silc_free(parser_context);
1083 /* If protocol for this connection is key exchange or rekey then we'll
1084 process all packets synchronously, since there might be packets in
1085 queue that we are not able to decrypt without first processing the
1086 packets before them. */
1087 if (sock->protocol && sock->protocol->protocol &&
1088 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1089 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1091 /* Parse the incoming packet type */
1092 silc_client_packet_parse_type(client, sock, packet);
1094 /* Reprocess the buffer since we'll return FALSE. This is because
1095 the `conn->internal->receive_key' might have become valid by processing
1096 the previous packet */
1097 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
1098 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
1099 conn->internal->hmac_receive,
1100 conn->internal->psn_receive,
1101 silc_client_packet_parse, client);
1103 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
1104 silc_client_packet_parse, client);
1106 silc_packet_context_free(packet);
1107 silc_free(parser_context);
1112 /* Parse the incoming packet type */
1113 silc_client_packet_parse_type(client, sock, packet);
1114 silc_packet_context_free(packet);
1115 silc_free(parser_context);
1119 /* Parses the packet type and calls what ever routines the packet type
1120 requires. This is done for all incoming packets. */
1122 void silc_client_packet_parse_type(SilcClient client,
1123 SilcSocketConnection sock,
1124 SilcPacketContext *packet)
1126 SilcBuffer buffer = packet->buffer;
1127 SilcPacketType type = packet->type;
1129 SILC_LOG_DEBUG(("Parsing %s packet", silc_get_packet_name(type)));
1131 /* Parse the packet type */
1134 case SILC_PACKET_DISCONNECT:
1135 silc_client_disconnected_by_server(client, sock, buffer);
1138 case SILC_PACKET_SUCCESS:
1140 * Success received for something. For now we can have only
1141 * one protocol for connection executing at once hence this
1142 * success message is for whatever protocol is executing currently.
1145 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1148 case SILC_PACKET_FAILURE:
1150 * Failure received for some protocol. Set the protocol state to
1151 * error and call the protocol callback. This fill cause error on
1152 * protocol and it will call the final callback.
1154 silc_client_process_failure(client, sock, packet);
1157 case SILC_PACKET_REJECT:
1160 case SILC_PACKET_NOTIFY:
1162 * Received notify message
1164 silc_client_notify_by_server(client, sock, packet);
1167 case SILC_PACKET_ERROR:
1169 * Received error message
1171 silc_client_error_by_server(client, sock, buffer);
1174 case SILC_PACKET_CHANNEL_MESSAGE:
1176 * Received message to (from, actually) a channel
1178 silc_client_channel_message(client, sock, packet);
1181 case SILC_PACKET_CHANNEL_KEY:
1183 * Received key for a channel. By receiving this key the client will be
1184 * able to talk to the channel it has just joined. This can also be
1185 * a new key for existing channel as keys expire peridiocally.
1187 silc_client_receive_channel_key(client, sock, buffer);
1190 case SILC_PACKET_PRIVATE_MESSAGE:
1192 * Received private message
1194 silc_client_private_message(client, sock, packet);
1197 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1199 * Received private message key indicator
1201 silc_client_private_message_key(client, sock, packet);
1204 case SILC_PACKET_COMMAND:
1206 * Received command packet, a special case since normally client
1207 * does not receive commands.
1209 silc_client_command_process(client, sock, packet);
1212 case SILC_PACKET_COMMAND_REPLY:
1214 * Recived reply for a command
1216 silc_client_command_reply_process(client, sock, packet);
1219 case SILC_PACKET_KEY_EXCHANGE:
1220 if (sock->protocol && sock->protocol->protocol &&
1221 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
1222 SilcClientKEInternalContext *proto_ctx =
1223 (SilcClientKEInternalContext *)sock->protocol->context;
1225 proto_ctx->packet = silc_packet_context_dup(packet);
1226 proto_ctx->dest_id_type = packet->src_id_type;
1227 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1228 packet->src_id_type);
1229 if (!proto_ctx->dest_id)
1232 /* Let the protocol handle the packet */
1233 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1235 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1236 "protocol active, packet dropped."));
1240 case SILC_PACKET_KEY_EXCHANGE_1:
1241 if (sock->protocol && sock->protocol->protocol &&
1242 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1243 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1245 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1246 SilcClientRekeyInternalContext *proto_ctx =
1247 (SilcClientRekeyInternalContext *)sock->protocol->context;
1249 if (proto_ctx->packet)
1250 silc_packet_context_free(proto_ctx->packet);
1252 proto_ctx->packet = silc_packet_context_dup(packet);
1254 /* Let the protocol handle the packet */
1255 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1257 SilcClientKEInternalContext *proto_ctx =
1258 (SilcClientKEInternalContext *)sock->protocol->context;
1260 if (proto_ctx->packet)
1261 silc_packet_context_free(proto_ctx->packet);
1263 proto_ctx->packet = silc_packet_context_dup(packet);
1264 proto_ctx->dest_id_type = packet->src_id_type;
1265 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1266 packet->src_id_type);
1267 if (!proto_ctx->dest_id)
1270 /* Let the protocol handle the packet */
1271 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1274 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1275 "protocol active, packet dropped."));
1279 case SILC_PACKET_KEY_EXCHANGE_2:
1280 if (sock->protocol && sock->protocol->protocol &&
1281 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1282 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1284 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1285 SilcClientRekeyInternalContext *proto_ctx =
1286 (SilcClientRekeyInternalContext *)sock->protocol->context;
1288 if (proto_ctx->packet)
1289 silc_packet_context_free(proto_ctx->packet);
1291 proto_ctx->packet = silc_packet_context_dup(packet);
1293 /* Let the protocol handle the packet */
1294 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1296 SilcClientKEInternalContext *proto_ctx =
1297 (SilcClientKEInternalContext *)sock->protocol->context;
1299 if (proto_ctx->packet)
1300 silc_packet_context_free(proto_ctx->packet);
1301 if (proto_ctx->dest_id)
1302 silc_free(proto_ctx->dest_id);
1303 proto_ctx->packet = silc_packet_context_dup(packet);
1304 proto_ctx->dest_id_type = packet->src_id_type;
1305 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1306 packet->src_id_type);
1307 if (!proto_ctx->dest_id)
1310 /* Let the protocol handle the packet */
1311 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1314 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1315 "protocol active, packet dropped."));
1319 case SILC_PACKET_NEW_ID:
1322 * Received new ID from server. This packet is received at
1323 * the connection to the server. New ID is also received when
1324 * user changes nickname but in that case the new ID is received
1325 * as command reply and not as this packet type.
1329 idp = silc_id_payload_parse(buffer->data, buffer->len);
1332 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1335 silc_client_receive_new_id(client, sock, idp);
1336 silc_id_payload_free(idp);
1340 case SILC_PACKET_HEARTBEAT:
1342 * Received heartbeat packet
1344 SILC_LOG_DEBUG(("Heartbeat packet"));
1347 case SILC_PACKET_KEY_AGREEMENT:
1349 * Received key agreement packet
1351 SILC_LOG_DEBUG(("Key agreement packet"));
1352 silc_client_key_agreement(client, sock, packet);
1355 case SILC_PACKET_REKEY:
1356 SILC_LOG_DEBUG(("Re-key packet"));
1357 /* We ignore this for now */
1360 case SILC_PACKET_REKEY_DONE:
1361 SILC_LOG_DEBUG(("Re-key done packet"));
1363 if (sock->protocol && sock->protocol->protocol &&
1364 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1366 SilcClientRekeyInternalContext *proto_ctx =
1367 (SilcClientRekeyInternalContext *)sock->protocol->context;
1369 if (proto_ctx->packet)
1370 silc_packet_context_free(proto_ctx->packet);
1372 proto_ctx->packet = silc_packet_context_dup(packet);
1374 /* Let the protocol handle the packet */
1375 if (proto_ctx->responder == FALSE)
1376 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1378 /* Let the protocol handle the packet */
1379 silc_protocol_execute(sock->protocol, client->schedule,
1382 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1383 "protocol active, packet dropped."));
1387 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1389 * Reveived reply to our connection authentication method request
1390 * packet. This is used to resolve the authentication method for the
1391 * current session from the server if the client does not know it.
1393 silc_client_connection_auth_request(client, sock, packet);
1396 case SILC_PACKET_FTP:
1397 /* Received file transfer packet. */
1398 silc_client_ftp(client, sock, packet);
1402 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1407 /* Sends packet. This doesn't actually send the packet instead it assembles
1408 it and marks it to be sent. However, if force_send is TRUE the packet
1409 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1410 will be derived from sock argument. Otherwise the valid arguments sent
1413 void silc_client_packet_send(SilcClient client,
1414 SilcSocketConnection sock,
1415 SilcPacketType type,
1417 SilcIdType dst_id_type,
1420 unsigned char *data,
1421 SilcUInt32 data_len,
1424 SilcPacketContext packetdata;
1425 const SilcBufferStruct packet;
1427 SilcUInt32 sequence = 0;
1432 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1434 /* Get data used in the packet sending, keys and stuff */
1435 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1436 if (!cipher && ((SilcClientConnection)sock->user_data)->internal->send_key)
1437 cipher = ((SilcClientConnection)sock->user_data)->internal->send_key;
1439 if (!hmac && ((SilcClientConnection)sock->user_data)->internal->hmac_send)
1440 hmac = ((SilcClientConnection)sock->user_data)->internal->hmac_send;
1442 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1443 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1444 dst_id_type = SILC_ID_SERVER;
1448 sequence = ((SilcClientConnection)sock->user_data)->internal->psn_send++;
1450 /* Check for mandatory rekey */
1451 if (sequence == SILC_CLIENT_REKEY_THRESHOLD)
1452 silc_schedule_task_add(client->schedule, sock->sock,
1453 silc_client_rekey_callback, sock, 0, 1,
1454 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1457 block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1459 /* Set the packet context pointers */
1460 packetdata.flags = 0;
1461 packetdata.type = type;
1462 if (sock->user_data &&
1463 ((SilcClientConnection)sock->user_data)->local_id_data) {
1464 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1465 packetdata.src_id_len =
1466 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1469 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1470 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1472 packetdata.src_id_type = SILC_ID_CLIENT;
1474 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1475 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1476 packetdata.dst_id_type = dst_id_type;
1478 packetdata.dst_id = NULL;
1479 packetdata.dst_id_len = 0;
1480 packetdata.dst_id_type = SILC_ID_NONE;
1482 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1483 packetdata.src_id_len +
1484 packetdata.dst_id_len));
1485 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1486 packetdata.src_id_len + packetdata.dst_id_len;
1487 if (type == SILC_PACKET_CONNECTION_AUTH)
1488 SILC_PACKET_PADLEN_MAX(packetdata.truelen, block_len, packetdata.padlen);
1490 SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
1492 /* Create the outgoing packet */
1493 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
1494 data, data_len, (const SilcBuffer)&packet)) {
1495 SILC_LOG_ERROR(("Error assembling packet"));
1499 /* Encrypt the packet */
1501 silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet,
1504 SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
1505 packet.data, packet.len);
1507 /* Now actually send the packet */
1508 silc_client_packet_send_real(client, sock, force_send);
1511 /* Packet sending routine for application. This is the only routine that
1512 is provided for application to send SILC packets. */
1514 bool silc_client_send_packet(SilcClient client,
1515 SilcClientConnection conn,
1516 SilcPacketType type,
1517 const unsigned char *data,
1518 SilcUInt32 data_len)
1525 silc_client_packet_send(client, conn->sock, type, NULL, 0, NULL, NULL,
1526 (unsigned char *)data, data_len, TRUE);
1530 void silc_client_packet_queue_purge(SilcClient client,
1531 SilcSocketConnection sock)
1533 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1534 !(SILC_IS_DISCONNECTED(sock))) {
1537 ret = silc_packet_send(sock, TRUE);
1539 if (sock->outbuf && sock->outbuf->len > 0) {
1540 /* Couldn't send all data, put the queue back up, we'll send
1542 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
1543 SILC_SET_OUTBUF_PENDING(sock);
1548 /* Purged all data */
1549 SILC_UNSET_OUTBUF_PENDING(sock);
1550 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1551 silc_buffer_clear(sock->outbuf);
1555 /* Closes connection to remote end. Free's all allocated data except
1556 for some information such as nickname etc. that are valid at all time.
1557 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1558 provided it will be checked whether the sock and `conn->sock' are the
1559 same (they can be different, ie. a socket can use `conn' as its
1560 connection but `conn->sock' might be actually a different connection
1561 than the `sock'). */
1563 void silc_client_close_connection_real(SilcClient client,
1564 SilcSocketConnection sock,
1565 SilcClientConnection conn)
1569 SILC_LOG_DEBUG(("Start"));
1574 if (!sock || (sock && conn->sock == sock))
1581 silc_client_del_connection(client, conn);
1585 /* We won't listen for this connection anymore */
1586 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1588 /* Unregister all tasks */
1589 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1591 /* Close the actual connection */
1592 silc_net_close_connection(sock->sock);
1594 /* Cancel any active protocol */
1595 if (sock->protocol) {
1596 if (sock->protocol->protocol->type ==
1597 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1598 sock->protocol->protocol->type ==
1599 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1600 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1601 silc_protocol_execute_final(sock->protocol, client->schedule);
1602 /* The application will recall this function with these protocols
1603 (the ops->connected client operation). */
1606 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1607 silc_protocol_execute_final(sock->protocol, client->schedule);
1608 sock->protocol = NULL;
1612 /* Free everything */
1613 if (del && sock->user_data)
1614 silc_client_del_connection(client, conn);
1616 silc_socket_free(sock);
1619 /* Closes the connection to the remote end */
1621 void silc_client_close_connection(SilcClient client,
1622 SilcClientConnection conn)
1624 silc_client_close_connection_real(client, NULL, conn);
1627 /* Called when we receive disconnection packet from server. This
1628 closes our end properly and displays the reason of the disconnection
1631 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1633 SilcClient client = (SilcClient)context;
1634 SilcSocketConnection sock;
1636 SILC_CLIENT_GET_SOCK(client, fd, sock);
1640 silc_client_close_connection_real(client, sock, sock->user_data);
1643 /* Called when we receive disconnection packet from server. This
1644 closes our end properly and displays the reason of the disconnection
1647 void silc_client_disconnected_by_server(SilcClient client,
1648 SilcSocketConnection sock,
1651 SilcClientConnection conn;
1653 char *message = NULL;
1655 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1657 if (packet->len < 1)
1660 status = (SilcStatus)packet->data[0];
1662 if (packet->len > 1 &&
1663 silc_utf8_valid(packet->data + 1, packet->len - 1))
1664 message = silc_memdup(packet->data + 1, packet->len - 1);
1666 conn = (SilcClientConnection)sock->user_data;
1667 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1668 client->internal->ops->disconnected(client, conn, status, message);
1672 SILC_SET_DISCONNECTED(sock);
1674 /* Close connection through scheduler. */
1675 silc_schedule_task_add(client->schedule, sock->sock,
1676 silc_client_disconnected_by_server_later,
1677 client, 0, 1, SILC_TASK_TIMEOUT,
1678 SILC_TASK_PRI_NORMAL);
1681 /* Received error message from server. Display it on the screen.
1682 We don't take any action what so ever of the error message. */
1684 void silc_client_error_by_server(SilcClient client,
1685 SilcSocketConnection sock,
1690 msg = silc_memdup(message->data, message->len);
1691 client->internal->ops->say(client, sock->user_data,
1692 SILC_CLIENT_MESSAGE_AUDIT, msg);
1696 /* Auto-nicking callback to send NICK command to server. */
1698 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1700 SilcClientConnection conn = (SilcClientConnection)context;
1701 SilcClient client = conn->client;
1703 silc_client_command_send(client, conn, SILC_COMMAND_NICK,
1704 ++conn->cmd_ident, 1, 1,
1705 client->nickname, strlen(client->nickname));
1708 /* Client session resuming callback. If the session was resumed
1709 this callback is called after the resuming is completed. This
1710 will call the `connect' client operation to the application
1711 since it has not been called yet. */
1713 static void silc_client_resume_session_cb(SilcClient client,
1714 SilcClientConnection conn,
1720 /* Notify application that connection is created to server */
1721 client->internal->ops->connected(client, conn, success ?
1722 SILC_CLIENT_CONN_SUCCESS_RESUME :
1723 SILC_CLIENT_CONN_ERROR_RESUME);
1726 /* Issue INFO command to fetch the real server name and server
1727 information and other stuff. */
1728 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1729 silc_client_command_reply_info_i, 0,
1731 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1732 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1733 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1734 silc_buffer_free(sidp);
1738 /* Processes the received new Client ID from server. Old Client ID is
1739 deleted from cache and new one is added. */
1741 void silc_client_receive_new_id(SilcClient client,
1742 SilcSocketConnection sock,
1745 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1746 int connecting = FALSE;
1747 SilcClientID *client_id = silc_id_payload_get_id(idp);
1749 if (!conn->local_entry)
1752 /* Delete old ID from ID cache */
1753 if (conn->local_id) {
1754 /* Check whether they are different */
1755 if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1756 silc_free(client_id);
1760 silc_idcache_del_by_context(conn->internal->client_cache,
1762 silc_free(conn->local_id);
1765 /* Save the new ID */
1767 if (conn->local_id_data)
1768 silc_free(conn->local_id_data);
1770 conn->local_id = client_id;
1771 conn->local_id_data = silc_id_payload_get_data(idp);
1772 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1774 if (!conn->local_entry)
1775 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1777 conn->local_entry->nickname = conn->nickname;
1778 if (!conn->local_entry->username)
1779 conn->local_entry->username = strdup(client->username);
1780 if (!conn->local_entry->server)
1781 conn->local_entry->server = strdup(conn->remote_host);
1782 conn->local_entry->id = conn->local_id;
1783 conn->local_entry->valid = TRUE;
1784 if (!conn->local_entry->channels)
1785 conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
1790 /* Put it to the ID cache */
1791 silc_idcache_add(conn->internal->client_cache,
1792 strdup(conn->nickname), conn->local_id,
1793 (void *)conn->local_entry, 0, NULL);
1798 /* Issue IDENTIFY command for itself to get resolved hostname
1799 correctly from server. */
1800 silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
1801 silc_client_command_reply_identify_i, 0,
1803 sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT);
1804 silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
1805 conn->cmd_ident, 1, 5, sidp->data, sidp->len);
1806 silc_buffer_free(sidp);
1808 if (!conn->internal->params.detach_data) {
1809 /* Send NICK command if the nickname was set by the application (and is
1810 not same as the username). Send this with little timeout. */
1811 if (client->nickname &&
1812 !silc_utf8_strcasecmp(client->nickname, client->username))
1813 silc_schedule_task_add(client->schedule, 0,
1814 silc_client_send_auto_nick, conn,
1815 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1817 /* Notify application of successful connection. We do it here now that
1818 we've received the Client ID and are allowed to send traffic. */
1819 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_SUCCESS);
1821 /* Issue INFO command to fetch the real server name and server
1822 information and other stuff. */
1823 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1824 silc_client_command_reply_info_i, 0,
1826 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1827 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1828 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1829 silc_buffer_free(sidp);
1831 /* We are resuming session. Start resolving informations from the
1832 server we need to set the client libary in the state before
1833 detaching the session. The connect client operation is called
1834 after this is successfully completed */
1835 silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1841 /* Removes a client entry from all channels it has joined. */
1843 void silc_client_remove_from_channels(SilcClient client,
1844 SilcClientConnection conn,
1845 SilcClientEntry client_entry)
1847 SilcHashTableList htl;
1848 SilcChannelUser chu;
1850 silc_hash_table_list(client_entry->channels, &htl);
1851 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1852 silc_hash_table_del(chu->client->channels, chu->channel);
1853 silc_hash_table_del(chu->channel->user_list, chu->client);
1857 silc_hash_table_list_reset(&htl);
1860 /* Replaces `old' client entries from all channels to `new' client entry.
1861 This can be called for example when nickname changes and old ID entry
1862 is replaced from ID cache with the new one. If the old ID entry is only
1863 updated, then this fucntion needs not to be called. */
1865 void silc_client_replace_from_channels(SilcClient client,
1866 SilcClientConnection conn,
1867 SilcClientEntry old,
1868 SilcClientEntry new)
1870 SilcHashTableList htl;
1871 SilcChannelUser chu;
1873 silc_hash_table_list(old->channels, &htl);
1874 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1875 /* Replace client entry */
1876 silc_hash_table_del(chu->client->channels, chu->channel);
1877 silc_hash_table_del(chu->channel->user_list, chu->client);
1880 silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1881 silc_hash_table_add(chu->client->channels, chu->channel, chu);
1883 silc_hash_table_list_reset(&htl);
1886 /* Registers failure timeout to process the received failure packet
1889 void silc_client_process_failure(SilcClient client,
1890 SilcSocketConnection sock,
1891 SilcPacketContext *packet)
1893 SilcUInt32 failure = 0;
1895 if (sock->protocol) {
1896 if (packet->buffer->len >= 4)
1897 SILC_GET32_MSB(failure, packet->buffer->data);
1899 /* Notify application */
1900 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1901 SILC_32_TO_PTR(failure));
1905 /* A timeout callback for the re-key. We will be the initiator of the
1908 SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback)
1910 SilcSocketConnection sock = (SilcSocketConnection)context;
1911 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1912 SilcClient client = (SilcClient)conn->internal->rekey->context;
1913 SilcProtocol protocol;
1914 SilcClientRekeyInternalContext *proto_ctx;
1916 SILC_LOG_DEBUG(("Start"));
1918 /* If rekey protocol is active already wait for it to finish */
1919 if (sock->protocol && sock->protocol->protocol &&
1920 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)
1923 /* Allocate internal protocol context. This is sent as context
1925 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1926 proto_ctx->client = (void *)client;
1927 proto_ctx->sock = silc_socket_dup(sock);
1928 proto_ctx->responder = FALSE;
1929 proto_ctx->pfs = conn->internal->rekey->pfs;
1931 /* Perform rekey protocol. Will call the final callback after the
1932 protocol is over. */
1933 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1934 &protocol, proto_ctx, silc_client_rekey_final);
1935 sock->protocol = protocol;
1937 /* Run the protocol */
1938 silc_protocol_execute(protocol, client->schedule, 0, 0);
1941 /* The final callback for the REKEY protocol. This will actually take the
1942 new key material into use. */
1944 SILC_TASK_CALLBACK(silc_client_rekey_final)
1946 SilcProtocol protocol = (SilcProtocol)context;
1947 SilcClientRekeyInternalContext *ctx =
1948 (SilcClientRekeyInternalContext *)protocol->context;
1949 SilcClient client = (SilcClient)ctx->client;
1950 SilcSocketConnection sock = ctx->sock;
1951 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1953 SILC_LOG_DEBUG(("Start"));
1955 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1956 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1957 /* Error occured during protocol */
1958 silc_protocol_cancel(protocol, client->schedule);
1959 silc_protocol_free(protocol);
1960 sock->protocol = NULL;
1962 silc_packet_context_free(ctx->packet);
1964 silc_ske_free(ctx->ske);
1965 silc_socket_free(ctx->sock);
1970 /* Purge the outgoing data queue to assure that all rekey packets really
1971 go to the network before we quit the protocol. */
1972 silc_client_packet_queue_purge(client, sock);
1974 /* Re-register re-key timeout */
1975 if (ctx->responder == FALSE)
1976 silc_schedule_task_add(client->schedule, sock->sock,
1977 silc_client_rekey_callback,
1978 sock, conn->internal->rekey->timeout, 0,
1979 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1982 silc_protocol_free(protocol);
1983 sock->protocol = NULL;
1985 silc_packet_context_free(ctx->packet);
1987 silc_ske_free(ctx->ske);
1988 silc_socket_free(ctx->sock);
1992 /* Processes incoming connection authentication method request packet.
1993 It is a reply to our previously sent request. The packet can be used
1994 to resolve the authentication method for the current session if the
1995 client does not know it beforehand. */
1997 void silc_client_connection_auth_request(SilcClient client,
1998 SilcSocketConnection sock,
1999 SilcPacketContext *packet)
2001 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2002 SilcUInt16 conn_type, auth_meth;
2005 /* If we haven't send our request then ignore this one. */
2006 if (!conn->internal->connauth)
2009 /* Parse the payload */
2010 ret = silc_buffer_unformat(packet->buffer,
2011 SILC_STR_UI_SHORT(&conn_type),
2012 SILC_STR_UI_SHORT(&auth_meth),
2015 auth_meth = SILC_AUTH_NONE;
2017 /* Call the request callback to notify application for received
2018 authentication method information. */
2019 if (conn->internal->connauth->callback)
2020 (*conn->internal->connauth->callback)(client, conn, auth_meth,
2021 conn->internal->connauth->context);
2023 silc_schedule_task_del(client->schedule, conn->internal->connauth->timeout);
2025 silc_free(conn->internal->connauth);
2026 conn->internal->connauth = NULL;
2029 /* Timeout task callback called if the server does not reply to our
2030 connection authentication method request in the specified time interval. */
2032 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
2034 SilcClientConnection conn = (SilcClientConnection)context;
2035 SilcClient client = conn->client;
2037 if (!conn->internal->connauth)
2040 /* Call the request callback to notify application */
2041 if (conn->internal->connauth->callback)
2042 (*conn->internal->connauth->callback)(client, conn, SILC_AUTH_NONE,
2043 conn->internal->connauth->context);
2045 silc_free(conn->internal->connauth);
2046 conn->internal->connauth = NULL;
2049 /* This function can be used to request the current authentication method
2050 from the server. This may be called when connecting to the server
2051 and the client library requests the authentication data from the
2052 application. If the application does not know the current authentication
2053 method it can request it from the server using this function.
2054 The `callback' with `context' will be called after the server has
2055 replied back with the current authentication method. */
2058 silc_client_request_authentication_method(SilcClient client,
2059 SilcClientConnection conn,
2060 SilcConnectionAuthRequest callback,
2063 SilcClientConnAuthRequest connauth;
2066 assert(client && conn);
2067 connauth = silc_calloc(1, sizeof(*connauth));
2068 connauth->callback = callback;
2069 connauth->context = context;
2071 if (conn->internal->connauth)
2072 silc_free(conn->internal->connauth);
2074 conn->internal->connauth = connauth;
2076 /* Assemble the request packet and send it to the server */
2077 packet = silc_buffer_alloc(4);
2078 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
2079 silc_buffer_format(packet,
2080 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
2081 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
2083 silc_client_packet_send(client, conn->sock,
2084 SILC_PACKET_CONNECTION_AUTH_REQUEST,
2085 NULL, 0, NULL, NULL,
2086 packet->data, packet->len, FALSE);
2087 silc_buffer_free(packet);
2089 /* Register a timeout in case server does not reply anything back. */
2091 silc_schedule_task_add(client->schedule, conn->sock->sock,
2092 silc_client_request_authentication_method_timeout,
2094 client->internal->params->connauth_request_secs, 0,
2095 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);