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;
1266 if (!conn->local_entry)
1269 /* Delete old ID from ID cache */
1270 if (conn->local_id) {
1271 silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1272 silc_free(conn->local_id);
1275 /* Save the new ID */
1277 if (conn->local_id_data)
1278 silc_free(conn->local_id_data);
1280 conn->local_id = silc_id_payload_get_id(idp);
1281 conn->local_id_data = silc_id_payload_get_data(idp);
1282 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1284 if (!conn->local_entry)
1285 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1287 conn->local_entry->nickname = conn->nickname;
1288 if (!conn->local_entry->username) {
1289 conn->local_entry->username =
1290 silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1291 sizeof(conn->local_entry->username));
1292 sprintf(conn->local_entry->username, "%s@%s", client->username,
1295 conn->local_entry->server = strdup(conn->remote_host);
1296 conn->local_entry->id = conn->local_id;
1298 /* Put it to the ID cache */
1299 silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id,
1300 (void *)conn->local_entry, FALSE);
1302 /* Notify application of successful connection. We do it here now that
1303 we've received the Client ID and are allowed to send traffic. */
1305 client->ops->connect(client, conn, TRUE);
1308 /* Processed received Channel ID for a channel. This is called when client
1309 joins to channel and server replies with channel ID. The ID is cached.
1310 Returns the created channel entry. */
1312 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1313 SilcSocketConnection sock,
1318 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1319 SilcChannelEntry channel;
1321 SILC_LOG_DEBUG(("New channel ID"));
1323 channel = silc_calloc(1, sizeof(*channel));
1324 channel->channel_name = channel_name;
1325 channel->id = silc_id_payload_get_id(idp);
1326 channel->mode = mode;
1327 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1329 conn->current_channel = channel;
1331 /* Put it to the ID cache */
1332 silc_idcache_add(conn->channel_cache, channel_name, (void *)channel->id,
1333 (void *)channel, FALSE);
1338 /* Removes a client entry from all channel it has joined. This really is
1339 a performance killer (client_entry should have pointers to channel
1342 void silc_client_remove_from_channels(SilcClient client,
1343 SilcClientConnection conn,
1344 SilcClientEntry client_entry)
1346 SilcIDCacheEntry id_cache;
1347 SilcIDCacheList list;
1348 SilcChannelEntry channel;
1349 SilcChannelUser chu;
1351 if (!silc_idcache_get_all(conn->channel_cache, &list))
1354 silc_idcache_list_first(list, &id_cache);
1355 channel = (SilcChannelEntry)id_cache->context;
1359 /* Remove client from channel */
1360 silc_list_start(channel->clients);
1361 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1362 if (chu->client == client_entry) {
1363 silc_list_del(channel->clients, chu);
1369 if (!silc_idcache_list_next(list, &id_cache))
1372 channel = (SilcChannelEntry)id_cache->context;
1375 silc_idcache_list_free(list);
1378 /* Replaces `old' client entries from all channels to `new' client entry.
1379 This can be called for example when nickname changes and old ID entry
1380 is replaced from ID cache with the new one. If the old ID entry is only
1381 updated, then this fucntion needs not to be called. */
1383 void silc_client_replace_from_channels(SilcClient client,
1384 SilcClientConnection conn,
1385 SilcClientEntry old,
1386 SilcClientEntry new)
1388 SilcIDCacheEntry id_cache;
1389 SilcIDCacheList list;
1390 SilcChannelEntry channel;
1391 SilcChannelUser chu;
1393 if (!silc_idcache_get_all(conn->channel_cache, &list))
1396 silc_idcache_list_first(list, &id_cache);
1397 channel = (SilcChannelEntry)id_cache->context;
1401 /* Replace client entry */
1402 silc_list_start(channel->clients);
1403 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1404 if (chu->client == old) {
1410 if (!silc_idcache_list_next(list, &id_cache))
1413 channel = (SilcChannelEntry)id_cache->context;
1416 silc_idcache_list_free(list);
1419 /* Registers failure timeout to process the received failure packet
1422 void silc_client_process_failure(SilcClient client,
1423 SilcSocketConnection sock,
1424 SilcPacketContext *packet)
1428 if (sock->protocol) {
1429 if (packet->buffer->len >= 4)
1430 SILC_GET32_MSB(failure, packet->buffer->data);
1432 /* Notify application */
1433 client->ops->failure(client, sock->user_data, sock->protocol,
1438 /* A timeout callback for the re-key. We will be the initiator of the
1441 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1443 SilcSocketConnection sock = (SilcSocketConnection)context;
1444 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1445 SilcClient client = (SilcClient)conn->rekey->context;
1446 SilcProtocol protocol;
1447 SilcClientRekeyInternalContext *proto_ctx;
1449 SILC_LOG_DEBUG(("Start"));
1451 /* Allocate internal protocol context. This is sent as context
1453 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1454 proto_ctx->client = (void *)client;
1455 proto_ctx->sock = silc_socket_dup(sock);
1456 proto_ctx->responder = FALSE;
1457 proto_ctx->pfs = conn->rekey->pfs;
1459 /* Perform rekey protocol. Will call the final callback after the
1460 protocol is over. */
1461 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1462 &protocol, proto_ctx, silc_client_rekey_final);
1463 sock->protocol = protocol;
1465 /* Run the protocol */
1466 silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
1468 /* Re-register re-key timeout */
1469 silc_task_register(client->timeout_queue, sock->sock,
1470 silc_client_rekey_callback,
1471 context, conn->rekey->timeout, 0,
1472 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1475 /* The final callback for the REKEY protocol. This will actually take the
1476 new key material into use. */
1478 SILC_TASK_CALLBACK(silc_client_rekey_final)
1480 SilcProtocol protocol = (SilcProtocol)context;
1481 SilcClientRekeyInternalContext *ctx =
1482 (SilcClientRekeyInternalContext *)protocol->context;
1483 SilcClient client = (SilcClient)ctx->client;
1484 SilcSocketConnection sock = ctx->sock;
1486 SILC_LOG_DEBUG(("Start"));
1488 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1489 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1490 /* Error occured during protocol */
1491 silc_protocol_cancel(protocol, client->timeout_queue);
1492 silc_protocol_free(protocol);
1493 sock->protocol = NULL;
1495 silc_packet_context_free(ctx->packet);
1497 silc_ske_free(ctx->ske);
1498 silc_socket_free(ctx->sock);
1504 silc_protocol_free(protocol);
1505 sock->protocol = NULL;
1507 silc_packet_context_free(ctx->packet);
1509 silc_ske_free(ctx->ske);
1510 silc_socket_free(ctx->sock);