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 SilcBool 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(SilcBool 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 SilcBool 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(SilcBool 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 SilcBool 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,
1415 SilcBool force_send)
1417 SilcPacketContext packetdata;
1418 const SilcBufferStruct packet;
1420 SilcUInt32 sequence = 0;
1425 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1427 /* Get data used in the packet sending, keys and stuff */
1428 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1429 if (!cipher && ((SilcClientConnection)sock->user_data)->internal->send_key)
1430 cipher = ((SilcClientConnection)sock->user_data)->internal->send_key;
1432 if (!hmac && ((SilcClientConnection)sock->user_data)->internal->hmac_send)
1433 hmac = ((SilcClientConnection)sock->user_data)->internal->hmac_send;
1435 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1436 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1437 dst_id_type = SILC_ID_SERVER;
1441 sequence = ((SilcClientConnection)sock->user_data)->internal->psn_send++;
1443 /* Check for mandatory rekey */
1444 if (sequence == SILC_CLIENT_REKEY_THRESHOLD)
1445 silc_schedule_task_add(client->schedule, sock->sock,
1446 silc_client_rekey_callback, sock, 0, 1,
1447 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1450 block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1452 /* Set the packet context pointers */
1453 packetdata.flags = 0;
1454 packetdata.type = type;
1455 if (sock->user_data &&
1456 ((SilcClientConnection)sock->user_data)->local_id_data) {
1457 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1458 packetdata.src_id_len =
1459 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1462 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1463 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1465 packetdata.src_id_type = SILC_ID_CLIENT;
1467 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1468 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1469 packetdata.dst_id_type = dst_id_type;
1471 packetdata.dst_id = NULL;
1472 packetdata.dst_id_len = 0;
1473 packetdata.dst_id_type = SILC_ID_NONE;
1475 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1476 packetdata.src_id_len +
1477 packetdata.dst_id_len));
1478 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1479 packetdata.src_id_len + packetdata.dst_id_len;
1480 if (type == SILC_PACKET_CONNECTION_AUTH)
1481 SILC_PACKET_PADLEN_MAX(packetdata.truelen, block_len, packetdata.padlen);
1483 SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
1485 /* Create the outgoing packet */
1486 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
1487 data, data_len, (const SilcBuffer)&packet)) {
1488 SILC_LOG_ERROR(("Error assembling packet"));
1492 /* Encrypt the packet */
1494 silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet,
1497 SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
1498 packet.data, packet.len);
1500 /* Now actually send the packet */
1501 silc_client_packet_send_real(client, sock, force_send);
1504 /* Packet sending routine for application. This is the only routine that
1505 is provided for application to send SILC packets. */
1507 SilcBool silc_client_send_packet(SilcClient client,
1508 SilcClientConnection conn,
1509 SilcPacketType type,
1510 const unsigned char *data,
1511 SilcUInt32 data_len)
1518 silc_client_packet_send(client, conn->sock, type, NULL, 0, NULL, NULL,
1519 (unsigned char *)data, data_len, TRUE);
1523 void silc_client_packet_queue_purge(SilcClient client,
1524 SilcSocketConnection sock)
1526 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1527 !(SILC_IS_DISCONNECTED(sock))) {
1530 ret = silc_packet_send(sock, TRUE);
1532 if (sock->outbuf && sock->outbuf->len > 0) {
1533 /* Couldn't send all data, put the queue back up, we'll send
1535 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
1536 SILC_SET_OUTBUF_PENDING(sock);
1541 /* Purged all data */
1542 SILC_UNSET_OUTBUF_PENDING(sock);
1543 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1544 silc_buffer_clear(sock->outbuf);
1548 /* Closes connection to remote end. Free's all allocated data except
1549 for some information such as nickname etc. that are valid at all time.
1550 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1551 provided it will be checked whether the sock and `conn->sock' are the
1552 same (they can be different, ie. a socket can use `conn' as its
1553 connection but `conn->sock' might be actually a different connection
1554 than the `sock'). */
1556 void silc_client_close_connection_real(SilcClient client,
1557 SilcSocketConnection sock,
1558 SilcClientConnection conn)
1562 SILC_LOG_DEBUG(("Start"));
1567 if (!sock || (sock && conn->sock == sock))
1574 silc_client_del_connection(client, conn);
1578 /* We won't listen for this connection anymore */
1579 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1581 /* Unregister all tasks */
1582 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1584 /* Close the actual connection */
1585 silc_net_close_connection(sock->sock);
1587 /* Cancel any active protocol */
1588 if (sock->protocol) {
1589 if (sock->protocol->protocol->type ==
1590 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1591 sock->protocol->protocol->type ==
1592 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1593 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1594 silc_protocol_execute_final(sock->protocol, client->schedule);
1595 /* The application will recall this function with these protocols
1596 (the ops->connected client operation). */
1599 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1600 silc_protocol_execute_final(sock->protocol, client->schedule);
1601 sock->protocol = NULL;
1605 /* Free everything */
1606 if (del && sock->user_data)
1607 silc_client_del_connection(client, conn);
1609 silc_socket_free(sock);
1612 /* Closes the connection to the remote end */
1614 void silc_client_close_connection(SilcClient client,
1615 SilcClientConnection conn)
1617 silc_client_close_connection_real(client, NULL, conn);
1620 /* Called when we receive disconnection packet from server. This
1621 closes our end properly and displays the reason of the disconnection
1624 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1626 SilcClient client = (SilcClient)context;
1627 SilcSocketConnection sock;
1629 SILC_CLIENT_GET_SOCK(client, fd, sock);
1633 silc_client_close_connection_real(client, sock, sock->user_data);
1636 /* Called when we receive disconnection packet from server. This
1637 closes our end properly and displays the reason of the disconnection
1640 void silc_client_disconnected_by_server(SilcClient client,
1641 SilcSocketConnection sock,
1644 SilcClientConnection conn;
1646 char *message = NULL;
1648 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1650 if (packet->len < 1)
1653 status = (SilcStatus)packet->data[0];
1655 if (packet->len > 1 &&
1656 silc_utf8_valid(packet->data + 1, packet->len - 1))
1657 message = silc_memdup(packet->data + 1, packet->len - 1);
1659 conn = (SilcClientConnection)sock->user_data;
1660 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1661 client->internal->ops->disconnected(client, conn, status, message);
1665 SILC_SET_DISCONNECTED(sock);
1667 /* Close connection through scheduler. */
1668 silc_schedule_task_add(client->schedule, sock->sock,
1669 silc_client_disconnected_by_server_later,
1670 client, 0, 1, SILC_TASK_TIMEOUT,
1671 SILC_TASK_PRI_NORMAL);
1674 /* Received error message from server. Display it on the screen.
1675 We don't take any action what so ever of the error message. */
1677 void silc_client_error_by_server(SilcClient client,
1678 SilcSocketConnection sock,
1683 msg = silc_memdup(message->data, message->len);
1684 client->internal->ops->say(client, sock->user_data,
1685 SILC_CLIENT_MESSAGE_AUDIT, msg);
1689 /* Auto-nicking callback to send NICK command to server. */
1691 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1693 SilcClientConnection conn = (SilcClientConnection)context;
1694 SilcClient client = conn->client;
1696 silc_client_command_send(client, conn, SILC_COMMAND_NICK,
1697 ++conn->cmd_ident, 1, 1,
1698 client->nickname, strlen(client->nickname));
1701 /* Client session resuming callback. If the session was resumed
1702 this callback is called after the resuming is completed. This
1703 will call the `connect' client operation to the application
1704 since it has not been called yet. */
1706 static void silc_client_resume_session_cb(SilcClient client,
1707 SilcClientConnection conn,
1713 /* Notify application that connection is created to server */
1714 client->internal->ops->connected(client, conn, success ?
1715 SILC_CLIENT_CONN_SUCCESS_RESUME :
1716 SILC_CLIENT_CONN_ERROR_RESUME);
1719 /* Issue INFO command to fetch the real server name and server
1720 information and other stuff. */
1721 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1722 silc_client_command_reply_info_i, 0,
1724 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1725 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1726 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1727 silc_buffer_free(sidp);
1731 /* Processes the received new Client ID from server. Old Client ID is
1732 deleted from cache and new one is added. */
1734 void silc_client_receive_new_id(SilcClient client,
1735 SilcSocketConnection sock,
1738 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1739 int connecting = FALSE;
1740 SilcClientID *client_id = silc_id_payload_get_id(idp);
1743 if (!conn->local_entry)
1746 /* Delete old ID from ID cache */
1747 if (conn->local_id) {
1748 /* Check whether they are different */
1749 if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1750 silc_free(client_id);
1754 silc_idcache_del_by_context(conn->internal->client_cache,
1756 silc_free(conn->local_id);
1759 /* Save the new ID */
1761 if (conn->local_id_data)
1762 silc_free(conn->local_id_data);
1764 conn->local_id = client_id;
1765 conn->local_id_data = silc_id_payload_get_data(idp);
1766 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1768 if (!conn->local_entry)
1769 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1771 conn->local_entry->nickname = conn->nickname;
1772 if (!conn->local_entry->username)
1773 conn->local_entry->username = strdup(client->username);
1774 if (!conn->local_entry->server)
1775 conn->local_entry->server = strdup(conn->remote_host);
1776 conn->local_entry->id = conn->local_id;
1777 conn->local_entry->valid = TRUE;
1778 if (!conn->local_entry->channels)
1779 conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
1784 /* Normalize nickname */
1785 nickname = silc_identifier_check(conn->nickname, strlen(conn->nickname),
1786 SILC_STRING_UTF8, 128, NULL);
1790 /* Put it to the ID cache */
1791 silc_idcache_add(conn->internal->client_cache, nickname, conn->local_id,
1792 (void *)conn->local_entry, 0, NULL);
1797 /* Issue IDENTIFY command for itself to get resolved hostname
1798 correctly from server. */
1799 silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
1800 silc_client_command_reply_identify_i, 0,
1802 sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT);
1803 silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
1804 conn->cmd_ident, 1, 5, sidp->data, sidp->len);
1805 silc_buffer_free(sidp);
1807 if (!conn->internal->params.detach_data) {
1808 /* Send NICK command if the nickname was set by the application (and is
1809 not same as the username). Send this with little timeout. */
1810 if (client->nickname &&
1811 !silc_utf8_strcasecmp(client->nickname, client->username))
1812 silc_schedule_task_add(client->schedule, 0,
1813 silc_client_send_auto_nick, conn,
1814 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1816 /* Notify application of successful connection. We do it here now that
1817 we've received the Client ID and are allowed to send traffic. */
1818 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_SUCCESS);
1820 /* Issue INFO command to fetch the real server name and server
1821 information and other stuff. */
1822 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1823 silc_client_command_reply_info_i, 0,
1825 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1826 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1827 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1828 silc_buffer_free(sidp);
1830 /* We are resuming session. Start resolving informations from the
1831 server we need to set the client libary in the state before
1832 detaching the session. The connect client operation is called
1833 after this is successfully completed */
1834 silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1840 /* Removes a client entry from all channels it has joined. */
1842 void silc_client_remove_from_channels(SilcClient client,
1843 SilcClientConnection conn,
1844 SilcClientEntry client_entry)
1846 SilcHashTableList htl;
1847 SilcChannelUser chu;
1849 silc_hash_table_list(client_entry->channels, &htl);
1850 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1851 silc_hash_table_del(chu->client->channels, chu->channel);
1852 silc_hash_table_del(chu->channel->user_list, chu->client);
1856 silc_hash_table_list_reset(&htl);
1859 /* Replaces `old' client entries from all channels to `new' client entry.
1860 This can be called for example when nickname changes and old ID entry
1861 is replaced from ID cache with the new one. If the old ID entry is only
1862 updated, then this fucntion needs not to be called. */
1864 void silc_client_replace_from_channels(SilcClient client,
1865 SilcClientConnection conn,
1866 SilcClientEntry old,
1867 SilcClientEntry new)
1869 SilcHashTableList htl;
1870 SilcChannelUser chu;
1872 silc_hash_table_list(old->channels, &htl);
1873 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1874 /* Replace client entry */
1875 silc_hash_table_del(chu->client->channels, chu->channel);
1876 silc_hash_table_del(chu->channel->user_list, chu->client);
1879 silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1880 silc_hash_table_add(chu->client->channels, chu->channel, chu);
1882 silc_hash_table_list_reset(&htl);
1885 /* Registers failure timeout to process the received failure packet
1888 void silc_client_process_failure(SilcClient client,
1889 SilcSocketConnection sock,
1890 SilcPacketContext *packet)
1892 SilcUInt32 failure = 0;
1894 if (sock->protocol) {
1895 if (packet->buffer->len >= 4)
1896 SILC_GET32_MSB(failure, packet->buffer->data);
1898 /* Notify application */
1899 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1900 SILC_32_TO_PTR(failure));
1904 /* A timeout callback for the re-key. We will be the initiator of the
1907 SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback)
1909 SilcSocketConnection sock = (SilcSocketConnection)context;
1910 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1911 SilcClient client = (SilcClient)conn->internal->rekey->context;
1912 SilcProtocol protocol;
1913 SilcClientRekeyInternalContext *proto_ctx;
1915 SILC_LOG_DEBUG(("Start"));
1917 /* If rekey protocol is active already wait for it to finish */
1918 if (sock->protocol && sock->protocol->protocol &&
1919 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)
1922 /* Allocate internal protocol context. This is sent as context
1924 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1925 proto_ctx->client = (void *)client;
1926 proto_ctx->sock = silc_socket_dup(sock);
1927 proto_ctx->responder = FALSE;
1928 proto_ctx->pfs = conn->internal->rekey->pfs;
1930 /* Perform rekey protocol. Will call the final callback after the
1931 protocol is over. */
1932 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1933 &protocol, proto_ctx, silc_client_rekey_final);
1934 sock->protocol = protocol;
1936 /* Run the protocol */
1937 silc_protocol_execute(protocol, client->schedule, 0, 0);
1940 /* The final callback for the REKEY protocol. This will actually take the
1941 new key material into use. */
1943 SILC_TASK_CALLBACK(silc_client_rekey_final)
1945 SilcProtocol protocol = (SilcProtocol)context;
1946 SilcClientRekeyInternalContext *ctx =
1947 (SilcClientRekeyInternalContext *)protocol->context;
1948 SilcClient client = (SilcClient)ctx->client;
1949 SilcSocketConnection sock = ctx->sock;
1950 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1952 SILC_LOG_DEBUG(("Start"));
1954 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1955 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1956 /* Error occured during protocol */
1957 silc_protocol_cancel(protocol, client->schedule);
1958 silc_protocol_free(protocol);
1959 sock->protocol = NULL;
1961 silc_packet_context_free(ctx->packet);
1963 silc_ske_free(ctx->ske);
1964 silc_socket_free(ctx->sock);
1969 /* Purge the outgoing data queue to assure that all rekey packets really
1970 go to the network before we quit the protocol. */
1971 silc_client_packet_queue_purge(client, sock);
1973 /* Re-register re-key timeout */
1974 if (ctx->responder == FALSE)
1975 silc_schedule_task_add(client->schedule, sock->sock,
1976 silc_client_rekey_callback,
1977 sock, conn->internal->rekey->timeout, 0,
1978 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1981 silc_protocol_free(protocol);
1982 sock->protocol = NULL;
1984 silc_packet_context_free(ctx->packet);
1986 silc_ske_free(ctx->ske);
1987 silc_socket_free(ctx->sock);
1991 /* Processes incoming connection authentication method request packet.
1992 It is a reply to our previously sent request. The packet can be used
1993 to resolve the authentication method for the current session if the
1994 client does not know it beforehand. */
1996 void silc_client_connection_auth_request(SilcClient client,
1997 SilcSocketConnection sock,
1998 SilcPacketContext *packet)
2000 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2001 SilcUInt16 conn_type, auth_meth;
2004 /* If we haven't send our request then ignore this one. */
2005 if (!conn->internal->connauth)
2008 /* Parse the payload */
2009 ret = silc_buffer_unformat(packet->buffer,
2010 SILC_STR_UI_SHORT(&conn_type),
2011 SILC_STR_UI_SHORT(&auth_meth),
2014 auth_meth = SILC_AUTH_NONE;
2016 /* Call the request callback to notify application for received
2017 authentication method information. */
2018 if (conn->internal->connauth->callback)
2019 (*conn->internal->connauth->callback)(client, conn, auth_meth,
2020 conn->internal->connauth->context);
2022 silc_schedule_task_del(client->schedule, conn->internal->connauth->timeout);
2024 silc_free(conn->internal->connauth);
2025 conn->internal->connauth = NULL;
2028 /* Timeout task callback called if the server does not reply to our
2029 connection authentication method request in the specified time interval. */
2031 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
2033 SilcClientConnection conn = (SilcClientConnection)context;
2034 SilcClient client = conn->client;
2036 if (!conn->internal->connauth)
2039 /* Call the request callback to notify application */
2040 if (conn->internal->connauth->callback)
2041 (*conn->internal->connauth->callback)(client, conn, SILC_AUTH_NONE,
2042 conn->internal->connauth->context);
2044 silc_free(conn->internal->connauth);
2045 conn->internal->connauth = NULL;
2048 /* This function can be used to request the current authentication method
2049 from the server. This may be called when connecting to the server
2050 and the client library requests the authentication data from the
2051 application. If the application does not know the current authentication
2052 method it can request it from the server using this function.
2053 The `callback' with `context' will be called after the server has
2054 replied back with the current authentication method. */
2057 silc_client_request_authentication_method(SilcClient client,
2058 SilcClientConnection conn,
2059 SilcConnectionAuthRequest callback,
2062 SilcClientConnAuthRequest connauth;
2065 assert(client && conn);
2066 connauth = silc_calloc(1, sizeof(*connauth));
2067 connauth->callback = callback;
2068 connauth->context = context;
2070 if (conn->internal->connauth)
2071 silc_free(conn->internal->connauth);
2073 conn->internal->connauth = connauth;
2075 /* Assemble the request packet and send it to the server */
2076 packet = silc_buffer_alloc(4);
2077 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
2078 silc_buffer_format(packet,
2079 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
2080 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
2082 silc_client_packet_send(client, conn->sock,
2083 SILC_PACKET_CONNECTION_AUTH_REQUEST,
2084 NULL, 0, NULL, NULL,
2085 packet->data, packet->len, FALSE);
2086 silc_buffer_free(packet);
2088 /* Register a timeout in case server does not reply anything back. */
2090 silc_schedule_task_add(client->schedule, conn->sock->sock,
2091 silc_client_request_authentication_method_timeout,
2093 client->internal->params->connauth_request_secs, 0,
2094 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);