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 SILC Key Exchange (SKE) protocol to negotiate shared secret
247 key material between client and server. This function can be called
248 directly if application is performing its own connecting and does not
249 use the connecting provided by this library. */
251 int silc_client_start_key_exchange(SilcClient client,
252 SilcClientConnection conn,
255 SilcProtocol protocol;
256 SilcClientKEInternalContext *proto_ctx;
259 /* Allocate new socket connection object */
260 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
261 if (conn->sock == NULL) {
262 client->ops->say(client, conn,
263 "Error: Could not allocate connection socket");
267 conn->nickname = strdup(client->username);
268 conn->sock->hostname = conn->remote_host;
269 conn->sock->port = conn->remote_port;
271 /* Allocate internal Key Exchange context. This is sent to the
272 protocol as context. */
273 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
274 proto_ctx->client = (void *)client;
275 proto_ctx->sock = conn->sock;
276 proto_ctx->rng = client->rng;
277 proto_ctx->responder = FALSE;
279 /* Perform key exchange protocol. silc_client_connect_to_server_final
280 will be called after the protocol is finished. */
281 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
282 &protocol, (void *)proto_ctx,
283 silc_client_connect_to_server_second);
285 client->ops->say(client, conn,
286 "Error: Could not start authentication protocol");
289 conn->sock->protocol = protocol;
291 /* Register the connection for network input and output. This sets
292 that scheduler will listen for incoming packets for this connection
293 and sets that outgoing packets may be sent to this connection as well.
294 However, this doesn't set the scheduler for outgoing traffic, it will
295 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
296 later when outgoing data is available. */
297 context = (void *)client;
298 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
300 /* Execute the protocol */
301 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
305 /* Start of the connection to the remote server. This is called after
306 succesful TCP/IP connection has been established to the remote host. */
308 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
310 SilcClientInternalConnectContext *ctx =
311 (SilcClientInternalConnectContext *)context;
312 SilcClient client = ctx->client;
313 SilcClientConnection conn = ctx->conn;
314 int opt, opt_len = sizeof(opt);
316 SILC_LOG_DEBUG(("Start"));
318 /* Check the socket status as it might be in error */
319 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
321 if (ctx->tries < 2) {
322 /* Connection failed but lets try again */
323 client->ops->say(client, conn, "Could not connect to server %s: %s",
324 ctx->host, strerror(opt));
325 client->ops->say(client, conn,
326 "Connecting to port %d of server %s resumed",
327 ctx->port, ctx->host);
329 /* Unregister old connection try */
330 silc_schedule_unset_listen_fd(fd);
331 silc_net_close_connection(fd);
332 silc_task_unregister(client->io_queue, ctx->task);
335 silc_client_connect_to_server_internal(ctx);
338 /* Connection failed and we won't try anymore */
339 client->ops->say(client, conn, "Could not connect to server %s: %s",
340 ctx->host, strerror(opt));
341 silc_schedule_unset_listen_fd(fd);
342 silc_net_close_connection(fd);
343 silc_task_unregister(client->io_queue, ctx->task);
346 /* Notify application of failure */
347 client->ops->connect(client, conn, FALSE);
348 silc_client_del_connection(client, conn);
353 silc_schedule_unset_listen_fd(fd);
354 silc_task_unregister(client->io_queue, ctx->task);
357 if (!silc_client_start_key_exchange(client, conn, fd)) {
358 silc_net_close_connection(fd);
359 client->ops->connect(client, conn, FALSE);
363 /* Second part of the connecting to the server. This executed
364 authentication protocol. */
366 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
368 SilcProtocol protocol = (SilcProtocol)context;
369 SilcClientKEInternalContext *ctx =
370 (SilcClientKEInternalContext *)protocol->context;
371 SilcClient client = (SilcClient)ctx->client;
372 SilcSocketConnection sock = NULL;
373 SilcClientConnAuthInternalContext *proto_ctx;
375 SILC_LOG_DEBUG(("Start"));
377 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
378 /* Error occured during protocol */
379 SILC_LOG_DEBUG(("Error during KE protocol"));
380 silc_protocol_free(protocol);
382 silc_ske_free(ctx->ske);
384 silc_free(ctx->dest_id);
385 ctx->sock->protocol = NULL;
388 /* Notify application of failure */
389 client->ops->connect(client, ctx->sock->user_data, FALSE);
393 /* Allocate internal context for the authentication protocol. This
394 is sent as context for the protocol. */
395 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
396 proto_ctx->client = (void *)client;
397 proto_ctx->sock = sock = ctx->sock;
398 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
399 proto_ctx->dest_id_type = ctx->dest_id_type;
400 proto_ctx->dest_id = ctx->dest_id;
402 /* Resolve the authentication method to be used in this connection */
403 if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
404 sock->port, &proto_ctx->auth_meth,
405 &proto_ctx->auth_data,
406 &proto_ctx->auth_data_len))
408 /* XXX do AUTH_REQUEST resolcing with server */
409 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
412 /* Free old protocol as it is finished now */
413 silc_protocol_free(protocol);
415 silc_buffer_free(ctx->packet);
417 /* silc_free(ctx->keymat....); */
418 sock->protocol = NULL;
420 /* Allocate the authentication protocol. This is allocated here
421 but we won't start it yet. We will be receiving party of this
422 protocol thus we will wait that connecting party will make
424 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
425 &sock->protocol, (void *)proto_ctx,
426 silc_client_connect_to_server_final);
428 /* Execute the protocol */
429 sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
432 /* Finalizes the connection to the remote SILC server. This is called
433 after authentication protocol has been completed. This send our
434 user information to the server to receive our client ID from
437 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
439 SilcProtocol protocol = (SilcProtocol)context;
440 SilcClientConnAuthInternalContext *ctx =
441 (SilcClientConnAuthInternalContext *)protocol->context;
442 SilcClient client = (SilcClient)ctx->client;
443 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
446 SILC_LOG_DEBUG(("Start"));
448 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
449 /* Error occured during protocol */
450 SILC_LOG_DEBUG(("Error during authentication protocol"));
451 silc_protocol_free(protocol);
453 silc_free(ctx->auth_data);
455 silc_ske_free(ctx->ske);
457 silc_free(ctx->dest_id);
459 conn->sock->protocol = NULL;
461 /* Notify application of failure */
462 client->ops->connect(client, ctx->sock->user_data, FALSE);
466 /* Send NEW_CLIENT packet to the server. We will become registered
467 to the SILC network after sending this packet and we will receive
468 client ID from the server. */
469 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
470 strlen(client->realname));
471 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
472 silc_buffer_format(packet,
473 SILC_STR_UI_SHORT(strlen(client->username)),
474 SILC_STR_UI_XNSTRING(client->username,
475 strlen(client->username)),
476 SILC_STR_UI_SHORT(strlen(client->realname)),
477 SILC_STR_UI_XNSTRING(client->realname,
478 strlen(client->realname)),
481 /* Send the packet */
482 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
484 packet->data, packet->len, TRUE);
485 silc_buffer_free(packet);
487 /* Save remote ID. */
488 conn->remote_id = ctx->dest_id;
489 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
490 conn->remote_id_data_len = SILC_ID_SERVER_LEN;
492 /* Notify application of successful connection */
493 client->ops->connect(client, conn, TRUE);
495 silc_protocol_free(protocol);
497 silc_free(ctx->auth_data);
499 silc_ske_free(ctx->ske);
501 silc_free(ctx->dest_id);
503 conn->sock->protocol = NULL;
506 /* Internal routine that sends packet or marks packet to be sent. This
507 is used directly only in special cases. Normal cases should use
508 silc_server_packet_send. Returns < 0 on error. */
510 static int silc_client_packet_send_real(SilcClient client,
511 SilcSocketConnection sock,
516 /* Send the packet */
517 ret = silc_packet_send(sock, force_send);
521 /* Mark that there is some outgoing data available for this connection.
522 This call sets the connection both for input and output (the input
523 is set always and this call keeps the input setting, actually).
524 Actual data sending is performed by silc_client_packet_process. */
525 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
527 /* Mark to socket that data is pending in outgoing buffer. This flag
528 is needed if new data is added to the buffer before the earlier
529 put data is sent to the network. */
530 SILC_SET_OUTBUF_PENDING(sock);
535 /* Packet processing callback. This is used to send and receive packets
536 from network. This is generic task. */
538 SILC_TASK_CALLBACK(silc_client_packet_process)
540 SilcClient client = (SilcClient)context;
541 SilcSocketConnection sock = NULL;
542 SilcClientConnection conn;
545 SILC_LOG_DEBUG(("Processing packet"));
547 SILC_CLIENT_GET_SOCK(client, fd, sock);
551 conn = (SilcClientConnection)sock->user_data;
554 if (type == SILC_TASK_WRITE) {
555 SILC_LOG_DEBUG(("Writing data to connection"));
557 if (sock->outbuf->data - sock->outbuf->head)
558 silc_buffer_push(sock->outbuf,
559 sock->outbuf->data - sock->outbuf->head);
561 ret = silc_client_packet_send_real(client, sock, TRUE);
563 /* If returned -2 could not write to connection now, will do
568 /* The packet has been sent and now it is time to set the connection
569 back to only for input. When there is again some outgoing data
570 available for this connection it will be set for output as well.
571 This call clears the output setting and sets it only for input. */
572 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
573 SILC_UNSET_OUTBUF_PENDING(sock);
575 silc_buffer_clear(sock->outbuf);
579 /* Packet receiving */
580 if (type == SILC_TASK_READ) {
581 SILC_LOG_DEBUG(("Reading data from connection"));
583 /* Read data from network */
584 ret = silc_packet_receive(sock);
590 SILC_LOG_DEBUG(("Read EOF"));
592 /* If connection is disconnecting already we will finally
593 close the connection */
594 if (SILC_IS_DISCONNECTING(sock)) {
595 client->ops->disconnect(client, conn);
596 silc_client_close_connection(client, sock);
600 client->ops->say(client, conn, "Connection closed: premature EOF");
601 SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
602 client->ops->disconnect(client, conn);
603 silc_client_close_connection(client, sock);
607 /* Process the packet. This will call the parser that will then
608 decrypt and parse the packet. */
609 silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
610 silc_client_packet_parse, client);
614 /* Parses whole packet, received earlier. */
616 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
618 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
619 SilcClient client = (SilcClient)parse_ctx->context;
620 SilcPacketContext *packet = parse_ctx->packet;
621 SilcBuffer buffer = packet->buffer;
622 SilcSocketConnection sock = parse_ctx->sock;
623 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
626 SILC_LOG_DEBUG(("Start"));
628 /* Decrypt the received packet */
629 ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
634 /* Parse the packet. Packet type is returned. */
635 ret = silc_packet_parse(packet);
637 /* Parse the packet header in special way as this is "special"
639 ret = silc_packet_parse_special(packet);
642 if (ret == SILC_PACKET_NONE)
645 /* Parse the incoming packet type */
646 silc_client_packet_parse_type(client, sock, packet);
649 silc_buffer_clear(buffer);
651 silc_free(parse_ctx);
654 /* Parser callback called by silc_packet_receive_process. Thie merely
655 registers timeout that will handle the actual parsing when appropriate. */
657 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
659 SilcClient client = (SilcClient)parser_context->context;
661 /* Parse the packet */
662 silc_task_register(client->timeout_queue, parser_context->sock->sock,
663 silc_client_packet_parse_real,
664 (void *)parser_context, 0, 1,
666 SILC_TASK_PRI_NORMAL);
669 /* Parses the packet type and calls what ever routines the packet type
670 requires. This is done for all incoming packets. */
672 void silc_client_packet_parse_type(SilcClient client,
673 SilcSocketConnection sock,
674 SilcPacketContext *packet)
676 SilcBuffer buffer = packet->buffer;
677 SilcPacketType type = packet->type;
679 SILC_LOG_DEBUG(("Parsing packet type %d", type));
681 /* Parse the packet type */
683 case SILC_PACKET_DISCONNECT:
684 silc_client_disconnected_by_server(client, sock, buffer);
686 case SILC_PACKET_SUCCESS:
688 * Success received for something. For now we can have only
689 * one protocol for connection executing at once hence this
690 * success message is for whatever protocol is executing currently.
692 if (sock->protocol) {
693 sock->protocol->execute(client->timeout_queue, 0,
694 sock->protocol, sock->sock, 0, 0);
697 case SILC_PACKET_FAILURE:
699 * Failure received for some protocol. Set the protocol state to
700 * error and call the protocol callback. This fill cause error on
701 * protocol and it will call the final callback.
703 if (sock->protocol) {
704 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
705 sock->protocol->execute(client->timeout_queue, 0,
706 sock->protocol, sock->sock, 0, 0);
709 case SILC_PACKET_REJECT:
712 case SILC_PACKET_NOTIFY:
714 * Received notify message
716 silc_client_notify_by_server(client, sock, buffer);
719 case SILC_PACKET_ERROR:
721 * Received error message
723 silc_client_error_by_server(client, sock, buffer);
726 case SILC_PACKET_CHANNEL_MESSAGE:
728 * Received message to (from, actually) a channel
730 silc_client_channel_message(client, sock, packet);
732 case SILC_PACKET_CHANNEL_KEY:
734 * Received key for a channel. By receiving this key the client will be
735 * able to talk to the channel it has just joined. This can also be
736 * a new key for existing channel as keys expire peridiocally.
738 silc_client_receive_channel_key(client, sock, buffer);
741 case SILC_PACKET_PRIVATE_MESSAGE:
743 * Received private message
745 silc_client_private_message(client, sock, packet);
747 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
749 * Received private message key
753 case SILC_PACKET_COMMAND_REPLY:
755 * Recived reply for a command
757 silc_client_command_reply_process(client, sock, packet);
760 case SILC_PACKET_KEY_EXCHANGE:
761 if (sock->protocol) {
762 SilcClientKEInternalContext *proto_ctx =
763 (SilcClientKEInternalContext *)sock->protocol->context;
765 proto_ctx->packet = buffer;
766 proto_ctx->dest_id_type = packet->src_id_type;
767 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
769 /* Let the protocol handle the packet */
770 sock->protocol->execute(client->timeout_queue, 0,
771 sock->protocol, sock->sock, 0, 0);
773 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
774 "protocol active, packet dropped."));
776 /* XXX Trigger KE protocol?? Rekey actually! */
780 case SILC_PACKET_KEY_EXCHANGE_1:
781 if (sock->protocol) {
784 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
785 "protocol active, packet dropped."));
788 case SILC_PACKET_KEY_EXCHANGE_2:
789 if (sock->protocol) {
790 SilcClientKEInternalContext *proto_ctx =
791 (SilcClientKEInternalContext *)sock->protocol->context;
793 if (proto_ctx->packet)
794 silc_buffer_free(proto_ctx->packet);
796 proto_ctx->packet = buffer;
797 proto_ctx->dest_id_type = packet->src_id_type;
798 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
800 /* Let the protocol handle the packet */
801 sock->protocol->execute(client->timeout_queue, 0,
802 sock->protocol, sock->sock, 0, 0);
804 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
805 "protocol active, packet dropped."));
809 case SILC_PACKET_NEW_ID:
812 * Received new ID from server. This packet is received at
813 * the connection to the server. New ID is also received when
814 * user changes nickname but in that case the new ID is received
815 * as command reply and not as this packet type.
817 unsigned char *id_string;
818 unsigned short id_type;
820 silc_buffer_unformat(buffer,
821 SILC_STR_UI_SHORT(&id_type),
822 SILC_STR_UI16_STRING_ALLOC(&id_string),
825 if ((SilcIdType)id_type != SILC_ID_CLIENT)
828 silc_client_receive_new_id(client, sock, id_string);
829 silc_free(id_string);
834 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
839 /* Sends packet. This doesn't actually send the packet instead it assembles
840 it and marks it to be sent. However, if force_send is TRUE the packet
841 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
842 will be derived from sock argument. Otherwise the valid arguments sent
845 void silc_client_packet_send(SilcClient client,
846 SilcSocketConnection sock,
849 SilcIdType dst_id_type,
853 unsigned int data_len,
856 SilcPacketContext packetdata;
858 SILC_LOG_DEBUG(("Sending packet, type %d", type));
860 /* Get data used in the packet sending, keys and stuff */
861 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
862 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
863 cipher = ((SilcClientConnection)sock->user_data)->send_key;
865 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
866 hmac = ((SilcClientConnection)sock->user_data)->hmac;
868 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
869 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
870 dst_id_type = SILC_ID_SERVER;
874 /* Set the packet context pointers */
875 packetdata.flags = 0;
876 packetdata.type = type;
877 if (((SilcClientConnection)sock->user_data)->local_id_data)
878 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
880 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
881 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
882 packetdata.src_id_type = SILC_ID_CLIENT;
884 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
885 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
886 packetdata.dst_id_type = dst_id_type;
888 packetdata.dst_id = NULL;
889 packetdata.dst_id_len = 0;
890 packetdata.dst_id_type = SILC_ID_NONE;
892 packetdata.rng = client->rng;
893 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
894 packetdata.src_id_len + packetdata.dst_id_len;
895 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
897 /* Prepare outgoing data buffer for packet sending */
898 silc_packet_send_prepare(sock,
899 SILC_PACKET_HEADER_LEN +
900 packetdata.src_id_len +
901 packetdata.dst_id_len,
905 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
907 packetdata.buffer = sock->outbuf;
909 /* Put the data to the buffer */
910 if (data && data_len)
911 silc_buffer_put(sock->outbuf, data, data_len);
913 /* Create the outgoing packet */
914 silc_packet_assemble(&packetdata);
916 /* Encrypt the packet */
918 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
920 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
921 sock->outbuf->data, sock->outbuf->len);
923 /* Now actually send the packet */
924 silc_client_packet_send_real(client, sock, force_send);
927 /* Sends packet to a channel. Packet to channel is always encrypted
928 differently from "normal" packets. SILC header of the packet is
929 encrypted with the next receiver's key and the rest of the packet is
930 encrypted with the channel specific key. Padding and HMAC is computed
931 with the next receiver's key. */
933 void silc_client_packet_send_to_channel(SilcClient client,
934 SilcSocketConnection sock,
935 SilcChannelEntry channel,
937 unsigned int data_len,
941 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
943 SilcPacketContext packetdata;
946 unsigned char *id_string;
948 SILC_LOG_DEBUG(("Sending packet to channel"));
950 if (!channel || !channel->key) {
951 client->ops->say(client, conn,
952 "Cannot talk to channel: key does not exist");
958 for (i = 0; i < 16; i++)
959 channel->iv[i] = silc_rng_get_byte(client->rng);
961 silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
963 /* Encode the channel payload */
964 payload = silc_channel_encode_payload(strlen(conn->nickname), conn->nickname,
965 data_len, data, 16, channel->iv,
968 client->ops->say(client, conn,
969 "Error: Could not create packet to be sent to channel");
973 /* Get data used in packet header encryption, keys and stuff. Rest
974 of the packet (the payload) is, however, encrypted with the
975 specified channel key. */
976 cipher = conn->send_key;
978 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
980 /* Set the packet context pointers. The destination ID is always
981 the Channel ID of the channel. Server and router will handle the
982 distribution of the packet. */
983 packetdata.flags = 0;
984 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
985 packetdata.src_id = conn->local_id_data;
986 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
987 packetdata.src_id_type = SILC_ID_CLIENT;
988 packetdata.dst_id = id_string;
989 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
990 packetdata.dst_id_type = SILC_ID_CHANNEL;
991 packetdata.rng = client->rng;
992 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
993 packetdata.src_id_len + packetdata.dst_id_len;
994 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
995 packetdata.src_id_len +
996 packetdata.dst_id_len));
998 /* Prepare outgoing data buffer for packet sending */
999 silc_packet_send_prepare(sock,
1000 SILC_PACKET_HEADER_LEN +
1001 packetdata.src_id_len +
1002 packetdata.dst_id_len,
1006 packetdata.buffer = sock->outbuf;
1008 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1009 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1010 payload->data, payload->data,
1011 payload->len - 16, /* -IV_LEN */
1014 /* Put the actual encrypted payload data into the buffer. */
1015 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1017 /* Create the outgoing packet */
1018 silc_packet_assemble(&packetdata);
1020 /* Encrypt the header and padding of the packet. This is encrypted
1021 with normal session key shared with our server. */
1022 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1023 packetdata.src_id_len + packetdata.dst_id_len +
1026 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1027 sock->outbuf->data, sock->outbuf->len);
1029 /* Now actually send the packet */
1030 silc_client_packet_send_real(client, sock, force_send);
1031 silc_buffer_free(payload);
1032 silc_free(id_string);
1035 /* Sends private message to remote client. If private message key has
1036 not been set with this client then the message will be encrypted using
1037 normal session keys. Private messages are special packets in SILC
1038 network hence we need this own function for them. This is similiar
1039 to silc_client_packet_send_to_channel except that we send private
1042 void silc_client_packet_send_private_message(SilcClient client,
1043 SilcSocketConnection sock,
1044 SilcClientEntry client_entry,
1045 unsigned char *data,
1046 unsigned int data_len,
1049 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1051 SilcPacketContext packetdata;
1052 unsigned int nick_len;
1056 SILC_LOG_DEBUG(("Sending private message"));
1058 /* Create private message payload */
1059 nick_len = strlen(conn->nickname);
1060 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1061 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1062 silc_buffer_format(buffer,
1063 SILC_STR_UI_SHORT(nick_len),
1064 SILC_STR_UI_XNSTRING(conn->nickname,
1066 SILC_STR_UI_XNSTRING(data, data_len),
1069 /* If we don't have private message specific key then private messages
1070 are just as any normal packet thus call normal packet sending. If
1071 the key exist then the encryption process is a bit different and
1072 will be done in the rest of this function. */
1073 if (!client_entry->send_key) {
1074 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1075 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1076 buffer->data, buffer->len, force_send);
1080 /* We have private message specific key */
1082 /* Get data used in the encryption */
1083 cipher = client_entry->send_key;
1086 /* Set the packet context pointers. */
1087 packetdata.flags = 0;
1088 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1089 packetdata.src_id = conn->local_id_data;
1090 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1091 packetdata.src_id_type = SILC_ID_CLIENT;
1093 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1095 packetdata.dst_id = conn->local_id_data;
1096 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1097 packetdata.dst_id_type = SILC_ID_CLIENT;
1098 packetdata.rng = client->rng;
1099 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1100 packetdata.src_id_len + packetdata.dst_id_len;
1101 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1102 packetdata.src_id_len +
1103 packetdata.dst_id_len));
1105 /* Prepare outgoing data buffer for packet sending */
1106 silc_packet_send_prepare(sock,
1107 SILC_PACKET_HEADER_LEN +
1108 packetdata.src_id_len +
1109 packetdata.dst_id_len,
1113 packetdata.buffer = sock->outbuf;
1115 /* Encrypt payload of the packet. Encrypt with private message specific
1116 key if it exist, otherwise with session key. */
1117 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1118 buffer->len, cipher->iv);
1120 /* Put the actual encrypted payload data into the buffer. */
1121 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1123 /* Create the outgoing packet */
1124 silc_packet_assemble(&packetdata);
1126 /* Encrypt the header and padding of the packet. */
1127 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1128 packetdata.src_id_len + packetdata.dst_id_len +
1131 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1132 sock->outbuf->data, sock->outbuf->len);
1134 /* Now actually send the packet */
1135 silc_client_packet_send_real(client, sock, force_send);
1136 silc_free(packetdata.dst_id);
1142 /* Closes connection to remote end. Free's all allocated data except
1143 for some information such as nickname etc. that are valid at all time. */
1145 void silc_client_close_connection(SilcClient client,
1146 SilcSocketConnection sock)
1148 SilcClientConnection conn;
1150 /* We won't listen for this connection anymore */
1151 silc_schedule_unset_listen_fd(sock->sock);
1153 /* Unregister all tasks */
1154 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1155 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1157 /* Close the actual connection */
1158 silc_net_close_connection(sock->sock);
1160 client->ops->say(client, sock->user_data,
1161 "Closed connection to host %s", sock->hostname ?
1162 sock->hostname : sock->ip);
1164 /* Free everything */
1165 if (sock->user_data) {
1166 conn = (SilcClientConnection)sock->user_data;
1168 /* XXX Free all client entries and channel entries. */
1170 /* Clear ID caches */
1171 silc_idcache_del_all(conn->client_cache);
1172 silc_idcache_del_all(conn->channel_cache);
1175 if (conn->remote_host)
1176 silc_free(conn->remote_host);
1178 silc_free(conn->local_id);
1179 if (conn->local_id_data)
1180 silc_free(conn->local_id_data);
1182 silc_cipher_free(conn->send_key);
1183 if (conn->receive_key)
1184 silc_cipher_free(conn->receive_key);
1186 silc_hmac_free(conn->hmac);
1187 if (conn->hmac_key) {
1188 memset(conn->hmac_key, 0, conn->hmac_key_len);
1189 silc_free(conn->hmac_key);
1193 conn->remote_port = 0;
1194 conn->remote_type = 0;
1195 conn->send_key = NULL;
1196 conn->receive_key = NULL;
1198 conn->hmac_key = NULL;
1199 conn->hmac_key_len = 0;
1200 conn->local_id = NULL;
1201 conn->local_id_data = NULL;
1202 conn->remote_host = NULL;
1203 conn->current_channel = NULL;
1205 silc_client_del_connection(client, conn);
1208 if (sock->protocol) {
1209 silc_protocol_free(sock->protocol);
1210 sock->protocol = NULL;
1212 silc_socket_free(sock);
1215 /* Called when we receive disconnection packet from server. This
1216 closes our end properly and displays the reason of the disconnection
1219 void silc_client_disconnected_by_server(SilcClient client,
1220 SilcSocketConnection sock,
1225 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1227 msg = silc_calloc(message->len + 1, sizeof(char));
1228 memcpy(msg, message->data, message->len);
1229 client->ops->say(client, sock->user_data, msg);
1232 SILC_SET_DISCONNECTED(sock);
1233 silc_client_close_connection(client, sock);
1236 /* Received error message from server. Display it on the screen.
1237 We don't take any action what so ever of the error message. */
1239 void silc_client_error_by_server(SilcClient client,
1240 SilcSocketConnection sock,
1245 msg = silc_calloc(message->len + 1, sizeof(char));
1246 memcpy(msg, message->data, message->len);
1247 client->ops->say(client, sock->user_data, msg);
1251 /* Received notify message from server */
1253 void silc_client_notify_by_server(SilcClient client,
1254 SilcSocketConnection sock,
1258 SilcNotifyType type;
1260 SILC_GET16_MSB(type, message->data);
1261 silc_buffer_pull(message, 2);
1263 msg = silc_calloc(message->len + 1, sizeof(char));
1264 memcpy(msg, message->data, message->len);
1265 client->ops->notify(client, sock->user_data, type, msg);
1269 /* Processes the received new Client ID from server. Old Client ID is
1270 deleted from cache and new one is added. */
1272 void silc_client_receive_new_id(SilcClient client,
1273 SilcSocketConnection sock,
1274 unsigned char *id_string)
1276 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1278 /* Delete old ID from ID cache */
1279 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1281 /* Save the new ID */
1283 silc_free(conn->local_id);
1284 conn->local_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
1285 if (conn->local_id_data)
1286 silc_free(conn->local_id_data);
1287 conn->local_id_data =
1288 silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1289 memcpy(conn->local_id_data, id_string, SILC_ID_CLIENT_LEN);
1290 conn->local_id_data_len = SILC_ID_CLIENT_LEN;
1291 if (!conn->local_entry)
1292 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1293 conn->local_entry->nickname = conn->nickname;
1294 conn->local_entry->id = conn->local_id;
1296 /* Put it to the ID cache */
1297 silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1298 conn->local_id, (void *)conn->local_entry, TRUE);
1301 /* Processed received Channel ID for a channel. This is called when client
1302 joins to channel and server replies with channel ID. The ID is cached. */
1304 void silc_client_new_channel_id(SilcClient client,
1305 SilcSocketConnection sock,
1308 unsigned char *id_string)
1310 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1312 SilcChannelEntry channel;
1314 SILC_LOG_DEBUG(("New channel ID"));
1316 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1317 channel = silc_calloc(1, sizeof(*channel));
1318 channel->channel_name = channel_name;
1320 channel->mode = mode;
1321 conn->current_channel = channel;
1323 /* Put it to the ID cache */
1324 silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1325 (void *)id, (void *)channel, TRUE);
1328 /* Processes received key for channel. The received key will be used
1329 to protect the traffic on the channel for now on. Client must receive
1330 the key to the channel before talking on the channel is possible.
1331 This is the key that server has generated, this is not the channel
1332 private key, it is entirely local setting. */
1334 void silc_client_receive_channel_key(SilcClient client,
1335 SilcSocketConnection sock,
1338 unsigned char *id_string, *key, *cipher;
1339 unsigned int key_len;
1340 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1342 SilcIDCacheEntry id_cache = NULL;
1343 SilcChannelEntry channel;
1344 SilcChannelKeyPayload payload;
1346 SILC_LOG_DEBUG(("Received key for channel"));
1348 payload = silc_channel_key_parse_payload(packet);
1352 id_string = silc_channel_key_get_id(payload, NULL);
1354 silc_channel_key_free_payload(payload);
1357 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1360 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1361 SILC_ID_CHANNEL, &id_cache))
1365 key = silc_channel_key_get_key(payload, &key_len);
1366 cipher = silc_channel_key_get_cipher(payload, NULL);
1368 channel = (SilcChannelEntry)id_cache->context;
1369 channel->key_len = key_len;
1370 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1371 memcpy(channel->key, key, key_len);
1373 silc_cipher_alloc(cipher, &channel->channel_key);
1374 if (!channel->channel_key) {
1375 client->ops->say(client, conn,
1376 "Cannot talk to channel: unsupported cipher %s", cipher);
1379 channel->channel_key->cipher->set_key(channel->channel_key->context,
1382 /* Client is now joined to the channel */
1383 channel->on_channel = TRUE;
1387 silc_channel_key_free_payload(payload);
1390 /* Process received message to a channel (or from a channel, really). This
1391 decrypts the channel message with channel specific key and parses the
1392 channel payload. Finally it displays the message on the screen. */
1394 void silc_client_channel_message(SilcClient client,
1395 SilcSocketConnection sock,
1396 SilcPacketContext *packet)
1398 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1399 SilcBuffer buffer = packet->buffer;
1400 SilcChannelPayload payload = NULL;
1401 SilcChannelID *id = NULL;
1402 SilcChannelEntry channel;
1403 SilcIDCacheEntry id_cache = NULL;
1406 if (packet->dst_id_type != SILC_ID_CHANNEL)
1409 id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1411 /* Find the channel entry from channels on this connection */
1412 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1413 SILC_ID_CHANNEL, &id_cache))
1416 channel = (SilcChannelEntry)id_cache->context;
1418 /* Decrypt the channel message payload. Push the IV out of the way,
1419 since it is not encrypted (after pushing buffer->tail has the IV). */
1420 silc_buffer_push_tail(buffer, 16);
1421 channel->channel_key->cipher->decrypt(channel->channel_key->context,
1422 buffer->data, buffer->data,
1423 buffer->len, buffer->tail);
1424 silc_buffer_pull_tail(buffer, 16);
1426 /* Parse the channel message payload */
1427 payload = silc_channel_parse_payload(buffer);
1431 /* Pass the message to application */
1432 if (packet->src_id_type == SILC_ID_CLIENT) {
1433 client->ops->channel_message(client, conn,
1434 silc_channel_get_nickname(payload, NULL),
1435 channel->channel_name,
1436 silc_channel_get_data(payload, NULL));
1438 /* Message from server */
1439 /* XXX maybe this should be passed to app... */
1440 client->ops->say(client, conn, "%s", silc_channel_get_data(payload, NULL));
1447 silc_channel_free_payload(payload);
1450 /* Private message received. This processes the private message and
1451 finally displays it on the screen. */
1453 void silc_client_private_message(SilcClient client,
1454 SilcSocketConnection sock,
1455 SilcPacketContext *packet)
1457 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1458 SilcBuffer buffer = packet->buffer;
1459 unsigned short nick_len;
1460 unsigned char *nickname, *message;
1463 silc_buffer_unformat(buffer,
1464 SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
1466 silc_buffer_pull(buffer, 2 + nick_len);
1468 message = silc_calloc(buffer->len + 1, sizeof(char));
1469 memcpy(message, buffer->data, buffer->len);
1471 /* Pass the private message to application */
1472 client->ops->private_message(client, conn, nickname, message);
1474 /* See if we are away (gone). If we are away we will reply to the
1475 sender with the set away message. */
1476 if (conn->away && conn->away->away) {
1477 SilcClientID *remote_id;
1478 SilcClientEntry remote_client;
1479 SilcIDCacheEntry id_cache;
1481 if (packet->src_id_type != SILC_ID_CLIENT)
1484 remote_id = silc_id_str2id(packet->src_id, SILC_ID_CLIENT);
1488 if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
1491 /* Check whether we know this client already */
1492 if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
1493 SILC_ID_CLIENT, &id_cache))
1495 /* Allocate client entry */
1496 remote_client = silc_calloc(1, sizeof(*remote_client));
1497 remote_client->id = remote_id;
1498 remote_client->nickname = strdup(nickname);
1500 /* Save the client to cache */
1501 silc_idcache_add(conn->client_cache, remote_client->nickname,
1502 SILC_ID_CLIENT, remote_client->id, remote_client,
1505 silc_free(remote_id);
1506 remote_client = (SilcClientEntry)id_cache->context;
1509 /* Send the away message */
1510 silc_client_packet_send_private_message(client, sock, remote_client,
1512 strlen(conn->away->away), TRUE);
1516 memset(message, 0, buffer->len);
1518 silc_free(nickname);