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 if (!client->internal->params->dont_register_crypto_library) {
124 /* Initialize the crypto library. If application has done this already
125 this has no effect. Also, we will not be overriding something
126 application might have registered earlier. */
127 silc_cipher_register_default();
128 silc_pkcs_register_default();
129 silc_hash_register_default();
130 silc_hmac_register_default();
133 /* Initialize hash functions for client to use */
134 silc_hash_alloc("md5", &client->md5hash);
135 silc_hash_alloc("sha1", &client->sha1hash);
137 /* Initialize none cipher */
138 silc_cipher_alloc("none", &client->internal->none_cipher);
140 /* Initialize random number generator */
141 client->rng = silc_rng_alloc();
142 silc_rng_init(client->rng);
143 silc_rng_global_init(client->rng);
145 /* Register protocols */
146 silc_client_protocols_register();
148 /* Initialize the scheduler */
150 silc_schedule_init(client->internal->params->task_max ?
151 client->internal->params->task_max : 200, client);
152 if (!client->schedule)
155 /* Register commands */
156 silc_client_commands_register(client);
161 /* Stops the client. This is called to stop the client and thus to stop
164 void silc_client_stop(SilcClient client)
166 SILC_LOG_DEBUG(("Stopping client"));
168 silc_schedule_stop(client->schedule);
169 silc_schedule_uninit(client->schedule);
171 silc_client_protocols_unregister();
172 silc_client_commands_unregister(client);
174 SILC_LOG_DEBUG(("Client stopped"));
177 /* Runs the client. This starts the scheduler from the utility library.
178 When this functions returns the execution of the appliation is over. */
180 void silc_client_run(SilcClient client)
182 SILC_LOG_DEBUG(("Running client"));
185 assert(client->pkcs);
186 assert(client->public_key);
187 assert(client->private_key);
189 /* Start the scheduler, the heart of the SILC client. When this returns
190 the program will be terminated. */
191 silc_schedule(client->schedule);
194 /* Runs the client and returns immeadiately. This function is used when
195 the SILC Client object indicated by the `client' is run under some
196 other scheduler, or event loop or main loop. On GUI applications,
197 for example this may be desired to use to run the client under the
198 GUI application's main loop. Typically the GUI application would
199 register an idle task that calls this function multiple times in
200 a second to quickly process the SILC specific data. */
202 void silc_client_run_one(SilcClient client)
204 /* Run the scheduler once. */
205 silc_schedule_one(client->schedule, 0);
208 static void silc_client_entry_destructor(SilcIDCache cache,
209 SilcIDCacheEntry entry)
211 silc_free(entry->name);
214 /* Allocates and adds new connection to the client. This adds the allocated
215 connection to the connection table and returns a pointer to it. A client
216 can have multiple connections to multiple servers. Every connection must
217 be added to the client using this function. User data `context' may
218 be sent as argument. This function is normally used only if the
219 application performed the connecting outside the library. The library
220 however may use this internally. */
223 silc_client_add_connection(SilcClient client,
224 SilcClientConnectionParams *params,
225 char *hostname, int port, void *context)
227 SilcClientConnection conn;
230 SILC_LOG_DEBUG(("Adding new connection to %s:%d", hostname, port));
232 conn = silc_calloc(1, sizeof(*conn));
233 conn->internal = silc_calloc(1, sizeof(*conn->internal));
235 /* Initialize ID caches */
236 conn->client = client;
237 conn->remote_host = strdup(hostname);
238 conn->remote_port = port;
239 conn->context = context;
240 conn->internal->client_cache =
241 silc_idcache_alloc(0, SILC_ID_CLIENT, silc_client_entry_destructor,
243 conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL,
245 conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL,
247 conn->internal->pending_commands = silc_dlist_init();
248 conn->internal->ftp_sessions = silc_dlist_init();
251 if (params->detach_data)
252 conn->internal->params.detach_data =
253 silc_memdup(params->detach_data,
254 params->detach_data_len);
255 conn->internal->params.detach_data_len = params->detach_data_len;
258 /* Add the connection to connections table */
259 for (i = 0; i < client->internal->conns_count; i++)
260 if (client->internal->conns && !client->internal->conns[i]) {
261 client->internal->conns[i] = conn;
265 client->internal->conns =
266 silc_realloc(client->internal->conns, sizeof(*client->internal->conns)
267 * (client->internal->conns_count + 1));
268 client->internal->conns[client->internal->conns_count] = conn;
269 client->internal->conns_count++;
274 /* Removes connection from client. Frees all memory. */
276 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
280 for (i = 0; i < client->internal->conns_count; i++)
281 if (client->internal->conns[i] == conn) {
282 /* Free all cache entries */
283 SilcIDCacheList list;
284 SilcIDCacheEntry entry;
285 SilcClientCommandPending *r;
288 if (silc_idcache_get_all(conn->internal->client_cache, &list)) {
289 ret = silc_idcache_list_first(list, &entry);
291 silc_client_del_client(client, conn, entry->context);
292 ret = silc_idcache_list_next(list, &entry);
294 silc_idcache_list_free(list);
297 if (silc_idcache_get_all(conn->internal->channel_cache, &list)) {
298 ret = silc_idcache_list_first(list, &entry);
300 silc_client_del_channel(client, conn, entry->context);
301 ret = silc_idcache_list_next(list, &entry);
303 silc_idcache_list_free(list);
306 if (silc_idcache_get_all(conn->internal->server_cache, &list)) {
307 ret = silc_idcache_list_first(list, &entry);
309 silc_client_del_server(client, conn, entry->context);
310 ret = silc_idcache_list_next(list, &entry);
312 silc_idcache_list_free(list);
315 /* Clear ID caches */
316 if (conn->internal->client_cache)
317 silc_idcache_free(conn->internal->client_cache);
318 if (conn->internal->channel_cache)
319 silc_idcache_free(conn->internal->channel_cache);
320 if (conn->internal->server_cache)
321 silc_idcache_free(conn->internal->server_cache);
323 /* Free data (my ID is freed in above silc_client_del_client).
324 conn->nickname is freed when freeing the local_entry->nickname. */
325 silc_free(conn->remote_host);
326 silc_free(conn->local_id_data);
327 if (conn->internal->send_key)
328 silc_cipher_free(conn->internal->send_key);
329 if (conn->internal->receive_key)
330 silc_cipher_free(conn->internal->receive_key);
331 if (conn->internal->hmac_send)
332 silc_hmac_free(conn->internal->hmac_send);
333 if (conn->internal->hmac_receive)
334 silc_hmac_free(conn->internal->hmac_receive);
335 silc_free(conn->internal->rekey);
337 if (conn->internal->active_session) {
339 conn->sock->user_data = NULL;
340 silc_client_ftp_session_free(conn->internal->active_session);
341 conn->internal->active_session = NULL;
344 silc_client_ftp_free_sessions(client, conn);
346 if (conn->internal->pending_commands) {
347 silc_dlist_start(conn->internal->pending_commands);
348 while ((r = silc_dlist_get(conn->internal->pending_commands))
350 silc_dlist_del(conn->internal->pending_commands, r);
351 silc_dlist_uninit(conn->internal->pending_commands);
354 silc_free(conn->internal);
355 memset(conn, 0, sizeof(*conn));
358 client->internal->conns[i] = NULL;
362 /* Adds listener socket to the listener sockets table. This function is
363 used to add socket objects that are listeners to the client. This should
364 not be used to add other connection objects. */
366 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
370 if (!client->internal->sockets) {
371 client->internal->sockets =
372 silc_calloc(1, sizeof(*client->internal->sockets));
373 client->internal->sockets[0] = silc_socket_dup(sock);
374 client->internal->sockets_count = 1;
378 for (i = 0; i < client->internal->sockets_count; i++) {
379 if (client->internal->sockets[i] == NULL) {
380 client->internal->sockets[i] = silc_socket_dup(sock);
385 client->internal->sockets =
386 silc_realloc(client->internal->sockets,
387 sizeof(*client->internal->sockets) *
388 (client->internal->sockets_count + 1));
389 client->internal->sockets[client->internal->sockets_count] =
390 silc_socket_dup(sock);
391 client->internal->sockets_count++;
394 /* Deletes listener socket from the listener sockets table. */
396 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
400 if (!client->internal->sockets)
403 for (i = 0; i < client->internal->sockets_count; i++) {
404 if (client->internal->sockets[i] == sock) {
405 silc_socket_free(sock);
406 client->internal->sockets[i] = NULL;
413 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
417 /* XXX In the future we should give up this non-blocking connect all
418 together and use threads instead. */
419 /* Create connection to server asynchronously */
420 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
424 /* Register task that will receive the async connect and will
426 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
427 silc_client_connect_to_server_start,
430 SILC_TASK_PRI_NORMAL);
431 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE,
439 /* Connects to remote server. This is the main routine used to connect
440 to SILC server. Returns -1 on error and the created socket otherwise.
441 The `context' is user context that is saved into the SilcClientConnection
442 that is created after the connection is created. Note that application
443 may handle the connecting process outside the library. If this is the
444 case then this function is not used at all. When the connecting is
445 done the `connect' client operation is called. */
447 int silc_client_connect_to_server(SilcClient client,
448 SilcClientConnectionParams *params,
449 int port, char *host, void *context)
451 SilcClientInternalConnectContext *ctx;
452 SilcClientConnection conn;
455 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
458 conn = silc_client_add_connection(client, params, host, port, context);
460 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
461 "Connecting to port %d of server %s", port, host);
463 /* Allocate internal context for connection process. This is
464 needed as we are doing async connecting. */
465 ctx = silc_calloc(1, sizeof(*ctx));
466 ctx->client = client;
468 ctx->host = strdup(host);
469 ctx->port = port ? port : 706;
472 /* Do the actual connecting process */
473 sock = silc_client_connect_to_server_internal(ctx);
475 silc_client_del_connection(client, conn);
479 /* Socket hostname and IP lookup callback that is called before actually
480 starting the key exchange. The lookup is called from the function
481 silc_client_start_key_exchange. */
483 static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
486 SilcClientConnection conn = (SilcClientConnection)context;
487 SilcClient client = conn->client;
488 SilcProtocol protocol;
489 SilcClientKEInternalContext *proto_ctx;
491 SILC_LOG_DEBUG(("Start"));
493 if (conn->sock->hostname) {
494 silc_free(conn->remote_host);
495 conn->remote_host = strdup(conn->sock->hostname);
497 conn->sock->hostname = strdup(conn->remote_host);
500 conn->sock->ip = strdup(conn->sock->hostname);
501 conn->sock->port = conn->remote_port;
503 /* Allocate internal Key Exchange context. This is sent to the
504 protocol as context. */
505 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
506 proto_ctx->client = (void *)client;
507 proto_ctx->sock = silc_socket_dup(conn->sock);
508 proto_ctx->rng = client->rng;
509 proto_ctx->responder = FALSE;
510 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
511 proto_ctx->verify = silc_client_protocol_ke_verify_key;
513 /* Perform key exchange protocol. silc_client_connect_to_server_final
514 will be called after the protocol is finished. */
515 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
516 &protocol, (void *)proto_ctx,
517 silc_client_connect_to_server_second);
519 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
520 "Error: Could not start key exchange protocol");
521 silc_net_close_connection(conn->sock->sock);
522 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
525 conn->sock->protocol = protocol;
527 /* Register the connection for network input and output. This sets
528 that scheduler will listen for incoming packets for this connection
529 and sets that outgoing packets may be sent to this connection as well.
530 However, this doesn't set the scheduler for outgoing traffic, it will
531 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
532 later when outgoing data is available. */
533 context = (void *)client;
534 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(conn->sock->sock);
536 /* Execute the protocol */
537 silc_protocol_execute(protocol, client->schedule, 0, 0);
540 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
541 key material between client and server. This function can be called
542 directly if application is performing its own connecting and does not
543 use the connecting provided by this library. This function is normally
544 used only if the application performed the connecting outside the library.
545 The library however may use this internally. */
547 void silc_client_start_key_exchange(SilcClient client,
548 SilcClientConnection conn,
551 assert(client->pkcs);
552 assert(client->public_key);
553 assert(client->private_key);
555 /* Allocate new socket connection object */
556 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
558 /* Sometimes when doing quick reconnects the new socket may be same as
559 the old one and there might be pending stuff for the old socket.
560 If new one is same then those pending sutff might cause problems.
561 Make sure they do not do that. */
562 silc_schedule_task_del_by_fd(client->schedule, fd);
564 conn->nickname = (client->nickname ? strdup(client->nickname) :
565 strdup(client->username));
567 /* Resolve the remote hostname and IP address for our socket connection */
568 silc_socket_host_lookup(conn->sock, FALSE, silc_client_start_key_exchange_cb,
569 conn, client->schedule);
572 /* Callback called when error has occurred during connecting (KE) to
573 the server. The `connect' client operation will be called. */
575 SILC_TASK_CALLBACK(silc_client_connect_failure)
577 SilcClientKEInternalContext *ctx =
578 (SilcClientKEInternalContext *)context;
579 SilcClient client = (SilcClient)ctx->client;
581 client->internal->ops->connected(client, ctx->sock->user_data,
582 SILC_CLIENT_CONN_ERROR_KE);
584 silc_packet_context_free(ctx->packet);
588 /* Callback called when error has occurred during connecting (auth) to
589 the server. The `connect' client operation will be called. */
591 SILC_TASK_CALLBACK(silc_client_connect_failure_auth)
593 SilcClientConnAuthInternalContext *ctx =
594 (SilcClientConnAuthInternalContext *)context;
595 SilcClient client = (SilcClient)ctx->client;
597 client->internal->ops->connected(client, ctx->sock->user_data, ctx->status);
601 /* Start of the connection to the remote server. This is called after
602 succesful TCP/IP connection has been established to the remote host. */
604 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
606 SilcClientInternalConnectContext *ctx =
607 (SilcClientInternalConnectContext *)context;
608 SilcClient client = ctx->client;
609 SilcClientConnection conn = ctx->conn;
610 int opt, opt_len = sizeof(opt);
612 SILC_LOG_DEBUG(("Start"));
614 /* Check the socket status as it might be in error */
615 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
617 if (ctx->tries < 2) {
618 /* Connection failed but lets try again */
619 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
620 "Could not connect to server %s: %s",
621 ctx->host, strerror(opt));
622 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
623 "Connecting to port %d of server %s resumed",
624 ctx->port, ctx->host);
626 /* Unregister old connection try */
627 silc_schedule_unset_listen_fd(client->schedule, fd);
628 silc_net_close_connection(fd);
629 silc_schedule_task_del(client->schedule, ctx->task);
632 silc_client_connect_to_server_internal(ctx);
635 /* Connection failed and we won't try anymore */
636 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
637 "Could not connect to server %s: %s",
638 ctx->host, strerror(opt));
639 silc_schedule_unset_listen_fd(client->schedule, fd);
640 silc_net_close_connection(fd);
641 silc_schedule_task_del(client->schedule, ctx->task);
644 /* Notify application of failure */
645 client->internal->ops->connected(client, conn,
646 SILC_CLIENT_CONN_ERROR_TIMEOUT);
651 silc_schedule_unset_listen_fd(client->schedule, fd);
652 silc_schedule_task_del(client->schedule, ctx->task);
655 silc_client_start_key_exchange(client, conn, fd);
658 /* Second part of the connecting to the server. This executed
659 authentication protocol. */
661 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
663 SilcProtocol protocol = (SilcProtocol)context;
664 SilcClientKEInternalContext *ctx =
665 (SilcClientKEInternalContext *)protocol->context;
666 SilcClient client = (SilcClient)ctx->client;
667 SilcSocketConnection sock = NULL;
668 SilcClientConnAuthInternalContext *proto_ctx;
670 SILC_LOG_DEBUG(("Start"));
672 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
673 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
674 /* Error occured during protocol */
675 SILC_LOG_DEBUG(("Error during KE protocol"));
676 silc_protocol_free(protocol);
677 silc_ske_free_key_material(ctx->keymat);
679 silc_ske_free(ctx->ske);
681 silc_free(ctx->dest_id);
682 ctx->sock->protocol = NULL;
683 silc_socket_free(ctx->sock);
685 /* Notify application of failure */
686 silc_schedule_task_add(client->schedule, ctx->sock->sock,
687 silc_client_connect_failure, ctx,
688 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
692 /* We now have the key material as the result of the key exchange
693 protocol. Take the key material into use. Free the raw key material
694 as soon as we've set them into use. */
695 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
696 ctx->ske->prop->cipher,
697 ctx->ske->prop->pkcs,
698 ctx->ske->prop->hash,
699 ctx->ske->prop->hmac,
700 ctx->ske->prop->group,
702 silc_ske_free_key_material(ctx->keymat);
704 /* Allocate internal context for the authentication protocol. This
705 is sent as context for the protocol. */
706 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
707 proto_ctx->client = (void *)client;
708 proto_ctx->sock = sock = ctx->sock;
709 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
710 proto_ctx->dest_id_type = ctx->dest_id_type;
711 proto_ctx->dest_id = ctx->dest_id;
713 /* Free old protocol as it is finished now */
714 silc_protocol_free(protocol);
716 silc_packet_context_free(ctx->packet);
719 sock->protocol = NULL;
721 /* Resolve the authentication method to be used in this connection. The
722 completion callback is called after the application has resolved
723 the authentication method. */
724 client->internal->ops->get_auth_method(client, sock->user_data,
727 silc_client_resolve_auth_method,
731 /* Authentication method resolving callback. Application calls this function
732 after we've called the client->internal->ops->get_auth_method
733 client operation to resolve the authentication method. We will continue
734 the executiong of the protocol in this function. */
736 void silc_client_resolve_auth_method(bool success,
737 SilcProtocolAuthMeth auth_meth,
738 const unsigned char *auth_data,
739 SilcUInt32 auth_data_len, void *context)
741 SilcClientConnAuthInternalContext *proto_ctx =
742 (SilcClientConnAuthInternalContext *)context;
743 SilcClient client = (SilcClient)proto_ctx->client;
746 auth_meth = SILC_AUTH_NONE;
748 proto_ctx->auth_meth = auth_meth;
750 if (success && auth_data && auth_data_len) {
752 /* Passphrase must be UTF-8 encoded, if it isn't encode it */
753 if (auth_meth == SILC_AUTH_PASSWORD &&
754 !silc_utf8_valid(auth_data, auth_data_len)) {
756 unsigned char *autf8 = NULL;
757 payload_len = silc_utf8_encoded_len(auth_data, auth_data_len,
759 autf8 = silc_calloc(payload_len, sizeof(*autf8));
760 auth_data_len = silc_utf8_encode(auth_data, auth_data_len,
761 SILC_STRING_ASCII, autf8, payload_len);
765 proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
766 proto_ctx->auth_data_len = auth_data_len;
769 /* Allocate the authenteication protocol and execute it. */
770 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
771 &proto_ctx->sock->protocol, (void *)proto_ctx,
772 silc_client_connect_to_server_final);
774 /* Execute the protocol */
775 silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
778 /* Finalizes the connection to the remote SILC server. This is called
779 after authentication protocol has been completed. This send our
780 user information to the server to receive our client ID from
783 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
785 SilcProtocol protocol = (SilcProtocol)context;
786 SilcClientConnAuthInternalContext *ctx =
787 (SilcClientConnAuthInternalContext *)protocol->context;
788 SilcClient client = (SilcClient)ctx->client;
789 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
792 SILC_LOG_DEBUG(("Start"));
794 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
795 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
796 /* Error occured during protocol */
797 SILC_LOG_DEBUG(("Error during authentication protocol"));
798 ctx->status = SILC_CLIENT_CONN_ERROR_AUTH;
802 if (conn->internal->params.detach_data) {
803 /* Send RESUME_CLIENT packet to the server, which is used to resume
804 old detached session back. */
806 SilcClientID *old_client_id;
807 unsigned char *old_id;
808 SilcUInt16 old_id_len;
810 if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len)) {
811 ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
815 old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT);
816 if (!old_client_id) {
818 ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
822 /* Generate authentication data that server will verify */
823 auth = silc_auth_public_key_auth_generate(client->public_key,
826 conn->internal->hash,
827 old_client_id, SILC_ID_CLIENT);
829 silc_free(old_client_id);
831 ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
835 packet = silc_buffer_alloc_size(2 + old_id_len + auth->len);
836 silc_buffer_format(packet,
837 SILC_STR_UI_SHORT(old_id_len),
838 SILC_STR_UI_XNSTRING(old_id, old_id_len),
839 SILC_STR_UI_XNSTRING(auth->data, auth->len),
842 /* Send the packet */
843 silc_client_packet_send(client, ctx->sock, SILC_PACKET_RESUME_CLIENT,
845 packet->data, packet->len, TRUE);
846 silc_buffer_free(packet);
847 silc_buffer_free(auth);
848 silc_free(old_client_id);
851 /* Send NEW_CLIENT packet to the server. We will become registered
852 to the SILC network after sending this packet and we will receive
853 client ID from the server. */
854 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
855 strlen(client->realname));
856 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
857 silc_buffer_format(packet,
858 SILC_STR_UI_SHORT(strlen(client->username)),
859 SILC_STR_UI_XNSTRING(client->username,
860 strlen(client->username)),
861 SILC_STR_UI_SHORT(strlen(client->realname)),
862 SILC_STR_UI_XNSTRING(client->realname,
863 strlen(client->realname)),
866 /* Send the packet */
867 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
869 packet->data, packet->len, TRUE);
870 silc_buffer_free(packet);
873 /* Save remote ID. */
874 conn->remote_id = ctx->dest_id;
875 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
876 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
878 /* Register re-key timeout */
879 conn->internal->rekey->timeout = client->internal->params->rekey_secs;
880 conn->internal->rekey->context = (void *)client;
881 silc_schedule_task_add(client->schedule, conn->sock->sock,
882 silc_client_rekey_callback,
883 (void *)conn->sock, conn->internal->rekey->timeout, 0,
884 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
886 silc_protocol_free(protocol);
887 silc_free(ctx->auth_data);
889 silc_ske_free(ctx->ske);
890 silc_socket_free(ctx->sock);
892 conn->sock->protocol = NULL;
896 silc_protocol_free(protocol);
897 silc_free(ctx->auth_data);
898 silc_free(ctx->dest_id);
900 silc_ske_free(ctx->ske);
901 conn->sock->protocol = NULL;
902 silc_socket_free(ctx->sock);
904 /* Notify application of failure */
905 silc_schedule_task_add(client->schedule, ctx->sock->sock,
906 silc_client_connect_failure_auth, ctx,
907 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
910 /* Internal routine that sends packet or marks packet to be sent. This
911 is used directly only in special cases. Normal cases should use
912 silc_server_packet_send. Returns < 0 on error. */
914 int silc_client_packet_send_real(SilcClient client,
915 SilcSocketConnection sock,
920 /* If rekey protocol is active we must assure that all packets are
921 sent through packet queue. */
922 if (SILC_CLIENT_IS_REKEY(sock))
925 /* If outbound data is already pending do not force send */
926 if (SILC_IS_OUTBUF_PENDING(sock))
929 /* Send the packet */
930 ret = silc_packet_send(sock, force_send);
934 /* Mark that there is some outgoing data available for this connection.
935 This call sets the connection both for input and output (the input
936 is set always and this call keeps the input setting, actually).
937 Actual data sending is performed by silc_client_packet_process. */
938 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
940 /* Mark to socket that data is pending in outgoing buffer. This flag
941 is needed if new data is added to the buffer before the earlier
942 put data is sent to the network. */
943 SILC_SET_OUTBUF_PENDING(sock);
948 /* Packet processing callback. This is used to send and receive packets
949 from network. This is generic task. */
951 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
953 SilcClient client = (SilcClient)context;
954 SilcSocketConnection sock = NULL;
955 SilcClientConnection conn;
958 SILC_LOG_DEBUG(("Processing packet"));
960 SILC_CLIENT_GET_SOCK(client, fd, sock);
964 conn = (SilcClientConnection)sock->user_data;
967 if (type == SILC_TASK_WRITE) {
968 /* Do not send data to disconnected connection */
969 if (SILC_IS_DISCONNECTED(sock))
972 ret = silc_packet_send(sock, TRUE);
974 /* If returned -2 could not write to connection now, will do
983 /* The packet has been sent and now it is time to set the connection
984 back to only for input. When there is again some outgoing data
985 available for this connection it will be set for output as well.
986 This call clears the output setting and sets it only for input. */
987 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
988 SILC_UNSET_OUTBUF_PENDING(sock);
990 silc_buffer_clear(sock->outbuf);
994 /* Packet receiving */
995 if (type == SILC_TASK_READ) {
996 /* Read data from network */
997 ret = silc_packet_receive(sock);
1003 SILC_LOG_DEBUG(("Read EOF"));
1005 /* If connection is disconnecting already we will finally
1006 close the connection */
1007 if (SILC_IS_DISCONNECTING(sock)) {
1008 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1009 client->internal->ops->disconnected(client, conn, 0, NULL);
1010 silc_client_close_connection_real(client, sock, conn);
1014 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
1015 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1016 client->internal->ops->disconnected(client, conn, 0, NULL);
1017 silc_client_close_connection_real(client, sock, conn);
1021 /* Process the packet. This will call the parser that will then
1022 decrypt and parse the packet. */
1023 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
1024 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
1025 conn->internal->hmac_receive,
1026 conn->internal->psn_receive,
1027 silc_client_packet_parse, client);
1029 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
1030 silc_client_packet_parse, client);
1034 /* Parser callback called by silc_packet_receive_process. Thie merely
1035 registers timeout that will handle the actual parsing when appropriate. */
1037 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
1040 SilcClient client = (SilcClient)context;
1041 SilcSocketConnection sock = parser_context->sock;
1042 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1043 SilcPacketContext *packet = parser_context->packet;
1046 if (conn && conn->internal->hmac_receive && conn->sock == sock)
1047 conn->internal->psn_receive = parser_context->packet->sequence + 1;
1049 /* Parse the packet immediately */
1050 if (parser_context->normal)
1051 ret = silc_packet_parse(packet, conn->internal->receive_key);
1053 ret = silc_packet_parse_special(packet, conn->internal->receive_key);
1055 if (ret == SILC_PACKET_NONE) {
1056 silc_packet_context_free(packet);
1057 silc_free(parser_context);
1061 /* If protocol for this connection is key exchange or rekey then we'll
1062 process all packets synchronously, since there might be packets in
1063 queue that we are not able to decrypt without first processing the
1064 packets before them. */
1065 if (sock->protocol && sock->protocol->protocol &&
1066 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1067 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1069 /* Parse the incoming packet type */
1070 silc_client_packet_parse_type(client, sock, packet);
1072 /* Reprocess the buffer since we'll return FALSE. This is because
1073 the `conn->internal->receive_key' might have become valid by processing
1074 the previous packet */
1075 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
1076 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
1077 conn->internal->hmac_receive,
1078 conn->internal->psn_receive,
1079 silc_client_packet_parse, client);
1081 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
1082 silc_client_packet_parse, client);
1084 silc_packet_context_free(packet);
1085 silc_free(parser_context);
1090 /* Parse the incoming packet type */
1091 silc_client_packet_parse_type(client, sock, packet);
1092 silc_packet_context_free(packet);
1093 silc_free(parser_context);
1097 /* Parses the packet type and calls what ever routines the packet type
1098 requires. This is done for all incoming packets. */
1100 void silc_client_packet_parse_type(SilcClient client,
1101 SilcSocketConnection sock,
1102 SilcPacketContext *packet)
1104 SilcBuffer buffer = packet->buffer;
1105 SilcPacketType type = packet->type;
1107 SILC_LOG_DEBUG(("Parsing %s packet", silc_get_packet_name(type)));
1109 /* Parse the packet type */
1112 case SILC_PACKET_DISCONNECT:
1113 silc_client_disconnected_by_server(client, sock, buffer);
1116 case SILC_PACKET_SUCCESS:
1118 * Success received for something. For now we can have only
1119 * one protocol for connection executing at once hence this
1120 * success message is for whatever protocol is executing currently.
1123 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1126 case SILC_PACKET_FAILURE:
1128 * Failure received for some protocol. Set the protocol state to
1129 * error and call the protocol callback. This fill cause error on
1130 * protocol and it will call the final callback.
1132 silc_client_process_failure(client, sock, packet);
1135 case SILC_PACKET_REJECT:
1138 case SILC_PACKET_NOTIFY:
1140 * Received notify message
1142 silc_client_notify_by_server(client, sock, packet);
1145 case SILC_PACKET_ERROR:
1147 * Received error message
1149 silc_client_error_by_server(client, sock, buffer);
1152 case SILC_PACKET_CHANNEL_MESSAGE:
1154 * Received message to (from, actually) a channel
1156 silc_client_channel_message(client, sock, packet);
1159 case SILC_PACKET_CHANNEL_KEY:
1161 * Received key for a channel. By receiving this key the client will be
1162 * able to talk to the channel it has just joined. This can also be
1163 * a new key for existing channel as keys expire peridiocally.
1165 silc_client_receive_channel_key(client, sock, buffer);
1168 case SILC_PACKET_PRIVATE_MESSAGE:
1170 * Received private message
1172 silc_client_private_message(client, sock, packet);
1175 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1177 * Received private message key indicator
1179 silc_client_private_message_key(client, sock, packet);
1182 case SILC_PACKET_COMMAND:
1184 * Received command packet, a special case since normally client
1185 * does not receive commands.
1187 silc_client_command_process(client, sock, packet);
1190 case SILC_PACKET_COMMAND_REPLY:
1192 * Recived reply for a command
1194 silc_client_command_reply_process(client, sock, packet);
1197 case SILC_PACKET_KEY_EXCHANGE:
1198 if (sock->protocol && sock->protocol->protocol &&
1199 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
1200 SilcClientKEInternalContext *proto_ctx =
1201 (SilcClientKEInternalContext *)sock->protocol->context;
1203 proto_ctx->packet = silc_packet_context_dup(packet);
1204 proto_ctx->dest_id_type = packet->src_id_type;
1205 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1206 packet->src_id_type);
1207 if (!proto_ctx->dest_id)
1210 /* Let the protocol handle the packet */
1211 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1213 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1214 "protocol active, packet dropped."));
1218 case SILC_PACKET_KEY_EXCHANGE_1:
1219 if (sock->protocol && sock->protocol->protocol &&
1220 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1221 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1223 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1224 SilcClientRekeyInternalContext *proto_ctx =
1225 (SilcClientRekeyInternalContext *)sock->protocol->context;
1227 if (proto_ctx->packet)
1228 silc_packet_context_free(proto_ctx->packet);
1230 proto_ctx->packet = silc_packet_context_dup(packet);
1232 /* Let the protocol handle the packet */
1233 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1235 SilcClientKEInternalContext *proto_ctx =
1236 (SilcClientKEInternalContext *)sock->protocol->context;
1238 if (proto_ctx->packet)
1239 silc_packet_context_free(proto_ctx->packet);
1241 proto_ctx->packet = silc_packet_context_dup(packet);
1242 proto_ctx->dest_id_type = packet->src_id_type;
1243 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1244 packet->src_id_type);
1245 if (!proto_ctx->dest_id)
1248 /* Let the protocol handle the packet */
1249 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1252 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1253 "protocol active, packet dropped."));
1257 case SILC_PACKET_KEY_EXCHANGE_2:
1258 if (sock->protocol && sock->protocol->protocol &&
1259 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1260 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1262 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1263 SilcClientRekeyInternalContext *proto_ctx =
1264 (SilcClientRekeyInternalContext *)sock->protocol->context;
1266 if (proto_ctx->packet)
1267 silc_packet_context_free(proto_ctx->packet);
1269 proto_ctx->packet = silc_packet_context_dup(packet);
1271 /* Let the protocol handle the packet */
1272 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1274 SilcClientKEInternalContext *proto_ctx =
1275 (SilcClientKEInternalContext *)sock->protocol->context;
1277 if (proto_ctx->packet)
1278 silc_packet_context_free(proto_ctx->packet);
1279 if (proto_ctx->dest_id)
1280 silc_free(proto_ctx->dest_id);
1281 proto_ctx->packet = silc_packet_context_dup(packet);
1282 proto_ctx->dest_id_type = packet->src_id_type;
1283 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1284 packet->src_id_type);
1285 if (!proto_ctx->dest_id)
1288 /* Let the protocol handle the packet */
1289 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1292 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1293 "protocol active, packet dropped."));
1297 case SILC_PACKET_NEW_ID:
1300 * Received new ID from server. This packet is received at
1301 * the connection to the server. New ID is also received when
1302 * user changes nickname but in that case the new ID is received
1303 * as command reply and not as this packet type.
1307 idp = silc_id_payload_parse(buffer->data, buffer->len);
1310 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1313 silc_client_receive_new_id(client, sock, idp);
1314 silc_id_payload_free(idp);
1318 case SILC_PACKET_HEARTBEAT:
1320 * Received heartbeat packet
1322 SILC_LOG_DEBUG(("Heartbeat packet"));
1325 case SILC_PACKET_KEY_AGREEMENT:
1327 * Received key agreement packet
1329 SILC_LOG_DEBUG(("Key agreement packet"));
1330 silc_client_key_agreement(client, sock, packet);
1333 case SILC_PACKET_REKEY:
1334 SILC_LOG_DEBUG(("Re-key packet"));
1335 /* We ignore this for now */
1338 case SILC_PACKET_REKEY_DONE:
1339 SILC_LOG_DEBUG(("Re-key done packet"));
1341 if (sock->protocol && sock->protocol->protocol &&
1342 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1344 SilcClientRekeyInternalContext *proto_ctx =
1345 (SilcClientRekeyInternalContext *)sock->protocol->context;
1347 if (proto_ctx->packet)
1348 silc_packet_context_free(proto_ctx->packet);
1350 proto_ctx->packet = silc_packet_context_dup(packet);
1352 /* Let the protocol handle the packet */
1353 if (proto_ctx->responder == FALSE)
1354 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1356 /* Let the protocol handle the packet */
1357 silc_protocol_execute(sock->protocol, client->schedule,
1360 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1361 "protocol active, packet dropped."));
1365 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1367 * Reveived reply to our connection authentication method request
1368 * packet. This is used to resolve the authentication method for the
1369 * current session from the server if the client does not know it.
1371 silc_client_connection_auth_request(client, sock, packet);
1374 case SILC_PACKET_FTP:
1375 /* Received file transfer packet. */
1376 silc_client_ftp(client, sock, packet);
1380 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1385 /* Sends packet. This doesn't actually send the packet instead it assembles
1386 it and marks it to be sent. However, if force_send is TRUE the packet
1387 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1388 will be derived from sock argument. Otherwise the valid arguments sent
1391 void silc_client_packet_send(SilcClient client,
1392 SilcSocketConnection sock,
1393 SilcPacketType type,
1395 SilcIdType dst_id_type,
1398 unsigned char *data,
1399 SilcUInt32 data_len,
1402 SilcPacketContext packetdata;
1403 const SilcBufferStruct packet;
1405 SilcUInt32 sequence = 0;
1410 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1412 /* Get data used in the packet sending, keys and stuff */
1413 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1414 if (!cipher && ((SilcClientConnection)sock->user_data)->internal->send_key)
1415 cipher = ((SilcClientConnection)sock->user_data)->internal->send_key;
1417 if (!hmac && ((SilcClientConnection)sock->user_data)->internal->hmac_send)
1418 hmac = ((SilcClientConnection)sock->user_data)->internal->hmac_send;
1420 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1421 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1422 dst_id_type = SILC_ID_SERVER;
1426 sequence = ((SilcClientConnection)sock->user_data)->internal->psn_send++;
1428 /* Check for mandatory rekey */
1429 if (sequence == SILC_CLIENT_REKEY_THRESHOLD)
1430 silc_schedule_task_add(client->schedule, sock->sock,
1431 silc_client_rekey_callback, sock, 0, 1,
1432 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1435 block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1437 /* Set the packet context pointers */
1438 packetdata.flags = 0;
1439 packetdata.type = type;
1440 if (sock->user_data &&
1441 ((SilcClientConnection)sock->user_data)->local_id_data) {
1442 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1443 packetdata.src_id_len =
1444 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1447 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1448 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1450 packetdata.src_id_type = SILC_ID_CLIENT;
1452 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1453 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1454 packetdata.dst_id_type = dst_id_type;
1456 packetdata.dst_id = NULL;
1457 packetdata.dst_id_len = 0;
1458 packetdata.dst_id_type = SILC_ID_NONE;
1460 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1461 packetdata.src_id_len +
1462 packetdata.dst_id_len));
1463 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1464 packetdata.src_id_len + packetdata.dst_id_len;
1465 if (type == SILC_PACKET_CONNECTION_AUTH)
1466 SILC_PACKET_PADLEN_MAX(packetdata.truelen, block_len, packetdata.padlen);
1468 SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
1470 /* Create the outgoing packet */
1471 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
1472 data, data_len, (const SilcBuffer)&packet)) {
1473 SILC_LOG_ERROR(("Error assembling packet"));
1477 /* Encrypt the packet */
1479 silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet,
1482 SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
1483 packet.data, packet.len);
1485 /* Now actually send the packet */
1486 silc_client_packet_send_real(client, sock, force_send);
1489 /* Packet sending routine for application. This is the only routine that
1490 is provided for application to send SILC packets. */
1492 bool silc_client_send_packet(SilcClient client,
1493 SilcClientConnection conn,
1494 SilcPacketType type,
1495 const unsigned char *data,
1496 SilcUInt32 data_len)
1503 silc_client_packet_send(client, conn->sock, type, NULL, 0, NULL, NULL,
1504 (unsigned char *)data, data_len, TRUE);
1508 void silc_client_packet_queue_purge(SilcClient client,
1509 SilcSocketConnection sock)
1511 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1512 !(SILC_IS_DISCONNECTED(sock))) {
1515 ret = silc_packet_send(sock, TRUE);
1517 if (sock->outbuf && sock->outbuf->len > 0) {
1518 /* Couldn't send all data, put the queue back up, we'll send
1520 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
1521 SILC_SET_OUTBUF_PENDING(sock);
1526 /* Purged all data */
1527 SILC_UNSET_OUTBUF_PENDING(sock);
1528 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1529 silc_buffer_clear(sock->outbuf);
1533 /* Closes connection to remote end. Free's all allocated data except
1534 for some information such as nickname etc. that are valid at all time.
1535 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1536 provided it will be checked whether the sock and `conn->sock' are the
1537 same (they can be different, ie. a socket can use `conn' as its
1538 connection but `conn->sock' might be actually a different connection
1539 than the `sock'). */
1541 void silc_client_close_connection_real(SilcClient client,
1542 SilcSocketConnection sock,
1543 SilcClientConnection conn)
1547 SILC_LOG_DEBUG(("Start"));
1552 if (!sock || (sock && conn->sock == sock))
1559 silc_client_del_connection(client, conn);
1563 /* We won't listen for this connection anymore */
1564 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1566 /* Unregister all tasks */
1567 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1569 /* Close the actual connection */
1570 silc_net_close_connection(sock->sock);
1572 /* Cancel any active protocol */
1573 if (sock->protocol) {
1574 if (sock->protocol->protocol->type ==
1575 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1576 sock->protocol->protocol->type ==
1577 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1578 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1579 silc_protocol_execute_final(sock->protocol, client->schedule);
1580 /* The application will recall this function with these protocols
1581 (the ops->connected client operation). */
1584 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1585 silc_protocol_execute_final(sock->protocol, client->schedule);
1586 sock->protocol = NULL;
1590 /* Free everything */
1591 if (del && sock->user_data)
1592 silc_client_del_connection(client, conn);
1594 silc_socket_free(sock);
1597 /* Closes the connection to the remote end */
1599 void silc_client_close_connection(SilcClient client,
1600 SilcClientConnection conn)
1602 silc_client_close_connection_real(client, NULL, conn);
1605 /* Called when we receive disconnection packet from server. This
1606 closes our end properly and displays the reason of the disconnection
1609 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1611 SilcClient client = (SilcClient)context;
1612 SilcSocketConnection sock;
1614 SILC_CLIENT_GET_SOCK(client, fd, sock);
1618 silc_client_close_connection_real(client, sock, sock->user_data);
1621 /* Called when we receive disconnection packet from server. This
1622 closes our end properly and displays the reason of the disconnection
1625 void silc_client_disconnected_by_server(SilcClient client,
1626 SilcSocketConnection sock,
1629 SilcClientConnection conn;
1631 char *message = NULL;
1633 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1635 if (packet->len < 1)
1638 status = (SilcStatus)packet->data[0];
1640 if (packet->len > 1 &&
1641 silc_utf8_valid(packet->data + 1, packet->len - 1))
1642 message = silc_memdup(packet->data + 1, packet->len - 1);
1644 conn = (SilcClientConnection)sock->user_data;
1645 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1646 client->internal->ops->disconnected(client, conn, status, message);
1650 SILC_SET_DISCONNECTED(sock);
1652 /* Close connection through scheduler. */
1653 silc_schedule_task_add(client->schedule, sock->sock,
1654 silc_client_disconnected_by_server_later,
1655 client, 0, 1, SILC_TASK_TIMEOUT,
1656 SILC_TASK_PRI_NORMAL);
1659 /* Received error message from server. Display it on the screen.
1660 We don't take any action what so ever of the error message. */
1662 void silc_client_error_by_server(SilcClient client,
1663 SilcSocketConnection sock,
1668 msg = silc_memdup(message->data, message->len);
1669 client->internal->ops->say(client, sock->user_data,
1670 SILC_CLIENT_MESSAGE_AUDIT, msg);
1674 /* Auto-nicking callback to send NICK command to server. */
1676 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1678 SilcClientConnection conn = (SilcClientConnection)context;
1679 SilcClient client = conn->client;
1681 silc_client_command_send(client, conn, SILC_COMMAND_NICK,
1682 ++conn->cmd_ident, 1, 1,
1683 client->nickname, strlen(client->nickname));
1686 /* Client session resuming callback. If the session was resumed
1687 this callback is called after the resuming is completed. This
1688 will call the `connect' client operation to the application
1689 since it has not been called yet. */
1691 static void silc_client_resume_session_cb(SilcClient client,
1692 SilcClientConnection conn,
1698 /* Notify application that connection is created to server */
1699 client->internal->ops->connected(client, conn, success ?
1700 SILC_CLIENT_CONN_SUCCESS_RESUME :
1701 SILC_CLIENT_CONN_ERROR_RESUME);
1704 /* Issue INFO command to fetch the real server name and server
1705 information and other stuff. */
1706 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1707 silc_client_command_reply_info_i, 0,
1709 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1710 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1711 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1712 silc_buffer_free(sidp);
1716 /* Processes the received new Client ID from server. Old Client ID is
1717 deleted from cache and new one is added. */
1719 void silc_client_receive_new_id(SilcClient client,
1720 SilcSocketConnection sock,
1723 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1724 int connecting = FALSE;
1725 SilcClientID *client_id = silc_id_payload_get_id(idp);
1727 if (!conn->local_entry)
1730 /* Delete old ID from ID cache */
1731 if (conn->local_id) {
1732 /* Check whether they are different */
1733 if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1734 silc_free(client_id);
1738 silc_idcache_del_by_context(conn->internal->client_cache,
1740 silc_free(conn->local_id);
1743 /* Save the new ID */
1745 if (conn->local_id_data)
1746 silc_free(conn->local_id_data);
1748 conn->local_id = client_id;
1749 conn->local_id_data = silc_id_payload_get_data(idp);
1750 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1752 if (!conn->local_entry)
1753 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1755 conn->local_entry->nickname = conn->nickname;
1756 if (!conn->local_entry->username)
1757 conn->local_entry->username = strdup(client->username);
1758 if (!conn->local_entry->server)
1759 conn->local_entry->server = strdup(conn->remote_host);
1760 conn->local_entry->id = conn->local_id;
1761 conn->local_entry->valid = TRUE;
1762 if (!conn->local_entry->channels)
1763 conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
1768 /* Put it to the ID cache */
1769 silc_idcache_add(conn->internal->client_cache,
1770 strdup(conn->nickname), conn->local_id,
1771 (void *)conn->local_entry, 0, NULL);
1776 /* Issue IDENTIFY command for itself to get resolved hostname
1777 correctly from server. */
1778 silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
1779 silc_client_command_reply_identify_i, 0,
1781 sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT);
1782 silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
1783 conn->cmd_ident, 1, 5, sidp->data, sidp->len);
1784 silc_buffer_free(sidp);
1786 if (!conn->internal->params.detach_data) {
1787 /* Send NICK command if the nickname was set by the application (and is
1788 not same as the username). Send this with little timeout. */
1789 if (client->nickname && strcmp(client->nickname, client->username))
1790 silc_schedule_task_add(client->schedule, 0,
1791 silc_client_send_auto_nick, conn,
1792 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1794 /* Notify application of successful connection. We do it here now that
1795 we've received the Client ID and are allowed to send traffic. */
1796 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_SUCCESS);
1798 /* Issue INFO command to fetch the real server name and server
1799 information and other stuff. */
1800 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1801 silc_client_command_reply_info_i, 0,
1803 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1804 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1805 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1806 silc_buffer_free(sidp);
1808 /* We are resuming session. Start resolving informations from the
1809 server we need to set the client libary in the state before
1810 detaching the session. The connect client operation is called
1811 after this is successfully completed */
1812 silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1818 /* Removes a client entry from all channels it has joined. */
1820 void silc_client_remove_from_channels(SilcClient client,
1821 SilcClientConnection conn,
1822 SilcClientEntry client_entry)
1824 SilcHashTableList htl;
1825 SilcChannelUser chu;
1827 silc_hash_table_list(client_entry->channels, &htl);
1828 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1829 silc_hash_table_del(chu->client->channels, chu->channel);
1830 silc_hash_table_del(chu->channel->user_list, chu->client);
1834 silc_hash_table_list_reset(&htl);
1837 /* Replaces `old' client entries from all channels to `new' client entry.
1838 This can be called for example when nickname changes and old ID entry
1839 is replaced from ID cache with the new one. If the old ID entry is only
1840 updated, then this fucntion needs not to be called. */
1842 void silc_client_replace_from_channels(SilcClient client,
1843 SilcClientConnection conn,
1844 SilcClientEntry old,
1845 SilcClientEntry new)
1847 SilcHashTableList htl;
1848 SilcChannelUser chu;
1850 silc_hash_table_list(old->channels, &htl);
1851 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1852 /* Replace client entry */
1853 silc_hash_table_del(chu->client->channels, chu->channel);
1854 silc_hash_table_del(chu->channel->user_list, chu->client);
1857 silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1858 silc_hash_table_add(chu->client->channels, chu->channel, chu);
1860 silc_hash_table_list_reset(&htl);
1863 /* Registers failure timeout to process the received failure packet
1866 void silc_client_process_failure(SilcClient client,
1867 SilcSocketConnection sock,
1868 SilcPacketContext *packet)
1870 SilcUInt32 failure = 0;
1872 if (sock->protocol) {
1873 if (packet->buffer->len >= 4)
1874 SILC_GET32_MSB(failure, packet->buffer->data);
1876 /* Notify application */
1877 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1878 SILC_32_TO_PTR(failure));
1882 /* A timeout callback for the re-key. We will be the initiator of the
1885 SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback)
1887 SilcSocketConnection sock = (SilcSocketConnection)context;
1888 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1889 SilcClient client = (SilcClient)conn->internal->rekey->context;
1890 SilcProtocol protocol;
1891 SilcClientRekeyInternalContext *proto_ctx;
1893 SILC_LOG_DEBUG(("Start"));
1895 /* If rekey protocol is active already wait for it to finish */
1896 if (sock->protocol && sock->protocol->protocol &&
1897 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)
1900 /* Allocate internal protocol context. This is sent as context
1902 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1903 proto_ctx->client = (void *)client;
1904 proto_ctx->sock = silc_socket_dup(sock);
1905 proto_ctx->responder = FALSE;
1906 proto_ctx->pfs = conn->internal->rekey->pfs;
1908 /* Perform rekey protocol. Will call the final callback after the
1909 protocol is over. */
1910 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1911 &protocol, proto_ctx, silc_client_rekey_final);
1912 sock->protocol = protocol;
1914 /* Run the protocol */
1915 silc_protocol_execute(protocol, client->schedule, 0, 0);
1918 /* The final callback for the REKEY protocol. This will actually take the
1919 new key material into use. */
1921 SILC_TASK_CALLBACK(silc_client_rekey_final)
1923 SilcProtocol protocol = (SilcProtocol)context;
1924 SilcClientRekeyInternalContext *ctx =
1925 (SilcClientRekeyInternalContext *)protocol->context;
1926 SilcClient client = (SilcClient)ctx->client;
1927 SilcSocketConnection sock = ctx->sock;
1928 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1930 SILC_LOG_DEBUG(("Start"));
1932 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1933 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1934 /* Error occured during protocol */
1935 silc_protocol_cancel(protocol, client->schedule);
1936 silc_protocol_free(protocol);
1937 sock->protocol = NULL;
1939 silc_packet_context_free(ctx->packet);
1941 silc_ske_free(ctx->ske);
1942 silc_socket_free(ctx->sock);
1947 /* Purge the outgoing data queue to assure that all rekey packets really
1948 go to the network before we quit the protocol. */
1949 silc_client_packet_queue_purge(client, sock);
1951 /* Re-register re-key timeout */
1952 if (ctx->responder == FALSE)
1953 silc_schedule_task_add(client->schedule, sock->sock,
1954 silc_client_rekey_callback,
1955 sock, conn->internal->rekey->timeout, 0,
1956 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1959 silc_protocol_free(protocol);
1960 sock->protocol = NULL;
1962 silc_packet_context_free(ctx->packet);
1964 silc_ske_free(ctx->ske);
1965 silc_socket_free(ctx->sock);
1969 /* Processes incoming connection authentication method request packet.
1970 It is a reply to our previously sent request. The packet can be used
1971 to resolve the authentication method for the current session if the
1972 client does not know it beforehand. */
1974 void silc_client_connection_auth_request(SilcClient client,
1975 SilcSocketConnection sock,
1976 SilcPacketContext *packet)
1978 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1979 SilcUInt16 conn_type, auth_meth;
1982 /* If we haven't send our request then ignore this one. */
1983 if (!conn->internal->connauth)
1986 /* Parse the payload */
1987 ret = silc_buffer_unformat(packet->buffer,
1988 SILC_STR_UI_SHORT(&conn_type),
1989 SILC_STR_UI_SHORT(&auth_meth),
1992 auth_meth = SILC_AUTH_NONE;
1994 /* Call the request callback to notify application for received
1995 authentication method information. */
1996 if (conn->internal->connauth->callback)
1997 (*conn->internal->connauth->callback)(client, conn, auth_meth,
1998 conn->internal->connauth->context);
2000 silc_schedule_task_del(client->schedule, conn->internal->connauth->timeout);
2002 silc_free(conn->internal->connauth);
2003 conn->internal->connauth = NULL;
2006 /* Timeout task callback called if the server does not reply to our
2007 connection authentication method request in the specified time interval. */
2009 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
2011 SilcClientConnection conn = (SilcClientConnection)context;
2012 SilcClient client = conn->client;
2014 if (!conn->internal->connauth)
2017 /* Call the request callback to notify application */
2018 if (conn->internal->connauth->callback)
2019 (*conn->internal->connauth->callback)(client, conn, SILC_AUTH_NONE,
2020 conn->internal->connauth->context);
2022 silc_free(conn->internal->connauth);
2023 conn->internal->connauth = NULL;
2026 /* This function can be used to request the current authentication method
2027 from the server. This may be called when connecting to the server
2028 and the client library requests the authentication data from the
2029 application. If the application does not know the current authentication
2030 method it can request it from the server using this function.
2031 The `callback' with `context' will be called after the server has
2032 replied back with the current authentication method. */
2035 silc_client_request_authentication_method(SilcClient client,
2036 SilcClientConnection conn,
2037 SilcConnectionAuthRequest callback,
2040 SilcClientConnAuthRequest connauth;
2043 assert(client && conn);
2044 connauth = silc_calloc(1, sizeof(*connauth));
2045 connauth->callback = callback;
2046 connauth->context = context;
2048 if (conn->internal->connauth)
2049 silc_free(conn->internal->connauth);
2051 conn->internal->connauth = connauth;
2053 /* Assemble the request packet and send it to the server */
2054 packet = silc_buffer_alloc(4);
2055 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
2056 silc_buffer_format(packet,
2057 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
2058 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
2060 silc_client_packet_send(client, conn->sock,
2061 SILC_PACKET_CONNECTION_AUTH_REQUEST,
2062 NULL, 0, NULL, NULL,
2063 packet->data, packet->len, FALSE);
2064 silc_buffer_free(packet);
2066 /* Register a timeout in case server does not reply anything back. */
2068 silc_schedule_task_add(client->schedule, conn->sock->sock,
2069 silc_client_request_authentication_method_timeout,
2071 client->internal->params->connauth_request_secs, 0,
2072 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);