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_callback);
30 SILC_TASK_CALLBACK(silc_client_rekey_final);
32 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
34 static void silc_client_packet_parse_type(SilcClient client,
35 SilcSocketConnection sock,
36 SilcPacketContext *packet);
37 void silc_client_resolve_auth_method(bool success,
38 SilcProtocolAuthMeth auth_meth,
39 const unsigned char *auth_data,
40 SilcUInt32 auth_data_len, void *context);
42 /* Allocates new client object. This has to be done before client may
43 work. After calling this one must call silc_client_init to initialize
44 the client. The `application' is application specific user data pointer
45 and caller must free it. */
47 SilcClient silc_client_alloc(SilcClientOperations *ops,
48 SilcClientParams *params,
50 const char *version_string)
52 SilcClient new_client;
54 new_client = silc_calloc(1, sizeof(*new_client));
55 new_client->application = application;
57 new_client->internal = silc_calloc(1, sizeof(*new_client->internal));
58 new_client->internal->ops = ops;
59 new_client->internal->params =
60 silc_calloc(1, sizeof(*new_client->internal->params));
62 version_string = silc_version_string;
63 new_client->internal->silc_client_version = strdup(version_string);
66 memcpy(new_client->internal->params, params, sizeof(*params));
68 if (!new_client->internal->params->task_max)
69 new_client->internal->params->task_max = 200;
71 if (!new_client->internal->params->rekey_secs)
72 new_client->internal->params->rekey_secs = 3600;
74 if (!new_client->internal->params->connauth_request_secs)
75 new_client->internal->params->connauth_request_secs = 2;
77 new_client->internal->params->
78 nickname_format[sizeof(new_client->internal->
79 params->nickname_format) - 1] = 0;
84 /* Frees client object and its internals. */
86 void silc_client_free(SilcClient client)
90 silc_rng_free(client->rng);
92 silc_free(client->internal->params);
93 silc_free(client->internal->silc_client_version);
94 silc_free(client->internal);
99 /* Initializes the client. This makes all the necessary steps to make
100 the client ready to be run. One must call silc_client_run to run the
101 client. Returns FALSE if error occured, TRUE otherwise. */
103 int silc_client_init(SilcClient client)
105 SILC_LOG_DEBUG(("Initializing client"));
107 /* Initialize the crypto library. If application has done this already
108 this has no effect. Also, we will not be overriding something
109 application might have registered earlier. */
110 silc_cipher_register_default();
111 silc_pkcs_register_default();
112 silc_hash_register_default();
113 silc_hmac_register_default();
115 /* Initialize hash functions for client to use */
116 silc_hash_alloc("md5", &client->md5hash);
117 silc_hash_alloc("sha1", &client->sha1hash);
119 /* Initialize none cipher */
120 silc_cipher_alloc("none", &client->internal->none_cipher);
122 /* Initialize random number generator */
123 client->rng = silc_rng_alloc();
124 silc_rng_init(client->rng);
125 silc_rng_global_init(client->rng);
127 /* Register protocols */
128 silc_client_protocols_register();
130 /* Initialize the scheduler */
132 silc_schedule_init(client->internal->params->task_max ?
133 client->internal->params->task_max : 200, client);
134 if (!client->schedule)
137 /* Register commands */
138 silc_client_commands_register(client);
143 /* Stops the client. This is called to stop the client and thus to stop
146 void silc_client_stop(SilcClient client)
148 SILC_LOG_DEBUG(("Stopping client"));
150 silc_schedule_stop(client->schedule);
151 silc_schedule_uninit(client->schedule);
153 silc_client_protocols_unregister();
154 silc_client_commands_unregister(client);
156 SILC_LOG_DEBUG(("Client stopped"));
159 /* Runs the client. This starts the scheduler from the utility library.
160 When this functions returns the execution of the appliation is over. */
162 void silc_client_run(SilcClient client)
164 SILC_LOG_DEBUG(("Running client"));
166 /* Start the scheduler, the heart of the SILC client. When this returns
167 the program will be terminated. */
168 silc_schedule(client->schedule);
171 /* Runs the client and returns immeadiately. This function is used when
172 the SILC Client object indicated by the `client' is run under some
173 other scheduler, or event loop or main loop. On GUI applications,
174 for example this may be desired to use to run the client under the
175 GUI application's main loop. Typically the GUI application would
176 register an idle task that calls this function multiple times in
177 a second to quickly process the SILC specific data. */
179 void silc_client_run_one(SilcClient client)
181 /* Run the scheduler once. */
182 silc_schedule_one(client->schedule, 0);
185 static void silc_client_entry_destructor(SilcIDCache cache,
186 SilcIDCacheEntry entry)
188 silc_free(entry->name);
191 /* Allocates and adds new connection to the client. This adds the allocated
192 connection to the connection table and returns a pointer to it. A client
193 can have multiple connections to multiple servers. Every connection must
194 be added to the client using this function. User data `context' may
195 be sent as argument. This function is normally used only if the
196 application performed the connecting outside the library. The library
197 however may use this internally. */
200 silc_client_add_connection(SilcClient client,
201 SilcClientConnectionParams *params,
202 char *hostname, int port, void *context)
204 SilcClientConnection conn;
207 SILC_LOG_DEBUG(("Adding new connection to %s:%d", hostname, port));
209 conn = silc_calloc(1, sizeof(*conn));
211 /* Initialize ID caches */
212 conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT,
213 silc_client_entry_destructor);
214 conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
215 conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
216 conn->client = client;
217 conn->remote_host = strdup(hostname);
218 conn->remote_port = port;
219 conn->context = context;
220 conn->pending_commands = silc_dlist_init();
221 conn->ftp_sessions = silc_dlist_init();
224 if (params->detach_data)
225 conn->params.detach_data = silc_memdup(params->detach_data,
226 params->detach_data_len);
227 conn->params.detach_data_len = params->detach_data_len;
230 /* Add the connection to connections table */
231 for (i = 0; i < client->internal->conns_count; i++)
232 if (client->internal->conns && !client->internal->conns[i]) {
233 client->internal->conns[i] = conn;
237 client->internal->conns =
238 silc_realloc(client->internal->conns, sizeof(*client->internal->conns)
239 * (client->internal->conns_count + 1));
240 client->internal->conns[client->internal->conns_count] = conn;
241 client->internal->conns_count++;
246 /* Removes connection from client. Frees all memory. */
248 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
252 for (i = 0; i < client->internal->conns_count; i++)
253 if (client->internal->conns[i] == conn) {
255 silc_idcache_free(conn->client_cache);
256 silc_idcache_free(conn->channel_cache);
257 silc_idcache_free(conn->server_cache);
258 if (conn->pending_commands)
259 silc_dlist_uninit(conn->pending_commands);
260 silc_free(conn->remote_host);
261 if (conn->ftp_sessions)
262 silc_dlist_uninit(conn->ftp_sessions);
265 client->internal->conns[i] = NULL;
269 /* Adds listener socket to the listener sockets table. This function is
270 used to add socket objects that are listeners to the client. This should
271 not be used to add other connection objects. */
273 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
277 if (!client->internal->sockets) {
278 client->internal->sockets =
279 silc_calloc(1, sizeof(*client->internal->sockets));
280 client->internal->sockets[0] = silc_socket_dup(sock);
281 client->internal->sockets_count = 1;
285 for (i = 0; i < client->internal->sockets_count; i++) {
286 if (client->internal->sockets[i] == NULL) {
287 client->internal->sockets[i] = silc_socket_dup(sock);
292 client->internal->sockets =
293 silc_realloc(client->internal->sockets,
294 sizeof(*client->internal->sockets) *
295 (client->internal->sockets_count + 1));
296 client->internal->sockets[client->internal->sockets_count] =
297 silc_socket_dup(sock);
298 client->internal->sockets_count++;
301 /* Deletes listener socket from the listener sockets table. */
303 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
307 if (!client->internal->sockets)
310 for (i = 0; i < client->internal->sockets_count; i++) {
311 if (client->internal->sockets[i] == sock) {
312 silc_socket_free(sock);
313 client->internal->sockets[i] = NULL;
320 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
324 /* XXX In the future we should give up this non-blocking connect all
325 together and use threads instead. */
326 /* Create connection to server asynchronously */
327 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
331 /* Register task that will receive the async connect and will
333 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
334 silc_client_connect_to_server_start,
337 SILC_TASK_PRI_NORMAL);
338 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE,
346 /* Connects to remote server. This is the main routine used to connect
347 to SILC server. Returns -1 on error and the created socket otherwise.
348 The `context' is user context that is saved into the SilcClientConnection
349 that is created after the connection is created. Note that application
350 may handle the connecting process outside the library. If this is the
351 case then this function is not used at all. When the connecting is
352 done the `connect' client operation is called. */
354 int silc_client_connect_to_server(SilcClient client,
355 SilcClientConnectionParams *params,
356 int port, char *host, void *context)
358 SilcClientInternalConnectContext *ctx;
359 SilcClientConnection conn;
362 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
365 conn = silc_client_add_connection(client, params, host, port, context);
367 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
368 "Connecting to port %d of server %s", port, host);
370 /* Allocate internal context for connection process. This is
371 needed as we are doing async connecting. */
372 ctx = silc_calloc(1, sizeof(*ctx));
373 ctx->client = client;
375 ctx->host = strdup(host);
379 /* Do the actual connecting process */
380 sock = silc_client_connect_to_server_internal(ctx);
382 silc_client_del_connection(client, conn);
386 /* Socket hostname and IP lookup callback that is called before actually
387 starting the key exchange. The lookup is called from the function
388 silc_client_start_key_exchange. */
390 static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
393 SilcClientConnection conn = (SilcClientConnection)context;
394 SilcClient client = conn->client;
395 SilcProtocol protocol;
396 SilcClientKEInternalContext *proto_ctx;
398 SILC_LOG_DEBUG(("Start"));
400 if (conn->sock->hostname) {
401 silc_free(conn->remote_host);
402 conn->remote_host = strdup(conn->sock->hostname);
404 conn->sock->hostname = strdup(conn->remote_host);
407 conn->sock->ip = strdup(conn->sock->hostname);
408 conn->sock->port = conn->remote_port;
410 /* Allocate internal Key Exchange context. This is sent to the
411 protocol as context. */
412 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
413 proto_ctx->client = (void *)client;
414 proto_ctx->sock = silc_socket_dup(conn->sock);
415 proto_ctx->rng = client->rng;
416 proto_ctx->responder = FALSE;
417 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
418 proto_ctx->verify = silc_client_protocol_ke_verify_key;
420 /* Perform key exchange protocol. silc_client_connect_to_server_final
421 will be called after the protocol is finished. */
422 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
423 &protocol, (void *)proto_ctx,
424 silc_client_connect_to_server_second);
426 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
427 "Error: Could not start key exchange protocol");
428 silc_net_close_connection(conn->sock->sock);
429 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
432 conn->sock->protocol = protocol;
434 /* Register the connection for network input and output. This sets
435 that scheduler will listen for incoming packets for this connection
436 and sets that outgoing packets may be sent to this connection as well.
437 However, this doesn't set the scheduler for outgoing traffic, it will
438 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
439 later when outgoing data is available. */
440 context = (void *)client;
441 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(conn->sock->sock);
443 /* Execute the protocol */
444 silc_protocol_execute(protocol, client->schedule, 0, 0);
447 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
448 key material between client and server. This function can be called
449 directly if application is performing its own connecting and does not
450 use the connecting provided by this library. This function is normally
451 used only if the application performed the connecting outside the library.
452 The library however may use this internally. */
454 void silc_client_start_key_exchange(SilcClient client,
455 SilcClientConnection conn,
458 /* Allocate new socket connection object */
459 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
461 /* Sometimes when doing quick reconnects the new socket may be same as
462 the old one and there might be pending stuff for the old socket.
463 If new one is same then those pending sutff might cause problems.
464 Make sure they do not do that. */
465 silc_schedule_task_del_by_fd(client->schedule, fd);
467 conn->nickname = (client->nickname ? strdup(client->nickname) :
468 strdup(client->username));
470 /* Resolve the remote hostname and IP address for our socket connection */
471 silc_socket_host_lookup(conn->sock, FALSE, silc_client_start_key_exchange_cb,
472 conn, client->schedule);
475 /* Callback called when error has occurred during connecting (KE) to
476 the server. The `connect' client operation will be called. */
478 SILC_TASK_CALLBACK(silc_client_connect_failure)
480 SilcClientKEInternalContext *ctx =
481 (SilcClientKEInternalContext *)context;
482 SilcClient client = (SilcClient)ctx->client;
484 client->internal->ops->connected(client, ctx->sock->user_data,
485 SILC_CLIENT_CONN_ERROR);
487 silc_packet_context_free(ctx->packet);
491 /* Callback called when error has occurred during connecting (auth) to
492 the server. The `connect' client operation will be called. */
494 SILC_TASK_CALLBACK(silc_client_connect_failure_auth)
496 SilcClientConnAuthInternalContext *ctx =
497 (SilcClientConnAuthInternalContext *)context;
498 SilcClient client = (SilcClient)ctx->client;
500 client->internal->ops->connected(client, ctx->sock->user_data,
501 SILC_CLIENT_CONN_ERROR);
505 /* Start of the connection to the remote server. This is called after
506 succesful TCP/IP connection has been established to the remote host. */
508 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
510 SilcClientInternalConnectContext *ctx =
511 (SilcClientInternalConnectContext *)context;
512 SilcClient client = ctx->client;
513 SilcClientConnection conn = ctx->conn;
514 int opt, opt_len = sizeof(opt);
516 SILC_LOG_DEBUG(("Start"));
518 /* Check the socket status as it might be in error */
519 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
521 if (ctx->tries < 2) {
522 /* Connection failed but lets try again */
523 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
524 "Could not connect to server %s: %s",
525 ctx->host, strerror(opt));
526 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
527 "Connecting to port %d of server %s resumed",
528 ctx->port, ctx->host);
530 /* Unregister old connection try */
531 silc_schedule_unset_listen_fd(client->schedule, fd);
532 silc_net_close_connection(fd);
533 silc_schedule_task_del(client->schedule, ctx->task);
536 silc_client_connect_to_server_internal(ctx);
539 /* Connection failed and we won't try anymore */
540 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
541 "Could not connect to server %s: %s",
542 ctx->host, strerror(opt));
543 silc_schedule_unset_listen_fd(client->schedule, fd);
544 silc_net_close_connection(fd);
545 silc_schedule_task_del(client->schedule, ctx->task);
548 /* Notify application of failure */
549 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
550 silc_client_del_connection(client, conn);
555 silc_schedule_unset_listen_fd(client->schedule, fd);
556 silc_schedule_task_del(client->schedule, ctx->task);
559 silc_client_start_key_exchange(client, conn, fd);
562 /* Second part of the connecting to the server. This executed
563 authentication protocol. */
565 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
567 SilcProtocol protocol = (SilcProtocol)context;
568 SilcClientKEInternalContext *ctx =
569 (SilcClientKEInternalContext *)protocol->context;
570 SilcClient client = (SilcClient)ctx->client;
571 SilcSocketConnection sock = NULL;
572 SilcClientConnAuthInternalContext *proto_ctx;
574 SILC_LOG_DEBUG(("Start"));
576 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
577 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
578 /* Error occured during protocol */
579 SILC_LOG_DEBUG(("Error during KE protocol"));
580 silc_protocol_free(protocol);
581 silc_ske_free_key_material(ctx->keymat);
583 silc_ske_free(ctx->ske);
585 silc_free(ctx->dest_id);
586 ctx->sock->protocol = NULL;
587 silc_socket_free(ctx->sock);
589 /* Notify application of failure */
590 silc_schedule_task_add(client->schedule, ctx->sock->sock,
591 silc_client_connect_failure, ctx,
592 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
596 /* We now have the key material as the result of the key exchange
597 protocol. Take the key material into use. Free the raw key material
598 as soon as we've set them into use. */
599 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
600 ctx->ske->prop->cipher,
601 ctx->ske->prop->pkcs,
602 ctx->ske->prop->hash,
603 ctx->ske->prop->hmac,
604 ctx->ske->prop->group,
606 silc_ske_free_key_material(ctx->keymat);
608 /* Allocate internal context for the authentication protocol. This
609 is sent as context for the protocol. */
610 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
611 proto_ctx->client = (void *)client;
612 proto_ctx->sock = sock = ctx->sock;
613 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
614 proto_ctx->dest_id_type = ctx->dest_id_type;
615 proto_ctx->dest_id = ctx->dest_id;
617 /* Free old protocol as it is finished now */
618 silc_protocol_free(protocol);
620 silc_packet_context_free(ctx->packet);
623 sock->protocol = NULL;
625 /* Resolve the authentication method to be used in this connection. The
626 completion callback is called after the application has resolved
627 the authentication method. */
628 client->internal->ops->get_auth_method(client, sock->user_data,
631 silc_client_resolve_auth_method,
635 /* Authentication method resolving callback. Application calls this function
636 after we've called the client->internal->ops->get_auth_method
637 client operation to resolve the authentication method. We will continue
638 the executiong of the protocol in this function. */
640 void silc_client_resolve_auth_method(bool success,
641 SilcProtocolAuthMeth auth_meth,
642 const unsigned char *auth_data,
643 SilcUInt32 auth_data_len, void *context)
645 SilcClientConnAuthInternalContext *proto_ctx =
646 (SilcClientConnAuthInternalContext *)context;
647 SilcClient client = (SilcClient)proto_ctx->client;
650 auth_meth = SILC_AUTH_NONE;
652 proto_ctx->auth_meth = auth_meth;
654 if (success && auth_data && auth_data_len) {
656 /* Passphrase must be UTF-8 encoded, if it isn't encode it */
657 if (auth_meth == SILC_AUTH_PASSWORD &&
658 !silc_utf8_valid(auth_data, auth_data_len)) {
660 unsigned char *autf8 = NULL;
661 payload_len = silc_utf8_encoded_len(auth_data, auth_data_len,
663 autf8 = silc_calloc(payload_len, sizeof(*autf8));
664 auth_data_len = silc_utf8_encode(auth_data, auth_data_len,
665 SILC_STRING_ASCII, autf8, payload_len);
669 proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
670 proto_ctx->auth_data_len = auth_data_len;
673 /* Allocate the authenteication protocol and execute it. */
674 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
675 &proto_ctx->sock->protocol, (void *)proto_ctx,
676 silc_client_connect_to_server_final);
678 /* Execute the protocol */
679 silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
682 /* Finalizes the connection to the remote SILC server. This is called
683 after authentication protocol has been completed. This send our
684 user information to the server to receive our client ID from
687 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
689 SilcProtocol protocol = (SilcProtocol)context;
690 SilcClientConnAuthInternalContext *ctx =
691 (SilcClientConnAuthInternalContext *)protocol->context;
692 SilcClient client = (SilcClient)ctx->client;
693 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
696 SILC_LOG_DEBUG(("Start"));
698 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
699 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
700 /* Error occured during protocol */
701 SILC_LOG_DEBUG(("Error during authentication protocol"));
705 if (conn->params.detach_data) {
706 /* Send RESUME_CLIENT packet to the server, which is used to resume
707 old detached session back. */
709 SilcClientID *old_client_id;
710 unsigned char *old_id;
711 SilcUInt16 old_id_len;
713 if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len))
716 old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT);
717 if (!old_client_id) {
722 /* Generate authentication data that server will verify */
723 auth = silc_auth_public_key_auth_generate(client->public_key,
725 client->rng, conn->hash,
726 old_client_id, SILC_ID_CLIENT);
728 silc_free(old_client_id);
733 packet = silc_buffer_alloc_size(2 + old_id_len + auth->len);
734 silc_buffer_format(packet,
735 SILC_STR_UI_SHORT(old_id_len),
736 SILC_STR_UI_XNSTRING(old_id, old_id_len),
737 SILC_STR_UI_XNSTRING(auth->data, auth->len),
740 /* Send the packet */
741 silc_client_packet_send(client, ctx->sock, SILC_PACKET_RESUME_CLIENT,
743 packet->data, packet->len, TRUE);
744 silc_buffer_free(packet);
745 silc_buffer_free(auth);
746 silc_free(old_client_id);
749 /* Send NEW_CLIENT packet to the server. We will become registered
750 to the SILC network after sending this packet and we will receive
751 client ID from the server. */
752 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
753 strlen(client->realname));
754 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
755 silc_buffer_format(packet,
756 SILC_STR_UI_SHORT(strlen(client->username)),
757 SILC_STR_UI_XNSTRING(client->username,
758 strlen(client->username)),
759 SILC_STR_UI_SHORT(strlen(client->realname)),
760 SILC_STR_UI_XNSTRING(client->realname,
761 strlen(client->realname)),
764 /* Send the packet */
765 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
767 packet->data, packet->len, TRUE);
768 silc_buffer_free(packet);
771 /* Save remote ID. */
772 conn->remote_id = ctx->dest_id;
773 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
774 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
776 /* Register re-key timeout */
777 conn->rekey->timeout = client->internal->params->rekey_secs;
778 conn->rekey->context = (void *)client;
779 silc_schedule_task_add(client->schedule, conn->sock->sock,
780 silc_client_rekey_callback,
781 (void *)conn->sock, conn->rekey->timeout, 0,
782 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
784 silc_protocol_free(protocol);
785 silc_free(ctx->auth_data);
787 silc_ske_free(ctx->ske);
788 silc_socket_free(ctx->sock);
790 conn->sock->protocol = NULL;
794 silc_protocol_free(protocol);
795 silc_free(ctx->auth_data);
796 silc_free(ctx->dest_id);
798 silc_ske_free(ctx->ske);
799 conn->sock->protocol = NULL;
800 silc_socket_free(ctx->sock);
802 /* Notify application of failure */
803 silc_schedule_task_add(client->schedule, ctx->sock->sock,
804 silc_client_connect_failure_auth, ctx,
805 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
808 /* Internal routine that sends packet or marks packet to be sent. This
809 is used directly only in special cases. Normal cases should use
810 silc_server_packet_send. Returns < 0 on error. */
812 int silc_client_packet_send_real(SilcClient client,
813 SilcSocketConnection sock,
818 /* If rekey protocol is active we must assure that all packets are
819 sent through packet queue. */
820 if (SILC_CLIENT_IS_REKEY(sock))
823 /* If outbound data is already pending do not force send */
824 if (SILC_IS_OUTBUF_PENDING(sock))
827 /* Send the packet */
828 ret = silc_packet_send(sock, force_send);
832 /* Mark that there is some outgoing data available for this connection.
833 This call sets the connection both for input and output (the input
834 is set always and this call keeps the input setting, actually).
835 Actual data sending is performed by silc_client_packet_process. */
836 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
838 /* Mark to socket that data is pending in outgoing buffer. This flag
839 is needed if new data is added to the buffer before the earlier
840 put data is sent to the network. */
841 SILC_SET_OUTBUF_PENDING(sock);
846 /* Packet processing callback. This is used to send and receive packets
847 from network. This is generic task. */
849 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
851 SilcClient client = (SilcClient)context;
852 SilcSocketConnection sock = NULL;
853 SilcClientConnection conn;
856 SILC_LOG_DEBUG(("Processing packet"));
858 SILC_CLIENT_GET_SOCK(client, fd, sock);
862 conn = (SilcClientConnection)sock->user_data;
865 if (type == SILC_TASK_WRITE) {
866 /* Do not send data to disconnected connection */
867 if (SILC_IS_DISCONNECTED(sock))
870 ret = silc_packet_send(sock, TRUE);
872 /* If returned -2 could not write to connection now, will do
881 /* The packet has been sent and now it is time to set the connection
882 back to only for input. When there is again some outgoing data
883 available for this connection it will be set for output as well.
884 This call clears the output setting and sets it only for input. */
885 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
886 SILC_UNSET_OUTBUF_PENDING(sock);
888 silc_buffer_clear(sock->outbuf);
892 /* Packet receiving */
893 if (type == SILC_TASK_READ) {
894 /* Read data from network */
895 ret = silc_packet_receive(sock);
901 SILC_LOG_DEBUG(("Read EOF"));
903 /* If connection is disconnecting already we will finally
904 close the connection */
905 if (SILC_IS_DISCONNECTING(sock)) {
906 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
907 client->internal->ops->disconnected(client, conn, 0, NULL);
908 silc_client_close_connection_real(client, sock, conn);
912 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
913 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
914 client->internal->ops->disconnected(client, conn, 0, NULL);
915 silc_client_close_connection_real(client, sock, conn);
919 /* Process the packet. This will call the parser that will then
920 decrypt and parse the packet. */
921 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
922 silc_packet_receive_process(sock, FALSE, conn->receive_key,
923 conn->hmac_receive, conn->psn_receive,
924 silc_client_packet_parse, client);
926 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
927 silc_client_packet_parse, client);
931 /* Parser callback called by silc_packet_receive_process. Thie merely
932 registers timeout that will handle the actual parsing when appropriate. */
934 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
937 SilcClient client = (SilcClient)context;
938 SilcSocketConnection sock = parser_context->sock;
939 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
940 SilcPacketContext *packet = parser_context->packet;
943 if (conn && conn->hmac_receive && conn->sock == sock)
944 conn->psn_receive = parser_context->packet->sequence + 1;
946 /* Parse the packet immediately */
947 if (parser_context->normal)
948 ret = silc_packet_parse(packet, conn->receive_key);
950 ret = silc_packet_parse_special(packet, conn->receive_key);
952 if (ret == SILC_PACKET_NONE) {
953 silc_packet_context_free(packet);
954 silc_free(parser_context);
958 /* If protocol for this connection is key exchange or rekey then we'll
959 process all packets synchronously, since there might be packets in
960 queue that we are not able to decrypt without first processing the
961 packets before them. */
962 if ((ret == SILC_PACKET_REKEY || ret == SILC_PACKET_REKEY_DONE) ||
963 (sock->protocol && sock->protocol->protocol &&
964 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
965 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY))) {
967 /* Parse the incoming packet type */
968 silc_client_packet_parse_type(client, sock, packet);
969 silc_packet_context_free(packet);
970 silc_free(parser_context);
972 /* Reprocess the buffer since we'll return FALSE. This is because
973 the `conn->receive_key' might have become valid by processing
974 the previous packet */
975 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
976 silc_packet_receive_process(sock, FALSE, conn->receive_key,
977 conn->hmac_receive, conn->psn_receive,
978 silc_client_packet_parse, client);
980 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
981 silc_client_packet_parse, client);
986 /* Parse the incoming packet type */
987 silc_client_packet_parse_type(client, sock, packet);
988 silc_packet_context_free(packet);
989 silc_free(parser_context);
993 /* Parses the packet type and calls what ever routines the packet type
994 requires. This is done for all incoming packets. */
996 void silc_client_packet_parse_type(SilcClient client,
997 SilcSocketConnection sock,
998 SilcPacketContext *packet)
1000 SilcBuffer buffer = packet->buffer;
1001 SilcPacketType type = packet->type;
1003 SILC_LOG_DEBUG(("Parsing %s packet", silc_get_packet_name(type)));
1005 /* Parse the packet type */
1008 case SILC_PACKET_DISCONNECT:
1009 silc_client_disconnected_by_server(client, sock, buffer);
1012 case SILC_PACKET_SUCCESS:
1014 * Success received for something. For now we can have only
1015 * one protocol for connection executing at once hence this
1016 * success message is for whatever protocol is executing currently.
1019 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1022 case SILC_PACKET_FAILURE:
1024 * Failure received for some protocol. Set the protocol state to
1025 * error and call the protocol callback. This fill cause error on
1026 * protocol and it will call the final callback.
1028 silc_client_process_failure(client, sock, packet);
1031 case SILC_PACKET_REJECT:
1034 case SILC_PACKET_NOTIFY:
1036 * Received notify message
1038 silc_client_notify_by_server(client, sock, packet);
1041 case SILC_PACKET_ERROR:
1043 * Received error message
1045 silc_client_error_by_server(client, sock, buffer);
1048 case SILC_PACKET_CHANNEL_MESSAGE:
1050 * Received message to (from, actually) a channel
1052 silc_client_channel_message(client, sock, packet);
1055 case SILC_PACKET_CHANNEL_KEY:
1057 * Received key for a channel. By receiving this key the client will be
1058 * able to talk to the channel it has just joined. This can also be
1059 * a new key for existing channel as keys expire peridiocally.
1061 silc_client_receive_channel_key(client, sock, buffer);
1064 case SILC_PACKET_PRIVATE_MESSAGE:
1066 * Received private message
1068 silc_client_private_message(client, sock, packet);
1071 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1073 * Received private message key
1077 case SILC_PACKET_COMMAND:
1079 * Received command packet, a special case since normally client
1080 * does not receive commands.
1082 silc_client_command_process(client, sock, packet);
1085 case SILC_PACKET_COMMAND_REPLY:
1087 * Recived reply for a command
1089 silc_client_command_reply_process(client, sock, packet);
1092 case SILC_PACKET_KEY_EXCHANGE:
1093 if (sock->protocol && sock->protocol->protocol &&
1094 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
1095 SilcClientKEInternalContext *proto_ctx =
1096 (SilcClientKEInternalContext *)sock->protocol->context;
1098 proto_ctx->packet = silc_packet_context_dup(packet);
1099 proto_ctx->dest_id_type = packet->src_id_type;
1100 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1101 packet->src_id_type);
1102 if (!proto_ctx->dest_id)
1105 /* Let the protocol handle the packet */
1106 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1108 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1109 "protocol active, packet dropped."));
1113 case SILC_PACKET_KEY_EXCHANGE_1:
1114 if (sock->protocol && sock->protocol->protocol &&
1115 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1116 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1118 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1119 SilcClientRekeyInternalContext *proto_ctx =
1120 (SilcClientRekeyInternalContext *)sock->protocol->context;
1122 if (proto_ctx->packet)
1123 silc_packet_context_free(proto_ctx->packet);
1125 proto_ctx->packet = silc_packet_context_dup(packet);
1127 /* Let the protocol handle the packet */
1128 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1130 SilcClientKEInternalContext *proto_ctx =
1131 (SilcClientKEInternalContext *)sock->protocol->context;
1133 if (proto_ctx->packet)
1134 silc_packet_context_free(proto_ctx->packet);
1136 proto_ctx->packet = silc_packet_context_dup(packet);
1137 proto_ctx->dest_id_type = packet->src_id_type;
1138 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1139 packet->src_id_type);
1140 if (!proto_ctx->dest_id)
1143 /* Let the protocol handle the packet */
1144 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1147 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1148 "protocol active, packet dropped."));
1152 case SILC_PACKET_KEY_EXCHANGE_2:
1153 if (sock->protocol && sock->protocol->protocol &&
1154 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1155 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1157 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1158 SilcClientRekeyInternalContext *proto_ctx =
1159 (SilcClientRekeyInternalContext *)sock->protocol->context;
1161 if (proto_ctx->packet)
1162 silc_packet_context_free(proto_ctx->packet);
1164 proto_ctx->packet = silc_packet_context_dup(packet);
1166 /* Let the protocol handle the packet */
1167 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1169 SilcClientKEInternalContext *proto_ctx =
1170 (SilcClientKEInternalContext *)sock->protocol->context;
1172 if (proto_ctx->packet)
1173 silc_packet_context_free(proto_ctx->packet);
1174 if (proto_ctx->dest_id)
1175 silc_free(proto_ctx->dest_id);
1176 proto_ctx->packet = silc_packet_context_dup(packet);
1177 proto_ctx->dest_id_type = packet->src_id_type;
1178 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1179 packet->src_id_type);
1180 if (!proto_ctx->dest_id)
1183 /* Let the protocol handle the packet */
1184 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1187 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1188 "protocol active, packet dropped."));
1192 case SILC_PACKET_NEW_ID:
1195 * Received new ID from server. This packet is received at
1196 * the connection to the server. New ID is also received when
1197 * user changes nickname but in that case the new ID is received
1198 * as command reply and not as this packet type.
1202 idp = silc_id_payload_parse(buffer->data, buffer->len);
1205 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1208 silc_client_receive_new_id(client, sock, idp);
1209 silc_id_payload_free(idp);
1213 case SILC_PACKET_HEARTBEAT:
1215 * Received heartbeat packet
1217 SILC_LOG_DEBUG(("Heartbeat packet"));
1220 case SILC_PACKET_KEY_AGREEMENT:
1222 * Received key agreement packet
1224 SILC_LOG_DEBUG(("Key agreement packet"));
1225 silc_client_key_agreement(client, sock, packet);
1228 case SILC_PACKET_REKEY:
1229 SILC_LOG_DEBUG(("Re-key packet"));
1230 /* We ignore this for now */
1233 case SILC_PACKET_REKEY_DONE:
1234 SILC_LOG_DEBUG(("Re-key done packet"));
1236 if (sock->protocol && sock->protocol->protocol &&
1237 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1239 SilcClientRekeyInternalContext *proto_ctx =
1240 (SilcClientRekeyInternalContext *)sock->protocol->context;
1242 if (proto_ctx->packet)
1243 silc_packet_context_free(proto_ctx->packet);
1245 proto_ctx->packet = silc_packet_context_dup(packet);
1247 /* Let the protocol handle the packet */
1248 if (proto_ctx->responder == FALSE)
1249 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1251 /* Let the protocol handle the packet */
1252 silc_protocol_execute(sock->protocol, client->schedule,
1255 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1256 "protocol active, packet dropped."));
1260 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1262 * Reveived reply to our connection authentication method request
1263 * packet. This is used to resolve the authentication method for the
1264 * current session from the server if the client does not know it.
1266 silc_client_connection_auth_request(client, sock, packet);
1269 case SILC_PACKET_FTP:
1270 /* Received file transfer packet. */
1271 silc_client_ftp(client, sock, packet);
1275 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1280 /* Sends packet. This doesn't actually send the packet instead it assembles
1281 it and marks it to be sent. However, if force_send is TRUE the packet
1282 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1283 will be derived from sock argument. Otherwise the valid arguments sent
1286 void silc_client_packet_send(SilcClient client,
1287 SilcSocketConnection sock,
1288 SilcPacketType type,
1290 SilcIdType dst_id_type,
1293 unsigned char *data,
1294 SilcUInt32 data_len,
1297 SilcPacketContext packetdata;
1298 const SilcBufferStruct packet;
1300 SilcUInt32 sequence = 0;
1305 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1307 /* Get data used in the packet sending, keys and stuff */
1308 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1309 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1310 cipher = ((SilcClientConnection)sock->user_data)->send_key;
1312 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1313 hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1315 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1316 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1317 dst_id_type = SILC_ID_SERVER;
1321 sequence = ((SilcClientConnection)sock->user_data)->psn_send++;
1324 block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1326 /* Set the packet context pointers */
1327 packetdata.flags = 0;
1328 packetdata.type = type;
1329 if (sock->user_data &&
1330 ((SilcClientConnection)sock->user_data)->local_id_data) {
1331 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1332 packetdata.src_id_len =
1333 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1336 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1337 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1339 packetdata.src_id_type = SILC_ID_CLIENT;
1341 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1342 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1343 packetdata.dst_id_type = dst_id_type;
1345 packetdata.dst_id = NULL;
1346 packetdata.dst_id_len = 0;
1347 packetdata.dst_id_type = SILC_ID_NONE;
1349 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1350 packetdata.src_id_len +
1351 packetdata.dst_id_len));
1352 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1353 packetdata.src_id_len + packetdata.dst_id_len;
1354 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
1356 /* Create the outgoing packet */
1357 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
1358 data, data_len, (const SilcBuffer)&packet)) {
1359 SILC_LOG_ERROR(("Error assembling packet"));
1363 /* Encrypt the packet */
1365 silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet,
1368 SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
1369 packet.data, packet.len);
1371 /* Now actually send the packet */
1372 silc_client_packet_send_real(client, sock, force_send);
1375 void silc_client_packet_queue_purge(SilcClient client,
1376 SilcSocketConnection sock)
1378 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1379 (SILC_IS_DISCONNECTED(sock) == FALSE)) {
1380 silc_packet_send(sock, TRUE);
1381 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1382 SILC_UNSET_OUTBUF_PENDING(sock);
1383 silc_buffer_clear(sock->outbuf);
1387 /* Closes connection to remote end. Free's all allocated data except
1388 for some information such as nickname etc. that are valid at all time.
1389 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1390 provided it will be checked whether the sock and `conn->sock' are the
1391 same (they can be different, ie. a socket can use `conn' as its
1392 connection but `conn->sock' might be actually a different connection
1393 than the `sock'). */
1395 void silc_client_close_connection_real(SilcClient client,
1396 SilcSocketConnection sock,
1397 SilcClientConnection conn)
1401 SILC_LOG_DEBUG(("Start"));
1406 if (!sock || (sock && conn->sock == sock))
1411 /* We won't listen for this connection anymore */
1412 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1414 /* Unregister all tasks */
1415 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1417 /* Close the actual connection */
1418 silc_net_close_connection(sock->sock);
1420 /* Cancel any active protocol */
1421 if (sock->protocol) {
1422 if (sock->protocol->protocol->type ==
1423 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1424 sock->protocol->protocol->type ==
1425 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1426 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1427 silc_protocol_execute_final(sock->protocol, client->schedule);
1428 /* The application will recall this function with these protocols
1429 (the ops->connected client operation). */
1432 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1433 silc_protocol_execute_final(sock->protocol, client->schedule);
1434 sock->protocol = NULL;
1438 /* Free everything */
1439 if (del && sock->user_data) {
1440 /* Free all cache entries */
1441 SilcIDCacheList list;
1442 SilcIDCacheEntry entry;
1443 SilcClientCommandPending *r;
1446 if (silc_idcache_get_all(conn->client_cache, &list)) {
1447 ret = silc_idcache_list_first(list, &entry);
1449 silc_client_del_client(client, conn, entry->context);
1450 ret = silc_idcache_list_next(list, &entry);
1452 silc_idcache_list_free(list);
1455 if (silc_idcache_get_all(conn->channel_cache, &list)) {
1456 ret = silc_idcache_list_first(list, &entry);
1458 silc_client_del_channel(client, conn, entry->context);
1459 ret = silc_idcache_list_next(list, &entry);
1461 silc_idcache_list_free(list);
1464 if (silc_idcache_get_all(conn->server_cache, &list)) {
1465 ret = silc_idcache_list_first(list, &entry);
1467 silc_client_del_server(client, conn, entry->context);
1468 ret = silc_idcache_list_next(list, &entry);
1470 silc_idcache_list_free(list);
1473 /* Clear ID caches */
1474 if (conn->client_cache)
1475 silc_idcache_free(conn->client_cache);
1476 if (conn->channel_cache)
1477 silc_idcache_free(conn->channel_cache);
1478 if (conn->server_cache)
1479 silc_idcache_free(conn->server_cache);
1481 /* Free data (my ID is freed in above silc_client_del_client).
1482 conn->nickname is freed when freeing the local_entry->nickname. */
1483 if (conn->remote_host)
1484 silc_free(conn->remote_host);
1485 if (conn->local_id_data)
1486 silc_free(conn->local_id_data);
1488 silc_cipher_free(conn->send_key);
1489 if (conn->receive_key)
1490 silc_cipher_free(conn->receive_key);
1491 if (conn->hmac_send)
1492 silc_hmac_free(conn->hmac_send);
1493 if (conn->hmac_receive)
1494 silc_hmac_free(conn->hmac_receive);
1496 silc_free(conn->rekey);
1498 if (conn->active_session) {
1499 sock->user_data = NULL;
1500 silc_client_ftp_session_free(conn->active_session);
1501 conn->active_session = NULL;
1504 silc_client_ftp_free_sessions(client, conn);
1506 silc_dlist_start(conn->pending_commands);
1507 while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END)
1508 silc_dlist_del(conn->pending_commands, r);
1509 if (conn->pending_commands)
1510 silc_dlist_uninit(conn->pending_commands);
1512 memset(conn, 0, sizeof(*conn));
1513 silc_client_del_connection(client, conn);
1516 silc_socket_free(sock);
1519 /* Closes the connection to the remote end */
1521 void silc_client_close_connection(SilcClient client,
1522 SilcClientConnection conn)
1524 silc_client_close_connection_real(client, NULL, conn);
1527 /* Called when we receive disconnection packet from server. This
1528 closes our end properly and displays the reason of the disconnection
1531 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1533 SilcClient client = (SilcClient)context;
1534 SilcSocketConnection sock;
1536 SILC_CLIENT_GET_SOCK(client, fd, sock);
1540 silc_client_close_connection_real(client, sock, sock->user_data);
1543 /* Called when we receive disconnection packet from server. This
1544 closes our end properly and displays the reason of the disconnection
1547 void silc_client_disconnected_by_server(SilcClient client,
1548 SilcSocketConnection sock,
1551 SilcClientConnection conn;
1553 char *message = NULL;
1555 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1557 if (packet->len < 1)
1560 status = (SilcStatus)packet->data[0];
1562 if (packet->len > 1 &&
1563 silc_utf8_valid(packet->data + 1, packet->len - 1))
1564 message = silc_memdup(packet->data + 1, packet->len - 1);
1566 conn = (SilcClientConnection)sock->user_data;
1567 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1568 client->internal->ops->disconnected(client, conn, status, message);
1572 SILC_SET_DISCONNECTED(sock);
1574 /* Close connection through scheduler. */
1575 silc_schedule_task_add(client->schedule, sock->sock,
1576 silc_client_disconnected_by_server_later,
1577 client, 0, 1, SILC_TASK_TIMEOUT,
1578 SILC_TASK_PRI_NORMAL);
1581 /* Received error message from server. Display it on the screen.
1582 We don't take any action what so ever of the error message. */
1584 void silc_client_error_by_server(SilcClient client,
1585 SilcSocketConnection sock,
1590 msg = silc_memdup(message->data, message->len);
1591 client->internal->ops->say(client, sock->user_data,
1592 SILC_CLIENT_MESSAGE_AUDIT, msg);
1596 /* Auto-nicking callback to send NICK command to server. */
1598 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1600 SilcClientConnection conn = (SilcClientConnection)context;
1601 SilcClient client = conn->client;
1603 silc_client_command_send(client, conn, SILC_COMMAND_NICK,
1604 ++conn->cmd_ident, 1, 1,
1605 client->nickname, strlen(client->nickname));
1608 /* Client session resuming callback. If the session was resumed
1609 this callback is called after the resuming is completed. This
1610 will call the `connect' client operation to the application
1611 since it has not been called yet. */
1613 static void silc_client_resume_session_cb(SilcClient client,
1614 SilcClientConnection conn,
1620 /* Notify application that connection is created to server */
1621 client->internal->ops->connected(client, conn, success ?
1622 SILC_CLIENT_CONN_SUCCESS_RESUME :
1623 SILC_CLIENT_CONN_ERROR);
1626 /* Issue INFO command to fetch the real server name and server
1627 information and other stuff. */
1628 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1629 silc_client_command_reply_info_i, 0,
1631 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1632 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1633 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1634 silc_buffer_free(sidp);
1638 /* Processes the received new Client ID from server. Old Client ID is
1639 deleted from cache and new one is added. */
1641 void silc_client_receive_new_id(SilcClient client,
1642 SilcSocketConnection sock,
1645 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1646 int connecting = FALSE;
1647 SilcClientID *client_id = silc_id_payload_get_id(idp);
1649 if (!conn->local_entry)
1652 /* Delete old ID from ID cache */
1653 if (conn->local_id) {
1654 /* Check whether they are different */
1655 if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1656 silc_free(client_id);
1660 silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1661 silc_free(conn->local_id);
1664 /* Save the new ID */
1666 if (conn->local_id_data)
1667 silc_free(conn->local_id_data);
1669 conn->local_id = client_id;
1670 conn->local_id_data = silc_id_payload_get_data(idp);
1671 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1673 if (!conn->local_entry)
1674 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1676 conn->local_entry->nickname = conn->nickname;
1677 if (!conn->local_entry->username)
1678 conn->local_entry->username = strdup(client->username);
1679 if (!conn->local_entry->server)
1680 conn->local_entry->server = strdup(conn->remote_host);
1681 conn->local_entry->id = conn->local_id;
1682 conn->local_entry->valid = TRUE;
1683 if (!conn->local_entry->channels)
1684 conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
1689 /* Put it to the ID cache */
1690 silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id,
1691 (void *)conn->local_entry, 0, NULL);
1696 /* Issue IDENTIFY command for itself to get resolved hostname
1697 correctly from server. */
1698 silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
1699 silc_client_command_reply_identify_i, 0,
1701 sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT);
1702 silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
1703 conn->cmd_ident, 1, 5, sidp->data, sidp->len);
1704 silc_buffer_free(sidp);
1706 if (!conn->params.detach_data) {
1707 /* Send NICK command if the nickname was set by the application (and is
1708 not same as the username). Send this with little timeout. */
1709 if (client->nickname && strcmp(client->nickname, client->username))
1710 silc_schedule_task_add(client->schedule, 0,
1711 silc_client_send_auto_nick, conn,
1712 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1714 /* Notify application of successful connection. We do it here now that
1715 we've received the Client ID and are allowed to send traffic. */
1716 client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_SUCCESS);
1718 /* Issue INFO command to fetch the real server name and server
1719 information and other stuff. */
1720 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1721 silc_client_command_reply_info_i, 0,
1723 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1724 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1725 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1726 silc_buffer_free(sidp);
1728 /* We are resuming session. Start resolving informations from the
1729 server we need to set the client libary in the state before
1730 detaching the session. The connect client operation is called
1731 after this is successfully completed */
1732 silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1738 /* Removes a client entry from all channels it has joined. */
1740 void silc_client_remove_from_channels(SilcClient client,
1741 SilcClientConnection conn,
1742 SilcClientEntry client_entry)
1744 SilcHashTableList htl;
1745 SilcChannelUser chu;
1747 silc_hash_table_list(client_entry->channels, &htl);
1748 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1749 silc_hash_table_del(chu->client->channels, chu->channel);
1750 silc_hash_table_del(chu->channel->user_list, chu->client);
1754 silc_hash_table_list_reset(&htl);
1757 /* Replaces `old' client entries from all channels to `new' client entry.
1758 This can be called for example when nickname changes and old ID entry
1759 is replaced from ID cache with the new one. If the old ID entry is only
1760 updated, then this fucntion needs not to be called. */
1762 void silc_client_replace_from_channels(SilcClient client,
1763 SilcClientConnection conn,
1764 SilcClientEntry old,
1765 SilcClientEntry new)
1767 SilcHashTableList htl;
1768 SilcChannelUser chu;
1770 silc_hash_table_list(old->channels, &htl);
1771 while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1772 /* Replace client entry */
1773 silc_hash_table_del(chu->client->channels, chu->channel);
1774 silc_hash_table_del(chu->channel->user_list, chu->client);
1777 silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1778 silc_hash_table_add(chu->client->channels, chu->channel, chu);
1780 silc_hash_table_list_reset(&htl);
1783 /* Registers failure timeout to process the received failure packet
1786 void silc_client_process_failure(SilcClient client,
1787 SilcSocketConnection sock,
1788 SilcPacketContext *packet)
1790 SilcUInt32 failure = 0;
1792 if (sock->protocol) {
1793 if (packet->buffer->len >= 4)
1794 SILC_GET32_MSB(failure, packet->buffer->data);
1796 /* Notify application */
1797 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1802 /* A timeout callback for the re-key. We will be the initiator of the
1805 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1807 SilcSocketConnection sock = (SilcSocketConnection)context;
1808 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1809 SilcClient client = (SilcClient)conn->rekey->context;
1810 SilcProtocol protocol;
1811 SilcClientRekeyInternalContext *proto_ctx;
1813 SILC_LOG_DEBUG(("Start"));
1815 /* Allocate internal protocol context. This is sent as context
1817 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1818 proto_ctx->client = (void *)client;
1819 proto_ctx->sock = silc_socket_dup(sock);
1820 proto_ctx->responder = FALSE;
1821 proto_ctx->pfs = conn->rekey->pfs;
1823 /* Perform rekey protocol. Will call the final callback after the
1824 protocol is over. */
1825 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1826 &protocol, proto_ctx, silc_client_rekey_final);
1827 sock->protocol = protocol;
1829 /* Run the protocol */
1830 silc_protocol_execute(protocol, client->schedule, 0, 0);
1832 /* Re-register re-key timeout */
1833 silc_schedule_task_add(client->schedule, sock->sock,
1834 silc_client_rekey_callback,
1835 context, conn->rekey->timeout, 0,
1836 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1839 /* The final callback for the REKEY protocol. This will actually take the
1840 new key material into use. */
1842 SILC_TASK_CALLBACK(silc_client_rekey_final)
1844 SilcProtocol protocol = (SilcProtocol)context;
1845 SilcClientRekeyInternalContext *ctx =
1846 (SilcClientRekeyInternalContext *)protocol->context;
1847 SilcClient client = (SilcClient)ctx->client;
1848 SilcSocketConnection sock = ctx->sock;
1850 SILC_LOG_DEBUG(("Start"));
1852 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1853 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1854 /* Error occured during protocol */
1855 silc_protocol_cancel(protocol, client->schedule);
1856 silc_protocol_free(protocol);
1857 sock->protocol = NULL;
1859 silc_packet_context_free(ctx->packet);
1861 silc_ske_free(ctx->ske);
1862 silc_socket_free(ctx->sock);
1867 /* Purge the outgoing data queue to assure that all rekey packets really
1868 go to the network before we quit the protocol. */
1869 silc_client_packet_queue_purge(client, sock);
1872 silc_protocol_free(protocol);
1873 sock->protocol = NULL;
1875 silc_packet_context_free(ctx->packet);
1877 silc_ske_free(ctx->ske);
1878 silc_socket_free(ctx->sock);
1882 /* Processes incoming connection authentication method request packet.
1883 It is a reply to our previously sent request. The packet can be used
1884 to resolve the authentication method for the current session if the
1885 client does not know it beforehand. */
1887 void silc_client_connection_auth_request(SilcClient client,
1888 SilcSocketConnection sock,
1889 SilcPacketContext *packet)
1891 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1892 SilcUInt16 conn_type, auth_meth;
1895 /* If we haven't send our request then ignore this one. */
1896 if (!conn->connauth)
1899 /* Parse the payload */
1900 ret = silc_buffer_unformat(packet->buffer,
1901 SILC_STR_UI_SHORT(&conn_type),
1902 SILC_STR_UI_SHORT(&auth_meth),
1905 auth_meth = SILC_AUTH_NONE;
1907 /* Call the request callback to notify application for received
1908 authentication method information. */
1909 if (conn->connauth->callback)
1910 (*conn->connauth->callback)(client, conn, auth_meth,
1911 conn->connauth->context);
1913 silc_schedule_task_del(client->schedule, conn->connauth->timeout);
1915 silc_free(conn->connauth);
1916 conn->connauth = NULL;
1919 /* Timeout task callback called if the server does not reply to our
1920 connection authentication method request in the specified time interval. */
1922 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1924 SilcClientConnection conn = (SilcClientConnection)context;
1925 SilcClient client = conn->client;
1927 if (!conn->connauth)
1930 /* Call the request callback to notify application */
1931 if (conn->connauth->callback)
1932 (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE,
1933 conn->connauth->context);
1935 silc_free(conn->connauth);
1936 conn->connauth = NULL;
1939 /* This function can be used to request the current authentication method
1940 from the server. This may be called when connecting to the server
1941 and the client library requests the authentication data from the
1942 application. If the application does not know the current authentication
1943 method it can request it from the server using this function.
1944 The `callback' with `context' will be called after the server has
1945 replied back with the current authentication method. */
1948 silc_client_request_authentication_method(SilcClient client,
1949 SilcClientConnection conn,
1950 SilcConnectionAuthRequest callback,
1953 SilcClientConnAuthRequest connauth;
1956 connauth = silc_calloc(1, sizeof(*connauth));
1957 connauth->callback = callback;
1958 connauth->context = context;
1961 silc_free(conn->connauth);
1963 conn->connauth = connauth;
1965 /* Assemble the request packet and send it to the server */
1966 packet = silc_buffer_alloc(4);
1967 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1968 silc_buffer_format(packet,
1969 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
1970 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
1972 silc_client_packet_send(client, conn->sock,
1973 SILC_PACKET_CONNECTION_AUTH_REQUEST,
1974 NULL, 0, NULL, NULL,
1975 packet->data, packet->len, FALSE);
1976 silc_buffer_free(packet);
1978 /* Register a timeout in case server does not reply anything back. */
1980 silc_schedule_task_add(client->schedule, conn->sock->sock,
1981 silc_client_request_authentication_method_timeout,
1983 client->internal->params->connauth_request_secs, 0,
1984 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);