5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "clientlibincludes.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_packet_parse_real);
30 SILC_TASK_CALLBACK(silc_client_rekey_callback);
31 SILC_TASK_CALLBACK(silc_client_rekey_final);
33 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
34 static void silc_client_packet_parse_type(SilcClient client,
35 SilcSocketConnection sock,
36 SilcPacketContext *packet);
38 /* Allocates new client object. This has to be done before client may
39 work. After calling this one must call silc_client_init to initialize
40 the client. The `application' is application specific user data pointer
41 and caller must free it. */
43 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application,
44 const char *silc_version)
46 SilcClient new_client;
48 new_client = silc_calloc(1, sizeof(*new_client));
49 new_client->application = application;
50 new_client->ops = ops;
51 new_client->silc_client_version = strdup(silc_version);
56 /* Frees client object and its internals. */
58 void silc_client_free(SilcClient client)
62 silc_rng_free(client->rng);
68 /* Initializes the client. This makes all the necessary steps to make
69 the client ready to be run. One must call silc_client_run to run the
70 client. Returns FALSE if error occured, TRUE otherwise. */
72 int silc_client_init(SilcClient client)
74 SILC_LOG_DEBUG(("Initializing client"));
76 /* Initialize hash functions for client to use */
77 silc_hash_alloc("md5", &client->md5hash);
78 silc_hash_alloc("sha1", &client->sha1hash);
80 /* Initialize none cipher */
81 silc_cipher_alloc("none", &client->none_cipher);
83 /* Initialize random number generator */
84 client->rng = silc_rng_alloc();
85 silc_rng_init(client->rng);
86 silc_rng_global_init(client->rng);
88 /* Register protocols */
89 silc_client_protocols_register();
91 /* Initialize the scheduler */
92 client->schedule = silc_schedule_init(&client->io_queue,
93 &client->timeout_queue,
94 &client->generic_queue, 5000);
95 if (!client->schedule)
101 /* Stops the client. This is called to stop the client and thus to stop
104 void silc_client_stop(SilcClient client)
106 SILC_LOG_DEBUG(("Stopping client"));
108 /* Stop the scheduler, although it might be already stopped. This
109 doesn't hurt anyone. This removes all the tasks and task queues,
111 silc_schedule_stop(client->schedule);
112 silc_schedule_uninit(client->schedule);
114 silc_client_protocols_unregister();
116 SILC_LOG_DEBUG(("Client stopped"));
119 /* Runs the client. This starts the scheduler from the utility library.
120 When this functions returns the execution of the appliation is over. */
122 void silc_client_run(SilcClient client)
124 SILC_LOG_DEBUG(("Running client"));
126 /* Start the scheduler, the heart of the SILC client. When this returns
127 the program will be terminated. */
128 silc_schedule(client->schedule);
131 /* Allocates and adds new connection to the client. This adds the allocated
132 connection to the connection table and returns a pointer to it. A client
133 can have multiple connections to multiple servers. Every connection must
134 be added to the client using this function. User data `context' may
135 be sent as argument. This function is normally used only if the
136 application performed the connecting outside the library. The library
137 however may use this internally. */
139 SilcClientConnection silc_client_add_connection(SilcClient client,
144 SilcClientConnection conn;
147 conn = silc_calloc(1, sizeof(*conn));
149 /* Initialize ID caches */
150 conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, NULL);
151 conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
152 conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
153 conn->client = client;
154 conn->remote_host = strdup(hostname);
155 conn->remote_port = port;
156 conn->context = context;
157 conn->pending_commands = silc_dlist_init();
159 /* Add the connection to connections table */
160 for (i = 0; i < client->conns_count; i++)
161 if (client->conns && !client->conns[i]) {
162 client->conns[i] = conn;
166 client->conns = silc_realloc(client->conns, sizeof(*client->conns)
167 * (client->conns_count + 1));
168 client->conns[client->conns_count] = conn;
169 client->conns_count++;
174 /* Removes connection from client. Frees all memory. */
176 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
180 for (i = 0; i < client->conns_count; i++)
181 if (client->conns[i] == conn) {
182 if (conn->pending_commands)
183 silc_dlist_uninit(conn->pending_commands);
185 client->conns[i] = NULL;
189 /* Adds listener socket to the listener sockets table. This function is
190 used to add socket objects that are listeners to the client. This should
191 not be used to add other connection objects. */
193 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
197 if (!client->sockets) {
198 client->sockets = silc_calloc(1, sizeof(*client->sockets));
199 client->sockets[0] = silc_socket_dup(sock);
200 client->sockets_count = 1;
204 for (i = 0; i < client->sockets_count; i++) {
205 if (client->sockets[i] == NULL) {
206 client->sockets[i] = silc_socket_dup(sock);
211 client->sockets = silc_realloc(client->sockets, sizeof(*client->sockets) *
212 (client->sockets_count + 1));
213 client->sockets[client->sockets_count] = silc_socket_dup(sock);
214 client->sockets_count++;
217 /* Deletes listener socket from the listener sockets table. */
219 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
223 if (!client->sockets)
226 for (i = 0; i < client->sockets_count; i++) {
227 if (client->sockets[i] == sock) {
228 silc_socket_free(sock);
229 client->sockets[i] = NULL;
236 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
240 /* XXX In the future we should give up this non-blocking connect all
241 together and use threads instead. */
242 /* Create connection to server asynchronously */
243 sock = silc_net_create_connection_async(ctx->port, ctx->host);
247 /* Register task that will receive the async connect and will
249 ctx->task = silc_task_register(ctx->client->io_queue, sock,
250 silc_client_connect_to_server_start,
253 SILC_TASK_PRI_NORMAL);
254 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
255 silc_schedule_set_listen_fd(ctx->client->schedule, sock, ctx->task->iomask);
262 /* Connects to remote server. This is the main routine used to connect
263 to SILC server. Returns -1 on error and the created socket otherwise.
264 The `context' is user context that is saved into the SilcClientConnection
265 that is created after the connection is created. Note that application
266 may handle the connecting process outside the library. If this is the
267 case then this function is not used at all. When the connecting is
268 done the `connect' client operation is called. */
270 int silc_client_connect_to_server(SilcClient client, int port,
271 char *host, void *context)
273 SilcClientInternalConnectContext *ctx;
274 SilcClientConnection conn;
277 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
280 conn = silc_client_add_connection(client, host, port, context);
282 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
283 "Connecting to port %d of server %s", port, host);
285 /* Allocate internal context for connection process. This is
286 needed as we are doing async connecting. */
287 ctx = silc_calloc(1, sizeof(*ctx));
288 ctx->client = client;
290 ctx->host = strdup(host);
294 /* Do the actual connecting process */
295 sock = silc_client_connect_to_server_internal(ctx);
297 silc_client_del_connection(client, conn);
301 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
302 key material between client and server. This function can be called
303 directly if application is performing its own connecting and does not
304 use the connecting provided by this library. This function is normally
305 used only if the application performed the connecting outside the library.
306 The library however may use this internally. */
308 int silc_client_start_key_exchange(SilcClient client,
309 SilcClientConnection conn,
312 SilcProtocol protocol;
313 SilcClientKEInternalContext *proto_ctx;
316 /* Allocate new socket connection object */
317 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
319 conn->nickname = strdup(client->username);
320 conn->sock->hostname = conn->remote_host;
321 conn->sock->ip = strdup(conn->remote_host);
322 conn->sock->port = conn->remote_port;
324 /* Allocate internal Key Exchange context. This is sent to the
325 protocol as context. */
326 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
327 proto_ctx->client = (void *)client;
328 proto_ctx->sock = silc_socket_dup(conn->sock);
329 proto_ctx->rng = client->rng;
330 proto_ctx->responder = FALSE;
331 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
332 proto_ctx->verify = silc_client_protocol_ke_verify_key;
334 /* Perform key exchange protocol. silc_client_connect_to_server_final
335 will be called after the protocol is finished. */
336 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
337 &protocol, (void *)proto_ctx,
338 silc_client_connect_to_server_second);
340 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
341 "Error: Could not start authentication protocol");
344 conn->sock->protocol = protocol;
346 /* Register the connection for network input and output. This sets
347 that scheduler will listen for incoming packets for this connection
348 and sets that outgoing packets may be sent to this connection as well.
349 However, this doesn't set the scheduler for outgoing traffic, it will
350 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
351 later when outgoing data is available. */
352 context = (void *)client;
353 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
355 /* Execute the protocol */
356 silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
360 /* Start of the connection to the remote server. This is called after
361 succesful TCP/IP connection has been established to the remote host. */
363 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
365 SilcClientInternalConnectContext *ctx =
366 (SilcClientInternalConnectContext *)context;
367 SilcClient client = ctx->client;
368 SilcClientConnection conn = ctx->conn;
369 int opt, opt_len = sizeof(opt);
371 SILC_LOG_DEBUG(("Start"));
373 /* Check the socket status as it might be in error */
374 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
376 if (ctx->tries < 2) {
377 /* Connection failed but lets try again */
378 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
379 "Could not connect to server %s: %s",
380 ctx->host, strerror(opt));
381 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
382 "Connecting to port %d of server %s resumed",
383 ctx->port, ctx->host);
385 /* Unregister old connection try */
386 silc_schedule_unset_listen_fd(client->schedule, fd);
387 silc_net_close_connection(fd);
388 silc_task_unregister(client->io_queue, ctx->task);
391 silc_client_connect_to_server_internal(ctx);
394 /* Connection failed and we won't try anymore */
395 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
396 "Could not connect to server %s: %s",
397 ctx->host, strerror(opt));
398 silc_schedule_unset_listen_fd(client->schedule, fd);
399 silc_net_close_connection(fd);
400 silc_task_unregister(client->io_queue, ctx->task);
403 /* Notify application of failure */
404 client->ops->connect(client, conn, FALSE);
405 silc_client_del_connection(client, conn);
410 silc_schedule_unset_listen_fd(client->schedule, fd);
411 silc_task_unregister(client->io_queue, ctx->task);
414 if (!silc_client_start_key_exchange(client, conn, fd)) {
415 silc_net_close_connection(fd);
416 client->ops->connect(client, conn, FALSE);
420 /* Second part of the connecting to the server. This executed
421 authentication protocol. */
423 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
425 SilcProtocol protocol = (SilcProtocol)context;
426 SilcClientKEInternalContext *ctx =
427 (SilcClientKEInternalContext *)protocol->context;
428 SilcClient client = (SilcClient)ctx->client;
429 SilcSocketConnection sock = NULL;
430 SilcClientConnAuthInternalContext *proto_ctx;
432 SILC_LOG_DEBUG(("Start"));
434 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
435 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
436 /* Error occured during protocol */
437 SILC_LOG_DEBUG(("Error during KE protocol"));
438 silc_protocol_free(protocol);
439 silc_ske_free_key_material(ctx->keymat);
441 silc_ske_free(ctx->ske);
443 silc_free(ctx->dest_id);
444 ctx->sock->protocol = NULL;
445 silc_socket_free(ctx->sock);
447 /* Notify application of failure */
448 client->ops->connect(client, ctx->sock->user_data, FALSE);
453 /* We now have the key material as the result of the key exchange
454 protocol. Take the key material into use. Free the raw key material
455 as soon as we've set them into use. */
456 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
457 ctx->ske->prop->cipher,
458 ctx->ske->prop->pkcs,
459 ctx->ske->prop->hash,
460 ctx->ske->prop->hmac,
461 ctx->ske->prop->group);
462 silc_ske_free_key_material(ctx->keymat);
464 /* Allocate internal context for the authentication protocol. This
465 is sent as context for the protocol. */
466 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
467 proto_ctx->client = (void *)client;
468 proto_ctx->sock = sock = ctx->sock;
469 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
470 proto_ctx->dest_id_type = ctx->dest_id_type;
471 proto_ctx->dest_id = ctx->dest_id;
473 /* Resolve the authentication method to be used in this connection */
474 if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
475 sock->port, &proto_ctx->auth_meth,
476 &proto_ctx->auth_data,
477 &proto_ctx->auth_data_len))
478 proto_ctx->auth_meth = SILC_AUTH_NONE;
480 /* Free old protocol as it is finished now */
481 silc_protocol_free(protocol);
483 silc_packet_context_free(ctx->packet);
485 sock->protocol = NULL;
487 /* Allocate the authenteication protocol and execute it. */
488 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
489 &sock->protocol, (void *)proto_ctx,
490 silc_client_connect_to_server_final);
492 /* Execute the protocol */
493 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
496 /* Finalizes the connection to the remote SILC server. This is called
497 after authentication protocol has been completed. This send our
498 user information to the server to receive our client ID from
501 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
503 SilcProtocol protocol = (SilcProtocol)context;
504 SilcClientConnAuthInternalContext *ctx =
505 (SilcClientConnAuthInternalContext *)protocol->context;
506 SilcClient client = (SilcClient)ctx->client;
507 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
510 SILC_LOG_DEBUG(("Start"));
512 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
513 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
514 /* Error occured during protocol */
515 SILC_LOG_DEBUG(("Error during authentication protocol"));
516 silc_protocol_free(protocol);
518 silc_free(ctx->auth_data);
520 silc_ske_free(ctx->ske);
522 silc_free(ctx->dest_id);
523 conn->sock->protocol = NULL;
524 silc_socket_free(ctx->sock);
526 /* Notify application of failure */
527 client->ops->connect(client, ctx->sock->user_data, FALSE);
532 /* Send NEW_CLIENT packet to the server. We will become registered
533 to the SILC network after sending this packet and we will receive
534 client ID from the server. */
535 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
536 strlen(client->realname));
537 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
538 silc_buffer_format(packet,
539 SILC_STR_UI_SHORT(strlen(client->username)),
540 SILC_STR_UI_XNSTRING(client->username,
541 strlen(client->username)),
542 SILC_STR_UI_SHORT(strlen(client->realname)),
543 SILC_STR_UI_XNSTRING(client->realname,
544 strlen(client->realname)),
547 /* Send the packet */
548 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
550 packet->data, packet->len, TRUE);
551 silc_buffer_free(packet);
553 /* Save remote ID. */
554 conn->remote_id = ctx->dest_id;
555 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
556 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
558 /* Register re-key timeout */
559 conn->rekey->timeout = 3600; /* XXX hardcoded */
560 conn->rekey->context = (void *)client;
561 silc_task_register(client->timeout_queue, conn->sock->sock,
562 silc_client_rekey_callback,
563 (void *)conn->sock, conn->rekey->timeout, 0,
564 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
566 silc_protocol_free(protocol);
568 silc_free(ctx->auth_data);
570 silc_ske_free(ctx->ske);
571 silc_socket_free(ctx->sock);
573 conn->sock->protocol = NULL;
576 /* Internal routine that sends packet or marks packet to be sent. This
577 is used directly only in special cases. Normal cases should use
578 silc_server_packet_send. Returns < 0 on error. */
580 int silc_client_packet_send_real(SilcClient client,
581 SilcSocketConnection sock,
587 /* If rekey protocol is active we must assure that all packets are
588 sent through packet queue. */
589 if (flush == FALSE && SILC_CLIENT_IS_REKEY(sock))
592 /* Send the packet */
593 ret = silc_packet_send(sock, force_send);
597 /* Mark that there is some outgoing data available for this connection.
598 This call sets the connection both for input and output (the input
599 is set always and this call keeps the input setting, actually).
600 Actual data sending is performed by silc_client_packet_process. */
601 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
603 /* Mark to socket that data is pending in outgoing buffer. This flag
604 is needed if new data is added to the buffer before the earlier
605 put data is sent to the network. */
606 SILC_SET_OUTBUF_PENDING(sock);
611 /* Packet processing callback. This is used to send and receive packets
612 from network. This is generic task. */
614 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
616 SilcClient client = (SilcClient)context;
617 SilcSocketConnection sock = NULL;
618 SilcClientConnection conn;
621 SILC_LOG_DEBUG(("Processing packet"));
623 SILC_CLIENT_GET_SOCK(client, fd, sock);
627 conn = (SilcClientConnection)sock->user_data;
630 if (type == SILC_TASK_WRITE) {
631 SILC_LOG_DEBUG(("Writing data to connection"));
633 if (sock->outbuf->data - sock->outbuf->head)
634 silc_buffer_push(sock->outbuf,
635 sock->outbuf->data - sock->outbuf->head);
637 ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
639 /* If returned -2 could not write to connection now, will do
644 /* The packet has been sent and now it is time to set the connection
645 back to only for input. When there is again some outgoing data
646 available for this connection it will be set for output as well.
647 This call clears the output setting and sets it only for input. */
648 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
649 SILC_UNSET_OUTBUF_PENDING(sock);
651 silc_buffer_clear(sock->outbuf);
655 /* Packet receiving */
656 if (type == SILC_TASK_READ) {
657 SILC_LOG_DEBUG(("Reading data from connection"));
659 /* Read data from network */
660 ret = silc_packet_receive(sock);
666 SILC_LOG_DEBUG(("Read EOF"));
668 /* If connection is disconnecting already we will finally
669 close the connection */
670 if (SILC_IS_DISCONNECTING(sock)) {
671 if (sock == conn->sock)
672 client->ops->disconnect(client, conn);
673 silc_client_close_connection(client, sock, conn);
677 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
678 if (sock == conn->sock)
679 client->ops->disconnect(client, conn);
680 silc_client_close_connection(client, sock, conn);
684 /* Process the packet. This will call the parser that will then
685 decrypt and parse the packet. */
686 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
687 silc_packet_receive_process(sock, conn->receive_key, conn->hmac_receive,
688 silc_client_packet_parse, client);
690 silc_packet_receive_process(sock, NULL, NULL,
691 silc_client_packet_parse, client);
695 /* Callback function that the silc_packet_decrypt will call to make the
696 decision whether the packet is normal or special packet. We will
697 return TRUE if it is normal and FALSE if it is special */
699 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
701 SilcPacketContext *packet,
705 /* Packet is normal packet, if:
707 1) packet is private message packet and does not have private key set
708 2) is other packet than channel message packet
710 all other packets are special packets
713 if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
714 (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
717 if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
723 /* Parses whole packet, received earlier. */
725 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
727 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
728 SilcClient client = (SilcClient)parse_ctx->context;
729 SilcPacketContext *packet = parse_ctx->packet;
730 SilcBuffer buffer = packet->buffer;
731 SilcSocketConnection sock = parse_ctx->sock;
732 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
735 SILC_LOG_DEBUG(("Start"));
737 /* Decrypt the received packet */
738 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
739 ret = silc_packet_decrypt(conn->receive_key, conn->hmac_receive,
741 silc_client_packet_decrypt_check, parse_ctx);
743 ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
744 silc_client_packet_decrypt_check, parse_ctx);
750 /* Parse the packet. Packet type is returned. */
751 ret = silc_packet_parse(packet);
753 /* Parse the packet header in special way as this is "special"
755 ret = silc_packet_parse_special(packet);
758 if (ret == SILC_PACKET_NONE)
761 /* Parse the incoming packet type */
762 silc_client_packet_parse_type(client, sock, packet);
765 /* silc_buffer_clear(sock->inbuf); */
766 silc_packet_context_free(packet);
767 silc_free(parse_ctx);
770 /* Parser callback called by silc_packet_receive_process. Thie merely
771 registers timeout that will handle the actual parsing when appropriate. */
773 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
775 SilcClient client = (SilcClient)parser_context->context;
777 /* Parse the packet */
778 silc_task_register(client->timeout_queue, parser_context->sock->sock,
779 silc_client_packet_parse_real,
780 (void *)parser_context, 0, 1,
782 SILC_TASK_PRI_NORMAL);
785 /* Parses the packet type and calls what ever routines the packet type
786 requires. This is done for all incoming packets. */
788 void silc_client_packet_parse_type(SilcClient client,
789 SilcSocketConnection sock,
790 SilcPacketContext *packet)
792 SilcBuffer buffer = packet->buffer;
793 SilcPacketType type = packet->type;
795 SILC_LOG_DEBUG(("Parsing packet type %d", type));
797 /* Parse the packet type */
799 case SILC_PACKET_DISCONNECT:
800 silc_client_disconnected_by_server(client, sock, buffer);
802 case SILC_PACKET_SUCCESS:
804 * Success received for something. For now we can have only
805 * one protocol for connection executing at once hence this
806 * success message is for whatever protocol is executing currently.
809 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
811 case SILC_PACKET_FAILURE:
813 * Failure received for some protocol. Set the protocol state to
814 * error and call the protocol callback. This fill cause error on
815 * protocol and it will call the final callback.
817 silc_client_process_failure(client, sock, packet);
819 case SILC_PACKET_REJECT:
822 case SILC_PACKET_NOTIFY:
824 * Received notify message
826 silc_client_notify_by_server(client, sock, packet);
829 case SILC_PACKET_ERROR:
831 * Received error message
833 silc_client_error_by_server(client, sock, buffer);
836 case SILC_PACKET_CHANNEL_MESSAGE:
838 * Received message to (from, actually) a channel
840 silc_client_channel_message(client, sock, packet);
842 case SILC_PACKET_CHANNEL_KEY:
844 * Received key for a channel. By receiving this key the client will be
845 * able to talk to the channel it has just joined. This can also be
846 * a new key for existing channel as keys expire peridiocally.
848 silc_client_receive_channel_key(client, sock, buffer);
851 case SILC_PACKET_PRIVATE_MESSAGE:
853 * Received private message
855 silc_client_private_message(client, sock, packet);
857 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
859 * Received private message key
863 case SILC_PACKET_COMMAND_REPLY:
865 * Recived reply for a command
867 silc_client_command_reply_process(client, sock, packet);
870 case SILC_PACKET_KEY_EXCHANGE:
871 if (sock->protocol && sock->protocol->protocol &&
872 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
873 SilcClientKEInternalContext *proto_ctx =
874 (SilcClientKEInternalContext *)sock->protocol->context;
876 proto_ctx->packet = silc_packet_context_dup(packet);
877 proto_ctx->dest_id_type = packet->src_id_type;
878 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
879 packet->src_id_type);
880 if (!proto_ctx->dest_id)
883 /* Let the protocol handle the packet */
884 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
886 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
887 "protocol active, packet dropped."));
891 case SILC_PACKET_KEY_EXCHANGE_1:
892 if (sock->protocol && sock->protocol->protocol &&
893 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
894 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
896 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
897 SilcClientRekeyInternalContext *proto_ctx =
898 (SilcClientRekeyInternalContext *)sock->protocol->context;
900 if (proto_ctx->packet)
901 silc_packet_context_free(proto_ctx->packet);
903 proto_ctx->packet = silc_packet_context_dup(packet);
905 /* Let the protocol handle the packet */
906 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
908 SilcClientKEInternalContext *proto_ctx =
909 (SilcClientKEInternalContext *)sock->protocol->context;
911 if (proto_ctx->packet)
912 silc_packet_context_free(proto_ctx->packet);
914 proto_ctx->packet = silc_packet_context_dup(packet);
915 proto_ctx->dest_id_type = packet->src_id_type;
916 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
917 packet->src_id_type);
918 if (!proto_ctx->dest_id)
921 /* Let the protocol handle the packet */
922 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
925 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
926 "protocol active, packet dropped."));
929 case SILC_PACKET_KEY_EXCHANGE_2:
930 if (sock->protocol && sock->protocol->protocol &&
931 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
932 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
934 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
935 SilcClientRekeyInternalContext *proto_ctx =
936 (SilcClientRekeyInternalContext *)sock->protocol->context;
938 if (proto_ctx->packet)
939 silc_packet_context_free(proto_ctx->packet);
941 proto_ctx->packet = silc_packet_context_dup(packet);
943 /* Let the protocol handle the packet */
944 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
946 SilcClientKEInternalContext *proto_ctx =
947 (SilcClientKEInternalContext *)sock->protocol->context;
949 if (proto_ctx->packet)
950 silc_packet_context_free(proto_ctx->packet);
952 proto_ctx->packet = silc_packet_context_dup(packet);
953 proto_ctx->dest_id_type = packet->src_id_type;
954 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
955 packet->src_id_type);
956 if (!proto_ctx->dest_id)
959 /* Let the protocol handle the packet */
960 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
963 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
964 "protocol active, packet dropped."));
968 case SILC_PACKET_NEW_ID:
971 * Received new ID from server. This packet is received at
972 * the connection to the server. New ID is also received when
973 * user changes nickname but in that case the new ID is received
974 * as command reply and not as this packet type.
978 idp = silc_id_payload_parse(buffer);
981 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
984 silc_client_receive_new_id(client, sock, idp);
985 silc_id_payload_free(idp);
989 case SILC_PACKET_HEARTBEAT:
991 * Received heartbeat packet
993 SILC_LOG_DEBUG(("Heartbeat packet"));
996 case SILC_PACKET_KEY_AGREEMENT:
998 * Received key agreement packet
1000 SILC_LOG_DEBUG(("Key agreement packet"));
1001 silc_client_key_agreement(client, sock, packet);
1004 case SILC_PACKET_REKEY:
1005 SILC_LOG_DEBUG(("Re-key packet"));
1006 /* We ignore this for now */
1009 case SILC_PACKET_REKEY_DONE:
1010 SILC_LOG_DEBUG(("Re-key done packet"));
1012 if (sock->protocol && sock->protocol->protocol &&
1013 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1015 SilcClientRekeyInternalContext *proto_ctx =
1016 (SilcClientRekeyInternalContext *)sock->protocol->context;
1018 if (proto_ctx->packet)
1019 silc_packet_context_free(proto_ctx->packet);
1021 proto_ctx->packet = silc_packet_context_dup(packet);
1023 /* Let the protocol handle the packet */
1024 if (proto_ctx->responder == FALSE)
1025 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
1027 /* Let the protocol handle the packet */
1028 silc_protocol_execute(sock->protocol, client->timeout_queue,
1031 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1032 "protocol active, packet dropped."));
1037 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1042 /* Sends packet. This doesn't actually send the packet instead it assembles
1043 it and marks it to be sent. However, if force_send is TRUE the packet
1044 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1045 will be derived from sock argument. Otherwise the valid arguments sent
1048 void silc_client_packet_send(SilcClient client,
1049 SilcSocketConnection sock,
1050 SilcPacketType type,
1052 SilcIdType dst_id_type,
1055 unsigned char *data,
1059 SilcPacketContext packetdata;
1064 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1066 /* Get data used in the packet sending, keys and stuff */
1067 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1068 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1069 cipher = ((SilcClientConnection)sock->user_data)->send_key;
1071 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1072 hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1074 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1075 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1076 dst_id_type = SILC_ID_SERVER;
1080 /* Set the packet context pointers */
1081 packetdata.flags = 0;
1082 packetdata.type = type;
1083 if (sock->user_data &&
1084 ((SilcClientConnection)sock->user_data)->local_id_data) {
1085 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1086 packetdata.src_id_len =
1087 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1090 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1091 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1093 packetdata.src_id_type = SILC_ID_CLIENT;
1095 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1096 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1097 packetdata.dst_id_type = dst_id_type;
1099 packetdata.dst_id = NULL;
1100 packetdata.dst_id_len = 0;
1101 packetdata.dst_id_type = SILC_ID_NONE;
1103 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1104 packetdata.src_id_len + packetdata.dst_id_len;
1105 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1107 /* Prepare outgoing data buffer for packet sending */
1108 silc_packet_send_prepare(sock,
1109 SILC_PACKET_HEADER_LEN +
1110 packetdata.src_id_len +
1111 packetdata.dst_id_len,
1115 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1117 packetdata.buffer = sock->outbuf;
1119 /* Put the data to the buffer */
1120 if (data && data_len)
1121 silc_buffer_put(sock->outbuf, data, data_len);
1123 /* Create the outgoing packet */
1124 silc_packet_assemble(&packetdata);
1126 /* Encrypt the packet */
1128 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1130 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1131 sock->outbuf->data, sock->outbuf->len);
1133 /* Now actually send the packet */
1134 silc_client_packet_send_real(client, sock, force_send, FALSE);
1137 /* Closes connection to remote end. Free's all allocated data except
1138 for some information such as nickname etc. that are valid at all time.
1139 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1140 provided it will be checked whether the sock and `conn->sock' are the
1141 same (they can be different, ie. a socket can use `conn' as its
1142 connection but `conn->sock' might be actually a different connection
1143 than the `sock'). */
1145 void silc_client_close_connection(SilcClient client,
1146 SilcSocketConnection sock,
1147 SilcClientConnection conn)
1151 if (!sock || (sock && conn->sock == sock))
1156 /* We won't listen for this connection anymore */
1157 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1159 /* Unregister all tasks */
1160 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1161 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1163 /* Close the actual connection */
1164 silc_net_close_connection(sock->sock);
1166 /* Cancel any active protocol */
1167 if (sock->protocol) {
1168 if (sock->protocol->protocol->type ==
1169 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1170 sock->protocol->protocol->type ==
1171 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1172 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1173 silc_protocol_execute_final(sock->protocol, client->timeout_queue);
1174 sock->protocol = NULL;
1175 /* The application will recall this function with these protocols
1176 (the ops->connect client operation). */
1179 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1180 silc_protocol_execute_final(sock->protocol, client->timeout_queue);
1181 sock->protocol = NULL;
1185 /* Free everything */
1186 if (del && sock->user_data) {
1187 /* XXX Free all client entries and channel entries. */
1189 /* Clear ID caches */
1190 if (conn->client_cache)
1191 silc_idcache_del_all(conn->client_cache);
1192 if (conn->channel_cache)
1193 silc_idcache_del_all(conn->channel_cache);
1196 if (conn->remote_host)
1197 silc_free(conn->remote_host);
1199 silc_free(conn->local_id);
1200 if (conn->local_id_data)
1201 silc_free(conn->local_id_data);
1203 silc_cipher_free(conn->send_key);
1204 if (conn->receive_key)
1205 silc_cipher_free(conn->receive_key);
1206 if (conn->hmac_send) /* conn->hmac_receive is same */
1207 silc_hmac_free(conn->hmac_send);
1208 if (conn->pending_commands)
1209 silc_dlist_uninit(conn->pending_commands);
1211 silc_free(conn->rekey);
1213 memset(conn, 0, sizeof(*conn));
1214 silc_client_del_connection(client, conn);
1217 silc_socket_free(sock);
1220 /* Called when we receive disconnection packet from server. This
1221 closes our end properly and displays the reason of the disconnection
1224 void silc_client_disconnected_by_server(SilcClient client,
1225 SilcSocketConnection sock,
1230 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1232 msg = silc_calloc(message->len + 1, sizeof(char));
1233 memcpy(msg, message->data, message->len);
1234 client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
1237 SILC_SET_DISCONNECTED(sock);
1238 silc_client_close_connection(client, sock, sock->user_data);
1241 /* Received error message from server. Display it on the screen.
1242 We don't take any action what so ever of the error message. */
1244 void silc_client_error_by_server(SilcClient client,
1245 SilcSocketConnection sock,
1250 msg = silc_calloc(message->len + 1, sizeof(char));
1251 memcpy(msg, message->data, message->len);
1252 client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
1256 /* Processes the received new Client ID from server. Old Client ID is
1257 deleted from cache and new one is added. */
1259 void silc_client_receive_new_id(SilcClient client,
1260 SilcSocketConnection sock,
1263 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1264 int connecting = FALSE;
1267 if (!conn->local_entry)
1270 /* Delete old ID from ID cache */
1271 if (conn->local_id) {
1272 silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1273 silc_free(conn->local_id);
1276 /* Save the new ID */
1278 if (conn->local_id_data)
1279 silc_free(conn->local_id_data);
1281 conn->local_id = silc_id_payload_get_id(idp);
1282 conn->local_id_data = silc_id_payload_get_data(idp);
1283 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1285 if (!conn->local_entry)
1286 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1288 conn->local_entry->nickname = conn->nickname;
1289 if (!conn->local_entry->username) {
1290 conn->local_entry->username =
1291 silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1292 sizeof(conn->local_entry->username));
1293 sprintf(conn->local_entry->username, "%s@%s", client->username,
1296 conn->local_entry->server = strdup(conn->remote_host);
1297 conn->local_entry->id = conn->local_id;
1299 /* Put it to the ID cache */
1300 silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id,
1301 (void *)conn->local_entry, FALSE);
1303 /* Issue INFO command to fetch the real server name and server information
1305 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1306 silc_client_send_command(client, conn, SILC_COMMAND_INFO,
1307 ++conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1308 silc_buffer_free(sidp);
1310 /* Notify application of successful connection. We do it here now that
1311 we've received the Client ID and are allowed to send traffic. */
1313 client->ops->connect(client, conn, TRUE);
1316 /* Processed received Channel ID for a channel. This is called when client
1317 joins to channel and server replies with channel ID. The ID is cached.
1318 Returns the created channel entry. */
1320 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1321 SilcSocketConnection sock,
1326 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1327 SilcChannelEntry channel;
1329 SILC_LOG_DEBUG(("New channel ID"));
1331 channel = silc_calloc(1, sizeof(*channel));
1332 channel->channel_name = channel_name;
1333 channel->id = silc_id_payload_get_id(idp);
1334 channel->mode = mode;
1335 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1337 conn->current_channel = channel;
1339 /* Put it to the ID cache */
1340 silc_idcache_add(conn->channel_cache, channel_name, (void *)channel->id,
1341 (void *)channel, FALSE);
1346 /* Removes a client entry from all channel it has joined. This really is
1347 a performance killer (client_entry should have pointers to channel
1350 void silc_client_remove_from_channels(SilcClient client,
1351 SilcClientConnection conn,
1352 SilcClientEntry client_entry)
1354 SilcIDCacheEntry id_cache;
1355 SilcIDCacheList list;
1356 SilcChannelEntry channel;
1357 SilcChannelUser chu;
1359 if (!silc_idcache_get_all(conn->channel_cache, &list))
1362 silc_idcache_list_first(list, &id_cache);
1363 channel = (SilcChannelEntry)id_cache->context;
1367 /* Remove client from channel */
1368 silc_list_start(channel->clients);
1369 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1370 if (chu->client == client_entry) {
1371 silc_list_del(channel->clients, chu);
1377 if (!silc_idcache_list_next(list, &id_cache))
1380 channel = (SilcChannelEntry)id_cache->context;
1383 silc_idcache_list_free(list);
1386 /* Replaces `old' client entries from all channels to `new' client entry.
1387 This can be called for example when nickname changes and old ID entry
1388 is replaced from ID cache with the new one. If the old ID entry is only
1389 updated, then this fucntion needs not to be called. */
1391 void silc_client_replace_from_channels(SilcClient client,
1392 SilcClientConnection conn,
1393 SilcClientEntry old,
1394 SilcClientEntry new)
1396 SilcIDCacheEntry id_cache;
1397 SilcIDCacheList list;
1398 SilcChannelEntry channel;
1399 SilcChannelUser chu;
1401 if (!silc_idcache_get_all(conn->channel_cache, &list))
1404 silc_idcache_list_first(list, &id_cache);
1405 channel = (SilcChannelEntry)id_cache->context;
1409 /* Replace client entry */
1410 silc_list_start(channel->clients);
1411 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1412 if (chu->client == old) {
1418 if (!silc_idcache_list_next(list, &id_cache))
1421 channel = (SilcChannelEntry)id_cache->context;
1424 silc_idcache_list_free(list);
1427 /* Registers failure timeout to process the received failure packet
1430 void silc_client_process_failure(SilcClient client,
1431 SilcSocketConnection sock,
1432 SilcPacketContext *packet)
1436 if (sock->protocol) {
1437 if (packet->buffer->len >= 4)
1438 SILC_GET32_MSB(failure, packet->buffer->data);
1440 /* Notify application */
1441 client->ops->failure(client, sock->user_data, sock->protocol,
1446 /* A timeout callback for the re-key. We will be the initiator of the
1449 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1451 SilcSocketConnection sock = (SilcSocketConnection)context;
1452 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1453 SilcClient client = (SilcClient)conn->rekey->context;
1454 SilcProtocol protocol;
1455 SilcClientRekeyInternalContext *proto_ctx;
1457 SILC_LOG_DEBUG(("Start"));
1459 /* Allocate internal protocol context. This is sent as context
1461 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1462 proto_ctx->client = (void *)client;
1463 proto_ctx->sock = silc_socket_dup(sock);
1464 proto_ctx->responder = FALSE;
1465 proto_ctx->pfs = conn->rekey->pfs;
1467 /* Perform rekey protocol. Will call the final callback after the
1468 protocol is over. */
1469 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1470 &protocol, proto_ctx, silc_client_rekey_final);
1471 sock->protocol = protocol;
1473 /* Run the protocol */
1474 silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
1476 /* Re-register re-key timeout */
1477 silc_task_register(client->timeout_queue, sock->sock,
1478 silc_client_rekey_callback,
1479 context, conn->rekey->timeout, 0,
1480 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1483 /* The final callback for the REKEY protocol. This will actually take the
1484 new key material into use. */
1486 SILC_TASK_CALLBACK(silc_client_rekey_final)
1488 SilcProtocol protocol = (SilcProtocol)context;
1489 SilcClientRekeyInternalContext *ctx =
1490 (SilcClientRekeyInternalContext *)protocol->context;
1491 SilcClient client = (SilcClient)ctx->client;
1492 SilcSocketConnection sock = ctx->sock;
1494 SILC_LOG_DEBUG(("Start"));
1496 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1497 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1498 /* Error occured during protocol */
1499 silc_protocol_cancel(protocol, client->timeout_queue);
1500 silc_protocol_free(protocol);
1501 sock->protocol = NULL;
1503 silc_packet_context_free(ctx->packet);
1505 silc_ske_free(ctx->ske);
1506 silc_socket_free(ctx->sock);
1512 silc_protocol_free(protocol);
1513 sock->protocol = NULL;
1515 silc_packet_context_free(ctx->packet);
1517 silc_ske_free(ctx->ske);
1518 silc_socket_free(ctx->sock);