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 if (!silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
610 silc_client_packet_parse, client)) {
611 silc_buffer_clear(sock->inbuf);
617 /* Parses whole packet, received earlier. */
619 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
621 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
622 SilcClient client = (SilcClient)parse_ctx->context;
623 SilcPacketContext *packet = parse_ctx->packet;
624 SilcBuffer buffer = packet->buffer;
625 SilcSocketConnection sock = parse_ctx->sock;
626 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
629 SILC_LOG_DEBUG(("Start"));
631 /* Decrypt the received packet */
632 ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
637 /* Parse the packet. Packet type is returned. */
638 ret = silc_packet_parse(packet);
640 /* Parse the packet header in special way as this is "special"
642 ret = silc_packet_parse_special(packet);
645 if (ret == SILC_PACKET_NONE)
648 /* Parse the incoming packet type */
649 silc_client_packet_parse_type(client, sock, packet);
652 silc_buffer_clear(buffer);
654 silc_free(parse_ctx);
657 /* Parser callback called by silc_packet_receive_process. Thie merely
658 registers timeout that will handle the actual parsing when appropriate. */
660 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
662 SilcClient client = (SilcClient)parser_context->context;
664 /* Parse the packet */
665 silc_task_register(client->timeout_queue, parser_context->sock->sock,
666 silc_client_packet_parse_real,
667 (void *)parser_context, 0, 1,
669 SILC_TASK_PRI_NORMAL);
672 /* Parses the packet type and calls what ever routines the packet type
673 requires. This is done for all incoming packets. */
675 void silc_client_packet_parse_type(SilcClient client,
676 SilcSocketConnection sock,
677 SilcPacketContext *packet)
679 SilcBuffer buffer = packet->buffer;
680 SilcPacketType type = packet->type;
682 SILC_LOG_DEBUG(("Parsing packet type %d", type));
684 /* Parse the packet type */
686 case SILC_PACKET_DISCONNECT:
687 silc_client_disconnected_by_server(client, sock, buffer);
689 case SILC_PACKET_SUCCESS:
691 * Success received for something. For now we can have only
692 * one protocol for connection executing at once hence this
693 * success message is for whatever protocol is executing currently.
695 if (sock->protocol) {
696 sock->protocol->execute(client->timeout_queue, 0,
697 sock->protocol, sock->sock, 0, 0);
700 case SILC_PACKET_FAILURE:
702 * Failure received for some protocol. Set the protocol state to
703 * error and call the protocol callback. This fill cause error on
704 * protocol and it will call the final callback.
706 if (sock->protocol) {
707 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
708 sock->protocol->execute(client->timeout_queue, 0,
709 sock->protocol, sock->sock, 0, 0);
712 case SILC_PACKET_REJECT:
715 case SILC_PACKET_NOTIFY:
717 * Received notify message
719 silc_client_notify_by_server(client, sock, buffer);
722 case SILC_PACKET_ERROR:
724 * Received error message
726 silc_client_error_by_server(client, sock, buffer);
729 case SILC_PACKET_CHANNEL_MESSAGE:
731 * Received message to (from, actually) a channel
733 silc_client_channel_message(client, sock, packet);
735 case SILC_PACKET_CHANNEL_KEY:
737 * Received key for a channel. By receiving this key the client will be
738 * able to talk to the channel it has just joined. This can also be
739 * a new key for existing channel as keys expire peridiocally.
741 silc_client_receive_channel_key(client, sock, buffer);
744 case SILC_PACKET_PRIVATE_MESSAGE:
746 * Received private message
748 silc_client_private_message(client, sock, packet);
750 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
752 * Received private message key
756 case SILC_PACKET_COMMAND_REPLY:
758 * Recived reply for a command
760 silc_client_command_reply_process(client, sock, packet);
763 case SILC_PACKET_KEY_EXCHANGE:
764 if (sock->protocol) {
765 SilcClientKEInternalContext *proto_ctx =
766 (SilcClientKEInternalContext *)sock->protocol->context;
768 proto_ctx->packet = buffer;
769 proto_ctx->dest_id_type = packet->src_id_type;
770 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
772 /* Let the protocol handle the packet */
773 sock->protocol->execute(client->timeout_queue, 0,
774 sock->protocol, sock->sock, 0, 0);
776 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
777 "protocol active, packet dropped."));
779 /* XXX Trigger KE protocol?? Rekey actually! */
783 case SILC_PACKET_KEY_EXCHANGE_1:
784 if (sock->protocol) {
787 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
788 "protocol active, packet dropped."));
791 case SILC_PACKET_KEY_EXCHANGE_2:
792 if (sock->protocol) {
793 SilcClientKEInternalContext *proto_ctx =
794 (SilcClientKEInternalContext *)sock->protocol->context;
796 if (proto_ctx->packet)
797 silc_buffer_free(proto_ctx->packet);
799 proto_ctx->packet = buffer;
800 proto_ctx->dest_id_type = packet->src_id_type;
801 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
803 /* Let the protocol handle the packet */
804 sock->protocol->execute(client->timeout_queue, 0,
805 sock->protocol, sock->sock, 0, 0);
807 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
808 "protocol active, packet dropped."));
812 case SILC_PACKET_NEW_ID:
815 * Received new ID from server. This packet is received at
816 * the connection to the server. New ID is also received when
817 * user changes nickname but in that case the new ID is received
818 * as command reply and not as this packet type.
820 unsigned char *id_string;
821 unsigned short id_type;
823 silc_buffer_unformat(buffer,
824 SILC_STR_UI_SHORT(&id_type),
825 SILC_STR_UI16_STRING_ALLOC(&id_string),
828 if ((SilcIdType)id_type != SILC_ID_CLIENT)
831 silc_client_receive_new_id(client, sock, id_string);
832 silc_free(id_string);
837 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
842 /* Sends packet. This doesn't actually send the packet instead it assembles
843 it and marks it to be sent. However, if force_send is TRUE the packet
844 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
845 will be derived from sock argument. Otherwise the valid arguments sent
848 void silc_client_packet_send(SilcClient client,
849 SilcSocketConnection sock,
852 SilcIdType dst_id_type,
856 unsigned int data_len,
859 SilcPacketContext packetdata;
861 SILC_LOG_DEBUG(("Sending packet, type %d", type));
863 /* Get data used in the packet sending, keys and stuff */
864 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
865 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
866 cipher = ((SilcClientConnection)sock->user_data)->send_key;
868 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
869 hmac = ((SilcClientConnection)sock->user_data)->hmac;
871 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
872 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
873 dst_id_type = SILC_ID_SERVER;
877 /* Set the packet context pointers */
878 packetdata.flags = 0;
879 packetdata.type = type;
880 if (((SilcClientConnection)sock->user_data)->local_id_data)
881 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
883 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
884 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
885 packetdata.src_id_type = SILC_ID_CLIENT;
887 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
888 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
889 packetdata.dst_id_type = dst_id_type;
891 packetdata.dst_id = NULL;
892 packetdata.dst_id_len = 0;
893 packetdata.dst_id_type = SILC_ID_NONE;
895 packetdata.rng = client->rng;
896 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
897 packetdata.src_id_len + packetdata.dst_id_len;
898 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
900 /* Prepare outgoing data buffer for packet sending */
901 silc_packet_send_prepare(sock,
902 SILC_PACKET_HEADER_LEN +
903 packetdata.src_id_len +
904 packetdata.dst_id_len,
908 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
910 packetdata.buffer = sock->outbuf;
912 /* Put the data to the buffer */
913 if (data && data_len)
914 silc_buffer_put(sock->outbuf, data, data_len);
916 /* Create the outgoing packet */
917 silc_packet_assemble(&packetdata);
919 /* Encrypt the packet */
921 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
923 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
924 sock->outbuf->data, sock->outbuf->len);
926 /* Now actually send the packet */
927 silc_client_packet_send_real(client, sock, force_send);
930 /* Sends packet to a channel. Packet to channel is always encrypted
931 differently from "normal" packets. SILC header of the packet is
932 encrypted with the next receiver's key and the rest of the packet is
933 encrypted with the channel specific key. Padding and HMAC is computed
934 with the next receiver's key. */
936 void silc_client_packet_send_to_channel(SilcClient client,
937 SilcSocketConnection sock,
938 SilcChannelEntry channel,
940 unsigned int data_len,
944 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
946 SilcPacketContext packetdata;
949 unsigned char *id_string;
951 SILC_LOG_DEBUG(("Sending packet to channel"));
953 if (!channel || !channel->key) {
954 client->ops->say(client, conn,
955 "Cannot talk to channel: key does not exist");
961 for (i = 0; i < 16; i++)
962 channel->iv[i] = silc_rng_get_byte(client->rng);
964 silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
966 /* Encode the channel payload */
967 payload = silc_channel_encode_payload(strlen(conn->nickname), conn->nickname,
968 data_len, data, 16, channel->iv,
971 client->ops->say(client, conn,
972 "Error: Could not create packet to be sent to channel");
976 /* Get data used in packet header encryption, keys and stuff. Rest
977 of the packet (the payload) is, however, encrypted with the
978 specified channel key. */
979 cipher = conn->send_key;
981 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
983 /* Set the packet context pointers. The destination ID is always
984 the Channel ID of the channel. Server and router will handle the
985 distribution of the packet. */
986 packetdata.flags = 0;
987 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
988 packetdata.src_id = conn->local_id_data;
989 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
990 packetdata.src_id_type = SILC_ID_CLIENT;
991 packetdata.dst_id = id_string;
992 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
993 packetdata.dst_id_type = SILC_ID_CHANNEL;
994 packetdata.rng = client->rng;
995 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
996 packetdata.src_id_len + packetdata.dst_id_len;
997 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
998 packetdata.src_id_len +
999 packetdata.dst_id_len));
1001 /* Prepare outgoing data buffer for packet sending */
1002 silc_packet_send_prepare(sock,
1003 SILC_PACKET_HEADER_LEN +
1004 packetdata.src_id_len +
1005 packetdata.dst_id_len,
1009 packetdata.buffer = sock->outbuf;
1011 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1012 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1013 payload->data, payload->data,
1014 payload->len - 16, /* -IV_LEN */
1017 /* Put the actual encrypted payload data into the buffer. */
1018 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1020 /* Create the outgoing packet */
1021 silc_packet_assemble(&packetdata);
1023 /* Encrypt the header and padding of the packet. This is encrypted
1024 with normal session key shared with our server. */
1025 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1026 packetdata.src_id_len + packetdata.dst_id_len +
1029 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1030 sock->outbuf->data, sock->outbuf->len);
1032 /* Now actually send the packet */
1033 silc_client_packet_send_real(client, sock, force_send);
1034 silc_buffer_free(payload);
1035 silc_free(id_string);
1038 /* Sends private message to remote client. If private message key has
1039 not been set with this client then the message will be encrypted using
1040 normal session keys. Private messages are special packets in SILC
1041 network hence we need this own function for them. This is similiar
1042 to silc_client_packet_send_to_channel except that we send private
1045 void silc_client_packet_send_private_message(SilcClient client,
1046 SilcSocketConnection sock,
1047 SilcClientEntry client_entry,
1048 unsigned char *data,
1049 unsigned int data_len,
1052 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1054 SilcPacketContext packetdata;
1055 unsigned int nick_len;
1059 SILC_LOG_DEBUG(("Sending private message"));
1061 /* Create private message payload */
1062 nick_len = strlen(conn->nickname);
1063 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1064 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1065 silc_buffer_format(buffer,
1066 SILC_STR_UI_SHORT(nick_len),
1067 SILC_STR_UI_XNSTRING(conn->nickname,
1069 SILC_STR_UI_XNSTRING(data, data_len),
1072 /* If we don't have private message specific key then private messages
1073 are just as any normal packet thus call normal packet sending. If
1074 the key exist then the encryption process is a bit different and
1075 will be done in the rest of this function. */
1076 if (!client_entry->send_key) {
1077 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1078 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1079 buffer->data, buffer->len, force_send);
1083 /* We have private message specific key */
1085 /* Get data used in the encryption */
1086 cipher = client_entry->send_key;
1089 /* Set the packet context pointers. */
1090 packetdata.flags = 0;
1091 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1092 packetdata.src_id = conn->local_id_data;
1093 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1094 packetdata.src_id_type = SILC_ID_CLIENT;
1096 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1098 packetdata.dst_id = conn->local_id_data;
1099 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1100 packetdata.dst_id_type = SILC_ID_CLIENT;
1101 packetdata.rng = client->rng;
1102 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1103 packetdata.src_id_len + packetdata.dst_id_len;
1104 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1105 packetdata.src_id_len +
1106 packetdata.dst_id_len));
1108 /* Prepare outgoing data buffer for packet sending */
1109 silc_packet_send_prepare(sock,
1110 SILC_PACKET_HEADER_LEN +
1111 packetdata.src_id_len +
1112 packetdata.dst_id_len,
1116 packetdata.buffer = sock->outbuf;
1118 /* Encrypt payload of the packet. Encrypt with private message specific
1119 key if it exist, otherwise with session key. */
1120 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1121 buffer->len, cipher->iv);
1123 /* Put the actual encrypted payload data into the buffer. */
1124 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1126 /* Create the outgoing packet */
1127 silc_packet_assemble(&packetdata);
1129 /* Encrypt the header and padding of the packet. */
1130 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1131 packetdata.src_id_len + packetdata.dst_id_len +
1134 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1135 sock->outbuf->data, sock->outbuf->len);
1137 /* Now actually send the packet */
1138 silc_client_packet_send_real(client, sock, force_send);
1139 silc_free(packetdata.dst_id);
1145 /* Closes connection to remote end. Free's all allocated data except
1146 for some information such as nickname etc. that are valid at all time. */
1148 void silc_client_close_connection(SilcClient client,
1149 SilcSocketConnection sock)
1151 SilcClientConnection conn;
1153 /* We won't listen for this connection anymore */
1154 silc_schedule_unset_listen_fd(sock->sock);
1156 /* Unregister all tasks */
1157 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1158 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1160 /* Close the actual connection */
1161 silc_net_close_connection(sock->sock);
1163 client->ops->say(client, sock->user_data,
1164 "Closed connection to host %s", sock->hostname ?
1165 sock->hostname : sock->ip);
1167 /* Free everything */
1168 if (sock->user_data) {
1169 conn = (SilcClientConnection)sock->user_data;
1171 /* XXX Free all client entries and channel entries. */
1173 /* Clear ID caches */
1174 silc_idcache_del_all(conn->client_cache);
1175 silc_idcache_del_all(conn->channel_cache);
1178 if (conn->remote_host)
1179 silc_free(conn->remote_host);
1181 silc_free(conn->local_id);
1182 if (conn->local_id_data)
1183 silc_free(conn->local_id_data);
1185 silc_cipher_free(conn->send_key);
1186 if (conn->receive_key)
1187 silc_cipher_free(conn->receive_key);
1189 silc_hmac_free(conn->hmac);
1190 if (conn->hmac_key) {
1191 memset(conn->hmac_key, 0, conn->hmac_key_len);
1192 silc_free(conn->hmac_key);
1196 conn->remote_port = 0;
1197 conn->remote_type = 0;
1198 conn->send_key = NULL;
1199 conn->receive_key = NULL;
1201 conn->hmac_key = NULL;
1202 conn->hmac_key_len = 0;
1203 conn->local_id = NULL;
1204 conn->local_id_data = NULL;
1205 conn->remote_host = NULL;
1206 conn->current_channel = NULL;
1208 silc_client_del_connection(client, conn);
1211 if (sock->protocol) {
1212 silc_protocol_free(sock->protocol);
1213 sock->protocol = NULL;
1215 silc_socket_free(sock);
1218 /* Called when we receive disconnection packet from server. This
1219 closes our end properly and displays the reason of the disconnection
1222 void silc_client_disconnected_by_server(SilcClient client,
1223 SilcSocketConnection sock,
1228 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1230 msg = silc_calloc(message->len + 1, sizeof(char));
1231 memcpy(msg, message->data, message->len);
1232 client->ops->say(client, sock->user_data, msg);
1235 SILC_SET_DISCONNECTED(sock);
1236 silc_client_close_connection(client, sock);
1239 /* Received error message from server. Display it on the screen.
1240 We don't take any action what so ever of the error message. */
1242 void silc_client_error_by_server(SilcClient client,
1243 SilcSocketConnection sock,
1248 msg = silc_calloc(message->len + 1, sizeof(char));
1249 memcpy(msg, message->data, message->len);
1250 client->ops->say(client, sock->user_data, msg);
1254 /* Received notify message from server */
1256 void silc_client_notify_by_server(SilcClient client,
1257 SilcSocketConnection sock,
1261 SilcNotifyType type;
1263 SILC_GET16_MSB(type, message->data);
1264 silc_buffer_pull(message, 2);
1266 msg = silc_calloc(message->len + 1, sizeof(char));
1267 memcpy(msg, message->data, message->len);
1268 client->ops->notify(client, sock->user_data, type, msg);
1272 /* Processes the received new Client ID from server. Old Client ID is
1273 deleted from cache and new one is added. */
1275 void silc_client_receive_new_id(SilcClient client,
1276 SilcSocketConnection sock,
1277 unsigned char *id_string)
1279 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1281 /* Delete old ID from ID cache */
1282 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1284 /* Save the new ID */
1286 silc_free(conn->local_id);
1287 conn->local_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
1288 if (conn->local_id_data)
1289 silc_free(conn->local_id_data);
1290 conn->local_id_data =
1291 silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1292 memcpy(conn->local_id_data, id_string, SILC_ID_CLIENT_LEN);
1293 conn->local_id_data_len = SILC_ID_CLIENT_LEN;
1294 if (!conn->local_entry)
1295 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1296 conn->local_entry->nickname = conn->nickname;
1297 conn->local_entry->id = conn->local_id;
1299 /* Put it to the ID cache */
1300 silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1301 conn->local_id, (void *)conn->local_entry, TRUE);
1304 /* Processed received Channel ID for a channel. This is called when client
1305 joins to channel and server replies with channel ID. The ID is cached. */
1307 void silc_client_new_channel_id(SilcClient client,
1308 SilcSocketConnection sock,
1311 unsigned char *id_string)
1313 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1315 SilcChannelEntry channel;
1317 SILC_LOG_DEBUG(("New channel ID"));
1319 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1320 channel = silc_calloc(1, sizeof(*channel));
1321 channel->channel_name = channel_name;
1323 channel->mode = mode;
1324 conn->current_channel = channel;
1326 /* Put it to the ID cache */
1327 silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1328 (void *)id, (void *)channel, TRUE);
1331 /* Processes received key for channel. The received key will be used
1332 to protect the traffic on the channel for now on. Client must receive
1333 the key to the channel before talking on the channel is possible.
1334 This is the key that server has generated, this is not the channel
1335 private key, it is entirely local setting. */
1337 void silc_client_receive_channel_key(SilcClient client,
1338 SilcSocketConnection sock,
1341 unsigned char *id_string, *key, *cipher;
1342 unsigned int key_len;
1343 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1345 SilcIDCacheEntry id_cache = NULL;
1346 SilcChannelEntry channel;
1347 SilcChannelKeyPayload payload;
1349 SILC_LOG_DEBUG(("Received key for channel"));
1351 payload = silc_channel_key_parse_payload(packet);
1355 id_string = silc_channel_key_get_id(payload, NULL);
1357 silc_channel_key_free_payload(payload);
1360 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1363 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1364 SILC_ID_CHANNEL, &id_cache))
1368 key = silc_channel_key_get_key(payload, &key_len);
1369 cipher = silc_channel_key_get_cipher(payload, NULL);
1371 channel = (SilcChannelEntry)id_cache->context;
1372 channel->key_len = key_len;
1373 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1374 memcpy(channel->key, key, key_len);
1376 silc_cipher_alloc(cipher, &channel->channel_key);
1377 if (!channel->channel_key) {
1378 client->ops->say(client, conn,
1379 "Cannot talk to channel: unsupported cipher %s", cipher);
1382 channel->channel_key->cipher->set_key(channel->channel_key->context,
1385 /* Client is now joined to the channel */
1386 channel->on_channel = TRUE;
1390 silc_channel_key_free_payload(payload);
1393 /* Process received message to a channel (or from a channel, really). This
1394 decrypts the channel message with channel specific key and parses the
1395 channel payload. Finally it displays the message on the screen. */
1397 void silc_client_channel_message(SilcClient client,
1398 SilcSocketConnection sock,
1399 SilcPacketContext *packet)
1401 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1402 SilcBuffer buffer = packet->buffer;
1403 SilcChannelPayload payload = NULL;
1404 SilcChannelID *id = NULL;
1405 SilcChannelEntry channel;
1406 SilcIDCacheEntry id_cache = NULL;
1409 if (packet->dst_id_type != SILC_ID_CHANNEL)
1412 id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1414 /* Find the channel entry from channels on this connection */
1415 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1416 SILC_ID_CHANNEL, &id_cache))
1419 channel = (SilcChannelEntry)id_cache->context;
1421 /* Decrypt the channel message payload. Push the IV out of the way,
1422 since it is not encrypted (after pushing buffer->tail has the IV). */
1423 silc_buffer_push_tail(buffer, 16);
1424 channel->channel_key->cipher->decrypt(channel->channel_key->context,
1425 buffer->data, buffer->data,
1426 buffer->len, buffer->tail);
1427 silc_buffer_pull_tail(buffer, 16);
1429 /* Parse the channel message payload */
1430 payload = silc_channel_parse_payload(buffer);
1434 /* Pass the message to application */
1435 if (packet->src_id_type == SILC_ID_CLIENT) {
1436 client->ops->channel_message(client, conn,
1437 silc_channel_get_nickname(payload, NULL),
1438 channel->channel_name,
1439 silc_channel_get_data(payload, NULL));
1441 /* Message from server */
1442 /* XXX maybe this should be passed to app... */
1443 client->ops->say(client, conn, "%s", silc_channel_get_data(payload, NULL));
1450 silc_channel_free_payload(payload);
1453 /* Private message received. This processes the private message and
1454 finally displays it on the screen. */
1456 void silc_client_private_message(SilcClient client,
1457 SilcSocketConnection sock,
1458 SilcPacketContext *packet)
1460 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1461 SilcBuffer buffer = packet->buffer;
1462 unsigned short nick_len;
1463 unsigned char *nickname, *message;
1466 silc_buffer_unformat(buffer,
1467 SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
1469 silc_buffer_pull(buffer, 2 + nick_len);
1471 message = silc_calloc(buffer->len + 1, sizeof(char));
1472 memcpy(message, buffer->data, buffer->len);
1474 /* Pass the private message to application */
1475 client->ops->private_message(client, conn, nickname, message);
1477 /* See if we are away (gone). If we are away we will reply to the
1478 sender with the set away message. */
1479 if (conn->away && conn->away->away) {
1480 SilcClientID *remote_id;
1481 SilcClientEntry remote_client;
1482 SilcIDCacheEntry id_cache;
1484 if (packet->src_id_type != SILC_ID_CLIENT)
1487 remote_id = silc_id_str2id(packet->src_id, SILC_ID_CLIENT);
1491 if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
1494 /* Check whether we know this client already */
1495 if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
1496 SILC_ID_CLIENT, &id_cache))
1498 /* Allocate client entry */
1499 remote_client = silc_calloc(1, sizeof(*remote_client));
1500 remote_client->id = remote_id;
1501 remote_client->nickname = strdup(nickname);
1503 /* Save the client to cache */
1504 silc_idcache_add(conn->client_cache, remote_client->nickname,
1505 SILC_ID_CLIENT, remote_client->id, remote_client,
1508 silc_free(remote_id);
1509 remote_client = (SilcClientEntry)id_cache->context;
1512 /* Send the away message */
1513 silc_client_packet_send_private_message(client, sock, remote_client,
1515 strlen(conn->away->away), TRUE);
1519 memset(message, 0, buffer->len);
1521 silc_free(nickname);