5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "clientlibincludes.h"
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 /* Frees client object and its internals. */
54 void silc_client_free(SilcClient client)
58 silc_rng_free(client->rng);
64 /* Initializes the client. This makes all the necessary steps to make
65 the client ready to be run. One must call silc_client_run to run the
66 client. Returns FALSE if error occured, TRUE otherwise. */
68 int silc_client_init(SilcClient client)
70 SILC_LOG_DEBUG(("Initializing client"));
72 /* Initialize hash functions for client to use */
73 silc_hash_alloc("md5", &client->md5hash);
74 silc_hash_alloc("sha1", &client->sha1hash);
76 /* Initialize none cipher */
77 silc_cipher_alloc("none", &client->none_cipher);
79 /* Initialize random number generator */
80 client->rng = silc_rng_alloc();
81 silc_rng_init(client->rng);
82 silc_rng_global_init(client->rng);
84 /* Register protocols */
85 silc_client_protocols_register();
87 /* Initialize the scheduler */
88 silc_schedule_init(&client->io_queue, &client->timeout_queue,
89 &client->generic_queue, 5000);
94 /* Stops the client. This is called to stop the client and thus to stop
97 void silc_client_stop(SilcClient client)
99 SILC_LOG_DEBUG(("Stopping client"));
101 /* Stop the scheduler, although it might be already stopped. This
102 doesn't hurt anyone. This removes all the tasks and task queues,
104 silc_schedule_stop();
105 silc_schedule_uninit();
107 silc_client_protocols_unregister();
109 SILC_LOG_DEBUG(("Client stopped"));
112 /* Runs the client. This starts the scheduler from the utility library.
113 When this functions returns the execution of the appliation is over. */
115 void silc_client_run(SilcClient client)
117 SILC_LOG_DEBUG(("Running client"));
119 /* Start the scheduler, the heart of the SILC client. When this returns
120 the program will be terminated. */
124 /* Allocates and adds new connection to the client. This adds the allocated
125 connection to the connection table and returns a pointer to it. A client
126 can have multiple connections to multiple servers. Every connection must
127 be added to the client using this function. User data `context' may
128 be sent as argument. This function is normally used only if the
129 application performed the connecting outside the library. The library
130 however may use this internally. */
132 SilcClientConnection silc_client_add_connection(SilcClient client,
137 SilcClientConnection conn;
140 conn = silc_calloc(1, sizeof(*conn));
142 /* Initialize ID caches */
143 conn->client_cache = silc_idcache_alloc(0);
144 conn->channel_cache = silc_idcache_alloc(0);
145 conn->server_cache = silc_idcache_alloc(0);
146 conn->client = client;
147 conn->remote_host = strdup(hostname);
148 conn->remote_port = port;
149 conn->context = context;
150 conn->pending_commands = silc_dlist_init();
152 /* Add the connection to connections table */
153 for (i = 0; i < client->conns_count; i++)
154 if (client->conns && !client->conns[i]) {
155 client->conns[i] = conn;
159 client->conns = silc_realloc(client->conns, sizeof(*client->conns)
160 * (client->conns_count + 1));
161 client->conns[client->conns_count] = conn;
162 client->conns_count++;
167 /* Removes connection from client. Frees all memory. */
169 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
173 for (i = 0; i < client->conns_count; i++)
174 if (client->conns[i] == conn) {
175 if (conn->pending_commands)
176 silc_dlist_uninit(conn->pending_commands);
178 client->conns[i] = NULL;
182 /* Internal context for connection process. This is needed as we
183 doing asynchronous connecting. */
186 SilcClientConnection conn;
192 } SilcClientInternalConnectContext;
195 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
199 /* XXX In the future we should give up this non-blocking connect all
200 together and use threads instead. */
201 /* Create connection to server asynchronously */
202 sock = silc_net_create_connection_async(ctx->port, ctx->host);
206 /* Register task that will receive the async connect and will
208 ctx->task = silc_task_register(ctx->client->io_queue, sock,
209 silc_client_connect_to_server_start,
212 SILC_TASK_PRI_NORMAL);
213 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
214 silc_schedule_set_listen_fd(sock, ctx->task->iomask);
221 /* Connects to remote server. This is the main routine used to connect
222 to SILC server. Returns -1 on error and the created socket otherwise.
223 The `context' is user context that is saved into the SilcClientConnection
224 that is created after the connection is created. Note that application
225 may handle the connecting process outside the library. If this is the
226 case then this function is not used at all. When the connecting is
227 done the `connect' client operation is called. */
229 int silc_client_connect_to_server(SilcClient client, int port,
230 char *host, void *context)
232 SilcClientInternalConnectContext *ctx;
233 SilcClientConnection conn;
236 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
239 conn = silc_client_add_connection(client, host, port, context);
241 client->ops->say(client, conn,
242 "Connecting to port %d of server %s", port, host);
244 /* Allocate internal context for connection process. This is
245 needed as we are doing async connecting. */
246 ctx = silc_calloc(1, sizeof(*ctx));
247 ctx->client = client;
249 ctx->host = strdup(host);
253 /* Do the actual connecting process */
254 sock = silc_client_connect_to_server_internal(ctx);
256 silc_client_del_connection(client, conn);
260 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
261 key material between client and server. This function can be called
262 directly if application is performing its own connecting and does not
263 use the connecting provided by this library. This function is normally
264 used only if the application performed the connecting outside the library.
265 The library however may use this internally. */
267 int silc_client_start_key_exchange(SilcClient client,
268 SilcClientConnection conn,
271 SilcProtocol protocol;
272 SilcClientKEInternalContext *proto_ctx;
275 /* Allocate new socket connection object */
276 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
277 if (conn->sock == NULL) {
278 client->ops->say(client, conn,
279 "Error: Could not allocate connection socket");
283 conn->nickname = strdup(client->username);
284 conn->sock->hostname = conn->remote_host;
285 conn->sock->ip = strdup(conn->remote_host);
286 conn->sock->port = conn->remote_port;
288 /* Allocate internal Key Exchange context. This is sent to the
289 protocol as context. */
290 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
291 proto_ctx->client = (void *)client;
292 proto_ctx->sock = conn->sock;
293 proto_ctx->rng = client->rng;
294 proto_ctx->responder = FALSE;
296 /* Perform key exchange protocol. silc_client_connect_to_server_final
297 will be called after the protocol is finished. */
298 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
299 &protocol, (void *)proto_ctx,
300 silc_client_connect_to_server_second);
302 client->ops->say(client, conn,
303 "Error: Could not start authentication protocol");
306 conn->sock->protocol = protocol;
308 /* Register the connection for network input and output. This sets
309 that scheduler will listen for incoming packets for this connection
310 and sets that outgoing packets may be sent to this connection as well.
311 However, this doesn't set the scheduler for outgoing traffic, it will
312 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
313 later when outgoing data is available. */
314 context = (void *)client;
315 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
317 /* Execute the protocol */
318 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
322 /* Start of the connection to the remote server. This is called after
323 succesful TCP/IP connection has been established to the remote host. */
325 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
327 SilcClientInternalConnectContext *ctx =
328 (SilcClientInternalConnectContext *)context;
329 SilcClient client = ctx->client;
330 SilcClientConnection conn = ctx->conn;
331 int opt, opt_len = sizeof(opt);
333 SILC_LOG_DEBUG(("Start"));
335 /* Check the socket status as it might be in error */
336 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
338 if (ctx->tries < 2) {
339 /* Connection failed but lets try again */
340 client->ops->say(client, conn, "Could not connect to server %s: %s",
341 ctx->host, strerror(opt));
342 client->ops->say(client, conn,
343 "Connecting to port %d of server %s resumed",
344 ctx->port, ctx->host);
346 /* Unregister old connection try */
347 silc_schedule_unset_listen_fd(fd);
348 silc_net_close_connection(fd);
349 silc_task_unregister(client->io_queue, ctx->task);
352 silc_client_connect_to_server_internal(ctx);
355 /* Connection failed and we won't try anymore */
356 client->ops->say(client, conn, "Could not connect to server %s: %s",
357 ctx->host, strerror(opt));
358 silc_schedule_unset_listen_fd(fd);
359 silc_net_close_connection(fd);
360 silc_task_unregister(client->io_queue, ctx->task);
363 /* Notify application of failure */
364 client->ops->connect(client, conn, FALSE);
365 silc_client_del_connection(client, conn);
370 silc_schedule_unset_listen_fd(fd);
371 silc_task_unregister(client->io_queue, ctx->task);
374 if (!silc_client_start_key_exchange(client, conn, fd)) {
375 silc_net_close_connection(fd);
376 client->ops->connect(client, conn, FALSE);
380 /* Second part of the connecting to the server. This executed
381 authentication protocol. */
383 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
385 SilcProtocol protocol = (SilcProtocol)context;
386 SilcClientKEInternalContext *ctx =
387 (SilcClientKEInternalContext *)protocol->context;
388 SilcClient client = (SilcClient)ctx->client;
389 SilcSocketConnection sock = NULL;
390 SilcClientConnAuthInternalContext *proto_ctx;
392 SILC_LOG_DEBUG(("Start"));
394 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
395 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
396 /* Error occured during protocol */
397 SILC_LOG_DEBUG(("Error during KE protocol"));
398 silc_protocol_free(protocol);
400 silc_ske_free(ctx->ske);
402 silc_free(ctx->dest_id);
403 ctx->sock->protocol = NULL;
405 /* Notify application of failure */
406 client->ops->connect(client, ctx->sock->user_data, FALSE);
411 /* Allocate internal context for the authentication protocol. This
412 is sent as context for the protocol. */
413 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
414 proto_ctx->client = (void *)client;
415 proto_ctx->sock = sock = ctx->sock;
416 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
417 proto_ctx->dest_id_type = ctx->dest_id_type;
418 proto_ctx->dest_id = ctx->dest_id;
420 /* Resolve the authentication method to be used in this connection */
421 if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
422 sock->port, &proto_ctx->auth_meth,
423 &proto_ctx->auth_data,
424 &proto_ctx->auth_data_len))
426 /* XXX do AUTH_REQUEST resolcing with server */
427 proto_ctx->auth_meth = SILC_AUTH_NONE;
430 /* Free old protocol as it is finished now */
431 silc_protocol_free(protocol);
433 silc_packet_context_free(ctx->packet);
435 /* silc_free(ctx->keymat....); */
436 sock->protocol = NULL;
438 /* Allocate the authentication protocol. This is allocated here
439 but we won't start it yet. We will be receiving party of this
440 protocol thus we will wait that connecting party will make
442 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
443 &sock->protocol, (void *)proto_ctx,
444 silc_client_connect_to_server_final);
446 /* Execute the protocol */
447 sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
450 /* Finalizes the connection to the remote SILC server. This is called
451 after authentication protocol has been completed. This send our
452 user information to the server to receive our client ID from
455 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
457 SilcProtocol protocol = (SilcProtocol)context;
458 SilcClientConnAuthInternalContext *ctx =
459 (SilcClientConnAuthInternalContext *)protocol->context;
460 SilcClient client = (SilcClient)ctx->client;
461 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
464 SILC_LOG_DEBUG(("Start"));
466 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
467 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
468 /* Error occured during protocol */
469 SILC_LOG_DEBUG(("Error during authentication protocol"));
470 silc_protocol_free(protocol);
472 silc_free(ctx->auth_data);
474 silc_ske_free(ctx->ske);
476 silc_free(ctx->dest_id);
477 conn->sock->protocol = NULL;
479 /* Notify application of failure */
480 client->ops->connect(client, ctx->sock->user_data, FALSE);
485 /* Send NEW_CLIENT packet to the server. We will become registered
486 to the SILC network after sending this packet and we will receive
487 client ID from the server. */
488 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
489 strlen(client->realname));
490 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
491 silc_buffer_format(packet,
492 SILC_STR_UI_SHORT(strlen(client->username)),
493 SILC_STR_UI_XNSTRING(client->username,
494 strlen(client->username)),
495 SILC_STR_UI_SHORT(strlen(client->realname)),
496 SILC_STR_UI_XNSTRING(client->realname,
497 strlen(client->realname)),
500 /* Send the packet */
501 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
503 packet->data, packet->len, TRUE);
504 silc_buffer_free(packet);
506 /* Save remote ID. */
507 conn->remote_id = ctx->dest_id;
508 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
509 conn->remote_id_data_len = SILC_ID_SERVER_LEN;
511 silc_protocol_free(protocol);
513 silc_free(ctx->auth_data);
515 silc_ske_free(ctx->ske);
517 conn->sock->protocol = NULL;
520 /* Internal routine that sends packet or marks packet to be sent. This
521 is used directly only in special cases. Normal cases should use
522 silc_server_packet_send. Returns < 0 on error. */
524 static int silc_client_packet_send_real(SilcClient client,
525 SilcSocketConnection sock,
530 /* Send the packet */
531 ret = silc_packet_send(sock, force_send);
535 /* Mark that there is some outgoing data available for this connection.
536 This call sets the connection both for input and output (the input
537 is set always and this call keeps the input setting, actually).
538 Actual data sending is performed by silc_client_packet_process. */
539 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
541 /* Mark to socket that data is pending in outgoing buffer. This flag
542 is needed if new data is added to the buffer before the earlier
543 put data is sent to the network. */
544 SILC_SET_OUTBUF_PENDING(sock);
549 /* Packet processing callback. This is used to send and receive packets
550 from network. This is generic task. */
552 SILC_TASK_CALLBACK(silc_client_packet_process)
554 SilcClient client = (SilcClient)context;
555 SilcSocketConnection sock = NULL;
556 SilcClientConnection conn;
559 SILC_LOG_DEBUG(("Processing packet"));
561 SILC_CLIENT_GET_SOCK(client, fd, sock);
565 conn = (SilcClientConnection)sock->user_data;
568 if (type == SILC_TASK_WRITE) {
569 SILC_LOG_DEBUG(("Writing data to connection"));
571 if (sock->outbuf->data - sock->outbuf->head)
572 silc_buffer_push(sock->outbuf,
573 sock->outbuf->data - sock->outbuf->head);
575 ret = silc_client_packet_send_real(client, sock, TRUE);
577 /* If returned -2 could not write to connection now, will do
582 /* The packet has been sent and now it is time to set the connection
583 back to only for input. When there is again some outgoing data
584 available for this connection it will be set for output as well.
585 This call clears the output setting and sets it only for input. */
586 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
587 SILC_UNSET_OUTBUF_PENDING(sock);
589 silc_buffer_clear(sock->outbuf);
593 /* Packet receiving */
594 if (type == SILC_TASK_READ) {
595 SILC_LOG_DEBUG(("Reading data from connection"));
597 /* Read data from network */
598 ret = silc_packet_receive(sock);
604 SILC_LOG_DEBUG(("Read EOF"));
606 /* If connection is disconnecting already we will finally
607 close the connection */
608 if (SILC_IS_DISCONNECTING(sock)) {
609 client->ops->disconnect(client, conn);
610 silc_client_close_connection(client, conn);
614 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
615 client->ops->disconnect(client, conn);
616 silc_client_close_connection(client, conn);
620 /* Process the packet. This will call the parser that will then
621 decrypt and parse the packet. */
622 silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
623 silc_client_packet_parse, client);
627 /* Parses whole packet, received earlier. */
629 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
631 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
632 SilcClient client = (SilcClient)parse_ctx->context;
633 SilcPacketContext *packet = parse_ctx->packet;
634 SilcBuffer buffer = packet->buffer;
635 SilcSocketConnection sock = parse_ctx->sock;
636 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
639 SILC_LOG_DEBUG(("Start"));
641 /* Decrypt the received packet */
642 ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
647 /* Parse the packet. Packet type is returned. */
648 ret = silc_packet_parse(packet);
650 /* Parse the packet header in special way as this is "special"
652 ret = silc_packet_parse_special(packet);
655 if (ret == SILC_PACKET_NONE)
658 /* Parse the incoming packet type */
659 silc_client_packet_parse_type(client, sock, packet);
662 silc_buffer_clear(sock->inbuf);
663 silc_packet_context_free(packet);
664 silc_free(parse_ctx);
667 /* Parser callback called by silc_packet_receive_process. Thie merely
668 registers timeout that will handle the actual parsing when appropriate. */
670 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
672 SilcClient client = (SilcClient)parser_context->context;
674 /* Parse the packet */
675 silc_task_register(client->timeout_queue, parser_context->sock->sock,
676 silc_client_packet_parse_real,
677 (void *)parser_context, 0, 1,
679 SILC_TASK_PRI_NORMAL);
682 /* Parses the packet type and calls what ever routines the packet type
683 requires. This is done for all incoming packets. */
685 void silc_client_packet_parse_type(SilcClient client,
686 SilcSocketConnection sock,
687 SilcPacketContext *packet)
689 SilcBuffer buffer = packet->buffer;
690 SilcPacketType type = packet->type;
692 SILC_LOG_DEBUG(("Parsing packet type %d", type));
694 /* Parse the packet type */
696 case SILC_PACKET_DISCONNECT:
697 silc_client_disconnected_by_server(client, sock, buffer);
699 case SILC_PACKET_SUCCESS:
701 * Success received for something. For now we can have only
702 * one protocol for connection executing at once hence this
703 * success message is for whatever protocol is executing currently.
705 if (sock->protocol) {
706 sock->protocol->execute(client->timeout_queue, 0,
707 sock->protocol, sock->sock, 0, 0);
710 case SILC_PACKET_FAILURE:
712 * Failure received for some protocol. Set the protocol state to
713 * error and call the protocol callback. This fill cause error on
714 * protocol and it will call the final callback.
716 if (sock->protocol) {
717 sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
718 sock->protocol->execute(client->timeout_queue, 0,
719 sock->protocol, sock->sock, 0, 0);
721 /* XXX We have only two protocols currently thus we know what this
722 failure indication is. */
723 if (buffer->len >= 4) {
724 unsigned int failure;
726 SILC_GET32_MSB(failure, buffer->data);
728 /* Notify application */
729 client->ops->failure(client, sock->user_data, sock->protocol,
734 case SILC_PACKET_REJECT:
737 case SILC_PACKET_NOTIFY:
739 * Received notify message
741 silc_client_notify_by_server(client, sock, packet);
744 case SILC_PACKET_ERROR:
746 * Received error message
748 silc_client_error_by_server(client, sock, buffer);
751 case SILC_PACKET_CHANNEL_MESSAGE:
753 * Received message to (from, actually) a channel
755 silc_client_channel_message(client, sock, packet);
757 case SILC_PACKET_CHANNEL_KEY:
759 * Received key for a channel. By receiving this key the client will be
760 * able to talk to the channel it has just joined. This can also be
761 * a new key for existing channel as keys expire peridiocally.
763 silc_client_receive_channel_key(client, sock, buffer);
766 case SILC_PACKET_PRIVATE_MESSAGE:
768 * Received private message
770 silc_client_private_message(client, sock, packet);
772 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
774 * Received private message key
778 case SILC_PACKET_COMMAND_REPLY:
780 * Recived reply for a command
782 silc_client_command_reply_process(client, sock, packet);
785 case SILC_PACKET_KEY_EXCHANGE:
786 if (sock->protocol) {
787 SilcClientKEInternalContext *proto_ctx =
788 (SilcClientKEInternalContext *)sock->protocol->context;
790 proto_ctx->packet = silc_packet_context_dup(packet);
791 proto_ctx->dest_id_type = packet->src_id_type;
792 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
793 packet->src_id_type);
794 if (!proto_ctx->dest_id)
797 /* Let the protocol handle the packet */
798 sock->protocol->execute(client->timeout_queue, 0,
799 sock->protocol, sock->sock, 0, 0);
801 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
802 "protocol active, packet dropped."));
804 /* XXX Trigger KE protocol?? Rekey actually! */
808 case SILC_PACKET_KEY_EXCHANGE_1:
809 if (sock->protocol) {
812 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
813 "protocol active, packet dropped."));
816 case SILC_PACKET_KEY_EXCHANGE_2:
817 if (sock->protocol) {
818 SilcClientKEInternalContext *proto_ctx =
819 (SilcClientKEInternalContext *)sock->protocol->context;
821 if (proto_ctx->packet)
822 silc_packet_context_free(proto_ctx->packet);
824 proto_ctx->packet = silc_packet_context_dup(packet);
825 proto_ctx->dest_id_type = packet->src_id_type;
826 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
827 packet->src_id_type);
828 if (!proto_ctx->dest_id)
831 /* Let the protocol handle the packet */
832 sock->protocol->execute(client->timeout_queue, 0,
833 sock->protocol, sock->sock, 0, 0);
835 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
836 "protocol active, packet dropped."));
840 case SILC_PACKET_NEW_ID:
843 * Received new ID from server. This packet is received at
844 * the connection to the server. New ID is also received when
845 * user changes nickname but in that case the new ID is received
846 * as command reply and not as this packet type.
850 idp = silc_id_payload_parse(buffer);
853 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
856 silc_client_receive_new_id(client, sock, idp);
857 silc_id_payload_free(idp);
861 case SILC_PACKET_HEARTBEAT:
863 * Received heartbeat packet
865 SILC_LOG_DEBUG(("Heartbeat packet"));
869 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
874 /* Sends packet. This doesn't actually send the packet instead it assembles
875 it and marks it to be sent. However, if force_send is TRUE the packet
876 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
877 will be derived from sock argument. Otherwise the valid arguments sent
880 void silc_client_packet_send(SilcClient client,
881 SilcSocketConnection sock,
884 SilcIdType dst_id_type,
888 unsigned int data_len,
891 SilcPacketContext packetdata;
893 SILC_LOG_DEBUG(("Sending packet, type %d", type));
895 /* Get data used in the packet sending, keys and stuff */
896 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
897 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
898 cipher = ((SilcClientConnection)sock->user_data)->send_key;
900 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
901 hmac = ((SilcClientConnection)sock->user_data)->hmac;
903 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
904 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
905 dst_id_type = SILC_ID_SERVER;
909 /* Set the packet context pointers */
910 packetdata.flags = 0;
911 packetdata.type = type;
912 if (((SilcClientConnection)sock->user_data)->local_id_data)
913 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
915 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
916 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
917 packetdata.src_id_type = SILC_ID_CLIENT;
919 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
920 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
921 packetdata.dst_id_type = dst_id_type;
923 packetdata.dst_id = NULL;
924 packetdata.dst_id_len = 0;
925 packetdata.dst_id_type = SILC_ID_NONE;
927 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
928 packetdata.src_id_len + packetdata.dst_id_len;
929 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
931 /* Prepare outgoing data buffer for packet sending */
932 silc_packet_send_prepare(sock,
933 SILC_PACKET_HEADER_LEN +
934 packetdata.src_id_len +
935 packetdata.dst_id_len,
939 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
941 packetdata.buffer = sock->outbuf;
943 /* Put the data to the buffer */
944 if (data && data_len)
945 silc_buffer_put(sock->outbuf, data, data_len);
947 /* Create the outgoing packet */
948 silc_packet_assemble(&packetdata);
950 /* Encrypt the packet */
952 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
954 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
955 sock->outbuf->data, sock->outbuf->len);
957 /* Now actually send the packet */
958 silc_client_packet_send_real(client, sock, force_send);
961 /* Sends packet to the `channel'. Packet to channel is always encrypted
962 differently from "normal" packets. SILC header of the packet is
963 encrypted with the next receiver's key and the rest of the packet is
964 encrypted with the channel specific key. Padding and HMAC is computed
965 with the next receiver's key. The `data' is the channel message. If
966 the `force_send' is TRUE then the packet is sent immediately. */
968 void silc_client_send_channel_message(SilcClient client,
969 SilcClientConnection conn,
970 SilcChannelEntry channel,
972 unsigned int data_len,
976 SilcSocketConnection sock = conn->sock;
978 SilcPacketContext packetdata;
981 unsigned char *id_string;
982 unsigned int block_len;
984 SILC_LOG_DEBUG(("Sending packet to channel"));
986 if (!channel || !channel->key) {
987 client->ops->say(client, conn,
988 "Cannot talk to channel: key does not exist");
993 block_len = silc_cipher_get_block_len(channel->channel_key);
994 if (channel->iv[0] == '\0')
995 for (i = 0; i < block_len; i++) channel->iv[i] = silc_rng_get_byte(client->rng);
997 silc_hash_make(client->md5hash, channel->iv, block_len, channel->iv);
999 /* Encode the channel payload */
1000 payload = silc_channel_payload_encode(data_len, data, block_len,
1001 channel->iv, client->rng);
1003 client->ops->say(client, conn,
1004 "Error: Could not create packet to be sent to channel");
1008 /* Get data used in packet header encryption, keys and stuff. Rest
1009 of the packet (the payload) is, however, encrypted with the
1010 specified channel key. */
1011 cipher = conn->send_key;
1013 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1015 /* Set the packet context pointers. The destination ID is always
1016 the Channel ID of the channel. Server and router will handle the
1017 distribution of the packet. */
1018 packetdata.flags = 0;
1019 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1020 packetdata.src_id = conn->local_id_data;
1021 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1022 packetdata.src_id_type = SILC_ID_CLIENT;
1023 packetdata.dst_id = id_string;
1024 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1025 packetdata.dst_id_type = SILC_ID_CHANNEL;
1026 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
1027 packetdata.src_id_len + packetdata.dst_id_len;
1028 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1029 packetdata.src_id_len +
1030 packetdata.dst_id_len));
1032 /* Prepare outgoing data buffer for packet sending */
1033 silc_packet_send_prepare(sock,
1034 SILC_PACKET_HEADER_LEN +
1035 packetdata.src_id_len +
1036 packetdata.dst_id_len,
1040 packetdata.buffer = sock->outbuf;
1042 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1043 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1044 payload->data, payload->data,
1045 payload->len - block_len, /* -IV_LEN */
1048 /* Put the actual encrypted payload data into the buffer. */
1049 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1051 /* Create the outgoing packet */
1052 silc_packet_assemble(&packetdata);
1054 /* Encrypt the header and padding of the packet. This is encrypted
1055 with normal session key shared with our server. */
1056 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1057 packetdata.src_id_len + packetdata.dst_id_len +
1060 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1061 sock->outbuf->data, sock->outbuf->len);
1063 /* Now actually send the packet */
1064 silc_client_packet_send_real(client, sock, force_send);
1065 silc_buffer_free(payload);
1066 silc_free(id_string);
1069 /* Sends private message to remote client. If private message key has
1070 not been set with this client then the message will be encrypted using
1071 normal session keys. Private messages are special packets in SILC
1072 network hence we need this own function for them. This is similiar
1073 to silc_client_packet_send_to_channel except that we send private
1074 message. The `data' is the private message. If the `force_send' is
1075 TRUE the packet is sent immediately. */
1077 void silc_client_send_private_message(SilcClient client,
1078 SilcClientConnection conn,
1079 SilcClientEntry client_entry,
1080 unsigned char *data,
1081 unsigned int data_len,
1084 SilcSocketConnection sock = conn->sock;
1086 SilcPacketContext packetdata;
1087 unsigned int nick_len;
1091 SILC_LOG_DEBUG(("Sending private message"));
1093 /* Create private message payload */
1094 nick_len = strlen(conn->nickname);
1095 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1096 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1097 silc_buffer_format(buffer,
1098 SILC_STR_UI_SHORT(nick_len),
1099 SILC_STR_UI_XNSTRING(conn->nickname,
1101 SILC_STR_UI_XNSTRING(data, data_len),
1104 /* If we don't have private message specific key then private messages
1105 are just as any normal packet thus call normal packet sending. If
1106 the key exist then the encryption process is a bit different and
1107 will be done in the rest of this function. */
1108 if (!client_entry->send_key) {
1109 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1110 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1111 buffer->data, buffer->len, force_send);
1115 /* We have private message specific key */
1117 /* Get data used in the encryption */
1118 cipher = client_entry->send_key;
1121 /* Set the packet context pointers. */
1122 packetdata.flags = SILC_PACKET_FLAG_PRIVMSG_KEY;
1123 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1124 packetdata.src_id = conn->local_id_data;
1125 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1126 packetdata.src_id_type = SILC_ID_CLIENT;
1127 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1128 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1129 packetdata.dst_id_type = SILC_ID_CLIENT;
1130 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1131 packetdata.src_id_len + packetdata.dst_id_len;
1132 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1133 packetdata.src_id_len +
1134 packetdata.dst_id_len));
1136 /* Prepare outgoing data buffer for packet sending */
1137 silc_packet_send_prepare(sock,
1138 SILC_PACKET_HEADER_LEN +
1139 packetdata.src_id_len +
1140 packetdata.dst_id_len,
1144 packetdata.buffer = sock->outbuf;
1146 /* Encrypt payload of the packet. Encrypt with private message specific
1148 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1149 buffer->len, cipher->iv);
1151 /* Put the actual encrypted payload data into the buffer. */
1152 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1154 /* Create the outgoing packet */
1155 silc_packet_assemble(&packetdata);
1157 /* Encrypt the header and padding of the packet. */
1158 cipher = conn->send_key;
1159 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1160 packetdata.src_id_len + packetdata.dst_id_len +
1163 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1164 sock->outbuf->data, sock->outbuf->len);
1166 /* Now actually send the packet */
1167 silc_client_packet_send_real(client, sock, force_send);
1168 silc_free(packetdata.dst_id);
1174 /* Closes connection to remote end. Free's all allocated data except
1175 for some information such as nickname etc. that are valid at all time. */
1177 void silc_client_close_connection(SilcClient client,
1178 SilcClientConnection conn)
1180 SilcSocketConnection sock = conn->sock;
1182 /* We won't listen for this connection anymore */
1183 silc_schedule_unset_listen_fd(sock->sock);
1185 /* Unregister all tasks */
1186 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1187 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1189 /* Close the actual connection */
1190 silc_net_close_connection(sock->sock);
1192 client->ops->say(client, sock->user_data,
1193 "Closed connection to host %s", sock->hostname);
1195 /* Free everything */
1196 if (sock->user_data) {
1197 /* XXX Free all client entries and channel entries. */
1199 /* Clear ID caches */
1200 silc_idcache_del_all(conn->client_cache);
1201 silc_idcache_del_all(conn->channel_cache);
1204 if (conn->remote_host)
1205 silc_free(conn->remote_host);
1207 silc_free(conn->local_id);
1208 if (conn->local_id_data)
1209 silc_free(conn->local_id_data);
1211 silc_cipher_free(conn->send_key);
1212 if (conn->receive_key)
1213 silc_cipher_free(conn->receive_key);
1215 silc_hmac_free(conn->hmac);
1216 if (conn->hmac_key) {
1217 memset(conn->hmac_key, 0, conn->hmac_key_len);
1218 silc_free(conn->hmac_key);
1220 if (conn->pending_commands)
1221 silc_dlist_uninit(conn->pending_commands);
1224 conn->remote_port = 0;
1225 conn->remote_type = 0;
1226 conn->send_key = NULL;
1227 conn->receive_key = NULL;
1229 conn->hmac_key = NULL;
1230 conn->hmac_key_len = 0;
1231 conn->local_id = NULL;
1232 conn->local_id_data = NULL;
1233 conn->remote_host = NULL;
1234 conn->current_channel = NULL;
1235 conn->pending_commands = NULL;
1237 silc_client_del_connection(client, conn);
1240 if (sock->protocol) {
1241 silc_protocol_free(sock->protocol);
1242 sock->protocol = NULL;
1244 silc_socket_free(sock);
1247 /* Called when we receive disconnection packet from server. This
1248 closes our end properly and displays the reason of the disconnection
1251 void silc_client_disconnected_by_server(SilcClient client,
1252 SilcSocketConnection sock,
1257 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1259 msg = silc_calloc(message->len + 1, sizeof(char));
1260 memcpy(msg, message->data, message->len);
1261 client->ops->say(client, sock->user_data, msg);
1264 SILC_SET_DISCONNECTED(sock);
1265 silc_client_close_connection(client, sock->user_data);
1268 /* Received error message from server. Display it on the screen.
1269 We don't take any action what so ever of the error message. */
1271 void silc_client_error_by_server(SilcClient client,
1272 SilcSocketConnection sock,
1277 msg = silc_calloc(message->len + 1, sizeof(char));
1278 memcpy(msg, message->data, message->len);
1279 client->ops->say(client, sock->user_data, msg);
1283 /* Called when notify is received and some async operation (such as command)
1284 is required before processing the notify message. This calls again the
1285 silc_client_notify_by_server and reprocesses the original notify packet. */
1287 static void silc_client_notify_by_server_pending(void *context)
1289 SilcPacketContext *p = (SilcPacketContext *)context;
1290 silc_client_notify_by_server(p->context, p->sock, p);
1293 /* Destructor for the pending command callback */
1295 static void silc_client_notify_by_server_destructor(void *context)
1297 silc_packet_context_free((SilcPacketContext *)context);
1300 /* Resolve client information from server by Client ID. */
1302 static void silc_client_notify_by_server_resolve(SilcClient client,
1303 SilcClientConnection conn,
1304 SilcPacketContext *packet,
1305 SilcClientID *client_id)
1307 SilcPacketContext *p = silc_packet_context_dup(packet);
1308 SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1310 p->context = (void *)client;
1311 p->sock = conn->sock;
1313 silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, ++conn->cmd_ident,
1314 1, 3, idp->data, idp->len);
1315 silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
1316 silc_client_notify_by_server_destructor,
1317 silc_client_notify_by_server_pending, p);
1318 silc_buffer_free(idp);
1321 /* Received notify message from server */
1323 void silc_client_notify_by_server(SilcClient client,
1324 SilcSocketConnection sock,
1325 SilcPacketContext *packet)
1327 SilcBuffer buffer = packet->buffer;
1328 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1329 SilcNotifyPayload payload;
1330 SilcNotifyType type;
1331 SilcArgumentPayload args;
1333 SilcClientID *client_id = NULL;
1334 SilcChannelID *channel_id = NULL;
1335 SilcClientEntry client_entry;
1336 SilcClientEntry client_entry2;
1337 SilcChannelEntry channel;
1338 SilcChannelUser chu;
1339 SilcIDCacheEntry id_cache = NULL;
1341 unsigned int tmp_len, mode;
1343 payload = silc_notify_payload_parse(buffer);
1347 type = silc_notify_get_type(payload);
1348 args = silc_notify_get_args(payload);
1353 case SILC_NOTIFY_TYPE_NONE:
1354 /* Notify application */
1355 client->ops->notify(client, conn, type,
1356 silc_argument_get_arg_type(args, 1, NULL));
1359 case SILC_NOTIFY_TYPE_INVITE:
1361 * Someone invited me to a channel. Find Client and Channel entries
1362 * for the application.
1366 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1370 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1374 /* Find Client entry and if not found query it */
1375 client_entry = silc_client_get_client_by_id(client, conn, client_id);
1376 if (!client_entry) {
1377 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1381 /* Get Channel ID */
1382 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1386 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1390 /* XXX Will ALWAYS fail because currently we don't have way to resolve
1391 channel information for channel that we're not joined to. */
1392 /* XXX ways to fix: use (extended) LIST command, or define the channel
1393 name to the notfy type when name resolving is not mandatory. */
1394 /* Find channel entry */
1395 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1396 SILC_ID_CHANNEL, &id_cache))
1399 channel = (SilcChannelEntry)id_cache->context;
1401 /* Notify application */
1402 client->ops->notify(client, conn, type, client_entry, channel);
1405 case SILC_NOTIFY_TYPE_JOIN:
1407 * Someone has joined to a channel. Get their ID and nickname and
1408 * cache them for later use.
1412 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1416 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1420 /* Find Client entry and if not found query it */
1421 client_entry = silc_client_get_client_by_id(client, conn, client_id);
1422 if (!client_entry) {
1423 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1427 /* If nickname or username hasn't been resolved, do so */
1428 if (!client_entry->nickname || !client_entry->username) {
1429 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1433 /* Get Channel ID */
1434 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1438 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1442 /* Get channel entry */
1443 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1444 SILC_ID_CHANNEL, &id_cache))
1447 channel = (SilcChannelEntry)id_cache->context;
1449 /* Add client to channel */
1450 chu = silc_calloc(1, sizeof(*chu));
1451 chu->client = client_entry;
1452 silc_list_add(channel->clients, chu);
1454 /* XXX add support for multiple same nicks on same channel. Check
1457 /* Notify application. The channel entry is sent last as this notify
1458 is for channel but application don't know it from the arguments
1460 client->ops->notify(client, conn, type, client_entry, channel);
1463 case SILC_NOTIFY_TYPE_LEAVE:
1465 * Someone has left a channel. We will remove it from the channel but
1466 * we'll keep it in the cache in case we'll need it later.
1470 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1474 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1478 /* Find Client entry */
1480 silc_client_get_client_by_id(client, conn, client_id);
1484 /* Get channel entry */
1485 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1489 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1490 SILC_ID_CHANNEL, &id_cache))
1493 channel = (SilcChannelEntry)id_cache->context;
1495 /* Remove client from channel */
1496 silc_list_start(channel->clients);
1497 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1498 if (chu->client == client_entry) {
1499 silc_list_del(channel->clients, chu);
1505 /* Notify application. The channel entry is sent last as this notify
1506 is for channel but application don't know it from the arguments
1508 client->ops->notify(client, conn, type, client_entry, channel);
1511 case SILC_NOTIFY_TYPE_SIGNOFF:
1513 * Someone left SILC. We'll remove it from all channels and from cache.
1517 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1521 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1525 /* Find Client entry */
1527 silc_client_get_client_by_id(client, conn, client_id);
1531 /* Remove from all channels */
1532 silc_client_remove_from_channels(client, conn, client_entry);
1534 /* Remove from cache */
1535 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1538 /* Get signoff message */
1539 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1543 /* Notify application */
1544 client->ops->notify(client, conn, type, client_entry, tmp);
1547 if (client_entry->nickname)
1548 silc_free(client_entry->nickname);
1549 if (client_entry->server)
1550 silc_free(client_entry->server);
1551 if (client_entry->id)
1552 silc_free(client_entry->id);
1553 if (client_entry->send_key)
1554 silc_cipher_free(client_entry->send_key);
1555 if (client_entry->receive_key)
1556 silc_cipher_free(client_entry->receive_key);
1559 case SILC_NOTIFY_TYPE_TOPIC_SET:
1561 * Someone set the topic on a channel.
1565 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1569 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1573 /* Find Client entry */
1575 silc_client_get_client_by_id(client, conn, client_id);
1580 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1584 /* Get channel entry */
1585 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1589 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1590 SILC_ID_CHANNEL, &id_cache))
1593 channel = (SilcChannelEntry)id_cache->context;
1595 /* Notify application. The channel entry is sent last as this notify
1596 is for channel but application don't know it from the arguments
1598 client->ops->notify(client, conn, type, client_entry, tmp, channel);
1601 case SILC_NOTIFY_TYPE_NICK_CHANGE:
1603 * Someone changed their nickname. If we don't have entry for the new
1604 * ID we will query it and return here after it's done. After we've
1605 * returned we fetch the old entry and free it and notify the
1609 /* Get new Client ID */
1610 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1614 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1619 if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1622 /* Find Client entry and if not found query it */
1624 silc_client_get_client_by_id(client, conn, client_id);
1625 if (!client_entry2) {
1626 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1629 silc_free(client_id);
1631 /* Get old Client ID */
1632 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1636 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1640 /* Find old Client entry */
1642 silc_client_get_client_by_id(client, conn, client_id);
1646 /* Remove the old from cache */
1647 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1650 /* Replace old ID entry with new one on all channels. */
1651 silc_client_replace_from_channels(client, conn, client_entry,
1654 /* Notify application */
1655 client->ops->notify(client, conn, type, client_entry, client_entry2);
1658 if (client_entry->nickname)
1659 silc_free(client_entry->nickname);
1660 if (client_entry->server)
1661 silc_free(client_entry->server);
1662 if (client_entry->id)
1663 silc_free(client_entry->id);
1664 if (client_entry->send_key)
1665 silc_cipher_free(client_entry->send_key);
1666 if (client_entry->receive_key)
1667 silc_cipher_free(client_entry->receive_key);
1670 case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1672 * Someone changed a channel mode
1676 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1680 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1684 /* Find Client entry */
1686 silc_client_get_client_by_id(client, conn, client_id);
1691 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1695 SILC_GET32_MSB(mode, tmp);
1697 /* Get channel entry */
1698 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1702 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1703 SILC_ID_CHANNEL, &id_cache))
1706 channel = (SilcChannelEntry)id_cache->context;
1708 /* Save the new mode */
1709 channel->mode = mode;
1711 /* Notify application. The channel entry is sent last as this notify
1712 is for channel but application don't know it from the arguments
1714 client->ops->notify(client, conn, type, client_entry, mode, channel);
1717 case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1719 * Someone changed user's mode on a channel
1723 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1727 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1731 /* Find Client entry */
1733 silc_client_get_client_by_id(client, conn, client_id);
1738 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1742 SILC_GET32_MSB(mode, tmp);
1744 /* Get target Client ID */
1745 tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1749 silc_free(client_id);
1750 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1754 /* Find target Client entry */
1756 silc_client_get_client_by_id(client, conn, client_id);
1760 /* Get channel entry */
1761 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1765 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1766 SILC_ID_CHANNEL, &id_cache))
1769 channel = (SilcChannelEntry)id_cache->context;
1772 silc_list_start(channel->clients);
1773 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1774 if (chu->client == client_entry) {
1780 /* Notify application. The channel entry is sent last as this notify
1781 is for channel but application don't know it from the arguments
1783 client->ops->notify(client, conn, type, client_entry, mode,
1784 client_entry2, channel);
1787 case SILC_NOTIFY_TYPE_MOTD:
1789 * Received Message of the day
1793 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1797 /* Notify application */
1798 client->ops->notify(client, conn, type, tmp);
1801 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1803 * Router has enforced a new ID to a channel. Let's change the old
1804 * ID to the one provided here.
1807 /* Get the old ID */
1808 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1811 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1815 /* Get the channel entry */
1816 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1817 SILC_ID_CHANNEL, &id_cache))
1820 channel = (SilcChannelEntry)id_cache->context;
1822 /* Free the old ID */
1823 silc_free(channel_id);
1824 silc_free(channel->id);
1826 /* Get the new ID */
1827 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1830 channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1834 id_cache->id = (void *)channel->id;
1836 /* Notify application */
1837 client->ops->notify(client, conn, type, channel, channel);
1840 case SILC_NOTIFY_TYPE_KICKED:
1842 * A client (maybe me) was kicked from a channel
1846 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1850 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1854 /* Find Client entry */
1856 silc_client_get_client_by_id(client, conn, client_id);
1860 /* Get channel entry */
1861 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1865 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1866 SILC_ID_CHANNEL, &id_cache))
1869 channel = (SilcChannelEntry)id_cache->context;
1872 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1874 /* Notify application. The channel entry is sent last as this notify
1875 is for channel but application don't know it from the arguments
1877 client->ops->notify(client, conn, type, client_entry, tmp, channel);
1879 /* If I was kicked from channel, remove the channel */
1880 if (client_entry == conn->local_entry) {
1881 if (conn->current_channel == channel)
1882 conn->current_channel = NULL;
1883 silc_idcache_del_by_id(conn->channel_cache,
1884 SILC_ID_CHANNEL, channel->id);
1885 silc_free(channel->channel_name);
1886 silc_free(channel->id);
1887 silc_free(channel->key);
1888 silc_cipher_free(channel->channel_key);
1898 silc_notify_payload_free(payload);
1900 silc_free(client_id);
1902 silc_free(channel_id);
1905 /* Processes the received new Client ID from server. Old Client ID is
1906 deleted from cache and new one is added. */
1908 void silc_client_receive_new_id(SilcClient client,
1909 SilcSocketConnection sock,
1912 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1913 int connecting = FALSE;
1915 if (!conn->local_entry)
1918 /* Delete old ID from ID cache */
1919 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1921 /* Save the new ID */
1923 silc_free(conn->local_id);
1924 if (conn->local_id_data)
1925 silc_free(conn->local_id_data);
1927 conn->local_id = silc_id_payload_get_id(idp);
1928 conn->local_id_data = silc_id_payload_get_data(idp);
1929 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1931 if (!conn->local_entry)
1932 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1934 conn->local_entry->nickname = conn->nickname;
1935 if (!conn->local_entry->username) {
1936 conn->local_entry->username =
1937 silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1938 sizeof(conn->local_entry->username));
1939 sprintf(conn->local_entry->username, "%s@%s", client->username,
1942 conn->local_entry->server = strdup(conn->remote_host);
1943 conn->local_entry->id = conn->local_id;
1945 /* Put it to the ID cache */
1946 silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1947 conn->local_id, (void *)conn->local_entry, TRUE);
1949 /* Notify application of successful connection. We do it here now that
1950 we've received the Client ID and are allowed to send traffic. */
1952 client->ops->connect(client, conn, TRUE);
1955 /* Processed received Channel ID for a channel. This is called when client
1956 joins to channel and server replies with channel ID. The ID is cached. */
1958 void silc_client_new_channel_id(SilcClient client,
1959 SilcSocketConnection sock,
1961 unsigned int mode, SilcIDPayload idp)
1963 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1964 SilcChannelEntry channel;
1966 SILC_LOG_DEBUG(("New channel ID"));
1968 channel = silc_calloc(1, sizeof(*channel));
1969 channel->channel_name = channel_name;
1970 channel->id = silc_id_payload_get_id(idp);
1971 channel->mode = mode;
1972 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1974 conn->current_channel = channel;
1976 /* Put it to the ID cache */
1977 silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1978 (void *)channel->id, (void *)channel, TRUE);
1981 /* Saves channel key from encoded `key_payload'. This is used when we
1982 receive Channel Key Payload and when we are processing JOIN command
1985 void silc_client_save_channel_key(SilcClientConnection conn,
1986 SilcBuffer key_payload,
1987 SilcChannelEntry channel)
1989 unsigned char *id_string, *key, *cipher;
1990 unsigned int tmp_len;
1992 SilcIDCacheEntry id_cache = NULL;
1993 SilcChannelKeyPayload payload;
1995 payload = silc_channel_key_payload_parse(key_payload);
1999 id_string = silc_channel_key_get_id(payload, &tmp_len);
2001 silc_channel_key_payload_free(payload);
2005 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
2007 silc_channel_key_payload_free(payload);
2013 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2014 SILC_ID_CHANNEL, &id_cache))
2017 /* Get channel entry */
2018 channel = (SilcChannelEntry)id_cache->context;
2022 key = silc_channel_key_get_key(payload, &tmp_len);
2023 cipher = silc_channel_key_get_cipher(payload, NULL);
2024 channel->key_len = tmp_len * 8;
2025 channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
2026 memcpy(channel->key, key, tmp_len);
2028 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
2029 conn->client->ops->say(conn->client, conn,
2030 "Cannot talk to channel: unsupported cipher %s", cipher);
2033 channel->channel_key->cipher->set_key(channel->channel_key->context,
2034 key, channel->key_len);
2036 /* Client is now joined to the channel */
2037 channel->on_channel = TRUE;
2041 silc_channel_key_payload_free(payload);
2044 /* Processes received key for channel. The received key will be used
2045 to protect the traffic on the channel for now on. Client must receive
2046 the key to the channel before talking on the channel is possible.
2047 This is the key that server has generated, this is not the channel
2048 private key, it is entirely local setting. */
2050 void silc_client_receive_channel_key(SilcClient client,
2051 SilcSocketConnection sock,
2054 SILC_LOG_DEBUG(("Received key for channel"));
2057 silc_client_save_channel_key(sock->user_data, packet, NULL);
2060 /* Process received message to a channel (or from a channel, really). This
2061 decrypts the channel message with channel specific key and parses the
2062 channel payload. Finally it displays the message on the screen. */
2064 void silc_client_channel_message(SilcClient client,
2065 SilcSocketConnection sock,
2066 SilcPacketContext *packet)
2068 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2069 SilcBuffer buffer = packet->buffer;
2070 SilcChannelPayload payload = NULL;
2071 SilcChannelID *id = NULL;
2072 SilcChannelEntry channel;
2073 SilcChannelUser chu;
2074 SilcIDCacheEntry id_cache = NULL;
2075 SilcClientID *client_id = NULL;
2077 unsigned int block_len;
2080 if (packet->dst_id_type != SILC_ID_CHANNEL)
2083 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2087 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2091 /* Find the channel entry from channels on this connection */
2092 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2093 SILC_ID_CHANNEL, &id_cache))
2096 channel = (SilcChannelEntry)id_cache->context;
2098 /* Decrypt the channel message payload. Push the IV out of the way,
2099 since it is not encrypted (after pushing buffer->tail has the IV). */
2100 block_len = silc_cipher_get_block_len(channel->channel_key);
2101 silc_buffer_push_tail(buffer, block_len);
2102 channel->channel_key->cipher->decrypt(channel->channel_key->context,
2103 buffer->data, buffer->data,
2104 buffer->len, buffer->tail);
2105 silc_buffer_pull_tail(buffer, block_len);
2107 /* Parse the channel message payload */
2108 payload = silc_channel_payload_parse(buffer);
2112 /* Find client entry */
2113 silc_list_start(channel->clients);
2114 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2115 if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2121 /* Pass the message to application */
2122 client->ops->channel_message(client, conn, found ? chu->client : NULL,
2123 channel, silc_channel_get_data(payload, NULL));
2129 silc_free(client_id);
2131 silc_channel_payload_free(payload);
2134 /* Private message received. This processes the private message and
2135 finally displays it on the screen. */
2137 void silc_client_private_message(SilcClient client,
2138 SilcSocketConnection sock,
2139 SilcPacketContext *packet)
2141 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2142 SilcBuffer buffer = packet->buffer;
2143 SilcIDCacheEntry id_cache;
2144 SilcClientID *remote_id = NULL;
2145 SilcClientEntry remote_client;
2146 unsigned short nick_len;
2147 unsigned char *nickname, *message = NULL;
2150 if (packet->src_id_type != SILC_ID_CLIENT)
2154 ret = silc_buffer_unformat(buffer,
2155 SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2160 silc_buffer_pull(buffer, 2 + nick_len);
2162 message = silc_calloc(buffer->len + 1, sizeof(char));
2163 memcpy(message, buffer->data, buffer->len);
2165 remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2170 /* Check whether we know this client already */
2171 if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2172 SILC_ID_CLIENT, &id_cache))
2174 /* Allocate client entry */
2175 remote_client = silc_calloc(1, sizeof(*remote_client));
2176 remote_client->id = remote_id;
2177 silc_parse_nickname(nickname, &remote_client->nickname,
2178 &remote_client->server, &remote_client->num);
2180 /* Save the client to cache */
2181 silc_idcache_add(conn->client_cache, remote_client->nickname,
2182 SILC_ID_CLIENT, remote_client->id, remote_client,
2185 remote_client = (SilcClientEntry)id_cache->context;
2188 /* Pass the private message to application */
2189 client->ops->private_message(client, conn, remote_client, message);
2191 /* See if we are away (gone). If we are away we will reply to the
2192 sender with the set away message. */
2193 if (conn->away && conn->away->away) {
2194 /* If it's me, ignore */
2195 if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2198 /* Send the away message */
2199 silc_client_send_private_message(client, conn, remote_client,
2201 strlen(conn->away->away), TRUE);
2206 silc_free(remote_id);
2209 memset(message, 0, buffer->len);
2212 silc_free(nickname);
2215 /* Removes a client entry from all channel it has joined. This really is
2216 a performance killer (client_entry should have pointers to channel
2219 void silc_client_remove_from_channels(SilcClient client,
2220 SilcClientConnection conn,
2221 SilcClientEntry client_entry)
2223 SilcIDCacheEntry id_cache;
2224 SilcIDCacheList list;
2225 SilcChannelEntry channel;
2226 SilcChannelUser chu;
2228 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2229 SILC_ID_CHANNEL, &list))
2232 silc_idcache_list_first(list, &id_cache);
2233 channel = (SilcChannelEntry)id_cache->context;
2237 /* Remove client from channel */
2238 silc_list_start(channel->clients);
2239 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2240 if (chu->client == client_entry) {
2241 silc_list_del(channel->clients, chu);
2247 if (!silc_idcache_list_next(list, &id_cache))
2250 channel = (SilcChannelEntry)id_cache->context;
2253 silc_idcache_list_free(list);
2256 /* Replaces `old' client entries from all channels to `new' client entry.
2257 This can be called for example when nickname changes and old ID entry
2258 is replaced from ID cache with the new one. If the old ID entry is only
2259 updated, then this fucntion needs not to be called. */
2261 void silc_client_replace_from_channels(SilcClient client,
2262 SilcClientConnection conn,
2263 SilcClientEntry old,
2264 SilcClientEntry new)
2266 SilcIDCacheEntry id_cache;
2267 SilcIDCacheList list;
2268 SilcChannelEntry channel;
2269 SilcChannelUser chu;
2271 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2272 SILC_ID_CHANNEL, &list))
2275 silc_idcache_list_first(list, &id_cache);
2276 channel = (SilcChannelEntry)id_cache->context;
2280 /* Replace client entry */
2281 silc_list_start(channel->clients);
2282 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2283 if (chu->client == old) {
2289 if (!silc_idcache_list_next(list, &id_cache))
2292 channel = (SilcChannelEntry)id_cache->context;
2295 silc_idcache_list_free(list);
2298 /* Parses mode mask and returns the mode as string. */
2300 char *silc_client_chmode(unsigned int mode)
2307 memset(string, 0, sizeof(string));
2309 if (mode & SILC_CHANNEL_MODE_PRIVATE)
2310 strncat(string, "p", 1);
2312 if (mode & SILC_CHANNEL_MODE_SECRET)
2313 strncat(string, "s", 1);
2315 if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2316 strncat(string, "k", 1);
2318 if (mode & SILC_CHANNEL_MODE_INVITE)
2319 strncat(string, "i", 1);
2321 if (mode & SILC_CHANNEL_MODE_TOPIC)
2322 strncat(string, "t", 1);
2324 if (mode & SILC_CHANNEL_MODE_ULIMIT)
2325 strncat(string, "l", 1);
2327 if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2328 strncat(string, "a", 1);
2330 /* Rest of mode is ignored */
2332 return strdup(string);
2335 /* Parses channel user mode mask and returns te mode as string */
2337 char *silc_client_chumode(unsigned int mode)
2344 memset(string, 0, sizeof(string));
2346 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2347 strncat(string, "f", 1);
2349 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2350 strncat(string, "o", 1);
2352 return strdup(string);
2355 /* Parses channel user mode and returns it as special mode character. */
2357 char *silc_client_chumode_char(unsigned int mode)
2364 memset(string, 0, sizeof(string));
2366 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2367 strncat(string, "*", 1);
2369 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2370 strncat(string, "@", 1);
2372 return strdup(string);
2375 /* Function that actually employes the received private message key */
2377 static void silc_client_private_message_key_cb(SilcClient client,
2378 SilcClientConnection conn,
2379 SilcClientEntry *clients,
2380 unsigned int clients_count,
2383 SilcPacketContext *packet = (SilcPacketContext *)context;
2385 unsigned short key_len;
2386 unsigned char *cipher;
2392 /* Parse the private message key payload */
2393 ret = silc_buffer_unformat(packet->buffer,
2394 SILC_STR_UI16_NSTRING(&key, &key_len),
2395 SILC_STR_UI16_STRING(&cipher),
2400 if (key_len > packet->buffer->len)
2403 /* Now take the key in use */
2404 if (!silc_client_add_private_message_key(client, conn, clients[0],
2405 cipher, key, key_len, FALSE))
2408 /* Print some info for application */
2409 client->ops->say(client, conn,
2410 "Received private message key from %s%s%s %s%s%s",
2411 clients[0]->nickname,
2412 clients[0]->server ? "@" : "",
2413 clients[0]->server ? clients[0]->server : "",
2414 clients[0]->username ? "(" : "",
2415 clients[0]->username ? clients[0]->username : "",
2416 clients[0]->username ? ")" : "");
2419 silc_packet_context_free(packet);
2422 /* Processes incoming Private Message Key payload. The libary always
2423 accepts the key and takes it into use. */
2425 void silc_client_private_message_key(SilcClient client,
2426 SilcSocketConnection sock,
2427 SilcPacketContext *packet)
2429 SilcClientID *remote_id;
2431 if (packet->src_id_type != SILC_ID_CLIENT)
2434 remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2439 silc_client_get_client_by_id_resolve(client, sock->user_data, remote_id,
2440 silc_client_private_message_key_cb,
2441 silc_packet_context_dup(packet));
2442 silc_free(remote_id);
2445 /* Adds private message key to the client library. The key will be used to
2446 encrypt all private message between the client and the remote client
2447 indicated by the `client_entry'. If the `key' is NULL and the boolean
2448 value `generate_key' is TRUE the library will generate random key.
2449 The `key' maybe for example pre-shared-key, passphrase or similar.
2450 The `cipher' MAY be provided but SHOULD be NULL to assure that the
2451 requirements of the SILC protocol are met. The API, however, allows
2452 to allocate any cipher.
2454 It is not necessary to set key for normal private message usage. If the
2455 key is not set then the private messages are encrypted using normal
2456 session keys. Setting the private key, however, increases the security.
2458 Returns FALSE if the key is already set for the `client_entry', TRUE
2461 int silc_client_add_private_message_key(SilcClient client,
2462 SilcClientConnection conn,
2463 SilcClientEntry client_entry,
2466 unsigned int key_len,
2469 unsigned char private_key[32];
2472 SilcSKEKeyMaterial *keymat;
2474 assert(client_entry);
2476 /* Return FALSE if key already set */
2477 if (client_entry->send_key && client_entry->receive_key)
2481 cipher = "aes-256-cbc";
2483 /* Check the requested cipher */
2484 if (!silc_cipher_is_supported(cipher))
2487 /* Generate key if not provided */
2488 if (!key && generate_key == TRUE) {
2490 for (i = 0; i < len; i++) private_key[i] = silc_rng_get_byte(client->rng);
2493 client_entry->generated = TRUE;
2497 client_entry->key = silc_calloc(key_len, sizeof(*client_entry->key));
2498 memcpy(client_entry->key, key, key_len);
2499 client_entry->key_len = key_len;
2501 /* Produce the key material as the protocol defines */
2502 keymat = silc_calloc(1, sizeof(*keymat));
2503 if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
2504 client->md5hash, keymat)
2505 != SILC_SKE_STATUS_OK)
2508 /* Allocate the ciphers */
2509 silc_cipher_alloc(cipher, &client_entry->send_key);
2510 silc_cipher_alloc(cipher, &client_entry->receive_key);
2513 silc_cipher_set_key(client_entry->send_key, keymat->send_enc_key,
2514 keymat->enc_key_len);
2515 silc_cipher_set_iv(client_entry->send_key, keymat->send_iv);
2516 silc_cipher_set_key(client_entry->receive_key, keymat->receive_enc_key,
2517 keymat->enc_key_len);
2518 silc_cipher_set_iv(client_entry->receive_key, keymat->receive_iv);
2520 /* Free the key material */
2521 silc_ske_free_key_material(keymat);
2526 /* Same as above but takes the key material from the SKE key material
2527 structure. This structure is received if the application uses the
2528 silc_client_send_key_agreement to negotiate the key material. The
2529 `cipher' SHOULD be provided as it is negotiated also in the SKE
2532 int silc_client_add_private_message_key_ske(SilcClient client,
2533 SilcClientConnection conn,
2534 SilcClientEntry client_entry,
2536 SilcSKEKeyMaterial *key)
2538 assert(client_entry);
2540 /* Return FALSE if key already set */
2541 if (client_entry->send_key && client_entry->receive_key)
2545 cipher = "aes-256-cbc";
2547 /* Check the requested cipher */
2548 if (!silc_cipher_is_supported(cipher))
2551 /* Allocate the ciphers */
2552 silc_cipher_alloc(cipher, &client_entry->send_key);
2553 silc_cipher_alloc(cipher, &client_entry->receive_key);
2556 silc_cipher_set_key(client_entry->send_key, key->send_enc_key,
2558 silc_cipher_set_iv(client_entry->send_key, key->send_iv);
2559 silc_cipher_set_key(client_entry->receive_key, key->receive_enc_key,
2561 silc_cipher_set_iv(client_entry->receive_key, key->receive_iv);
2566 /* Sends private message key payload to the remote client indicated by
2567 the `client_entry'. If the `force_send' is TRUE the packet is sent
2568 immediately. Returns FALSE if error occurs, TRUE otherwise. The
2569 application should call this function after setting the key to the
2572 Note that the key sent using this function is sent to the remote client
2573 through the SILC network. The packet is protected using normal session
2576 int silc_client_send_private_message_key(SilcClient client,
2577 SilcClientConnection conn,
2578 SilcClientEntry client_entry,
2581 SilcSocketConnection sock = conn->sock;
2585 if (!client_entry->send_key || !client_entry->key)
2588 SILC_LOG_DEBUG(("Sending private message key"));
2590 cipher_len = strlen(client_entry->send_key->cipher->name);
2592 /* Create private message key payload */
2593 buffer = silc_buffer_alloc(2 + client_entry->key_len);
2594 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
2595 silc_buffer_format(buffer,
2596 SILC_STR_UI_SHORT(client_entry->key_len),
2597 SILC_STR_UI_XNSTRING(client_entry->key,
2598 client_entry->key_len),
2599 SILC_STR_UI_SHORT(cipher_len),
2600 SILC_STR_UI_XNSTRING(client_entry->send_key->cipher->name,
2604 /* Send the packet */
2605 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE_KEY,
2606 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
2607 buffer->data, buffer->len, force_send);
2613 /* Removes the private message from the library. The key won't be used
2614 after this to protect the private messages with the remote `client_entry'
2615 client. Returns FALSE on error, TRUE otherwise. */
2617 int silc_client_del_private_message_key(SilcClient client,
2618 SilcClientConnection conn,
2619 SilcClientEntry client_entry)
2621 assert(client_entry);
2623 if (!client_entry->send_key && !client_entry->receive_key)
2626 silc_cipher_free(client_entry->send_key);
2627 silc_cipher_free(client_entry->receive_key);
2629 if (client_entry->key) {
2630 memset(client_entry->key, 0, client_entry->key_len);
2631 silc_free(client_entry->key);
2634 client_entry->send_key = NULL;
2635 client_entry->receive_key = NULL;
2636 client_entry->key = NULL;
2641 /* Returns array of set private message keys associated to the connection
2642 `conn'. Returns allocated SilcPrivateMessageKeys array and the array
2643 count to the `key_count' argument. The array must be freed by the caller
2644 by calling the silc_client_free_private_message_keys function. Note:
2645 the keys returned in the array is in raw format. It might not be desired
2646 to show the keys as is. The application might choose not to show the keys
2647 at all or to show the fingerprints of the keys. */
2649 SilcPrivateMessageKeys
2650 silc_client_list_private_message_keys(SilcClient client,
2651 SilcClientConnection conn,
2652 unsigned int *key_count)
2654 SilcPrivateMessageKeys keys;
2655 unsigned int count = 0;
2656 SilcIDCacheEntry id_cache;
2657 SilcIDCacheList list;
2658 SilcClientEntry entry;
2660 if (!silc_idcache_find_by_id(conn->client_cache, SILC_ID_CACHE_ANY,
2661 SILC_ID_CLIENT, &list))
2664 if (!silc_idcache_list_count(list)) {
2665 silc_idcache_list_free(list);
2669 keys = silc_calloc(silc_idcache_list_count(list), sizeof(*keys));
2671 silc_idcache_list_first(list, &id_cache);
2673 entry = (SilcClientEntry)id_cache->context;
2675 if (entry->send_key) {
2676 keys[count].client_entry = entry;
2677 keys[count].cipher = entry->send_key->cipher->name;
2678 keys[count].key = entry->generated == FALSE ? entry->key : NULL;
2679 keys[count].key_len = entry->generated == FALSE ? entry->key_len : 0;
2683 if (!silc_idcache_list_next(list, &id_cache))
2693 /* Frees the SilcPrivateMessageKeys array returned by the function
2694 silc_client_list_private_message_keys. */
2696 void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
2697 unsigned int key_count)
2702 /* Adds private key for channel. This may be set only if the channel's mode
2703 mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
2704 mode is not set. When channel has private key then the messages are
2705 encrypted using that key. All clients on the channel must also know the
2706 key in order to decrypt the messages. However, it is possible to have
2707 several private keys per one channel. In this case only some of the
2708 clients on the channel may now the one key and only some the other key.
2710 The private key for channel is optional. If it is not set then the
2711 channel messages are encrypted using the channel key generated by the
2712 server. However, setting the private key (or keys) for the channel
2713 significantly adds security. If more than one key is set the library
2714 will automatically try all keys at the message decryption phase. Note:
2715 setting many keys slows down the decryption phase as all keys has to
2716 be tried in order to find the correct decryption key. However, setting
2717 a few keys does not have big impact to the decryption performace.
2719 NOTE: that this is entirely local setting. The key set using this function
2720 is not sent to the network at any phase.
2722 NOTE: If the key material was originated by the SKE protocol (using
2723 silc_client_send_key_agreement) then the `key' MUST be the
2724 key->send_enc_key as this is dictated by the SILC protocol. However,
2725 currently it is not expected that the SKE key material would be used
2726 as channel private key. However, this API allows it. */
2728 int silc_client_add_channel_private_key(SilcClient client,
2729 SilcClientConnection conn,
2730 SilcChannelEntry channel,
2733 unsigned int key_len)
2739 /* Removes all private keys from the `channel'. The old channel key is used
2740 after calling this to protect the channel messages. Returns FALSE on
2741 on error, TRUE otherwise. */
2743 int silc_client_del_channel_private_keys(SilcClient client,
2744 SilcClientConnection conn,
2745 SilcChannelEntry channel)
2751 /* Removes and frees private key `key' from the channel `channel'. The `key'
2752 is retrieved by calling the function silc_client_list_channel_private_keys.
2753 The key is not used after this. If the key was last private key then the
2754 old channel key is used hereafter to protect the channel messages. This
2755 returns FALSE on error, TRUE otherwise. */
2757 int silc_client_del_channel_private_key(SilcClient client,
2758 SilcClientConnection conn,
2759 SilcChannelEntry channel,
2760 SilcChannelPrivateKey key)
2766 /* Returns array (pointers) of private keys associated to the `channel'.
2767 The caller must free the array by calling the function
2768 silc_client_free_channel_private_keys. The pointers in the array may be
2769 used to delete the specific key by giving the pointer as argument to the
2770 function silc_client_del_channel_private_key. */
2772 SilcChannelPrivateKey *
2773 silc_client_list_channel_private_keys(SilcClient client,
2774 SilcClientConnection conn,
2775 SilcChannelEntry channel,
2776 unsigned int key_count)
2782 /* Frees the SilcChannelPrivateKey array. */
2784 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
2785 unsigned int key_count)
2790 /* Sends key agreement request to the remote client indicated by the
2791 `client_entry'. If the caller provides the `hostname' and the `port'
2792 arguments then the library will bind the client to that hostname and
2793 that port for the key agreement protocol. It also sends the `hostname'
2794 and the `port' in the key agreement packet to the remote client. This
2795 would indicate that the remote client may initiate the key agreement
2796 protocol to the `hostname' on the `port'.
2798 If the `hostname' and `port' is not provided then empty key agreement
2799 packet is sent to the remote client. The remote client may reply with
2800 the same packet including its hostname and port. If the library receives
2801 the reply from the remote client the `key_agreement' client operation
2802 callback will be called to verify whether the user wants to perform the
2803 key agreement or not.
2805 NOTE: If the application provided the `hostname' and the `port' and the
2806 remote side initiates the key agreement protocol it is not verified
2807 from the user anymore whether the protocol should be executed or not.
2808 By setting the `hostname' and `port' the user gives permission to
2809 perform the protocol (we are responder in this case).
2811 NOTE: If the remote side decides not to initiate the key agreement
2812 or decides not to reply with the key agreement packet then we cannot
2813 perform the key agreement at all. If the key agreement protocol is
2814 performed the `completion' callback with the `context' will be called.
2815 If remote side decides to ignore the request the `completion' will never
2816 be called and the caller is responsible of freeing the `context' memory.
2817 The application can do this by setting, for example, timeout. */
2819 void silc_client_send_key_agreement(SilcClient client,
2820 SilcClientConnection conn,
2821 SilcClientEntry client_entry,
2824 SilcKeyAgreementCallback completion,
2830 /* Performs the actual key agreement protocol. Application may use this
2831 to initiate the key agreement protocol. This can be called for example
2832 after the application has received the `key_agreement' client operation,
2833 and did not return TRUE from it.
2835 The `hostname' is the remote hostname (or IP address) and the `port'
2836 is the remote port. The `completion' callblack with the `context' will
2837 be called after the key agreement protocol.
2839 NOTE: If the application returns TRUE in the `key_agreement' client
2840 operation the library will automatically start the key agreement. In this
2841 case the application must not call this function. However, application
2842 may choose to just ignore the `key_agreement' client operation (and
2843 merely just print information about it on the screen) and call this
2844 function when the user whishes to do so (by, for example, giving some
2845 specific command). Thus, the API provides both, automatic and manual
2846 initiation of the key agreement. Calling this function is the manual
2847 initiation and returning TRUE in the `key_agreement' client operation
2848 is the automatic initiation. */
2850 void silc_client_perform_key_agreement(SilcClient client,
2851 SilcClientConnection conn,
2852 SilcClientEntry client_entry,
2855 SilcKeyAgreementCallback completion,
2861 /* This function can be called to unbind the hostname and the port for
2862 the key agreement protocol. However, this function has effect only
2863 before the key agreement protocol has been performed. After it has
2864 been performed the library will automatically unbind the port. The
2865 `client_entry' is the client to which we sent the key agreement
2868 void silc_client_abort_key_agreement(SilcClient client,
2869 SilcClientConnection conn,
2870 SilcClientEntry client_entry)