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 /* Allocates and adds new connection to the client. This adds the allocated
231 connection to the connection table and returns a pointer to it. A client
232 can have multiple connections to multiple servers. Every connection must
233 be added to the client using this function. User data `context' may
234 be sent as argument. This function is normally used only if the
235 application performed the connecting outside the library. The library
236 however may use this internally. */
239 silc_client_add_connection(SilcClient client,
240 SilcClientConnectionParams *params,
241 char *hostname, int port, void *context)
243 SilcClientConnection conn;
246 SILC_LOG_DEBUG(("Adding new connection to %s:%d", hostname, port));
248 conn = silc_calloc(1, sizeof(*conn));
249 conn->internal = silc_calloc(1, sizeof(*conn->internal));
251 /* Initialize ID caches */
252 conn->client = client;
253 conn->remote_host = strdup(hostname);
254 conn->remote_port = port;
255 conn->context = context;
256 conn->internal->client_cache =
257 silc_idcache_alloc(0, SILC_ID_CLIENT, NULL, NULL, FALSE, TRUE);
258 conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL,
260 conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL,
262 conn->internal->pending_commands = silc_dlist_init();
263 conn->internal->ftp_sessions = silc_dlist_init();
266 if (params->detach_data)
267 conn->internal->params.detach_data =
268 silc_memdup(params->detach_data,
269 params->detach_data_len);
270 conn->internal->params.detach_data_len = params->detach_data_len;
273 /* Add the connection to connections table */
274 for (i = 0; i < client->internal->conns_count; i++)
275 if (client->internal->conns && !client->internal->conns[i]) {
276 client->internal->conns[i] = conn;
280 client->internal->conns =
281 silc_realloc(client->internal->conns, sizeof(*client->internal->conns)
282 * (client->internal->conns_count + 1));
283 client->internal->conns[client->internal->conns_count] = conn;
284 client->internal->conns_count++;
289 /* Removes connection from client. Frees all memory. */
291 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
295 for (i = 0; i < client->internal->conns_count; i++)
296 if (client->internal->conns[i] == conn) {
297 /* Free all cache entries */
298 SilcIDCacheList list;
299 SilcIDCacheEntry entry;
300 SilcClientCommandPending *r;
303 if (silc_idcache_get_all(conn->internal->client_cache, &list)) {
304 ret = silc_idcache_list_first(list, &entry);
306 silc_client_del_client(client, conn, entry->context);
307 ret = silc_idcache_list_next(list, &entry);
309 silc_idcache_list_free(list);
312 if (silc_idcache_get_all(conn->internal->channel_cache, &list)) {
313 ret = silc_idcache_list_first(list, &entry);
315 silc_client_del_channel(client, conn, entry->context);
316 ret = silc_idcache_list_next(list, &entry);
318 silc_idcache_list_free(list);
321 if (silc_idcache_get_all(conn->internal->server_cache, &list)) {
322 ret = silc_idcache_list_first(list, &entry);
324 silc_client_del_server(client, conn, entry->context);
325 ret = silc_idcache_list_next(list, &entry);
327 silc_idcache_list_free(list);
330 /* Clear ID caches */
331 if (conn->internal->client_cache)
332 silc_idcache_free(conn->internal->client_cache);
333 if (conn->internal->channel_cache)
334 silc_idcache_free(conn->internal->channel_cache);
335 if (conn->internal->server_cache)
336 silc_idcache_free(conn->internal->server_cache);
338 /* Free data (my ID is freed in above silc_client_del_client).
339 conn->nickname is freed when freeing the local_entry->nickname. */
340 silc_free(conn->remote_host);
341 silc_free(conn->local_id_data);
342 if (conn->internal->send_key)
343 silc_cipher_free(conn->internal->send_key);
344 if (conn->internal->receive_key)
345 silc_cipher_free(conn->internal->receive_key);
346 if (conn->internal->hmac_send)
347 silc_hmac_free(conn->internal->hmac_send);
348 if (conn->internal->hmac_receive)
349 silc_hmac_free(conn->internal->hmac_receive);
350 silc_free(conn->internal->rekey);
352 if (conn->internal->active_session) {
354 conn->sock->user_data = NULL;
355 silc_client_ftp_session_free(conn->internal->active_session);
356 conn->internal->active_session = NULL;
359 silc_client_ftp_free_sessions(client, conn);
361 if (conn->internal->pending_commands) {
362 silc_dlist_start(conn->internal->pending_commands);
363 while ((r = silc_dlist_get(conn->internal->pending_commands))
365 silc_dlist_del(conn->internal->pending_commands, r);
366 silc_dlist_uninit(conn->internal->pending_commands);
369 silc_free(conn->internal);
370 memset(conn, 0, sizeof(*conn));
373 client->internal->conns[i] = NULL;
377 /* Adds listener socket to the listener sockets table. This function is
378 used to add socket objects that are listeners to the client. This should
379 not be used to add other connection objects. */
381 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
385 if (!client->internal->sockets) {
386 client->internal->sockets =
387 silc_calloc(1, sizeof(*client->internal->sockets));
388 client->internal->sockets[0] = silc_socket_dup(sock);
389 client->internal->sockets_count = 1;
393 for (i = 0; i < client->internal->sockets_count; i++) {
394 if (client->internal->sockets[i] == NULL) {
395 client->internal->sockets[i] = silc_socket_dup(sock);
400 client->internal->sockets =
401 silc_realloc(client->internal->sockets,
402 sizeof(*client->internal->sockets) *
403 (client->internal->sockets_count + 1));
404 client->internal->sockets[client->internal->sockets_count] =
405 silc_socket_dup(sock);
406 client->internal->sockets_count++;
409 /* Deletes listener socket from the listener sockets table. */
411 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
415 if (!client->internal->sockets)
418 for (i = 0; i < client->internal->sockets_count; i++) {
419 if (client->internal->sockets[i] == sock) {
420 silc_socket_free(sock);
421 client->internal->sockets[i] = NULL;
428 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
432 /* XXX In the future we should give up this non-blocking connect all
433 together and use threads instead. */
434 /* Create connection to server asynchronously */
435 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
439 /* Register task that will receive the async connect and will
441 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
442 silc_client_connect_to_server_start,
445 SILC_TASK_PRI_NORMAL);
446 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE,
454 /* Connects to remote server. This is the main routine used to connect
455 to SILC server. Returns -1 on error and the created socket otherwise.
456 The `context' is user context that is saved into the SilcClientConnection
457 that is created after the connection is created. Note that application
458 may handle the connecting process outside the library. If this is the
459 case then this function is not used at all. When the connecting is
460 done the `connect' client operation is called. */
462 int silc_client_connect_to_server(SilcClient client,
463 SilcClientConnectionParams *params,
464 int port, char *host, void *context)
466 SilcClientInternalConnectContext *ctx;
467 SilcClientConnection conn;
470 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
473 conn = silc_client_add_connection(client, params, host, port, context);
475 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
476 "Connecting to port %d of server %s", port, host);
478 /* Allocate internal context for connection process. This is
479 needed as we are doing async connecting. */
480 ctx = silc_calloc(1, sizeof(*ctx));
481 ctx->client = client;
483 ctx->host = strdup(host);
484 ctx->port = port ? port : 706;
487 /* Do the actual connecting process */
488 sock = silc_client_connect_to_server_internal(ctx);
490 silc_client_del_connection(client, conn);
494 /* Socket hostname and IP lookup callback that is called before actually
495 starting the key exchange. The lookup is called from the function
496 silc_client_start_key_exchange. */
498 static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
501 SilcClientConnection conn = (SilcClientConnection)context;
502 SilcClient client = conn->client;
503 SilcProtocol protocol;
504 SilcClientKEInternalContext *proto_ctx;
506 SILC_LOG_DEBUG(("Start"));
508 if (conn->sock->hostname) {
509 silc_free(conn->remote_host);
510 conn->remote_host = strdup(conn->sock->hostname);
512 conn->sock->hostname = strdup(conn->remote_host);
515 conn->sock->ip = strdup(conn->sock->hostname);
516 conn->sock->port = conn->remote_port;
518 /* Allocate internal Key Exchange context. This is sent to the
519 protocol as context. */
520 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
521 proto_ctx->client = (void *)client;
522 proto_ctx->sock = silc_socket_dup(conn->sock);
523 proto_ctx->rng = client->rng;
524 proto_ctx->responder = FALSE;
525 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
526 proto_ctx->verify = silc_client_protocol_ke_verify_key;
528 /* Perform key exchange protocol. silc_client_connect_to_server_final
529 will be called after the protocol is finished. */
530 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
531 &protocol, (void *)proto_ctx,
532 silc_client_connect_to_server_second);
534 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
535 "Error: Could not start key exchange protocol");
536 silc_net_close_connection(conn->sock->sock);
537 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
540 conn->sock->protocol = protocol;
542 /* Register the connection for network input and output. This sets
543 that scheduler will listen for incoming packets for this connection
544 and sets that outgoing packets may be sent to this connection as well.
545 However, this doesn't set the scheduler for outgoing traffic, it will
546 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
547 later when outgoing data is available. */
548 context = (void *)client;
549 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(conn->sock->sock);
551 /* Execute the protocol */
552 silc_protocol_execute(protocol, client->schedule, 0, 0);
555 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
556 key material between client and server. This function can be called
557 directly if application is performing its own connecting and does not
558 use the connecting provided by this library. This function is normally
559 used only if the application performed the connecting outside the library.
560 The library however may use this internally. */
562 void silc_client_start_key_exchange(SilcClient client,
563 SilcClientConnection conn,
566 assert(client->pkcs);
567 assert(client->public_key);
568 assert(client->private_key);
570 /* Allocate new socket connection object */
571 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
573 /* Sometimes when doing quick reconnects the new socket may be same as
574 the old one and there might be pending stuff for the old socket.
575 If new one is same then those pending sutff might cause problems.
576 Make sure they do not do that. */
577 silc_schedule_task_del_by_fd(client->schedule, fd);
579 conn->nickname = (client->nickname ? strdup(client->nickname) :
580 strdup(client->username));
582 /* Resolve the remote hostname and IP address for our socket connection */
583 silc_socket_host_lookup(conn->sock, FALSE, silc_client_start_key_exchange_cb,
584 conn, client->schedule);
587 /* Callback called when error has occurred during connecting (KE) to
588 the server. The `connect' client operation will be called. */
590 SILC_TASK_CALLBACK(silc_client_connect_failure)
592 SilcClientKEInternalContext *ctx =
593 (SilcClientKEInternalContext *)context;
594 SilcClient client = (SilcClient)ctx->client;
596 client->internal->ops->connected(client, ctx->sock->user_data,
597 SILC_CLIENT_CONN_ERROR_KE);
599 silc_packet_context_free(ctx->packet);
603 /* Callback called when error has occurred during connecting (auth) to
604 the server. The `connect' client operation will be called. */
606 SILC_TASK_CALLBACK(silc_client_connect_failure_auth)
608 SilcClientConnAuthInternalContext *ctx =
609 (SilcClientConnAuthInternalContext *)context;
610 SilcClient client = (SilcClient)ctx->client;
612 client->internal->ops->connected(client, ctx->sock->user_data, ctx->status);
616 /* Start of the connection to the remote server. This is called after
617 succesful TCP/IP connection has been established to the remote host. */
619 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
621 SilcClientInternalConnectContext *ctx =
622 (SilcClientInternalConnectContext *)context;
623 SilcClient client = ctx->client;
624 SilcClientConnection conn = ctx->conn;
625 int opt, opt_len = sizeof(opt);
627 SILC_LOG_DEBUG(("Start"));
629 /* Check the socket status as it might be in error */
630 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
632 if (ctx->tries < 2) {
633 /* Connection failed but lets try again */
634 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
635 "Could not connect to server %s: %s",
636 ctx->host, strerror(opt));
637 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
638 "Connecting to port %d of server %s resumed",
639 ctx->port, ctx->host);
641 /* Unregister old connection try */
642 silc_schedule_unset_listen_fd(client->schedule, fd);
643 silc_net_close_connection(fd);
644 silc_schedule_task_del(client->schedule, ctx->task);
647 silc_client_connect_to_server_internal(ctx);
650 /* Connection failed and we won't try anymore */
651 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
652 "Could not connect to server %s: %s",
653 ctx->host, strerror(opt));
654 silc_schedule_unset_listen_fd(client->schedule, fd);
655 silc_net_close_connection(fd);
656 silc_schedule_task_del(client->schedule, ctx->task);
659 /* Notify application of failure */
660 client->internal->ops->connected(client, conn,
661 SILC_CLIENT_CONN_ERROR_TIMEOUT);
666 silc_schedule_unset_listen_fd(client->schedule, fd);
667 silc_schedule_task_del(client->schedule, ctx->task);
670 silc_client_start_key_exchange(client, conn, fd);
673 /* Second part of the connecting to the server. This executed
674 authentication protocol. */
676 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
678 SilcProtocol protocol = (SilcProtocol)context;
679 SilcClientKEInternalContext *ctx =
680 (SilcClientKEInternalContext *)protocol->context;
681 SilcClient client = (SilcClient)ctx->client;
682 SilcSocketConnection sock = NULL;
683 SilcClientConnAuthInternalContext *proto_ctx;
685 SILC_LOG_DEBUG(("Start"));
687 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
688 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
689 /* Error occured during protocol */
690 SILC_LOG_DEBUG(("Error during KE protocol"));
691 silc_protocol_free(protocol);
692 silc_ske_free_key_material(ctx->keymat);
694 silc_ske_free(ctx->ske);
696 silc_free(ctx->dest_id);
697 ctx->sock->protocol = NULL;
698 silc_socket_free(ctx->sock);
700 /* Notify application of failure */
701 silc_schedule_task_add(client->schedule, ctx->sock->sock,
702 silc_client_connect_failure, ctx,
703 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
707 /* We now have the key material as the result of the key exchange
708 protocol. Take the key material into use. Free the raw key material
709 as soon as we've set them into use. */
710 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
711 ctx->ske->prop->cipher,
712 ctx->ske->prop->pkcs,
713 ctx->ske->prop->hash,
714 ctx->ske->prop->hmac,
715 ctx->ske->prop->group,
717 silc_ske_free_key_material(ctx->keymat);
719 /* Allocate internal context for the authentication protocol. This
720 is sent as context for the protocol. */
721 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
722 proto_ctx->client = (void *)client;
723 proto_ctx->sock = sock = ctx->sock;
724 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
725 proto_ctx->dest_id_type = ctx->dest_id_type;
726 proto_ctx->dest_id = ctx->dest_id;
728 /* Free old protocol as it is finished now */
729 silc_protocol_free(protocol);
731 silc_packet_context_free(ctx->packet);
734 sock->protocol = NULL;
736 /* Resolve the authentication method to be used in this connection. The
737 completion callback is called after the application has resolved
738 the authentication method. */
739 client->internal->ops->get_auth_method(client, sock->user_data,
742 silc_client_resolve_auth_method,
746 /* Authentication method resolving callback. Application calls this function
747 after we've called the client->internal->ops->get_auth_method
748 client operation to resolve the authentication method. We will continue
749 the executiong of the protocol in this function. */
751 void silc_client_resolve_auth_method(bool success,
752 SilcProtocolAuthMeth auth_meth,
753 const unsigned char *auth_data,
754 SilcUInt32 auth_data_len, void *context)
756 SilcClientConnAuthInternalContext *proto_ctx =
757 (SilcClientConnAuthInternalContext *)context;
758 SilcClient client = (SilcClient)proto_ctx->client;
761 auth_meth = SILC_AUTH_NONE;
763 proto_ctx->auth_meth = auth_meth;
765 if (success && auth_data && auth_data_len) {
767 /* Passphrase must be UTF-8 encoded, if it isn't encode it */
768 if (auth_meth == SILC_AUTH_PASSWORD &&
769 !silc_utf8_valid(auth_data, auth_data_len)) {
771 unsigned char *autf8 = NULL;
772 payload_len = silc_utf8_encoded_len(auth_data, auth_data_len,
774 autf8 = silc_calloc(payload_len, sizeof(*autf8));
775 auth_data_len = silc_utf8_encode(auth_data, auth_data_len,
776 SILC_STRING_ASCII, autf8, payload_len);
780 proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
781 proto_ctx->auth_data_len = auth_data_len;
784 /* Allocate the authenteication protocol and execute it. */
785 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
786 &proto_ctx->sock->protocol, (void *)proto_ctx,
787 silc_client_connect_to_server_final);
789 /* Execute the protocol */
790 silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
793 /* Finalizes the connection to the remote SILC server. This is called
794 after authentication protocol has been completed. This send our
795 user information to the server to receive our client ID from
798 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
800 SilcProtocol protocol = (SilcProtocol)context;
801 SilcClientConnAuthInternalContext *ctx =
802 (SilcClientConnAuthInternalContext *)protocol->context;
803 SilcClient client = (SilcClient)ctx->client;
804 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
807 SILC_LOG_DEBUG(("Start"));
809 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
810 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
811 /* Error occured during protocol */
812 SILC_LOG_DEBUG(("Error during authentication protocol"));
813 ctx->status = SILC_CLIENT_CONN_ERROR_AUTH;
817 if (conn->internal->params.detach_data) {
818 /* Send RESUME_CLIENT packet to the server, which is used to resume
819 old detached session back. */
821 SilcClientID *old_client_id;
822 unsigned char *old_id;
823 SilcUInt16 old_id_len;
825 if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len)) {
826 ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
830 old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT);
831 if (!old_client_id) {
833 ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
837 /* Generate authentication data that server will verify */
838 auth = silc_auth_public_key_auth_generate(client->public_key,
841 conn->internal->hash,
842 old_client_id, SILC_ID_CLIENT);
844 silc_free(old_client_id);
846 ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
850 packet = silc_buffer_alloc_size(2 + old_id_len + auth->len);
851 silc_buffer_format(packet,
852 SILC_STR_UI_SHORT(old_id_len),
853 SILC_STR_UI_XNSTRING(old_id, old_id_len),
854 SILC_STR_UI_XNSTRING(auth->data, auth->len),
857 /* Send the packet */
858 silc_client_packet_send(client, ctx->sock, SILC_PACKET_RESUME_CLIENT,
860 packet->data, packet->len, TRUE);
861 silc_buffer_free(packet);
862 silc_buffer_free(auth);
863 silc_free(old_client_id);
866 /* Send NEW_CLIENT packet to the server. We will become registered
867 to the SILC network after sending this packet and we will receive
868 client ID from the server. */
869 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
870 strlen(client->realname));
871 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
872 silc_buffer_format(packet,
873 SILC_STR_UI_SHORT(strlen(client->username)),
874 SILC_STR_UI_XNSTRING(client->username,
875 strlen(client->username)),
876 SILC_STR_UI_SHORT(strlen(client->realname)),
877 SILC_STR_UI_XNSTRING(client->realname,
878 strlen(client->realname)),
881 /* Send the packet */
882 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
884 packet->data, packet->len, TRUE);
885 silc_buffer_free(packet);
888 /* Save remote ID. */
889 conn->remote_id = ctx->dest_id;
890 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
891 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
893 /* Register re-key timeout */
894 conn->internal->rekey->timeout = client->internal->params->rekey_secs;
895 conn->internal->rekey->context = (void *)client;
896 silc_schedule_task_add(client->schedule, conn->sock->sock,
897 silc_client_rekey_callback,
898 (void *)conn->sock, conn->internal->rekey->timeout, 0,
899 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
901 silc_protocol_free(protocol);
902 silc_free(ctx->auth_data);
904 silc_ske_free(ctx->ske);
905 silc_socket_free(ctx->sock);
907 conn->sock->protocol = NULL;
911 silc_protocol_free(protocol);
912 silc_free(ctx->auth_data);
913 silc_free(ctx->dest_id);
915 silc_ske_free(ctx->ske);
916 conn->sock->protocol = NULL;
917 silc_socket_free(ctx->sock);
919 /* Notify application of failure */
920 silc_schedule_task_add(client->schedule, ctx->sock->sock,
921 silc_client_connect_failure_auth, ctx,
922 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
925 /* Internal routine that sends packet or marks packet to be sent. This
926 is used directly only in special cases. Normal cases should use
927 silc_server_packet_send. Returns < 0 on error. */
929 int silc_client_packet_send_real(SilcClient client,
930 SilcSocketConnection sock,
935 /* If rekey protocol is active we must assure that all packets are
936 sent through packet queue. */
937 if (SILC_CLIENT_IS_REKEY(sock))
940 /* If outbound data is already pending do not force send */
941 if (SILC_IS_OUTBUF_PENDING(sock))
944 /* Send the packet */
945 ret = silc_packet_send(sock, force_send);
949 /* Mark that there is some outgoing data available for this connection.
950 This call sets the connection both for input and output (the input
951 is set always and this call keeps the input setting, actually).
952 Actual data sending is performed by silc_client_packet_process. */
953 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
955 /* Mark to socket that data is pending in outgoing buffer. This flag
956 is needed if new data is added to the buffer before the earlier
957 put data is sent to the network. */
958 SILC_SET_OUTBUF_PENDING(sock);
963 /* Packet processing callback. This is used to send and receive packets
964 from network. This is generic task. */
966 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
968 SilcClient client = (SilcClient)context;
969 SilcSocketConnection sock = NULL;
970 SilcClientConnection conn;
973 SILC_LOG_DEBUG(("Processing packet"));
975 SILC_CLIENT_GET_SOCK(client, fd, sock);
979 conn = (SilcClientConnection)sock->user_data;
982 if (type == SILC_TASK_WRITE) {
983 /* Do not send data to disconnected connection */
984 if (SILC_IS_DISCONNECTED(sock))
987 ret = silc_packet_send(sock, TRUE);
989 /* If returned -2 could not write to connection now, will do
998 /* The packet has been sent and now it is time to set the connection
999 back to only for input. When there is again some outgoing data
1000 available for this connection it will be set for output as well.
1001 This call clears the output setting and sets it only for input. */
1002 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
1003 SILC_UNSET_OUTBUF_PENDING(sock);
1005 silc_buffer_clear(sock->outbuf);
1009 /* Packet receiving */
1010 if (type == SILC_TASK_READ) {
1011 /* Read data from network */
1012 ret = silc_packet_receive(sock);
1018 SILC_LOG_DEBUG(("Read EOF"));
1020 /* If connection is disconnecting already we will finally
1021 close the connection */
1022 if (SILC_IS_DISCONNECTING(sock)) {
1023 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1024 client->internal->ops->disconnected(client, conn, 0, NULL);
1025 silc_client_close_connection_real(client, sock, conn);
1029 SILC_LOG_DEBUG(("EOF from connection %d", sock->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 /* Process the packet. This will call the parser that will then
1037 decrypt and parse the packet. */
1038 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
1039 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
1040 conn->internal->hmac_receive,
1041 conn->internal->psn_receive,
1042 silc_client_packet_parse, client);
1044 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
1045 silc_client_packet_parse, client);
1049 /* Parser callback called by silc_packet_receive_process. Thie merely
1050 registers timeout that will handle the actual parsing when appropriate. */
1052 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
1055 SilcClient client = (SilcClient)context;
1056 SilcSocketConnection sock = parser_context->sock;
1057 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1058 SilcPacketContext *packet = parser_context->packet;
1061 if (conn && conn->internal->hmac_receive && conn->sock == sock)
1062 conn->internal->psn_receive = parser_context->packet->sequence + 1;
1064 /* Parse the packet immediately */
1065 if (parser_context->normal)
1066 ret = silc_packet_parse(packet, conn->internal->receive_key);
1068 ret = silc_packet_parse_special(packet, conn->internal->receive_key);
1070 if (ret == SILC_PACKET_NONE) {
1071 silc_packet_context_free(packet);
1072 silc_free(parser_context);
1076 /* If protocol for this connection is key exchange or rekey then we'll
1077 process all packets synchronously, since there might be packets in
1078 queue that we are not able to decrypt without first processing the
1079 packets before them. */
1080 if (sock->protocol && sock->protocol->protocol &&
1081 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1082 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1084 /* Parse the incoming packet type */
1085 silc_client_packet_parse_type(client, sock, packet);
1087 /* Reprocess the buffer since we'll return FALSE. This is because
1088 the `conn->internal->receive_key' might have become valid by processing
1089 the previous packet */
1090 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
1091 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
1092 conn->internal->hmac_receive,
1093 conn->internal->psn_receive,
1094 silc_client_packet_parse, client);
1096 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
1097 silc_client_packet_parse, client);
1099 silc_packet_context_free(packet);
1100 silc_free(parser_context);
1105 /* Parse the incoming packet type */
1106 silc_client_packet_parse_type(client, sock, packet);
1107 silc_packet_context_free(packet);
1108 silc_free(parser_context);
1112 /* Parses the packet type and calls what ever routines the packet type
1113 requires. This is done for all incoming packets. */
1115 void silc_client_packet_parse_type(SilcClient client,
1116 SilcSocketConnection sock,
1117 SilcPacketContext *packet)
1119 SilcBuffer buffer = packet->buffer;
1120 SilcPacketType type = packet->type;
1122 SILC_LOG_DEBUG(("Parsing %s packet", silc_get_packet_name(type)));
1124 /* Parse the packet type */
1127 case SILC_PACKET_DISCONNECT:
1128 silc_client_disconnected_by_server(client, sock, buffer);
1131 case SILC_PACKET_SUCCESS:
1133 * Success received for something. For now we can have only
1134 * one protocol for connection executing at once hence this
1135 * success message is for whatever protocol is executing currently.
1138 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1141 case SILC_PACKET_FAILURE:
1143 * Failure received for some protocol. Set the protocol state to
1144 * error and call the protocol callback. This fill cause error on
1145 * protocol and it will call the final callback.
1147 silc_client_process_failure(client, sock, packet);
1150 case SILC_PACKET_REJECT:
1153 case SILC_PACKET_NOTIFY:
1155 * Received notify message
1157 silc_client_notify_by_server(client, sock, packet);
1160 case SILC_PACKET_ERROR:
1162 * Received error message
1164 silc_client_error_by_server(client, sock, buffer);
1167 case SILC_PACKET_CHANNEL_MESSAGE:
1169 * Received message to (from, actually) a channel
1171 silc_client_channel_message(client, sock, packet);
1174 case SILC_PACKET_CHANNEL_KEY:
1176 * Received key for a channel. By receiving this key the client will be
1177 * able to talk to the channel it has just joined. This can also be
1178 * a new key for existing channel as keys expire peridiocally.
1180 silc_client_receive_channel_key(client, sock, buffer);
1183 case SILC_PACKET_PRIVATE_MESSAGE:
1185 * Received private message
1187 silc_client_private_message(client, sock, packet);
1190 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1192 * Received private message key indicator
1194 silc_client_private_message_key(client, sock, packet);
1197 case SILC_PACKET_COMMAND:
1199 * Received command packet, a special case since normally client
1200 * does not receive commands.
1202 silc_client_command_process(client, sock, packet);
1205 case SILC_PACKET_COMMAND_REPLY:
1207 * Recived reply for a command
1209 silc_client_command_reply_process(client, sock, packet);
1212 case SILC_PACKET_KEY_EXCHANGE:
1213 if (sock->protocol && sock->protocol->protocol &&
1214 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
1215 SilcClientKEInternalContext *proto_ctx =
1216 (SilcClientKEInternalContext *)sock->protocol->context;
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);
1228 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1229 "protocol active, packet dropped."));
1233 case SILC_PACKET_KEY_EXCHANGE_1:
1234 if (sock->protocol && sock->protocol->protocol &&
1235 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1236 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1238 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1239 SilcClientRekeyInternalContext *proto_ctx =
1240 (SilcClientRekeyInternalContext *)sock->protocol->context;
1242 if (proto_ctx->packet)
1243 silc_packet_context_free(proto_ctx->packet);
1245 proto_ctx->packet = silc_packet_context_dup(packet);
1247 /* Let the protocol handle the packet */
1248 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1250 SilcClientKEInternalContext *proto_ctx =
1251 (SilcClientKEInternalContext *)sock->protocol->context;
1253 if (proto_ctx->packet)
1254 silc_packet_context_free(proto_ctx->packet);
1256 proto_ctx->packet = silc_packet_context_dup(packet);
1257 proto_ctx->dest_id_type = packet->src_id_type;
1258 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1259 packet->src_id_type);
1260 if (!proto_ctx->dest_id)
1263 /* Let the protocol handle the packet */
1264 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1267 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1268 "protocol active, packet dropped."));
1272 case SILC_PACKET_KEY_EXCHANGE_2:
1273 if (sock->protocol && sock->protocol->protocol &&
1274 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1275 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1277 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1278 SilcClientRekeyInternalContext *proto_ctx =
1279 (SilcClientRekeyInternalContext *)sock->protocol->context;
1281 if (proto_ctx->packet)
1282 silc_packet_context_free(proto_ctx->packet);
1284 proto_ctx->packet = silc_packet_context_dup(packet);
1286 /* Let the protocol handle the packet */
1287 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1289 SilcClientKEInternalContext *proto_ctx =
1290 (SilcClientKEInternalContext *)sock->protocol->context;
1292 if (proto_ctx->packet)
1293 silc_packet_context_free(proto_ctx->packet);
1294 if (proto_ctx->dest_id)
1295 silc_free(proto_ctx->dest_id);
1296 proto_ctx->packet = silc_packet_context_dup(packet);
1297 proto_ctx->dest_id_type = packet->src_id_type;
1298 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1299 packet->src_id_type);
1300 if (!proto_ctx->dest_id)
1303 /* Let the protocol handle the packet */
1304 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1307 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1308 "protocol active, packet dropped."));
1312 case SILC_PACKET_NEW_ID:
1315 * Received new ID from server. This packet is received at
1316 * the connection to the server. New ID is also received when
1317 * user changes nickname but in that case the new ID is received
1318 * as command reply and not as this packet type.
1322 idp = silc_id_payload_parse(buffer->data, buffer->len);
1325 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1328 silc_client_receive_new_id(client, sock, idp);
1329 silc_id_payload_free(idp);
1333 case SILC_PACKET_HEARTBEAT:
1335 * Received heartbeat packet
1337 SILC_LOG_DEBUG(("Heartbeat packet"));
1340 case SILC_PACKET_KEY_AGREEMENT:
1342 * Received key agreement packet
1344 SILC_LOG_DEBUG(("Key agreement packet"));
1345 silc_client_key_agreement(client, sock, packet);
1348 case SILC_PACKET_REKEY:
1349 SILC_LOG_DEBUG(("Re-key packet"));
1350 /* We ignore this for now */
1353 case SILC_PACKET_REKEY_DONE:
1354 SILC_LOG_DEBUG(("Re-key done packet"));
1356 if (sock->protocol && sock->protocol->protocol &&
1357 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1359 SilcClientRekeyInternalContext *proto_ctx =
1360 (SilcClientRekeyInternalContext *)sock->protocol->context;
1362 if (proto_ctx->packet)
1363 silc_packet_context_free(proto_ctx->packet);
1365 proto_ctx->packet = silc_packet_context_dup(packet);
1367 /* Let the protocol handle the packet */
1368 if (proto_ctx->responder == FALSE)
1369 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1371 /* Let the protocol handle the packet */
1372 silc_protocol_execute(sock->protocol, client->schedule,
1375 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1376 "protocol active, packet dropped."));
1380 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1382 * Reveived reply to our connection authentication method request
1383 * packet. This is used to resolve the authentication method for the
1384 * current session from the server if the client does not know it.
1386 silc_client_connection_auth_request(client, sock, packet);
1389 case SILC_PACKET_FTP:
1390 /* Received file transfer packet. */
1391 silc_client_ftp(client, sock, packet);
1395 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1400 /* Sends packet. This doesn't actually send the packet instead it assembles
1401 it and marks it to be sent. However, if force_send is TRUE the packet
1402 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1403 will be derived from sock argument. Otherwise the valid arguments sent
1406 void silc_client_packet_send(SilcClient client,
1407 SilcSocketConnection sock,
1408 SilcPacketType type,
1410 SilcIdType dst_id_type,
1413 unsigned char *data,
1414 SilcUInt32 data_len,
1417 SilcPacketContext packetdata;
1418 const SilcBufferStruct packet;
1420 SilcUInt32 sequence = 0;
1421 int src_id_allocated = FALSE;
1426 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1428 /* Get data used in the packet sending, keys and stuff */
1429 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1430 if (!cipher && ((SilcClientConnection)sock->user_data)->internal->send_key)
1431 cipher = ((SilcClientConnection)sock->user_data)->internal->send_key;
1433 if (!hmac && ((SilcClientConnection)sock->user_data)->internal->hmac_send)
1434 hmac = ((SilcClientConnection)sock->user_data)->internal->hmac_send;
1436 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1437 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1438 dst_id_type = SILC_ID_SERVER;
1442 sequence = ((SilcClientConnection)sock->user_data)->internal->psn_send++;
1444 /* Check for mandatory rekey */
1445 if (sequence == SILC_CLIENT_REKEY_THRESHOLD)
1446 silc_schedule_task_add(client->schedule, sock->sock,
1447 silc_client_rekey_callback, sock, 0, 1,
1448 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1451 block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1453 /* Set the packet context pointers */
1454 packetdata.flags = 0;
1455 packetdata.type = type;
1456 if (sock->user_data &&
1457 ((SilcClientConnection)sock->user_data)->local_id_data) {
1458 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1459 packetdata.src_id_len =
1460 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1463 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1464 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1465 src_id_allocated = TRUE;
1467 packetdata.src_id_type = SILC_ID_CLIENT;
1469 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1470 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1471 packetdata.dst_id_type = dst_id_type;
1473 packetdata.dst_id = NULL;
1474 packetdata.dst_id_len = 0;
1475 packetdata.dst_id_type = SILC_ID_NONE;
1477 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1478 packetdata.src_id_len +
1479 packetdata.dst_id_len));
1480 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1481 packetdata.src_id_len + packetdata.dst_id_len;
1482 if (type == SILC_PACKET_CONNECTION_AUTH)
1483 SILC_PACKET_PADLEN_MAX(packetdata.truelen, block_len, packetdata.padlen);
1485 SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
1487 /* Create the outgoing packet */
1488 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
1489 data, data_len, (const SilcBuffer)&packet)) {
1490 SILC_LOG_ERROR(("Error assembling packet"));
1494 /* Encrypt the packet */
1496 silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet,
1499 SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
1500 packet.data, packet.len);
1502 /* Now actually send the packet */
1503 silc_client_packet_send_real(client, sock, force_send);
1506 if (src_id_allocated && packetdata.src_id)
1507 silc_free(packetdata.src_id);
1508 if (packetdata.dst_id)
1509 silc_free(packetdata.dst_id);
1512 /* Packet sending routine for application. This is the only routine that
1513 is provided for application to send SILC packets. */
1515 bool silc_client_send_packet(SilcClient client,
1516 SilcClientConnection conn,
1517 SilcPacketType type,
1518 const unsigned char *data,
1519 SilcUInt32 data_len)
1526 silc_client_packet_send(client, conn->sock, type, NULL, 0, NULL, NULL,
1527 (unsigned char *)data, data_len, TRUE);
1531 void silc_client_packet_queue_purge(SilcClient client,
1532 SilcSocketConnection sock)
1534 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1535 !(SILC_IS_DISCONNECTED(sock))) {
1538 ret = silc_packet_send(sock, TRUE);
1540 if (sock->outbuf && sock->outbuf->len > 0) {
1541 /* Couldn't send all data, put the queue back up, we'll send
1543 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
1544 SILC_SET_OUTBUF_PENDING(sock);
1549 /* Purged all data */
1550 SILC_UNSET_OUTBUF_PENDING(sock);
1551 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1552 silc_buffer_clear(sock->outbuf);
1556 /* Closes connection to remote end. Free's all allocated data except
1557 for some information such as nickname etc. that are valid at all time.
1558 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1559 provided it will be checked whether the sock and `conn->sock' are the
1560 same (they can be different, ie. a socket can use `conn' as its
1561 connection but `conn->sock' might be actually a different connection
1562 than the `sock'). */
1564 void silc_client_close_connection_real(SilcClient client,
1565 SilcSocketConnection sock,
1566 SilcClientConnection conn)
1570 SILC_LOG_DEBUG(("Start"));
1575 if (!sock || (sock && conn->sock == sock))
1582 silc_client_del_connection(client, conn);
1586 /* We won't listen for this connection anymore */
1587 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1589 /* Unregister all tasks */
1590 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1592 /* Close the actual connection */
1593 silc_net_close_connection(sock->sock);
1595 /* Cancel any active protocol */
1596 if (sock->protocol) {
1597 if (sock->protocol->protocol->type ==
1598 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1599 sock->protocol->protocol->type ==
1600 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1601 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1602 silc_protocol_execute_final(sock->protocol, client->schedule);
1603 /* The application will recall this function with these protocols
1604 (the ops->connected client operation). */
1607 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1608 silc_protocol_execute_final(sock->protocol, client->schedule);
1609 sock->protocol = NULL;
1613 /* Free everything */
1614 if (del && sock->user_data)
1615 silc_client_del_connection(client, conn);
1617 silc_socket_free(sock);
1620 /* Closes the connection to the remote end */
1622 void silc_client_close_connection(SilcClient client,
1623 SilcClientConnection conn)
1625 silc_client_close_connection_real(client, NULL, conn);
1628 /* Called when we receive disconnection packet from server. This
1629 closes our end properly and displays the reason of the disconnection
1632 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1634 SilcClient client = (SilcClient)context;
1635 SilcSocketConnection sock;
1637 SILC_CLIENT_GET_SOCK(client, fd, sock);
1641 silc_client_close_connection_real(client, sock, sock->user_data);
1644 /* Called when we receive disconnection packet from server. This
1645 closes our end properly and displays the reason of the disconnection
1648 void silc_client_disconnected_by_server(SilcClient client,
1649 SilcSocketConnection sock,
1652 SilcClientConnection conn;
1654 char *message = NULL;
1656 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1658 if (packet->len < 1)
1661 status = (SilcStatus)packet->data[0];
1663 if (packet->len > 1 &&
1664 silc_utf8_valid(packet->data + 1, packet->len - 1))
1665 message = silc_memdup(packet->data + 1, packet->len - 1);
1667 conn = (SilcClientConnection)sock->user_data;
1668 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1669 client->internal->ops->disconnected(client, conn, status, message);
1673 SILC_SET_DISCONNECTED(sock);
1675 /* Close connection through scheduler. */
1676 silc_schedule_task_add(client->schedule, sock->sock,
1677 silc_client_disconnected_by_server_later,
1678 client, 0, 1, SILC_TASK_TIMEOUT,
1679 SILC_TASK_PRI_NORMAL);
1682 /* Received error message from server. Display it on the screen.
1683 We don't take any action what so ever of the error message. */
1685 void silc_client_error_by_server(SilcClient client,
1686 SilcSocketConnection sock,
1691 msg = silc_memdup(message->data, message->len);
1692 client->internal->ops->say(client, sock->user_data,
1693 SILC_CLIENT_MESSAGE_AUDIT, msg);
1697 /* Auto-nicking callback to send NICK command to server. */
1699 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1701 SilcClientConnection conn = (SilcClientConnection)context;
1702 SilcClient client = conn->client;
1704 silc_client_command_send(client, conn, SILC_COMMAND_NICK,
1705 ++conn->cmd_ident, 1, 1,
1706 client->nickname, strlen(client->nickname));
1709 /* Client session resuming callback. If the session was resumed
1710 this callback is called after the resuming is completed. This
1711 will call the `connect' client operation to the application
1712 since it has not been called yet. */
1714 static void silc_client_resume_session_cb(SilcClient client,
1715 SilcClientConnection conn,
1721 /* Notify application that connection is created to server */
1722 client->internal->ops->connected(client, conn, success ?
1723 SILC_CLIENT_CONN_SUCCESS_RESUME :
1724 SILC_CLIENT_CONN_ERROR_RESUME);
1727 /* Issue INFO command to fetch the real server name and server
1728 information and other stuff. */
1729 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1730 silc_client_command_reply_info_i, 0,
1732 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1733 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1734 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1735 silc_buffer_free(sidp);
1739 /* Processes the received new Client ID from server. Old Client ID is
1740 deleted from cache and new one is added. */
1742 void silc_client_receive_new_id(SilcClient client,
1743 SilcSocketConnection sock,
1746 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1747 int connecting = FALSE;
1748 SilcClientID *client_id = silc_id_payload_get_id(idp);
1751 if (!conn->local_entry)
1754 /* Delete old ID from ID cache */
1755 if (conn->local_id) {
1756 /* Check whether they are different */
1757 if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1758 silc_free(client_id);
1762 silc_idcache_del_by_context(conn->internal->client_cache,
1764 silc_free(conn->local_id);
1767 /* Save the new ID */
1769 if (conn->local_id_data)
1770 silc_free(conn->local_id_data);
1772 conn->local_id = client_id;
1773 conn->local_id_data = silc_id_payload_get_data(idp);
1774 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1776 if (!conn->local_entry)
1777 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1779 conn->local_entry->nickname = conn->nickname;
1780 if (!conn->local_entry->username)
1781 conn->local_entry->username = strdup(client->username);
1782 if (!conn->local_entry->server)
1783 conn->local_entry->server = strdup(conn->remote_host);
1784 conn->local_entry->id = conn->local_id;
1785 conn->local_entry->valid = TRUE;
1786 if (!conn->local_entry->channels)
1787 conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
1792 /* Normalize nickname */
1793 nickname = silc_identifier_check(conn->nickname, strlen(conn->nickname),
1794 SILC_STRING_UTF8, 128, NULL);
1798 /* Put it to the ID cache */
1799 silc_idcache_add(conn->internal->client_cache, nickname, conn->local_id,
1800 (void *)conn->local_entry, 0, NULL);
1805 /* Issue IDENTIFY command for itself to get resolved hostname
1806 correctly from server. */
1807 silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
1808 silc_client_command_reply_identify_i, 0,
1810 sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT);
1811 silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
1812 conn->cmd_ident, 1, 5, sidp->data, sidp->len);
1813 silc_buffer_free(sidp);
1815 if (!conn->internal->params.detach_data) {
1816 /* Send NICK command if the nickname was set by the application (and is
1817 not same as the username). Send this with little timeout. */
1818 if (client->nickname &&
1819 !silc_utf8_strcasecmp(client->nickname, client->username))
1820 silc_schedule_task_add(client->schedule, 0,
1821 silc_client_send_auto_nick, conn,
1822 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1824 /* Notify application of successful connection. We do it here now that
1825 we've received the Client ID and are allowed to send traffic. */
1826 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_SUCCESS);
1828 /* Issue INFO command to fetch the real server name and server
1829 information and other stuff. */
1830 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1831 silc_client_command_reply_info_i, 0,
1833 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1834 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1835 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1836 silc_buffer_free(sidp);
1838 /* We are resuming session. Start resolving informations from the
1839 server we need to set the client libary in the state before
1840 detaching the session. The connect client operation is called
1841 after this is successfully completed */
1842 silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1848 /* Removes a client entry from all channels it has joined. */
1850 void silc_client_remove_from_channels(SilcClient client,
1851 SilcClientConnection conn,
1852 SilcClientEntry client_entry)
1854 SilcHashTableList htl;
1855 SilcChannelUser chu;
1857 silc_hash_table_list(client_entry->channels, &htl);
1858 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1859 silc_hash_table_del(chu->client->channels, chu->channel);
1860 silc_hash_table_del(chu->channel->user_list, chu->client);
1864 silc_hash_table_list_reset(&htl);
1867 /* Replaces `old' client entries from all channels to `new' client entry.
1868 This can be called for example when nickname changes and old ID entry
1869 is replaced from ID cache with the new one. If the old ID entry is only
1870 updated, then this fucntion needs not to be called. */
1872 void silc_client_replace_from_channels(SilcClient client,
1873 SilcClientConnection conn,
1874 SilcClientEntry old,
1875 SilcClientEntry new)
1877 SilcHashTableList htl;
1878 SilcChannelUser chu;
1880 silc_hash_table_list(old->channels, &htl);
1881 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1882 /* Replace client entry */
1883 silc_hash_table_del(chu->client->channels, chu->channel);
1884 silc_hash_table_del(chu->channel->user_list, chu->client);
1887 silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1888 silc_hash_table_add(chu->client->channels, chu->channel, chu);
1890 silc_hash_table_list_reset(&htl);
1893 /* Registers failure timeout to process the received failure packet
1896 void silc_client_process_failure(SilcClient client,
1897 SilcSocketConnection sock,
1898 SilcPacketContext *packet)
1900 SilcUInt32 failure = 0;
1902 if (sock->protocol) {
1903 if (packet->buffer->len >= 4)
1904 SILC_GET32_MSB(failure, packet->buffer->data);
1906 /* Notify application */
1907 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1908 SILC_32_TO_PTR(failure));
1912 /* A timeout callback for the re-key. We will be the initiator of the
1915 SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback)
1917 SilcSocketConnection sock = (SilcSocketConnection)context;
1918 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1919 SilcClient client = (SilcClient)conn->internal->rekey->context;
1920 SilcProtocol protocol;
1921 SilcClientRekeyInternalContext *proto_ctx;
1923 SILC_LOG_DEBUG(("Start"));
1925 /* If rekey protocol is active already wait for it to finish */
1926 if (sock->protocol && sock->protocol->protocol &&
1927 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)
1930 /* Allocate internal protocol context. This is sent as context
1932 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1933 proto_ctx->client = (void *)client;
1934 proto_ctx->sock = silc_socket_dup(sock);
1935 proto_ctx->responder = FALSE;
1936 proto_ctx->pfs = conn->internal->rekey->pfs;
1938 /* Perform rekey protocol. Will call the final callback after the
1939 protocol is over. */
1940 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1941 &protocol, proto_ctx, silc_client_rekey_final);
1942 sock->protocol = protocol;
1944 /* Run the protocol */
1945 silc_protocol_execute(protocol, client->schedule, 0, 0);
1948 /* The final callback for the REKEY protocol. This will actually take the
1949 new key material into use. */
1951 SILC_TASK_CALLBACK(silc_client_rekey_final)
1953 SilcProtocol protocol = (SilcProtocol)context;
1954 SilcClientRekeyInternalContext *ctx =
1955 (SilcClientRekeyInternalContext *)protocol->context;
1956 SilcClient client = (SilcClient)ctx->client;
1957 SilcSocketConnection sock = ctx->sock;
1958 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1960 SILC_LOG_DEBUG(("Start"));
1962 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1963 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1964 /* Error occured during protocol */
1965 silc_protocol_cancel(protocol, client->schedule);
1966 silc_protocol_free(protocol);
1967 sock->protocol = NULL;
1969 silc_packet_context_free(ctx->packet);
1971 silc_ske_free(ctx->ske);
1972 silc_socket_free(ctx->sock);
1977 /* Purge the outgoing data queue to assure that all rekey packets really
1978 go to the network before we quit the protocol. */
1979 silc_client_packet_queue_purge(client, sock);
1981 /* Re-register re-key timeout */
1982 if (ctx->responder == FALSE)
1983 silc_schedule_task_add(client->schedule, sock->sock,
1984 silc_client_rekey_callback,
1985 sock, conn->internal->rekey->timeout, 0,
1986 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1989 silc_protocol_free(protocol);
1990 sock->protocol = NULL;
1992 silc_packet_context_free(ctx->packet);
1994 silc_ske_free(ctx->ske);
1995 silc_socket_free(ctx->sock);
1999 /* Processes incoming connection authentication method request packet.
2000 It is a reply to our previously sent request. The packet can be used
2001 to resolve the authentication method for the current session if the
2002 client does not know it beforehand. */
2004 void silc_client_connection_auth_request(SilcClient client,
2005 SilcSocketConnection sock,
2006 SilcPacketContext *packet)
2008 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2009 SilcUInt16 conn_type, auth_meth;
2012 /* If we haven't send our request then ignore this one. */
2013 if (!conn->internal->connauth)
2016 /* Parse the payload */
2017 ret = silc_buffer_unformat(packet->buffer,
2018 SILC_STR_UI_SHORT(&conn_type),
2019 SILC_STR_UI_SHORT(&auth_meth),
2022 auth_meth = SILC_AUTH_NONE;
2024 /* Call the request callback to notify application for received
2025 authentication method information. */
2026 if (conn->internal->connauth->callback)
2027 (*conn->internal->connauth->callback)(client, conn, auth_meth,
2028 conn->internal->connauth->context);
2030 silc_schedule_task_del(client->schedule, conn->internal->connauth->timeout);
2032 silc_free(conn->internal->connauth);
2033 conn->internal->connauth = NULL;
2036 /* Timeout task callback called if the server does not reply to our
2037 connection authentication method request in the specified time interval. */
2039 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
2041 SilcClientConnection conn = (SilcClientConnection)context;
2042 SilcClient client = conn->client;
2044 if (!conn->internal->connauth)
2047 /* Call the request callback to notify application */
2048 if (conn->internal->connauth->callback)
2049 (*conn->internal->connauth->callback)(client, conn, SILC_AUTH_NONE,
2050 conn->internal->connauth->context);
2052 silc_free(conn->internal->connauth);
2053 conn->internal->connauth = NULL;
2056 /* This function can be used to request the current authentication method
2057 from the server. This may be called when connecting to the server
2058 and the client library requests the authentication data from the
2059 application. If the application does not know the current authentication
2060 method it can request it from the server using this function.
2061 The `callback' with `context' will be called after the server has
2062 replied back with the current authentication method. */
2065 silc_client_request_authentication_method(SilcClient client,
2066 SilcClientConnection conn,
2067 SilcConnectionAuthRequest callback,
2070 SilcClientConnAuthRequest connauth;
2073 assert(client && conn);
2074 connauth = silc_calloc(1, sizeof(*connauth));
2075 connauth->callback = callback;
2076 connauth->context = context;
2078 if (conn->internal->connauth)
2079 silc_free(conn->internal->connauth);
2081 conn->internal->connauth = connauth;
2083 /* Assemble the request packet and send it to the server */
2084 packet = silc_buffer_alloc(4);
2085 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
2086 silc_buffer_format(packet,
2087 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
2088 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
2090 silc_client_packet_send(client, conn->sock,
2091 SILC_PACKET_CONNECTION_AUTH_REQUEST,
2092 NULL, 0, NULL, NULL,
2093 packet->data, packet->len, FALSE);
2094 silc_buffer_free(packet);
2096 /* Register a timeout in case server does not reply anything back. */
2098 silc_schedule_task_add(client->schedule, conn->sock->sock,
2099 silc_client_request_authentication_method_timeout,
2101 client->internal->params->connauth_request_secs, 0,
2102 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);