5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "silcincludes.h"
22 #include "silcclient.h"
23 #include "client_internal.h"
25 /* Static task callback prototypes */
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
28 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
29 SILC_TASK_CALLBACK(silc_client_rekey_final);
31 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
33 static void silc_client_packet_parse_type(SilcClient client,
34 SilcSocketConnection sock,
35 SilcPacketContext *packet);
36 void silc_client_resolve_auth_method(bool success,
37 SilcProtocolAuthMeth auth_meth,
38 const unsigned char *auth_data,
39 SilcUInt32 auth_data_len, void *context);
41 /* Allocates new client object. This has to be done before client may
42 work. After calling this one must call silc_client_init to initialize
43 the client. The `application' is application specific user data pointer
44 and caller must free it. */
46 SilcClient silc_client_alloc(SilcClientOperations *ops,
47 SilcClientParams *params,
49 const char *version_string)
51 SilcClient new_client;
53 new_client = silc_calloc(1, sizeof(*new_client));
54 new_client->application = application;
56 new_client->internal = silc_calloc(1, sizeof(*new_client->internal));
57 new_client->internal->ops = ops;
58 new_client->internal->params =
59 silc_calloc(1, sizeof(*new_client->internal->params));
61 version_string = silc_version_string;
62 new_client->internal->silc_client_version = strdup(version_string);
65 memcpy(new_client->internal->params, params, sizeof(*params));
67 if (!new_client->internal->params->task_max)
68 new_client->internal->params->task_max = 200;
70 if (!new_client->internal->params->rekey_secs)
71 new_client->internal->params->rekey_secs = 3600;
73 if (!new_client->internal->params->connauth_request_secs)
74 new_client->internal->params->connauth_request_secs = 2;
76 new_client->internal->params->
77 nickname_format[sizeof(new_client->internal->
78 params->nickname_format) - 1] = 0;
83 /* Frees client object and its internals. */
85 void silc_client_free(SilcClient client)
89 silc_rng_free(client->rng);
91 silc_cipher_unregister_all();
92 silc_pkcs_unregister_all();
93 silc_hash_unregister_all();
94 silc_hmac_unregister_all();
96 silc_hash_free(client->md5hash);
97 silc_hash_free(client->sha1hash);
98 silc_hmac_free(client->internal->md5hmac);
99 silc_hmac_free(client->internal->sha1hmac);
100 silc_cipher_free(client->internal->none_cipher);
101 silc_free(client->internal->params);
102 silc_free(client->internal->silc_client_version);
103 silc_free(client->internal);
108 /* Initializes the client. This makes all the necessary steps to make
109 the client ready to be run. One must call silc_client_run to run the
110 client. Returns FALSE if error occured, TRUE otherwise. */
112 bool silc_client_init(SilcClient client)
114 SILC_LOG_DEBUG(("Initializing client"));
117 assert(client->username);
118 assert(client->hostname);
119 assert(client->realname);
121 /* Initialize the crypto library. If application has done this already
122 this has no effect. Also, we will not be overriding something
123 application might have registered earlier. */
124 silc_cipher_register_default();
125 silc_pkcs_register_default();
126 silc_hash_register_default();
127 silc_hmac_register_default();
129 /* Initialize hash functions for client to use */
130 silc_hash_alloc("md5", &client->md5hash);
131 silc_hash_alloc("sha1", &client->sha1hash);
133 /* Initialize none cipher */
134 silc_cipher_alloc("none", &client->internal->none_cipher);
136 /* Initialize random number generator */
137 client->rng = silc_rng_alloc();
138 silc_rng_init(client->rng);
139 silc_rng_global_init(client->rng);
141 /* Register protocols */
142 silc_client_protocols_register();
144 /* Initialize the scheduler */
146 silc_schedule_init(client->internal->params->task_max ?
147 client->internal->params->task_max : 200, client);
148 if (!client->schedule)
151 /* Register commands */
152 silc_client_commands_register(client);
157 /* Stops the client. This is called to stop the client and thus to stop
160 void silc_client_stop(SilcClient client)
162 SILC_LOG_DEBUG(("Stopping client"));
164 silc_schedule_stop(client->schedule);
165 silc_schedule_uninit(client->schedule);
167 silc_client_protocols_unregister();
168 silc_client_commands_unregister(client);
170 SILC_LOG_DEBUG(("Client stopped"));
173 /* Runs the client. This starts the scheduler from the utility library.
174 When this functions returns the execution of the appliation is over. */
176 void silc_client_run(SilcClient client)
178 SILC_LOG_DEBUG(("Running client"));
181 assert(client->pkcs);
182 assert(client->public_key);
183 assert(client->private_key);
185 /* Start the scheduler, the heart of the SILC client. When this returns
186 the program will be terminated. */
187 silc_schedule(client->schedule);
190 /* Runs the client and returns immeadiately. This function is used when
191 the SILC Client object indicated by the `client' is run under some
192 other scheduler, or event loop or main loop. On GUI applications,
193 for example this may be desired to use to run the client under the
194 GUI application's main loop. Typically the GUI application would
195 register an idle task that calls this function multiple times in
196 a second to quickly process the SILC specific data. */
198 void silc_client_run_one(SilcClient client)
200 /* Run the scheduler once. */
201 silc_schedule_one(client->schedule, 0);
204 static void silc_client_entry_destructor(SilcIDCache cache,
205 SilcIDCacheEntry entry)
207 silc_free(entry->name);
210 /* Allocates and adds new connection to the client. This adds the allocated
211 connection to the connection table and returns a pointer to it. A client
212 can have multiple connections to multiple servers. Every connection must
213 be added to the client using this function. User data `context' may
214 be sent as argument. This function is normally used only if the
215 application performed the connecting outside the library. The library
216 however may use this internally. */
219 silc_client_add_connection(SilcClient client,
220 SilcClientConnectionParams *params,
221 char *hostname, int port, void *context)
223 SilcClientConnection conn;
226 SILC_LOG_DEBUG(("Adding new connection to %s:%d", hostname, port));
228 conn = silc_calloc(1, sizeof(*conn));
229 conn->internal = silc_calloc(1, sizeof(*conn->internal));
231 /* Initialize ID caches */
232 conn->client = client;
233 conn->remote_host = strdup(hostname);
234 conn->remote_port = port;
235 conn->context = context;
236 conn->internal->client_cache =
237 silc_idcache_alloc(0, SILC_ID_CLIENT, silc_client_entry_destructor);
238 conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
239 conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
240 conn->internal->pending_commands = silc_dlist_init();
241 conn->internal->ftp_sessions = silc_dlist_init();
244 if (params->detach_data)
245 conn->internal->params.detach_data =
246 silc_memdup(params->detach_data,
247 params->detach_data_len);
248 conn->internal->params.detach_data_len = params->detach_data_len;
251 /* Add the connection to connections table */
252 for (i = 0; i < client->internal->conns_count; i++)
253 if (client->internal->conns && !client->internal->conns[i]) {
254 client->internal->conns[i] = conn;
258 client->internal->conns =
259 silc_realloc(client->internal->conns, sizeof(*client->internal->conns)
260 * (client->internal->conns_count + 1));
261 client->internal->conns[client->internal->conns_count] = conn;
262 client->internal->conns_count++;
267 /* Removes connection from client. Frees all memory. */
269 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
273 for (i = 0; i < client->internal->conns_count; i++)
274 if (client->internal->conns[i] == conn) {
275 /* Free all cache entries */
276 SilcIDCacheList list;
277 SilcIDCacheEntry entry;
278 SilcClientCommandPending *r;
281 if (silc_idcache_get_all(conn->internal->client_cache, &list)) {
282 ret = silc_idcache_list_first(list, &entry);
284 silc_client_del_client(client, conn, entry->context);
285 ret = silc_idcache_list_next(list, &entry);
287 silc_idcache_list_free(list);
290 if (silc_idcache_get_all(conn->internal->channel_cache, &list)) {
291 ret = silc_idcache_list_first(list, &entry);
293 silc_client_del_channel(client, conn, entry->context);
294 ret = silc_idcache_list_next(list, &entry);
296 silc_idcache_list_free(list);
299 if (silc_idcache_get_all(conn->internal->server_cache, &list)) {
300 ret = silc_idcache_list_first(list, &entry);
302 silc_client_del_server(client, conn, entry->context);
303 ret = silc_idcache_list_next(list, &entry);
305 silc_idcache_list_free(list);
308 /* Clear ID caches */
309 if (conn->internal->client_cache)
310 silc_idcache_free(conn->internal->client_cache);
311 if (conn->internal->channel_cache)
312 silc_idcache_free(conn->internal->channel_cache);
313 if (conn->internal->server_cache)
314 silc_idcache_free(conn->internal->server_cache);
316 /* Free data (my ID is freed in above silc_client_del_client).
317 conn->nickname is freed when freeing the local_entry->nickname. */
318 silc_free(conn->remote_host);
319 silc_free(conn->local_id_data);
320 if (conn->internal->send_key)
321 silc_cipher_free(conn->internal->send_key);
322 if (conn->internal->receive_key)
323 silc_cipher_free(conn->internal->receive_key);
324 if (conn->internal->hmac_send)
325 silc_hmac_free(conn->internal->hmac_send);
326 if (conn->internal->hmac_receive)
327 silc_hmac_free(conn->internal->hmac_receive);
328 silc_free(conn->internal->rekey);
330 if (conn->internal->active_session) {
331 conn->sock->user_data = NULL;
332 silc_client_ftp_session_free(conn->internal->active_session);
333 conn->internal->active_session = NULL;
336 silc_client_ftp_free_sessions(client, conn);
338 if (conn->internal->pending_commands) {
339 silc_dlist_start(conn->internal->pending_commands);
340 while ((r = silc_dlist_get(conn->internal->pending_commands))
342 silc_dlist_del(conn->internal->pending_commands, r);
343 silc_dlist_uninit(conn->internal->pending_commands);
346 silc_free(conn->internal);
347 memset(conn, 0, sizeof(*conn));
350 client->internal->conns[i] = NULL;
354 /* Adds listener socket to the listener sockets table. This function is
355 used to add socket objects that are listeners to the client. This should
356 not be used to add other connection objects. */
358 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
362 if (!client->internal->sockets) {
363 client->internal->sockets =
364 silc_calloc(1, sizeof(*client->internal->sockets));
365 client->internal->sockets[0] = silc_socket_dup(sock);
366 client->internal->sockets_count = 1;
370 for (i = 0; i < client->internal->sockets_count; i++) {
371 if (client->internal->sockets[i] == NULL) {
372 client->internal->sockets[i] = silc_socket_dup(sock);
377 client->internal->sockets =
378 silc_realloc(client->internal->sockets,
379 sizeof(*client->internal->sockets) *
380 (client->internal->sockets_count + 1));
381 client->internal->sockets[client->internal->sockets_count] =
382 silc_socket_dup(sock);
383 client->internal->sockets_count++;
386 /* Deletes listener socket from the listener sockets table. */
388 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
392 if (!client->internal->sockets)
395 for (i = 0; i < client->internal->sockets_count; i++) {
396 if (client->internal->sockets[i] == sock) {
397 silc_socket_free(sock);
398 client->internal->sockets[i] = NULL;
405 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
409 /* XXX In the future we should give up this non-blocking connect all
410 together and use threads instead. */
411 /* Create connection to server asynchronously */
412 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
416 /* Register task that will receive the async connect and will
418 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
419 silc_client_connect_to_server_start,
422 SILC_TASK_PRI_NORMAL);
423 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE,
431 /* Connects to remote server. This is the main routine used to connect
432 to SILC server. Returns -1 on error and the created socket otherwise.
433 The `context' is user context that is saved into the SilcClientConnection
434 that is created after the connection is created. Note that application
435 may handle the connecting process outside the library. If this is the
436 case then this function is not used at all. When the connecting is
437 done the `connect' client operation is called. */
439 bool silc_client_connect_to_server(SilcClient client,
440 SilcClientConnectionParams *params,
441 int port, char *host, void *context)
443 SilcClientInternalConnectContext *ctx;
444 SilcClientConnection conn;
447 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
450 conn = silc_client_add_connection(client, params, host, port, context);
452 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
453 "Connecting to port %d of server %s", port, host);
455 /* Allocate internal context for connection process. This is
456 needed as we are doing async connecting. */
457 ctx = silc_calloc(1, sizeof(*ctx));
458 ctx->client = client;
460 ctx->host = strdup(host);
461 ctx->port = port ? port : 706;
464 /* Do the actual connecting process */
465 sock = silc_client_connect_to_server_internal(ctx);
467 silc_client_del_connection(client, conn);
471 /* Socket hostname and IP lookup callback that is called before actually
472 starting the key exchange. The lookup is called from the function
473 silc_client_start_key_exchange. */
475 static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
478 SilcClientConnection conn = (SilcClientConnection)context;
479 SilcClient client = conn->client;
480 SilcProtocol protocol;
481 SilcClientKEInternalContext *proto_ctx;
483 SILC_LOG_DEBUG(("Start"));
485 if (conn->sock->hostname) {
486 silc_free(conn->remote_host);
487 conn->remote_host = strdup(conn->sock->hostname);
489 conn->sock->hostname = strdup(conn->remote_host);
492 conn->sock->ip = strdup(conn->sock->hostname);
493 conn->sock->port = conn->remote_port;
495 /* Allocate internal Key Exchange context. This is sent to the
496 protocol as context. */
497 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
498 proto_ctx->client = (void *)client;
499 proto_ctx->sock = silc_socket_dup(conn->sock);
500 proto_ctx->rng = client->rng;
501 proto_ctx->responder = FALSE;
502 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
503 proto_ctx->verify = silc_client_protocol_ke_verify_key;
505 /* Perform key exchange protocol. silc_client_connect_to_server_final
506 will be called after the protocol is finished. */
507 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
508 &protocol, (void *)proto_ctx,
509 silc_client_connect_to_server_second);
511 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
512 "Error: Could not start key exchange protocol");
513 silc_net_close_connection(conn->sock->sock);
514 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
517 conn->sock->protocol = protocol;
519 /* Register the connection for network input and output. This sets
520 that scheduler will listen for incoming packets for this connection
521 and sets that outgoing packets may be sent to this connection as well.
522 However, this doesn't set the scheduler for outgoing traffic, it will
523 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
524 later when outgoing data is available. */
525 context = (void *)client;
526 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(conn->sock->sock);
528 /* Execute the protocol */
529 silc_protocol_execute(protocol, client->schedule, 0, 0);
532 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
533 key material between client and server. This function can be called
534 directly if application is performing its own connecting and does not
535 use the connecting provided by this library. This function is normally
536 used only if the application performed the connecting outside the library.
537 The library however may use this internally. */
539 void silc_client_start_key_exchange(SilcClient client,
540 SilcClientConnection conn,
543 assert(client->pkcs);
544 assert(client->public_key);
545 assert(client->private_key);
547 /* Allocate new socket connection object */
548 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
550 /* Sometimes when doing quick reconnects the new socket may be same as
551 the old one and there might be pending stuff for the old socket.
552 If new one is same then those pending sutff might cause problems.
553 Make sure they do not do that. */
554 silc_schedule_task_del_by_fd(client->schedule, fd);
556 conn->nickname = (client->nickname ? strdup(client->nickname) :
557 strdup(client->username));
559 /* Resolve the remote hostname and IP address for our socket connection */
560 silc_socket_host_lookup(conn->sock, FALSE, silc_client_start_key_exchange_cb,
561 conn, client->schedule);
564 /* Callback called when error has occurred during connecting (KE) to
565 the server. The `connect' client operation will be called. */
567 SILC_TASK_CALLBACK(silc_client_connect_failure)
569 SilcClientKEInternalContext *ctx =
570 (SilcClientKEInternalContext *)context;
571 SilcClient client = (SilcClient)ctx->client;
573 client->internal->ops->connected(client, ctx->sock->user_data,
574 SILC_CLIENT_CONN_ERROR);
576 silc_packet_context_free(ctx->packet);
580 /* Callback called when error has occurred during connecting (auth) to
581 the server. The `connect' client operation will be called. */
583 SILC_TASK_CALLBACK(silc_client_connect_failure_auth)
585 SilcClientConnAuthInternalContext *ctx =
586 (SilcClientConnAuthInternalContext *)context;
587 SilcClient client = (SilcClient)ctx->client;
589 client->internal->ops->connected(client, ctx->sock->user_data,
590 SILC_CLIENT_CONN_ERROR);
594 /* Start of the connection to the remote server. This is called after
595 succesful TCP/IP connection has been established to the remote host. */
597 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
599 SilcClientInternalConnectContext *ctx =
600 (SilcClientInternalConnectContext *)context;
601 SilcClient client = ctx->client;
602 SilcClientConnection conn = ctx->conn;
603 int opt, opt_len = sizeof(opt);
605 SILC_LOG_DEBUG(("Start"));
607 /* Check the socket status as it might be in error */
608 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
610 if (ctx->tries < 2) {
611 /* Connection failed but lets try again */
612 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
613 "Could not connect to server %s: %s",
614 ctx->host, strerror(opt));
615 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
616 "Connecting to port %d of server %s resumed",
617 ctx->port, ctx->host);
619 /* Unregister old connection try */
620 silc_schedule_unset_listen_fd(client->schedule, fd);
621 silc_net_close_connection(fd);
622 silc_schedule_task_del(client->schedule, ctx->task);
625 silc_client_connect_to_server_internal(ctx);
628 /* Connection failed and we won't try anymore */
629 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
630 "Could not connect to server %s: %s",
631 ctx->host, strerror(opt));
632 silc_schedule_unset_listen_fd(client->schedule, fd);
633 silc_net_close_connection(fd);
634 silc_schedule_task_del(client->schedule, ctx->task);
637 /* Notify application of failure */
638 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
643 silc_schedule_unset_listen_fd(client->schedule, fd);
644 silc_schedule_task_del(client->schedule, ctx->task);
647 silc_client_start_key_exchange(client, conn, fd);
650 /* Second part of the connecting to the server. This executed
651 authentication protocol. */
653 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
655 SilcProtocol protocol = (SilcProtocol)context;
656 SilcClientKEInternalContext *ctx =
657 (SilcClientKEInternalContext *)protocol->context;
658 SilcClient client = (SilcClient)ctx->client;
659 SilcSocketConnection sock = NULL;
660 SilcClientConnAuthInternalContext *proto_ctx;
662 SILC_LOG_DEBUG(("Start"));
664 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
665 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
666 /* Error occured during protocol */
667 SILC_LOG_DEBUG(("Error during KE protocol"));
668 silc_protocol_free(protocol);
669 silc_ske_free_key_material(ctx->keymat);
671 silc_ske_free(ctx->ske);
673 silc_free(ctx->dest_id);
674 ctx->sock->protocol = NULL;
675 silc_socket_free(ctx->sock);
677 /* Notify application of failure */
678 silc_schedule_task_add(client->schedule, ctx->sock->sock,
679 silc_client_connect_failure, ctx,
680 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
684 /* We now have the key material as the result of the key exchange
685 protocol. Take the key material into use. Free the raw key material
686 as soon as we've set them into use. */
687 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
688 ctx->ske->prop->cipher,
689 ctx->ske->prop->pkcs,
690 ctx->ske->prop->hash,
691 ctx->ske->prop->hmac,
692 ctx->ske->prop->group,
694 silc_ske_free_key_material(ctx->keymat);
696 /* Allocate internal context for the authentication protocol. This
697 is sent as context for the protocol. */
698 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
699 proto_ctx->client = (void *)client;
700 proto_ctx->sock = sock = ctx->sock;
701 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
702 proto_ctx->dest_id_type = ctx->dest_id_type;
703 proto_ctx->dest_id = ctx->dest_id;
705 /* Free old protocol as it is finished now */
706 silc_protocol_free(protocol);
708 silc_packet_context_free(ctx->packet);
711 sock->protocol = NULL;
713 /* Resolve the authentication method to be used in this connection. The
714 completion callback is called after the application has resolved
715 the authentication method. */
716 client->internal->ops->get_auth_method(client, sock->user_data,
719 silc_client_resolve_auth_method,
723 /* Authentication method resolving callback. Application calls this function
724 after we've called the client->internal->ops->get_auth_method
725 client operation to resolve the authentication method. We will continue
726 the executiong of the protocol in this function. */
728 void silc_client_resolve_auth_method(bool success,
729 SilcProtocolAuthMeth auth_meth,
730 const unsigned char *auth_data,
731 SilcUInt32 auth_data_len, void *context)
733 SilcClientConnAuthInternalContext *proto_ctx =
734 (SilcClientConnAuthInternalContext *)context;
735 SilcClient client = (SilcClient)proto_ctx->client;
738 auth_meth = SILC_AUTH_NONE;
740 proto_ctx->auth_meth = auth_meth;
742 if (success && auth_data && auth_data_len) {
744 /* Passphrase must be UTF-8 encoded, if it isn't encode it */
745 if (auth_meth == SILC_AUTH_PASSWORD &&
746 !silc_utf8_valid(auth_data, auth_data_len)) {
748 unsigned char *autf8 = NULL;
749 payload_len = silc_utf8_encoded_len(auth_data, auth_data_len,
751 autf8 = silc_calloc(payload_len, sizeof(*autf8));
752 auth_data_len = silc_utf8_encode(auth_data, auth_data_len,
753 SILC_STRING_ASCII, autf8, payload_len);
757 proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
758 proto_ctx->auth_data_len = auth_data_len;
761 /* Allocate the authenteication protocol and execute it. */
762 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
763 &proto_ctx->sock->protocol, (void *)proto_ctx,
764 silc_client_connect_to_server_final);
766 /* Execute the protocol */
767 silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
770 /* Finalizes the connection to the remote SILC server. This is called
771 after authentication protocol has been completed. This send our
772 user information to the server to receive our client ID from
775 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
777 SilcProtocol protocol = (SilcProtocol)context;
778 SilcClientConnAuthInternalContext *ctx =
779 (SilcClientConnAuthInternalContext *)protocol->context;
780 SilcClient client = (SilcClient)ctx->client;
781 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
784 SILC_LOG_DEBUG(("Start"));
786 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
787 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
788 /* Error occured during protocol */
789 SILC_LOG_DEBUG(("Error during authentication protocol"));
793 if (conn->internal->params.detach_data) {
794 /* Send RESUME_CLIENT packet to the server, which is used to resume
795 old detached session back. */
797 SilcClientID *old_client_id;
798 unsigned char *old_id;
799 SilcUInt16 old_id_len;
801 if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len))
804 old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT);
805 if (!old_client_id) {
810 /* Generate authentication data that server will verify */
811 auth = silc_auth_public_key_auth_generate(client->public_key,
814 conn->internal->hash,
815 old_client_id, SILC_ID_CLIENT);
817 silc_free(old_client_id);
822 packet = silc_buffer_alloc_size(2 + old_id_len + auth->len);
823 silc_buffer_format(packet,
824 SILC_STR_UI_SHORT(old_id_len),
825 SILC_STR_UI_XNSTRING(old_id, old_id_len),
826 SILC_STR_UI_XNSTRING(auth->data, auth->len),
829 /* Send the packet */
830 silc_client_packet_send(client, ctx->sock, SILC_PACKET_RESUME_CLIENT,
832 packet->data, packet->len, TRUE);
833 silc_buffer_free(packet);
834 silc_buffer_free(auth);
835 silc_free(old_client_id);
838 /* Send NEW_CLIENT packet to the server. We will become registered
839 to the SILC network after sending this packet and we will receive
840 client ID from the server. */
841 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
842 strlen(client->realname));
843 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
844 silc_buffer_format(packet,
845 SILC_STR_UI_SHORT(strlen(client->username)),
846 SILC_STR_UI_XNSTRING(client->username,
847 strlen(client->username)),
848 SILC_STR_UI_SHORT(strlen(client->realname)),
849 SILC_STR_UI_XNSTRING(client->realname,
850 strlen(client->realname)),
853 /* Send the packet */
854 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
856 packet->data, packet->len, TRUE);
857 silc_buffer_free(packet);
860 /* Save remote ID. */
861 conn->remote_id = ctx->dest_id;
862 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
863 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
865 /* Register re-key timeout */
866 conn->internal->rekey->timeout = client->internal->params->rekey_secs;
867 conn->internal->rekey->context = (void *)client;
868 silc_schedule_task_add(client->schedule, conn->sock->sock,
869 silc_client_rekey_callback,
870 (void *)conn->sock, conn->internal->rekey->timeout, 0,
871 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
873 silc_protocol_free(protocol);
874 silc_free(ctx->auth_data);
876 silc_ske_free(ctx->ske);
877 silc_socket_free(ctx->sock);
879 conn->sock->protocol = NULL;
883 silc_protocol_free(protocol);
884 silc_free(ctx->auth_data);
885 silc_free(ctx->dest_id);
887 silc_ske_free(ctx->ske);
888 conn->sock->protocol = NULL;
889 silc_socket_free(ctx->sock);
891 /* Notify application of failure */
892 silc_schedule_task_add(client->schedule, ctx->sock->sock,
893 silc_client_connect_failure_auth, ctx,
894 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
897 /* Internal routine that sends packet or marks packet to be sent. This
898 is used directly only in special cases. Normal cases should use
899 silc_server_packet_send. Returns < 0 on error. */
901 bool silc_client_packet_send_real(SilcClient client,
902 SilcSocketConnection sock,
907 /* If rekey protocol is active we must assure that all packets are
908 sent through packet queue. */
909 if (SILC_CLIENT_IS_REKEY(sock))
912 /* If outbound data is already pending do not force send */
913 if (SILC_IS_OUTBUF_PENDING(sock))
916 /* Send the packet */
917 ret = silc_packet_send(sock, force_send);
921 /* Mark that there is some outgoing data available for this connection.
922 This call sets the connection both for input and output (the input
923 is set always and this call keeps the input setting, actually).
924 Actual data sending is performed by silc_client_packet_process. */
925 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
927 /* Mark to socket that data is pending in outgoing buffer. This flag
928 is needed if new data is added to the buffer before the earlier
929 put data is sent to the network. */
930 SILC_SET_OUTBUF_PENDING(sock);
935 /* Packet processing callback. This is used to send and receive packets
936 from network. This is generic task. */
938 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
940 SilcClient client = (SilcClient)context;
941 SilcSocketConnection sock = NULL;
942 SilcClientConnection conn;
945 SILC_LOG_DEBUG(("Processing packet"));
947 SILC_CLIENT_GET_SOCK(client, fd, sock);
951 conn = (SilcClientConnection)sock->user_data;
954 if (type == SILC_TASK_WRITE) {
955 /* Do not send data to disconnected connection */
956 if (SILC_IS_DISCONNECTED(sock))
959 ret = silc_packet_send(sock, TRUE);
961 /* If returned -2 could not write to connection now, will do
970 /* The packet has been sent and now it is time to set the connection
971 back to only for input. When there is again some outgoing data
972 available for this connection it will be set for output as well.
973 This call clears the output setting and sets it only for input. */
974 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
975 SILC_UNSET_OUTBUF_PENDING(sock);
977 silc_buffer_clear(sock->outbuf);
981 /* Packet receiving */
982 if (type == SILC_TASK_READ) {
983 /* Read data from network */
984 ret = silc_packet_receive(sock);
990 SILC_LOG_DEBUG(("Read EOF"));
992 /* If connection is disconnecting already we will finally
993 close the connection */
994 if (SILC_IS_DISCONNECTING(sock)) {
995 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
996 client->internal->ops->disconnected(client, conn, 0, NULL);
997 silc_client_close_connection_real(client, sock, conn);
1001 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
1002 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1003 client->internal->ops->disconnected(client, conn, 0, NULL);
1004 silc_client_close_connection_real(client, sock, conn);
1008 /* Process the packet. This will call the parser that will then
1009 decrypt and parse the packet. */
1010 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
1011 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
1012 conn->internal->hmac_receive,
1013 conn->internal->psn_receive,
1014 silc_client_packet_parse, client);
1016 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
1017 silc_client_packet_parse, client);
1021 /* Parser callback called by silc_packet_receive_process. Thie merely
1022 registers timeout that will handle the actual parsing when appropriate. */
1024 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
1027 SilcClient client = (SilcClient)context;
1028 SilcSocketConnection sock = parser_context->sock;
1029 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1030 SilcPacketContext *packet = parser_context->packet;
1033 if (conn && conn->internal->hmac_receive && conn->sock == sock)
1034 conn->internal->psn_receive = parser_context->packet->sequence + 1;
1036 /* Parse the packet immediately */
1037 if (parser_context->normal)
1038 ret = silc_packet_parse(packet, conn->internal->receive_key);
1040 ret = silc_packet_parse_special(packet, conn->internal->receive_key);
1042 if (ret == SILC_PACKET_NONE) {
1043 silc_packet_context_free(packet);
1044 silc_free(parser_context);
1048 /* If protocol for this connection is key exchange or rekey then we'll
1049 process all packets synchronously, since there might be packets in
1050 queue that we are not able to decrypt without first processing the
1051 packets before them. */
1052 if ((ret == SILC_PACKET_REKEY || ret == SILC_PACKET_REKEY_DONE) ||
1053 (sock->protocol && sock->protocol->protocol &&
1054 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1055 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY))) {
1057 /* Parse the incoming packet type */
1058 silc_client_packet_parse_type(client, sock, packet);
1059 silc_packet_context_free(packet);
1060 silc_free(parser_context);
1062 /* Reprocess the buffer since we'll return FALSE. This is because
1063 the `conn->internal->receive_key' might have become valid by processing
1064 the previous packet */
1065 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
1066 silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
1067 conn->internal->hmac_receive,
1068 conn->internal->psn_receive,
1069 silc_client_packet_parse, client);
1071 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
1072 silc_client_packet_parse, client);
1077 /* Parse the incoming packet type */
1078 silc_client_packet_parse_type(client, sock, packet);
1079 silc_packet_context_free(packet);
1080 silc_free(parser_context);
1084 /* Parses the packet type and calls what ever routines the packet type
1085 requires. This is done for all incoming packets. */
1087 void silc_client_packet_parse_type(SilcClient client,
1088 SilcSocketConnection sock,
1089 SilcPacketContext *packet)
1091 SilcBuffer buffer = packet->buffer;
1092 SilcPacketType type = packet->type;
1094 SILC_LOG_DEBUG(("Parsing %s packet", silc_get_packet_name(type)));
1096 /* Parse the packet type */
1099 case SILC_PACKET_DISCONNECT:
1100 silc_client_disconnected_by_server(client, sock, buffer);
1103 case SILC_PACKET_SUCCESS:
1105 * Success received for something. For now we can have only
1106 * one protocol for connection executing at once hence this
1107 * success message is for whatever protocol is executing currently.
1110 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1113 case SILC_PACKET_FAILURE:
1115 * Failure received for some protocol. Set the protocol state to
1116 * error and call the protocol callback. This fill cause error on
1117 * protocol and it will call the final callback.
1119 silc_client_process_failure(client, sock, packet);
1122 case SILC_PACKET_REJECT:
1125 case SILC_PACKET_NOTIFY:
1127 * Received notify message
1129 silc_client_notify_by_server(client, sock, packet);
1132 case SILC_PACKET_ERROR:
1134 * Received error message
1136 silc_client_error_by_server(client, sock, buffer);
1139 case SILC_PACKET_CHANNEL_MESSAGE:
1141 * Received message to (from, actually) a channel
1143 silc_client_channel_message(client, sock, packet);
1146 case SILC_PACKET_CHANNEL_KEY:
1148 * Received key for a channel. By receiving this key the client will be
1149 * able to talk to the channel it has just joined. This can also be
1150 * a new key for existing channel as keys expire peridiocally.
1152 silc_client_receive_channel_key(client, sock, buffer);
1155 case SILC_PACKET_PRIVATE_MESSAGE:
1157 * Received private message
1159 silc_client_private_message(client, sock, packet);
1162 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1164 * Received private message key
1168 case SILC_PACKET_COMMAND:
1170 * Received command packet, a special case since normally client
1171 * does not receive commands.
1173 silc_client_command_process(client, sock, packet);
1176 case SILC_PACKET_COMMAND_REPLY:
1178 * Recived reply for a command
1180 silc_client_command_reply_process(client, sock, packet);
1183 case SILC_PACKET_KEY_EXCHANGE:
1184 if (sock->protocol && sock->protocol->protocol &&
1185 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
1186 SilcClientKEInternalContext *proto_ctx =
1187 (SilcClientKEInternalContext *)sock->protocol->context;
1189 proto_ctx->packet = silc_packet_context_dup(packet);
1190 proto_ctx->dest_id_type = packet->src_id_type;
1191 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1192 packet->src_id_type);
1193 if (!proto_ctx->dest_id)
1196 /* Let the protocol handle the packet */
1197 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1199 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1200 "protocol active, packet dropped."));
1204 case SILC_PACKET_KEY_EXCHANGE_1:
1205 if (sock->protocol && sock->protocol->protocol &&
1206 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1207 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1209 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1210 SilcClientRekeyInternalContext *proto_ctx =
1211 (SilcClientRekeyInternalContext *)sock->protocol->context;
1213 if (proto_ctx->packet)
1214 silc_packet_context_free(proto_ctx->packet);
1216 proto_ctx->packet = silc_packet_context_dup(packet);
1218 /* Let the protocol handle the packet */
1219 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1221 SilcClientKEInternalContext *proto_ctx =
1222 (SilcClientKEInternalContext *)sock->protocol->context;
1224 if (proto_ctx->packet)
1225 silc_packet_context_free(proto_ctx->packet);
1227 proto_ctx->packet = silc_packet_context_dup(packet);
1228 proto_ctx->dest_id_type = packet->src_id_type;
1229 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1230 packet->src_id_type);
1231 if (!proto_ctx->dest_id)
1234 /* Let the protocol handle the packet */
1235 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1238 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1239 "protocol active, packet dropped."));
1243 case SILC_PACKET_KEY_EXCHANGE_2:
1244 if (sock->protocol && sock->protocol->protocol &&
1245 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1246 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1248 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1249 SilcClientRekeyInternalContext *proto_ctx =
1250 (SilcClientRekeyInternalContext *)sock->protocol->context;
1252 if (proto_ctx->packet)
1253 silc_packet_context_free(proto_ctx->packet);
1255 proto_ctx->packet = silc_packet_context_dup(packet);
1257 /* Let the protocol handle the packet */
1258 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1260 SilcClientKEInternalContext *proto_ctx =
1261 (SilcClientKEInternalContext *)sock->protocol->context;
1263 if (proto_ctx->packet)
1264 silc_packet_context_free(proto_ctx->packet);
1265 if (proto_ctx->dest_id)
1266 silc_free(proto_ctx->dest_id);
1267 proto_ctx->packet = silc_packet_context_dup(packet);
1268 proto_ctx->dest_id_type = packet->src_id_type;
1269 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1270 packet->src_id_type);
1271 if (!proto_ctx->dest_id)
1274 /* Let the protocol handle the packet */
1275 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1278 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1279 "protocol active, packet dropped."));
1283 case SILC_PACKET_NEW_ID:
1286 * Received new ID from server. This packet is received at
1287 * the connection to the server. New ID is also received when
1288 * user changes nickname but in that case the new ID is received
1289 * as command reply and not as this packet type.
1293 idp = silc_id_payload_parse(buffer->data, buffer->len);
1296 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1299 silc_client_receive_new_id(client, sock, idp);
1300 silc_id_payload_free(idp);
1304 case SILC_PACKET_HEARTBEAT:
1306 * Received heartbeat packet
1308 SILC_LOG_DEBUG(("Heartbeat packet"));
1311 case SILC_PACKET_KEY_AGREEMENT:
1313 * Received key agreement packet
1315 SILC_LOG_DEBUG(("Key agreement packet"));
1316 silc_client_key_agreement(client, sock, packet);
1319 case SILC_PACKET_REKEY:
1320 SILC_LOG_DEBUG(("Re-key packet"));
1321 /* We ignore this for now */
1324 case SILC_PACKET_REKEY_DONE:
1325 SILC_LOG_DEBUG(("Re-key done packet"));
1327 if (sock->protocol && sock->protocol->protocol &&
1328 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1330 SilcClientRekeyInternalContext *proto_ctx =
1331 (SilcClientRekeyInternalContext *)sock->protocol->context;
1333 if (proto_ctx->packet)
1334 silc_packet_context_free(proto_ctx->packet);
1336 proto_ctx->packet = silc_packet_context_dup(packet);
1338 /* Let the protocol handle the packet */
1339 if (proto_ctx->responder == FALSE)
1340 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1342 /* Let the protocol handle the packet */
1343 silc_protocol_execute(sock->protocol, client->schedule,
1346 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1347 "protocol active, packet dropped."));
1351 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1353 * Reveived reply to our connection authentication method request
1354 * packet. This is used to resolve the authentication method for the
1355 * current session from the server if the client does not know it.
1357 silc_client_connection_auth_request(client, sock, packet);
1360 case SILC_PACKET_FTP:
1361 /* Received file transfer packet. */
1362 silc_client_ftp(client, sock, packet);
1366 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1371 /* Sends packet. This doesn't actually send the packet instead it assembles
1372 it and marks it to be sent. However, if force_send is TRUE the packet
1373 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1374 will be derived from sock argument. Otherwise the valid arguments sent
1377 void silc_client_packet_send(SilcClient client,
1378 SilcSocketConnection sock,
1379 SilcPacketType type,
1381 SilcIdType dst_id_type,
1384 unsigned char *data,
1385 SilcUInt32 data_len,
1388 SilcPacketContext packetdata;
1389 const SilcBufferStruct packet;
1391 SilcUInt32 sequence = 0;
1396 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1398 /* Get data used in the packet sending, keys and stuff */
1399 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1400 if (!cipher && ((SilcClientConnection)sock->user_data)->internal->send_key)
1401 cipher = ((SilcClientConnection)sock->user_data)->internal->send_key;
1403 if (!hmac && ((SilcClientConnection)sock->user_data)->internal->hmac_send)
1404 hmac = ((SilcClientConnection)sock->user_data)->internal->hmac_send;
1406 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1407 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1408 dst_id_type = SILC_ID_SERVER;
1412 sequence = ((SilcClientConnection)sock->user_data)->internal->psn_send++;
1414 /* Check for mandatory rekey */
1415 if (sequence == SILC_CLIENT_REKEY_THRESHOLD)
1416 silc_schedule_task_add(client->schedule, sock->sock,
1417 silc_client_rekey_callback, sock, 0, 1,
1418 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1421 block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1423 /* Set the packet context pointers */
1424 packetdata.flags = 0;
1425 packetdata.type = type;
1426 if (sock->user_data &&
1427 ((SilcClientConnection)sock->user_data)->local_id_data) {
1428 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1429 packetdata.src_id_len =
1430 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1433 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1434 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1436 packetdata.src_id_type = SILC_ID_CLIENT;
1438 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1439 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1440 packetdata.dst_id_type = dst_id_type;
1442 packetdata.dst_id = NULL;
1443 packetdata.dst_id_len = 0;
1444 packetdata.dst_id_type = SILC_ID_NONE;
1446 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1447 packetdata.src_id_len +
1448 packetdata.dst_id_len));
1449 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1450 packetdata.src_id_len + packetdata.dst_id_len;
1451 if (type == SILC_PACKET_CONNECTION_AUTH)
1452 SILC_PACKET_PADLEN_MAX(packetdata.truelen, block_len, packetdata.padlen);
1454 SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
1456 /* Create the outgoing packet */
1457 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
1458 data, data_len, (const SilcBuffer)&packet)) {
1459 SILC_LOG_ERROR(("Error assembling packet"));
1463 /* Encrypt the packet */
1465 silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet,
1468 SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
1469 packet.data, packet.len);
1471 /* Now actually send the packet */
1472 silc_client_packet_send_real(client, sock, force_send);
1475 /* Packet sending routine for application. This is the only routine that
1476 is provided for application to send SILC packets. */
1478 bool silc_client_send_packet(SilcClient client,
1479 SilcClientConnection conn,
1480 SilcPacketType type,
1481 const unsigned char *data,
1482 SilcUInt32 data_len)
1489 silc_client_packet_send(client, conn->sock, type, NULL, 0, NULL, NULL,
1490 (unsigned char *)data, data_len, TRUE);
1494 void silc_client_packet_queue_purge(SilcClient client,
1495 SilcSocketConnection sock)
1497 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1498 (SILC_IS_DISCONNECTED(sock) == FALSE)) {
1499 silc_packet_send(sock, TRUE);
1500 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1501 SILC_UNSET_OUTBUF_PENDING(sock);
1502 silc_buffer_clear(sock->outbuf);
1506 /* Closes connection to remote end. Free's all allocated data except
1507 for some information such as nickname etc. that are valid at all time.
1508 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1509 provided it will be checked whether the sock and `conn->sock' are the
1510 same (they can be different, ie. a socket can use `conn' as its
1511 connection but `conn->sock' might be actually a different connection
1512 than the `sock'). */
1514 void silc_client_close_connection_real(SilcClient client,
1515 SilcSocketConnection sock,
1516 SilcClientConnection conn)
1520 SILC_LOG_DEBUG(("Start"));
1525 if (!sock || (sock && conn->sock == sock))
1530 /* We won't listen for this connection anymore */
1531 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1533 /* Unregister all tasks */
1534 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1536 /* Close the actual connection */
1537 silc_net_close_connection(sock->sock);
1539 /* Cancel any active protocol */
1540 if (sock->protocol) {
1541 if (sock->protocol->protocol->type ==
1542 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1543 sock->protocol->protocol->type ==
1544 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1545 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1546 silc_protocol_execute_final(sock->protocol, client->schedule);
1547 /* The application will recall this function with these protocols
1548 (the ops->connected client operation). */
1551 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1552 silc_protocol_execute_final(sock->protocol, client->schedule);
1553 sock->protocol = NULL;
1557 /* Free everything */
1558 if (del && sock->user_data)
1559 silc_client_del_connection(client, conn);
1561 silc_socket_free(sock);
1564 /* Closes the connection to the remote end */
1566 void silc_client_close_connection(SilcClient client,
1567 SilcClientConnection conn)
1569 silc_client_close_connection_real(client, NULL, conn);
1572 /* Called when we receive disconnection packet from server. This
1573 closes our end properly and displays the reason of the disconnection
1576 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1578 SilcClient client = (SilcClient)context;
1579 SilcSocketConnection sock;
1581 SILC_CLIENT_GET_SOCK(client, fd, sock);
1585 silc_client_close_connection_real(client, sock, sock->user_data);
1588 /* Called when we receive disconnection packet from server. This
1589 closes our end properly and displays the reason of the disconnection
1592 void silc_client_disconnected_by_server(SilcClient client,
1593 SilcSocketConnection sock,
1596 SilcClientConnection conn;
1598 char *message = NULL;
1600 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1602 if (packet->len < 1)
1605 status = (SilcStatus)packet->data[0];
1607 if (packet->len > 1 &&
1608 silc_utf8_valid(packet->data + 1, packet->len - 1))
1609 message = silc_memdup(packet->data + 1, packet->len - 1);
1611 conn = (SilcClientConnection)sock->user_data;
1612 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1613 client->internal->ops->disconnected(client, conn, status, message);
1617 SILC_SET_DISCONNECTED(sock);
1619 /* Close connection through scheduler. */
1620 silc_schedule_task_add(client->schedule, sock->sock,
1621 silc_client_disconnected_by_server_later,
1622 client, 0, 1, SILC_TASK_TIMEOUT,
1623 SILC_TASK_PRI_NORMAL);
1626 /* Received error message from server. Display it on the screen.
1627 We don't take any action what so ever of the error message. */
1629 void silc_client_error_by_server(SilcClient client,
1630 SilcSocketConnection sock,
1635 msg = silc_memdup(message->data, message->len);
1636 client->internal->ops->say(client, sock->user_data,
1637 SILC_CLIENT_MESSAGE_AUDIT, msg);
1641 /* Auto-nicking callback to send NICK command to server. */
1643 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1645 SilcClientConnection conn = (SilcClientConnection)context;
1646 SilcClient client = conn->client;
1648 silc_client_command_send(client, conn, SILC_COMMAND_NICK,
1649 ++conn->cmd_ident, 1, 1,
1650 client->nickname, strlen(client->nickname));
1653 /* Client session resuming callback. If the session was resumed
1654 this callback is called after the resuming is completed. This
1655 will call the `connect' client operation to the application
1656 since it has not been called yet. */
1658 static void silc_client_resume_session_cb(SilcClient client,
1659 SilcClientConnection conn,
1665 /* Notify application that connection is created to server */
1666 client->internal->ops->connected(client, conn, success ?
1667 SILC_CLIENT_CONN_SUCCESS_RESUME :
1668 SILC_CLIENT_CONN_ERROR);
1671 /* Issue INFO command to fetch the real server name and server
1672 information and other stuff. */
1673 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1674 silc_client_command_reply_info_i, 0,
1676 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1677 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1678 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1679 silc_buffer_free(sidp);
1683 /* Processes the received new Client ID from server. Old Client ID is
1684 deleted from cache and new one is added. */
1686 void silc_client_receive_new_id(SilcClient client,
1687 SilcSocketConnection sock,
1690 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1691 int connecting = FALSE;
1692 SilcClientID *client_id = silc_id_payload_get_id(idp);
1694 if (!conn->local_entry)
1697 /* Delete old ID from ID cache */
1698 if (conn->local_id) {
1699 /* Check whether they are different */
1700 if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1701 silc_free(client_id);
1705 silc_idcache_del_by_context(conn->internal->client_cache,
1707 silc_free(conn->local_id);
1710 /* Save the new ID */
1712 if (conn->local_id_data)
1713 silc_free(conn->local_id_data);
1715 conn->local_id = client_id;
1716 conn->local_id_data = silc_id_payload_get_data(idp);
1717 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1719 if (!conn->local_entry)
1720 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1722 conn->local_entry->nickname = conn->nickname;
1723 if (!conn->local_entry->username)
1724 conn->local_entry->username = strdup(client->username);
1725 if (!conn->local_entry->server)
1726 conn->local_entry->server = strdup(conn->remote_host);
1727 conn->local_entry->id = conn->local_id;
1728 conn->local_entry->valid = TRUE;
1729 if (!conn->local_entry->channels)
1730 conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
1735 /* Put it to the ID cache */
1736 silc_idcache_add(conn->internal->client_cache,
1737 strdup(conn->nickname), conn->local_id,
1738 (void *)conn->local_entry, 0, NULL);
1743 /* Issue IDENTIFY command for itself to get resolved hostname
1744 correctly from server. */
1745 silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
1746 silc_client_command_reply_identify_i, 0,
1748 sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT);
1749 silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
1750 conn->cmd_ident, 1, 5, sidp->data, sidp->len);
1751 silc_buffer_free(sidp);
1753 if (!conn->internal->params.detach_data) {
1754 /* Send NICK command if the nickname was set by the application (and is
1755 not same as the username). Send this with little timeout. */
1756 if (client->nickname && strcmp(client->nickname, client->username))
1757 silc_schedule_task_add(client->schedule, 0,
1758 silc_client_send_auto_nick, conn,
1759 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1761 /* Notify application of successful connection. We do it here now that
1762 we've received the Client ID and are allowed to send traffic. */
1763 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_SUCCESS);
1765 /* Issue INFO command to fetch the real server name and server
1766 information and other stuff. */
1767 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1768 silc_client_command_reply_info_i, 0,
1770 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1771 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1772 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1773 silc_buffer_free(sidp);
1775 /* We are resuming session. Start resolving informations from the
1776 server we need to set the client libary in the state before
1777 detaching the session. The connect client operation is called
1778 after this is successfully completed */
1779 silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1785 /* Removes a client entry from all channels it has joined. */
1787 void silc_client_remove_from_channels(SilcClient client,
1788 SilcClientConnection conn,
1789 SilcClientEntry client_entry)
1791 SilcHashTableList htl;
1792 SilcChannelUser chu;
1794 silc_hash_table_list(client_entry->channels, &htl);
1795 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1796 silc_hash_table_del(chu->client->channels, chu->channel);
1797 silc_hash_table_del(chu->channel->user_list, chu->client);
1801 silc_hash_table_list_reset(&htl);
1804 /* Replaces `old' client entries from all channels to `new' client entry.
1805 This can be called for example when nickname changes and old ID entry
1806 is replaced from ID cache with the new one. If the old ID entry is only
1807 updated, then this fucntion needs not to be called. */
1809 void silc_client_replace_from_channels(SilcClient client,
1810 SilcClientConnection conn,
1811 SilcClientEntry old,
1812 SilcClientEntry new)
1814 SilcHashTableList htl;
1815 SilcChannelUser chu;
1817 silc_hash_table_list(old->channels, &htl);
1818 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1819 /* Replace client entry */
1820 silc_hash_table_del(chu->client->channels, chu->channel);
1821 silc_hash_table_del(chu->channel->user_list, chu->client);
1824 silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1825 silc_hash_table_add(chu->client->channels, chu->channel, chu);
1827 silc_hash_table_list_reset(&htl);
1830 /* Registers failure timeout to process the received failure packet
1833 void silc_client_process_failure(SilcClient client,
1834 SilcSocketConnection sock,
1835 SilcPacketContext *packet)
1837 SilcUInt32 failure = 0;
1839 if (sock->protocol) {
1840 if (packet->buffer->len >= 4)
1841 SILC_GET32_MSB(failure, packet->buffer->data);
1843 /* Notify application */
1844 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1849 /* A timeout callback for the re-key. We will be the initiator of the
1852 SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback)
1854 SilcSocketConnection sock = (SilcSocketConnection)context;
1855 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1856 SilcClient client = (SilcClient)conn->internal->rekey->context;
1857 SilcProtocol protocol;
1858 SilcClientRekeyInternalContext *proto_ctx;
1860 SILC_LOG_DEBUG(("Start"));
1862 /* Allocate internal protocol context. This is sent as context
1864 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1865 proto_ctx->client = (void *)client;
1866 proto_ctx->sock = silc_socket_dup(sock);
1867 proto_ctx->responder = FALSE;
1868 proto_ctx->pfs = conn->internal->rekey->pfs;
1870 /* Perform rekey protocol. Will call the final callback after the
1871 protocol is over. */
1872 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1873 &protocol, proto_ctx, silc_client_rekey_final);
1874 sock->protocol = protocol;
1876 /* Run the protocol */
1877 silc_protocol_execute(protocol, client->schedule, 0, 0);
1879 /* Re-register re-key timeout */
1880 silc_schedule_task_add(client->schedule, sock->sock,
1881 silc_client_rekey_callback,
1882 context, conn->internal->rekey->timeout, 0,
1883 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1886 /* The final callback for the REKEY protocol. This will actually take the
1887 new key material into use. */
1889 SILC_TASK_CALLBACK(silc_client_rekey_final)
1891 SilcProtocol protocol = (SilcProtocol)context;
1892 SilcClientRekeyInternalContext *ctx =
1893 (SilcClientRekeyInternalContext *)protocol->context;
1894 SilcClient client = (SilcClient)ctx->client;
1895 SilcSocketConnection sock = ctx->sock;
1897 SILC_LOG_DEBUG(("Start"));
1899 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1900 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1901 /* Error occured during protocol */
1902 silc_protocol_cancel(protocol, client->schedule);
1903 silc_protocol_free(protocol);
1904 sock->protocol = NULL;
1906 silc_packet_context_free(ctx->packet);
1908 silc_ske_free(ctx->ske);
1909 silc_socket_free(ctx->sock);
1914 /* Purge the outgoing data queue to assure that all rekey packets really
1915 go to the network before we quit the protocol. */
1916 silc_client_packet_queue_purge(client, sock);
1919 silc_protocol_free(protocol);
1920 sock->protocol = NULL;
1922 silc_packet_context_free(ctx->packet);
1924 silc_ske_free(ctx->ske);
1925 silc_socket_free(ctx->sock);
1929 /* Processes incoming connection authentication method request packet.
1930 It is a reply to our previously sent request. The packet can be used
1931 to resolve the authentication method for the current session if the
1932 client does not know it beforehand. */
1934 void silc_client_connection_auth_request(SilcClient client,
1935 SilcSocketConnection sock,
1936 SilcPacketContext *packet)
1938 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1939 SilcUInt16 conn_type, auth_meth;
1942 /* If we haven't send our request then ignore this one. */
1943 if (!conn->internal->connauth)
1946 /* Parse the payload */
1947 ret = silc_buffer_unformat(packet->buffer,
1948 SILC_STR_UI_SHORT(&conn_type),
1949 SILC_STR_UI_SHORT(&auth_meth),
1952 auth_meth = SILC_AUTH_NONE;
1954 /* Call the request callback to notify application for received
1955 authentication method information. */
1956 if (conn->internal->connauth->callback)
1957 (*conn->internal->connauth->callback)(client, conn, auth_meth,
1958 conn->internal->connauth->context);
1960 silc_schedule_task_del(client->schedule, conn->internal->connauth->timeout);
1962 silc_free(conn->internal->connauth);
1963 conn->internal->connauth = NULL;
1966 /* Timeout task callback called if the server does not reply to our
1967 connection authentication method request in the specified time interval. */
1969 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1971 SilcClientConnection conn = (SilcClientConnection)context;
1972 SilcClient client = conn->client;
1974 if (!conn->internal->connauth)
1977 /* Call the request callback to notify application */
1978 if (conn->internal->connauth->callback)
1979 (*conn->internal->connauth->callback)(client, conn, SILC_AUTH_NONE,
1980 conn->internal->connauth->context);
1982 silc_free(conn->internal->connauth);
1983 conn->internal->connauth = NULL;
1986 /* This function can be used to request the current authentication method
1987 from the server. This may be called when connecting to the server
1988 and the client library requests the authentication data from the
1989 application. If the application does not know the current authentication
1990 method it can request it from the server using this function.
1991 The `callback' with `context' will be called after the server has
1992 replied back with the current authentication method. */
1995 silc_client_request_authentication_method(SilcClient client,
1996 SilcClientConnection conn,
1997 SilcConnectionAuthRequest callback,
2000 SilcClientConnAuthRequest connauth;
2003 assert(client && conn);
2004 connauth = silc_calloc(1, sizeof(*connauth));
2005 connauth->callback = callback;
2006 connauth->context = context;
2008 if (conn->internal->connauth)
2009 silc_free(conn->internal->connauth);
2011 conn->internal->connauth = connauth;
2013 /* Assemble the request packet and send it to the server */
2014 packet = silc_buffer_alloc(4);
2015 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
2016 silc_buffer_format(packet,
2017 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
2018 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
2020 silc_client_packet_send(client, conn->sock,
2021 SILC_PACKET_CONNECTION_AUTH_REQUEST,
2022 NULL, 0, NULL, NULL,
2023 packet->data, packet->len, FALSE);
2024 silc_buffer_free(packet);
2026 /* Register a timeout in case server does not reply anything back. */
2028 silc_schedule_task_add(client->schedule, conn->sock->sock,
2029 silc_client_request_authentication_method_timeout,
2031 client->internal->params->connauth_request_secs, 0,
2032 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);