5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 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"
24 /* Static task callback prototypes */
25 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
28 SILC_TASK_CALLBACK(silc_client_packet_process);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
31 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
32 static void silc_client_packet_parse_type(SilcClient client,
33 SilcSocketConnection sock,
34 SilcPacketContext *packet);
36 /* Allocates new client object. This has to be done before client may
37 work. After calling this one must call silc_client_init to initialize
38 the client. The `application' is application specific user data pointer
39 and caller must free it. */
41 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
43 SilcClient new_client;
45 new_client = silc_calloc(1, sizeof(*new_client));
46 new_client->application = application;
47 new_client->ops = ops;
52 /* Free's client object */
54 void silc_client_free(SilcClient client)
61 /* Initializes the client. This makes all the necessary steps to make
62 the client ready to be run. One must call silc_client_run to run the
65 int silc_client_init(SilcClient client)
67 SILC_LOG_DEBUG(("Initializing client"));
69 /* Initialize hash functions for client to use */
70 silc_hash_alloc("md5", &client->md5hash);
71 silc_hash_alloc("sha1", &client->sha1hash);
73 /* Initialize none cipher */
74 silc_cipher_alloc("none", &client->none_cipher);
76 /* Initialize random number generator */
77 client->rng = silc_rng_alloc();
78 silc_rng_init(client->rng);
79 silc_math_primegen_init(); /* XXX */
81 /* Register protocols */
82 silc_client_protocols_register();
84 /* Initialize the scheduler */
85 silc_schedule_init(&client->io_queue, &client->timeout_queue,
86 &client->generic_queue, 5000);
91 /* Stops the client. This is called to stop the client and thus to stop
94 void silc_client_stop(SilcClient client)
96 SILC_LOG_DEBUG(("Stopping client"));
98 /* Stop the scheduler, although it might be already stopped. This
99 doesn't hurt anyone. This removes all the tasks and task queues,
101 silc_schedule_stop();
102 silc_schedule_uninit();
104 silc_client_protocols_unregister();
106 SILC_LOG_DEBUG(("Client stopped"));
109 /* Runs the client. */
111 void silc_client_run(SilcClient client)
113 SILC_LOG_DEBUG(("Running client"));
115 /* Start the scheduler, the heart of the SILC client. When this returns
116 the program will be terminated. */
120 /* Allocates and adds new connection to the client. This adds the allocated
121 connection to the connection table and returns a pointer to it. A client
122 can have multiple connections to multiple servers. Every connection must
123 be added to the client using this function. User data `context' may
124 be sent as argument. */
126 SilcClientConnection silc_client_add_connection(SilcClient client,
129 SilcClientConnection conn;
132 conn = silc_calloc(1, sizeof(*conn));
134 /* Initialize ID caches */
135 conn->client_cache = silc_idcache_alloc(0);
136 conn->channel_cache = silc_idcache_alloc(0);
137 conn->server_cache = silc_idcache_alloc(0);
138 conn->client = client;
139 conn->context = context;
141 /* Add the connection to connections table */
142 for (i = 0; i < client->conns_count; i++)
143 if (client->conns && !client->conns[i]) {
144 client->conns[i] = conn;
148 client->conns = silc_realloc(client->conns, sizeof(*client->conns)
149 * (client->conns_count + 1));
150 client->conns[client->conns_count] = conn;
151 client->conns_count++;
156 /* Removes connection from client. */
158 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
162 for (i = 0; i < client->conns_count; i++)
163 if (client->conns[i] == conn) {
165 client->conns[i] = NULL;
169 /* Internal context for connection process. This is needed as we
170 doing asynchronous connecting. */
173 SilcClientConnection conn;
179 } SilcClientInternalConnectContext;
182 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
186 /* XXX In the future we should give up this non-blocking connect all
187 together and use threads instead. */
188 /* Create connection to server asynchronously */
189 sock = silc_net_create_connection_async(ctx->port, ctx->host);
193 /* Register task that will receive the async connect and will
195 ctx->task = silc_task_register(ctx->client->io_queue, sock,
196 silc_client_connect_to_server_start,
199 SILC_TASK_PRI_NORMAL);
200 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
201 silc_schedule_set_listen_fd(sock, ctx->task->iomask);
208 /* Connects to remote server. This is the main routine used to connect
209 to SILC server. Returns -1 on error and the created socket otherwise.
210 The `context' is user context that is saved into the SilcClientConnection
211 that is created after the connection is created. */
213 int silc_client_connect_to_server(SilcClient client, int port,
214 char *host, void *context)
216 SilcClientInternalConnectContext *ctx;
217 SilcClientConnection conn;
220 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
223 conn = silc_client_add_connection(client, context);
224 conn->remote_host = strdup(host);
225 conn->remote_port = port;
227 client->ops->say(client, conn,
228 "Connecting to port %d of server %s", port, host);
230 /* Allocate internal context for connection process. This is
231 needed as we are doing async connecting. */
232 ctx = silc_calloc(1, sizeof(*ctx));
233 ctx->client = client;
235 ctx->host = strdup(host);
239 /* Do the actual connecting process */
240 sock = silc_client_connect_to_server_internal(ctx);
242 silc_client_del_connection(client, conn);
246 /* Start of the connection to the remote server. This is called after
247 succesful TCP/IP connection has been established to the remote host. */
249 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
251 SilcClientInternalConnectContext *ctx =
252 (SilcClientInternalConnectContext *)context;
253 SilcClient client = ctx->client;
254 SilcClientConnection conn = ctx->conn;
255 SilcProtocol protocol;
256 SilcClientKEInternalContext *proto_ctx;
257 int opt, opt_len = sizeof(opt);
259 SILC_LOG_DEBUG(("Start"));
261 /* Check the socket status as it might be in error */
262 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
264 if (ctx->tries < 2) {
265 /* Connection failed but lets try again */
266 client->ops->say(client, conn, "Could not connect to server %s: %s",
267 ctx->host, strerror(opt));
268 client->ops->say(client, conn,
269 "Connecting to port %d of server %s resumed",
270 ctx->port, ctx->host);
272 /* Unregister old connection try */
273 silc_schedule_unset_listen_fd(fd);
274 silc_net_close_connection(fd);
275 silc_task_unregister(client->io_queue, ctx->task);
278 silc_client_connect_to_server_internal(ctx);
281 /* Connection failed and we won't try anymore */
282 client->ops->say(client, conn, "Could not connect to server %s: %s",
283 ctx->host, strerror(opt));
284 silc_schedule_unset_listen_fd(fd);
285 silc_net_close_connection(fd);
286 silc_task_unregister(client->io_queue, ctx->task);
289 /* Notify application of failure */
290 client->ops->connect(client, conn, FALSE);
291 silc_client_del_connection(client, conn);
296 silc_schedule_unset_listen_fd(fd);
297 silc_task_unregister(client->io_queue, ctx->task);
300 /* Allocate new socket connection object */
301 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
302 if (conn->sock == NULL) {
303 client->ops->say(client, conn,
304 "Error: Could not allocate connection socket");
305 silc_net_close_connection(fd);
306 client->ops->connect(client, conn, FALSE);
310 conn->nickname = strdup(client->username);
311 conn->sock->hostname = conn->remote_host;
312 conn->sock->port = conn->remote_port;
314 /* Allocate internal Key Exchange context. This is sent to the
315 protocol as context. */
316 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
317 proto_ctx->client = (void *)client;
318 proto_ctx->sock = conn->sock;
319 proto_ctx->rng = client->rng;
320 proto_ctx->responder = FALSE;
322 /* Perform key exchange protocol. silc_client_connect_to_server_final
323 will be called after the protocol is finished. */
324 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
325 &protocol, (void *)proto_ctx,
326 silc_client_connect_to_server_second);
328 client->ops->say(client, conn,
329 "Error: Could not start authentication protocol");
330 client->ops->connect(client, conn, FALSE);
333 conn->sock->protocol = protocol;
335 /* Register the connection for network input and output. This sets
336 that scheduler will listen for incoming packets for this connection
337 and sets that outgoing packets may be sent to this connection as well.
338 However, this doesn't set the scheduler for outgoing traffic, it will
339 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
340 later when outgoing data is available. */
341 context = (void *)client;
342 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
344 /* Execute the protocol */
345 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
348 /* Second part of the connecting to the server. This executed
349 authentication protocol. */
351 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
353 SilcProtocol protocol = (SilcProtocol)context;
354 SilcClientKEInternalContext *ctx =
355 (SilcClientKEInternalContext *)protocol->context;
356 SilcClient client = (SilcClient)ctx->client;
357 SilcSocketConnection sock = NULL;
358 SilcClientConnAuthInternalContext *proto_ctx;
360 SILC_LOG_DEBUG(("Start"));
362 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
363 /* Error occured during protocol */
364 SILC_LOG_DEBUG(("Error during KE protocol"));
365 silc_protocol_free(protocol);
367 silc_ske_free(ctx->ske);
369 silc_free(ctx->dest_id);
370 ctx->sock->protocol = NULL;
373 /* Notify application of failure */
374 client->ops->connect(client, ctx->sock->user_data, FALSE);
378 /* Allocate internal context for the authentication protocol. This
379 is sent as context for the protocol. */
380 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
381 proto_ctx->client = (void *)client;
382 proto_ctx->sock = sock = ctx->sock;
383 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
384 proto_ctx->dest_id_type = ctx->dest_id_type;
385 proto_ctx->dest_id = ctx->dest_id;
387 /* Resolve the authentication method to be used in this connection */
388 if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
389 sock->port, &proto_ctx->auth_meth,
390 &proto_ctx->auth_data,
391 &proto_ctx->auth_data_len))
393 /* XXX do AUTH_REQUEST resolcing with server */
394 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
397 /* Free old protocol as it is finished now */
398 silc_protocol_free(protocol);
400 silc_buffer_free(ctx->packet);
402 /* silc_free(ctx->keymat....); */
403 sock->protocol = NULL;
405 /* Allocate the authentication protocol. This is allocated here
406 but we won't start it yet. We will be receiving party of this
407 protocol thus we will wait that connecting party will make
409 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
410 &sock->protocol, (void *)proto_ctx,
411 silc_client_connect_to_server_final);
413 /* Execute the protocol */
414 sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
417 /* Finalizes the connection to the remote SILC server. This is called
418 after authentication protocol has been completed. This send our
419 user information to the server to receive our client ID from
422 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
424 SilcProtocol protocol = (SilcProtocol)context;
425 SilcClientConnAuthInternalContext *ctx =
426 (SilcClientConnAuthInternalContext *)protocol->context;
427 SilcClient client = (SilcClient)ctx->client;
428 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
431 SILC_LOG_DEBUG(("Start"));
433 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
434 /* Error occured during protocol */
435 SILC_LOG_DEBUG(("Error during authentication protocol"));
436 silc_protocol_free(protocol);
438 silc_free(ctx->auth_data);
440 silc_ske_free(ctx->ske);
442 silc_free(ctx->dest_id);
444 conn->sock->protocol = NULL;
446 /* Notify application of failure */
447 client->ops->connect(client, ctx->sock->user_data, FALSE);
451 /* Send NEW_CLIENT packet to the server. We will become registered
452 to the SILC network after sending this packet and we will receive
453 client ID from the server. */
454 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
455 strlen(client->realname));
456 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
457 silc_buffer_format(packet,
458 SILC_STR_UI_SHORT(strlen(client->username)),
459 SILC_STR_UI_XNSTRING(client->username,
460 strlen(client->username)),
461 SILC_STR_UI_SHORT(strlen(client->realname)),
462 SILC_STR_UI_XNSTRING(client->realname,
463 strlen(client->realname)),
466 /* Send the packet */
467 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
469 packet->data, packet->len, TRUE);
470 silc_buffer_free(packet);
472 /* Save remote ID. */
473 conn->remote_id = ctx->dest_id;
474 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
475 conn->remote_id_data_len = SILC_ID_SERVER_LEN;
477 client->ops->say(client, conn, "Connected to port %d of host %s",
478 conn->remote_port, conn->remote_host);
480 /* Notify application of successful connection */
481 client->ops->connect(client, conn, TRUE);
483 silc_protocol_free(protocol);
485 silc_free(ctx->auth_data);
487 silc_ske_free(ctx->ske);
489 silc_free(ctx->dest_id);
491 conn->sock->protocol = NULL;
494 /* Internal routine that sends packet or marks packet to be sent. This
495 is used directly only in special cases. Normal cases should use
496 silc_server_packet_send. Returns < 0 on error. */
498 static int silc_client_packet_send_real(SilcClient client,
499 SilcSocketConnection sock,
504 /* Send the packet */
505 ret = silc_packet_send(sock, force_send);
509 /* Mark that there is some outgoing data available for this connection.
510 This call sets the connection both for input and output (the input
511 is set always and this call keeps the input setting, actually).
512 Actual data sending is performed by silc_client_packet_process. */
513 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
515 /* Mark to socket that data is pending in outgoing buffer. This flag
516 is needed if new data is added to the buffer before the earlier
517 put data is sent to the network. */
518 SILC_SET_OUTBUF_PENDING(sock);
523 /* Packet processing callback. This is used to send and receive packets
524 from network. This is generic task. */
526 SILC_TASK_CALLBACK(silc_client_packet_process)
528 SilcClient client = (SilcClient)context;
529 SilcSocketConnection sock = NULL;
530 SilcClientConnection conn;
533 SILC_LOG_DEBUG(("Processing packet"));
535 SILC_CLIENT_GET_SOCK(client, fd, sock);
539 conn = (SilcClientConnection)sock->user_data;
542 if (type == SILC_TASK_WRITE) {
543 SILC_LOG_DEBUG(("Writing data to connection"));
545 if (sock->outbuf->data - sock->outbuf->head)
546 silc_buffer_push(sock->outbuf,
547 sock->outbuf->data - sock->outbuf->head);
549 ret = silc_client_packet_send_real(client, sock, TRUE);
551 /* If returned -2 could not write to connection now, will do
556 /* The packet has been sent and now it is time to set the connection
557 back to only for input. When there is again some outgoing data
558 available for this connection it will be set for output as well.
559 This call clears the output setting and sets it only for input. */
560 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
561 SILC_UNSET_OUTBUF_PENDING(sock);
563 silc_buffer_clear(sock->outbuf);
567 /* Packet receiving */
568 if (type == SILC_TASK_READ) {
569 SILC_LOG_DEBUG(("Reading data from connection"));
571 /* Read data from network */
572 ret = silc_packet_receive(sock);
578 SILC_LOG_DEBUG(("Read EOF"));
580 /* If connection is disconnecting already we will finally
581 close the connection */
582 if (SILC_IS_DISCONNECTING(sock)) {
583 client->ops->disconnect(client, conn);
584 silc_client_close_connection(client, sock);
588 client->ops->say(client, conn, "Connection closed: premature EOF");
589 SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
590 client->ops->disconnect(client, conn);
591 silc_client_close_connection(client, sock);
595 /* Process the packet. This will call the parser that will then
596 decrypt and parse the packet. */
597 if (!silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
598 silc_client_packet_parse, client)) {
599 silc_buffer_clear(sock->inbuf);
605 /* Parses whole packet, received earlier. */
607 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
609 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
610 SilcClient client = (SilcClient)parse_ctx->context;
611 SilcPacketContext *packet = parse_ctx->packet;
612 SilcBuffer buffer = packet->buffer;
613 SilcSocketConnection sock = parse_ctx->sock;
614 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
617 SILC_LOG_DEBUG(("Start"));
619 /* Decrypt the received packet */
620 ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
625 /* Parse the packet. Packet type is returned. */
626 ret = silc_packet_parse(packet);
628 /* Parse the packet header in special way as this is "special"
630 ret = silc_packet_parse_special(packet);
633 if (ret == SILC_PACKET_NONE)
636 /* Parse the incoming packet type */
637 silc_client_packet_parse_type(client, sock, packet);
640 silc_buffer_clear(buffer);
642 silc_free(parse_ctx);
645 /* Parser callback called by silc_packet_receive_process. Thie merely
646 registers timeout that will handle the actual parsing when appropriate. */
648 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
650 SilcClient client = (SilcClient)parser_context->context;
652 /* Parse the packet */
653 silc_task_register(client->timeout_queue, parser_context->sock->sock,
654 silc_client_packet_parse_real,
655 (void *)parser_context, 0, 1,
657 SILC_TASK_PRI_NORMAL);
660 /* Parses the packet type and calls what ever routines the packet type
661 requires. This is done for all incoming packets. */
663 void silc_client_packet_parse_type(SilcClient client,
664 SilcSocketConnection sock,
665 SilcPacketContext *packet)
667 SilcBuffer buffer = packet->buffer;
668 SilcPacketType type = packet->type;
670 SILC_LOG_DEBUG(("Parsing packet type %d", type));
672 /* Parse the packet type */
674 case SILC_PACKET_DISCONNECT:
675 silc_client_disconnected_by_server(client, sock, buffer);
677 case SILC_PACKET_SUCCESS:
679 * Success received for something. For now we can have only
680 * one protocol for connection executing at once hence this
681 * success message is for whatever protocol is executing currently.
683 if (sock->protocol) {
684 sock->protocol->execute(client->timeout_queue, 0,
685 sock->protocol, sock->sock, 0, 0);
688 case SILC_PACKET_FAILURE:
690 * Failure received for some protocol. Set the protocol state to
691 * error and call the protocol callback. This fill cause error on
692 * protocol and it will call the final callback.
694 if (sock->protocol) {
695 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
696 sock->protocol->execute(client->timeout_queue, 0,
697 sock->protocol, sock->sock, 0, 0);
700 case SILC_PACKET_REJECT:
703 case SILC_PACKET_NOTIFY:
705 * Received notify message
707 silc_client_notify_by_server(client, sock, buffer);
710 case SILC_PACKET_ERROR:
712 * Received error message
714 silc_client_error_by_server(client, sock, buffer);
717 case SILC_PACKET_CHANNEL_MESSAGE:
719 * Received message to (from, actually) a channel
721 silc_client_channel_message(client, sock, packet);
723 case SILC_PACKET_CHANNEL_KEY:
725 * Received key for a channel. By receiving this key the client will be
726 * able to talk to the channel it has just joined. This can also be
727 * a new key for existing channel as keys expire peridiocally.
729 silc_client_receive_channel_key(client, sock, buffer);
732 case SILC_PACKET_PRIVATE_MESSAGE:
734 * Received private message
736 silc_client_private_message(client, sock, packet);
738 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
740 * Received private message key
744 case SILC_PACKET_COMMAND_REPLY:
746 * Recived reply for a command
748 silc_client_command_reply_process(client, sock, packet);
751 case SILC_PACKET_KEY_EXCHANGE:
752 if (sock->protocol) {
753 SilcClientKEInternalContext *proto_ctx =
754 (SilcClientKEInternalContext *)sock->protocol->context;
756 proto_ctx->packet = buffer;
757 proto_ctx->dest_id_type = packet->src_id_type;
758 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
760 /* Let the protocol handle the packet */
761 sock->protocol->execute(client->timeout_queue, 0,
762 sock->protocol, sock->sock, 0, 0);
764 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
765 "protocol active, packet dropped."));
767 /* XXX Trigger KE protocol?? Rekey actually! */
771 case SILC_PACKET_KEY_EXCHANGE_1:
772 if (sock->protocol) {
775 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
776 "protocol active, packet dropped."));
779 case SILC_PACKET_KEY_EXCHANGE_2:
780 if (sock->protocol) {
781 SilcClientKEInternalContext *proto_ctx =
782 (SilcClientKEInternalContext *)sock->protocol->context;
784 if (proto_ctx->packet)
785 silc_buffer_free(proto_ctx->packet);
787 proto_ctx->packet = buffer;
788 proto_ctx->dest_id_type = packet->src_id_type;
789 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
791 /* Let the protocol handle the packet */
792 sock->protocol->execute(client->timeout_queue, 0,
793 sock->protocol, sock->sock, 0, 0);
795 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
796 "protocol active, packet dropped."));
800 case SILC_PACKET_NEW_ID:
803 * Received new ID from server. This packet is received at
804 * the connection to the server. New ID is also received when
805 * user changes nickname but in that case the new ID is received
806 * as command reply and not as this packet type.
808 unsigned char *id_string;
809 unsigned short id_type;
811 silc_buffer_unformat(buffer,
812 SILC_STR_UI_SHORT(&id_type),
813 SILC_STR_UI16_STRING_ALLOC(&id_string),
816 if ((SilcIdType)id_type != SILC_ID_CLIENT)
819 silc_client_receive_new_id(client, sock, id_string);
820 silc_free(id_string);
825 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
830 /* Sends packet. This doesn't actually send the packet instead it assembles
831 it and marks it to be sent. However, if force_send is TRUE the packet
832 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
833 will be derived from sock argument. Otherwise the valid arguments sent
836 void silc_client_packet_send(SilcClient client,
837 SilcSocketConnection sock,
840 SilcIdType dst_id_type,
844 unsigned int data_len,
847 SilcPacketContext packetdata;
849 SILC_LOG_DEBUG(("Sending packet, type %d", type));
851 /* Get data used in the packet sending, keys and stuff */
852 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
853 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
854 cipher = ((SilcClientConnection)sock->user_data)->send_key;
856 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
857 hmac = ((SilcClientConnection)sock->user_data)->hmac;
859 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
860 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
861 dst_id_type = SILC_ID_SERVER;
865 /* Set the packet context pointers */
866 packetdata.flags = 0;
867 packetdata.type = type;
868 if (((SilcClientConnection)sock->user_data)->local_id_data)
869 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
871 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
872 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
873 packetdata.src_id_type = SILC_ID_CLIENT;
875 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
876 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
877 packetdata.dst_id_type = dst_id_type;
879 packetdata.dst_id = NULL;
880 packetdata.dst_id_len = 0;
881 packetdata.dst_id_type = SILC_ID_NONE;
883 packetdata.rng = client->rng;
884 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
885 packetdata.src_id_len + packetdata.dst_id_len;
886 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
888 /* Prepare outgoing data buffer for packet sending */
889 silc_packet_send_prepare(sock,
890 SILC_PACKET_HEADER_LEN +
891 packetdata.src_id_len +
892 packetdata.dst_id_len,
896 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
898 packetdata.buffer = sock->outbuf;
900 /* Put the data to the buffer */
901 if (data && data_len)
902 silc_buffer_put(sock->outbuf, data, data_len);
904 /* Create the outgoing packet */
905 silc_packet_assemble(&packetdata);
907 /* Encrypt the packet */
909 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
911 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
912 sock->outbuf->data, sock->outbuf->len);
914 /* Now actually send the packet */
915 silc_client_packet_send_real(client, sock, force_send);
918 /* Sends packet to a channel. Packet to channel is always encrypted
919 differently from "normal" packets. SILC header of the packet is
920 encrypted with the next receiver's key and the rest of the packet is
921 encrypted with the channel specific key. Padding and HMAC is computed
922 with the next receiver's key. */
924 void silc_client_packet_send_to_channel(SilcClient client,
925 SilcSocketConnection sock,
926 SilcChannelEntry channel,
928 unsigned int data_len,
932 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
934 SilcPacketContext packetdata;
937 unsigned char *id_string;
939 SILC_LOG_DEBUG(("Sending packet to channel"));
941 if (!channel || !channel->key) {
942 client->ops->say(client, conn,
943 "Cannot talk to channel: key does not exist");
949 for (i = 0; i < 16; i++)
950 channel->iv[i] = silc_rng_get_byte(client->rng);
952 silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
954 /* Encode the channel payload */
955 payload = silc_channel_encode_payload(strlen(conn->nickname), conn->nickname,
956 data_len, data, 16, channel->iv,
959 client->ops->say(client, conn,
960 "Error: Could not create packet to be sent to channel");
964 /* Get data used in packet header encryption, keys and stuff. Rest
965 of the packet (the payload) is, however, encrypted with the
966 specified channel key. */
967 cipher = conn->send_key;
969 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
971 /* Set the packet context pointers. The destination ID is always
972 the Channel ID of the channel. Server and router will handle the
973 distribution of the packet. */
974 packetdata.flags = 0;
975 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
976 packetdata.src_id = conn->local_id_data;
977 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
978 packetdata.src_id_type = SILC_ID_CLIENT;
979 packetdata.dst_id = id_string;
980 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
981 packetdata.dst_id_type = SILC_ID_CHANNEL;
982 packetdata.rng = client->rng;
983 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
984 packetdata.src_id_len + packetdata.dst_id_len;
985 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
986 packetdata.src_id_len +
987 packetdata.dst_id_len));
989 /* Prepare outgoing data buffer for packet sending */
990 silc_packet_send_prepare(sock,
991 SILC_PACKET_HEADER_LEN +
992 packetdata.src_id_len +
993 packetdata.dst_id_len,
997 packetdata.buffer = sock->outbuf;
999 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1000 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1001 payload->data, payload->data,
1002 payload->len - 16, /* -IV_LEN */
1005 /* Put the actual encrypted payload data into the buffer. */
1006 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1008 /* Create the outgoing packet */
1009 silc_packet_assemble(&packetdata);
1011 /* Encrypt the header and padding of the packet. This is encrypted
1012 with normal session key shared with our server. */
1013 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1014 packetdata.src_id_len + packetdata.dst_id_len +
1017 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1018 sock->outbuf->data, sock->outbuf->len);
1020 /* Now actually send the packet */
1021 silc_client_packet_send_real(client, sock, force_send);
1022 silc_buffer_free(payload);
1023 silc_free(id_string);
1026 /* Sends private message to remote client. If private message key has
1027 not been set with this client then the message will be encrypted using
1028 normal session keys. Private messages are special packets in SILC
1029 network hence we need this own function for them. This is similiar
1030 to silc_client_packet_send_to_channel except that we send private
1033 void silc_client_packet_send_private_message(SilcClient client,
1034 SilcSocketConnection sock,
1035 SilcClientEntry client_entry,
1036 unsigned char *data,
1037 unsigned int data_len,
1040 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1042 SilcPacketContext packetdata;
1043 unsigned int nick_len;
1047 SILC_LOG_DEBUG(("Sending private message"));
1049 /* Create private message payload */
1050 nick_len = strlen(conn->nickname);
1051 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1052 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1053 silc_buffer_format(buffer,
1054 SILC_STR_UI_SHORT(nick_len),
1055 SILC_STR_UI_XNSTRING(conn->nickname,
1057 SILC_STR_UI_XNSTRING(data, data_len),
1060 /* If we don't have private message specific key then private messages
1061 are just as any normal packet thus call normal packet sending. If
1062 the key exist then the encryption process is a bit different and
1063 will be done in the rest of this function. */
1064 if (!client_entry->send_key) {
1065 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1066 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1067 buffer->data, buffer->len, force_send);
1071 /* We have private message specific key */
1073 /* Get data used in the encryption */
1074 cipher = client_entry->send_key;
1077 /* Set the packet context pointers. */
1078 packetdata.flags = 0;
1079 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1080 packetdata.src_id = conn->local_id_data;
1081 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1082 packetdata.src_id_type = SILC_ID_CLIENT;
1084 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1086 packetdata.dst_id = conn->local_id_data;
1087 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1088 packetdata.dst_id_type = SILC_ID_CLIENT;
1089 packetdata.rng = client->rng;
1090 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1091 packetdata.src_id_len + packetdata.dst_id_len;
1092 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1093 packetdata.src_id_len +
1094 packetdata.dst_id_len));
1096 /* Prepare outgoing data buffer for packet sending */
1097 silc_packet_send_prepare(sock,
1098 SILC_PACKET_HEADER_LEN +
1099 packetdata.src_id_len +
1100 packetdata.dst_id_len,
1104 packetdata.buffer = sock->outbuf;
1106 /* Encrypt payload of the packet. Encrypt with private message specific
1107 key if it exist, otherwise with session key. */
1108 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1109 buffer->len, cipher->iv);
1111 /* Put the actual encrypted payload data into the buffer. */
1112 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1114 /* Create the outgoing packet */
1115 silc_packet_assemble(&packetdata);
1117 /* Encrypt the header and padding of the packet. */
1118 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1119 packetdata.src_id_len + packetdata.dst_id_len +
1122 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1123 sock->outbuf->data, sock->outbuf->len);
1125 /* Now actually send the packet */
1126 silc_client_packet_send_real(client, sock, force_send);
1127 silc_free(packetdata.dst_id);
1133 /* Closes connection to remote end. Free's all allocated data except
1134 for some information such as nickname etc. that are valid at all time. */
1136 void silc_client_close_connection(SilcClient client,
1137 SilcSocketConnection sock)
1139 SilcClientConnection conn;
1141 /* We won't listen for this connection anymore */
1142 silc_schedule_unset_listen_fd(sock->sock);
1144 /* Unregister all tasks */
1145 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1146 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1148 /* Close the actual connection */
1149 silc_net_close_connection(sock->sock);
1151 client->ops->say(client, sock->user_data,
1152 "Closed connection to host %s", sock->hostname ?
1153 sock->hostname : sock->ip);
1155 /* Free everything */
1156 if (sock->user_data) {
1157 conn = (SilcClientConnection)sock->user_data;
1159 /* XXX Free all client entries and channel entries. */
1161 /* Clear ID caches */
1162 silc_idcache_del_all(conn->client_cache);
1163 silc_idcache_del_all(conn->channel_cache);
1166 if (conn->remote_host)
1167 silc_free(conn->remote_host);
1169 silc_free(conn->local_id);
1170 if (conn->local_id_data)
1171 silc_free(conn->local_id_data);
1173 silc_cipher_free(conn->send_key);
1174 if (conn->receive_key)
1175 silc_cipher_free(conn->receive_key);
1177 silc_hmac_free(conn->hmac);
1178 if (conn->hmac_key) {
1179 memset(conn->hmac_key, 0, conn->hmac_key_len);
1180 silc_free(conn->hmac_key);
1184 conn->remote_port = 0;
1185 conn->remote_type = 0;
1186 conn->send_key = NULL;
1187 conn->receive_key = NULL;
1189 conn->hmac_key = NULL;
1190 conn->hmac_key_len = 0;
1191 conn->local_id = NULL;
1192 conn->local_id_data = NULL;
1193 conn->remote_host = NULL;
1194 conn->current_channel = NULL;
1196 silc_client_del_connection(client, conn);
1199 if (sock->protocol) {
1200 silc_protocol_free(sock->protocol);
1201 sock->protocol = NULL;
1203 silc_socket_free(sock);
1206 /* Called when we receive disconnection packet from server. This
1207 closes our end properly and displays the reason of the disconnection
1210 void silc_client_disconnected_by_server(SilcClient client,
1211 SilcSocketConnection sock,
1216 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1218 msg = silc_calloc(message->len + 1, sizeof(char));
1219 memcpy(msg, message->data, message->len);
1220 client->ops->say(client, sock->user_data, msg);
1223 SILC_SET_DISCONNECTED(sock);
1224 silc_client_close_connection(client, sock);
1227 /* Received error message from server. Display it on the screen.
1228 We don't take any action what so ever of the error message. */
1230 void silc_client_error_by_server(SilcClient client,
1231 SilcSocketConnection sock,
1236 msg = silc_calloc(message->len + 1, sizeof(char));
1237 memcpy(msg, message->data, message->len);
1238 client->ops->say(client, sock->user_data, msg);
1242 /* Received notify message from server */
1244 void silc_client_notify_by_server(SilcClient client,
1245 SilcSocketConnection sock,
1249 SilcNotifyType type;
1251 SILC_GET16_MSB(type, message->data);
1252 silc_buffer_pull(message, 2);
1254 msg = silc_calloc(message->len + 1, sizeof(char));
1255 memcpy(msg, message->data, message->len);
1256 client->ops->notify(client, sock->user_data, type, msg);
1260 /* Processes the received new Client ID from server. Old Client ID is
1261 deleted from cache and new one is added. */
1263 void silc_client_receive_new_id(SilcClient client,
1264 SilcSocketConnection sock,
1265 unsigned char *id_string)
1267 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1269 /* Delete old ID from ID cache */
1270 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1272 /* Save the new ID */
1274 silc_free(conn->local_id);
1275 conn->local_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
1276 if (conn->local_id_data)
1277 silc_free(conn->local_id_data);
1278 conn->local_id_data =
1279 silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1280 memcpy(conn->local_id_data, id_string, SILC_ID_CLIENT_LEN);
1281 conn->local_id_data_len = SILC_ID_CLIENT_LEN;
1282 if (!conn->local_entry)
1283 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1284 conn->local_entry->nickname = conn->nickname;
1285 conn->local_entry->id = conn->local_id;
1287 /* Put it to the ID cache */
1288 silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1289 conn->local_id, (void *)conn->local_entry, TRUE);
1292 /* Processed received Channel ID for a channel. This is called when client
1293 joins to channel and server replies with channel ID. The ID is cached. */
1295 void silc_client_new_channel_id(SilcClient client,
1296 SilcSocketConnection sock,
1299 unsigned char *id_string)
1301 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1303 SilcChannelEntry channel;
1305 SILC_LOG_DEBUG(("New channel ID"));
1307 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1308 channel = silc_calloc(1, sizeof(*channel));
1309 channel->channel_name = channel_name;
1311 channel->mode = mode;
1312 conn->current_channel = channel;
1314 /* Put it to the ID cache */
1315 silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1316 (void *)id, (void *)channel, TRUE);
1319 /* Processes received key for channel. The received key will be used
1320 to protect the traffic on the channel for now on. Client must receive
1321 the key to the channel before talking on the channel is possible.
1322 This is the key that server has generated, this is not the channel
1323 private key, it is entirely local setting. */
1325 void silc_client_receive_channel_key(SilcClient client,
1326 SilcSocketConnection sock,
1329 unsigned char *id_string, *key, *cipher;
1330 unsigned int key_len;
1331 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1333 SilcIDCacheEntry id_cache = NULL;
1334 SilcChannelEntry channel;
1335 SilcChannelKeyPayload payload;
1337 SILC_LOG_DEBUG(("Received key for channel"));
1339 payload = silc_channel_key_parse_payload(packet);
1343 id_string = silc_channel_key_get_id(payload, NULL);
1345 silc_channel_key_free_payload(payload);
1348 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1351 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1352 SILC_ID_CHANNEL, &id_cache))
1356 key = silc_channel_key_get_key(payload, &key_len);
1357 cipher = silc_channel_key_get_cipher(payload, NULL);
1359 channel = (SilcChannelEntry)id_cache->context;
1360 channel->key_len = key_len;
1361 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1362 memcpy(channel->key, key, key_len);
1364 silc_cipher_alloc(cipher, &channel->channel_key);
1365 if (!channel->channel_key) {
1366 client->ops->say(client, conn,
1367 "Cannot talk to channel: unsupported cipher %s", cipher);
1370 channel->channel_key->cipher->set_key(channel->channel_key->context,
1373 /* Client is now joined to the channel */
1374 channel->on_channel = TRUE;
1378 silc_channel_key_free_payload(payload);
1381 /* Process received message to a channel (or from a channel, really). This
1382 decrypts the channel message with channel specific key and parses the
1383 channel payload. Finally it displays the message on the screen. */
1385 void silc_client_channel_message(SilcClient client,
1386 SilcSocketConnection sock,
1387 SilcPacketContext *packet)
1389 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1390 SilcBuffer buffer = packet->buffer;
1391 SilcChannelPayload payload = NULL;
1392 SilcChannelID *id = NULL;
1393 SilcChannelEntry channel;
1394 SilcIDCacheEntry id_cache = NULL;
1397 if (packet->dst_id_type != SILC_ID_CHANNEL)
1400 id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1402 /* Find the channel entry from channels on this connection */
1403 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1404 SILC_ID_CHANNEL, &id_cache))
1407 channel = (SilcChannelEntry)id_cache->context;
1409 /* Decrypt the channel message payload. Push the IV out of the way,
1410 since it is not encrypted (after pushing buffer->tail has the IV). */
1411 silc_buffer_push_tail(buffer, 16);
1412 channel->channel_key->cipher->decrypt(channel->channel_key->context,
1413 buffer->data, buffer->data,
1414 buffer->len, buffer->tail);
1415 silc_buffer_pull_tail(buffer, 16);
1417 /* Parse the channel message payload */
1418 payload = silc_channel_parse_payload(buffer);
1422 /* Pass the message to application */
1423 if (packet->src_id_type == SILC_ID_CLIENT) {
1424 client->ops->channel_message(client, conn,
1425 silc_channel_get_nickname(payload, NULL),
1426 channel->channel_name,
1427 silc_channel_get_data(payload, NULL));
1429 /* Message from server */
1430 /* XXX maybe this should be passed to app... */
1431 client->ops->say(client, conn, "%s", silc_channel_get_data(payload, NULL));
1438 silc_channel_free_payload(payload);
1441 /* Private message received. This processes the private message and
1442 finally displays it on the screen. */
1444 void silc_client_private_message(SilcClient client,
1445 SilcSocketConnection sock,
1446 SilcPacketContext *packet)
1448 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1449 SilcBuffer buffer = packet->buffer;
1450 unsigned short nick_len;
1451 unsigned char *nickname, *message;
1454 silc_buffer_unformat(buffer,
1455 SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
1457 silc_buffer_pull(buffer, 2 + nick_len);
1459 message = silc_calloc(buffer->len + 1, sizeof(char));
1460 memcpy(message, buffer->data, buffer->len);
1462 /* Pass the private message to application */
1463 client->ops->private_message(client, conn, nickname, message);
1465 /* See if we are away (gone). If we are away we will reply to the
1466 sender with the set away message. */
1467 if (conn->away && conn->away->away) {
1468 SilcClientID *remote_id;
1469 SilcClientEntry remote_client;
1470 SilcIDCacheEntry id_cache;
1472 if (packet->src_id_type != SILC_ID_CLIENT)
1475 remote_id = silc_id_str2id(packet->src_id, SILC_ID_CLIENT);
1479 if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
1482 /* Check whether we know this client already */
1483 if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
1484 SILC_ID_CLIENT, &id_cache))
1486 /* Allocate client entry */
1487 remote_client = silc_calloc(1, sizeof(*remote_client));
1488 remote_client->id = remote_id;
1489 remote_client->nickname = strdup(nickname);
1491 /* Save the client to cache */
1492 silc_idcache_add(conn->client_cache, remote_client->nickname,
1493 SILC_ID_CLIENT, remote_client->id, remote_client,
1496 silc_free(remote_id);
1497 remote_client = (SilcClientEntry)id_cache->context;
1500 /* Send the away message */
1501 silc_client_packet_send_private_message(client, sock, remote_client,
1503 strlen(conn->away->away), TRUE);
1507 memset(message, 0, buffer->len);
1509 silc_free(nickname);