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] =
996 silc_rng_get_byte(client->rng);
998 silc_hash_make(client->md5hash, channel->iv, block_len, channel->iv);
1000 /* Encode the channel payload */
1001 payload = silc_channel_payload_encode(data_len, data, block_len,
1002 channel->iv, client->rng);
1004 client->ops->say(client, conn,
1005 "Error: Could not create packet to be sent to channel");
1009 /* Get data used in packet header encryption, keys and stuff. Rest
1010 of the packet (the payload) is, however, encrypted with the
1011 specified channel key. */
1012 cipher = conn->send_key;
1014 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1016 /* Set the packet context pointers. The destination ID is always
1017 the Channel ID of the channel. Server and router will handle the
1018 distribution of the packet. */
1019 packetdata.flags = 0;
1020 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1021 packetdata.src_id = conn->local_id_data;
1022 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1023 packetdata.src_id_type = SILC_ID_CLIENT;
1024 packetdata.dst_id = id_string;
1025 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1026 packetdata.dst_id_type = SILC_ID_CHANNEL;
1027 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
1028 packetdata.src_id_len + packetdata.dst_id_len;
1029 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1030 packetdata.src_id_len +
1031 packetdata.dst_id_len));
1033 /* Prepare outgoing data buffer for packet sending */
1034 silc_packet_send_prepare(sock,
1035 SILC_PACKET_HEADER_LEN +
1036 packetdata.src_id_len +
1037 packetdata.dst_id_len,
1041 packetdata.buffer = sock->outbuf;
1043 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1044 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1045 payload->data, payload->data,
1046 payload->len - block_len, /* -IV_LEN */
1049 /* Put the actual encrypted payload data into the buffer. */
1050 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1052 /* Create the outgoing packet */
1053 silc_packet_assemble(&packetdata);
1055 /* Encrypt the header and padding of the packet. This is encrypted
1056 with normal session key shared with our server. */
1057 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1058 packetdata.src_id_len + packetdata.dst_id_len +
1061 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1062 sock->outbuf->data, sock->outbuf->len);
1064 /* Now actually send the packet */
1065 silc_client_packet_send_real(client, sock, force_send);
1066 silc_buffer_free(payload);
1067 silc_free(id_string);
1070 /* Sends private message to remote client. If private message key has
1071 not been set with this client then the message will be encrypted using
1072 normal session keys. Private messages are special packets in SILC
1073 network hence we need this own function for them. This is similiar
1074 to silc_client_packet_send_to_channel except that we send private
1075 message. The `data' is the private message. If the `force_send' is
1076 TRUE the packet is sent immediately. */
1078 void silc_client_send_private_message(SilcClient client,
1079 SilcClientConnection conn,
1080 SilcClientEntry client_entry,
1081 unsigned char *data,
1082 unsigned int data_len,
1085 SilcSocketConnection sock = conn->sock;
1087 SilcPacketContext packetdata;
1088 unsigned int nick_len;
1092 SILC_LOG_DEBUG(("Sending private message"));
1094 /* Create private message payload */
1095 nick_len = strlen(conn->nickname);
1096 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1097 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1098 silc_buffer_format(buffer,
1099 SILC_STR_UI_SHORT(nick_len),
1100 SILC_STR_UI_XNSTRING(conn->nickname,
1102 SILC_STR_UI_XNSTRING(data, data_len),
1105 /* If we don't have private message specific key then private messages
1106 are just as any normal packet thus call normal packet sending. If
1107 the key exist then the encryption process is a bit different and
1108 will be done in the rest of this function. */
1109 if (!client_entry->send_key) {
1110 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1111 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1112 buffer->data, buffer->len, force_send);
1116 /* We have private message specific key */
1118 /* Get data used in the encryption */
1119 cipher = client_entry->send_key;
1122 /* Set the packet context pointers. */
1123 packetdata.flags = SILC_PACKET_FLAG_PRIVMSG_KEY;
1124 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1125 packetdata.src_id = conn->local_id_data;
1126 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1127 packetdata.src_id_type = SILC_ID_CLIENT;
1128 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1129 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1130 packetdata.dst_id_type = SILC_ID_CLIENT;
1131 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1132 packetdata.src_id_len + packetdata.dst_id_len;
1133 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1134 packetdata.src_id_len +
1135 packetdata.dst_id_len));
1137 /* Prepare outgoing data buffer for packet sending */
1138 silc_packet_send_prepare(sock,
1139 SILC_PACKET_HEADER_LEN +
1140 packetdata.src_id_len +
1141 packetdata.dst_id_len,
1145 packetdata.buffer = sock->outbuf;
1147 /* Encrypt payload of the packet. Encrypt with private message specific
1149 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1150 buffer->len, cipher->iv);
1152 /* Put the actual encrypted payload data into the buffer. */
1153 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1155 /* Create the outgoing packet */
1156 silc_packet_assemble(&packetdata);
1158 /* Encrypt the header and padding of the packet. */
1159 cipher = conn->send_key;
1160 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1161 packetdata.src_id_len + packetdata.dst_id_len +
1164 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1165 sock->outbuf->data, sock->outbuf->len);
1167 /* Now actually send the packet */
1168 silc_client_packet_send_real(client, sock, force_send);
1169 silc_free(packetdata.dst_id);
1175 /* Closes connection to remote end. Free's all allocated data except
1176 for some information such as nickname etc. that are valid at all time. */
1178 void silc_client_close_connection(SilcClient client,
1179 SilcClientConnection conn)
1181 SilcSocketConnection sock = conn->sock;
1183 /* We won't listen for this connection anymore */
1184 silc_schedule_unset_listen_fd(sock->sock);
1186 /* Unregister all tasks */
1187 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1188 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1190 /* Close the actual connection */
1191 silc_net_close_connection(sock->sock);
1193 client->ops->say(client, sock->user_data,
1194 "Closed connection to host %s", sock->hostname);
1196 /* Free everything */
1197 if (sock->user_data) {
1198 /* XXX Free all client entries and channel entries. */
1200 /* Clear ID caches */
1201 silc_idcache_del_all(conn->client_cache);
1202 silc_idcache_del_all(conn->channel_cache);
1205 if (conn->remote_host)
1206 silc_free(conn->remote_host);
1208 silc_free(conn->local_id);
1209 if (conn->local_id_data)
1210 silc_free(conn->local_id_data);
1212 silc_cipher_free(conn->send_key);
1213 if (conn->receive_key)
1214 silc_cipher_free(conn->receive_key);
1216 silc_hmac_free(conn->hmac);
1217 if (conn->hmac_key) {
1218 memset(conn->hmac_key, 0, conn->hmac_key_len);
1219 silc_free(conn->hmac_key);
1221 if (conn->pending_commands)
1222 silc_dlist_uninit(conn->pending_commands);
1225 conn->remote_port = 0;
1226 conn->remote_type = 0;
1227 conn->send_key = NULL;
1228 conn->receive_key = NULL;
1230 conn->hmac_key = NULL;
1231 conn->hmac_key_len = 0;
1232 conn->local_id = NULL;
1233 conn->local_id_data = NULL;
1234 conn->remote_host = NULL;
1235 conn->current_channel = NULL;
1236 conn->pending_commands = NULL;
1238 silc_client_del_connection(client, conn);
1241 if (sock->protocol) {
1242 silc_protocol_free(sock->protocol);
1243 sock->protocol = NULL;
1245 silc_socket_free(sock);
1248 /* Called when we receive disconnection packet from server. This
1249 closes our end properly and displays the reason of the disconnection
1252 void silc_client_disconnected_by_server(SilcClient client,
1253 SilcSocketConnection sock,
1258 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1260 msg = silc_calloc(message->len + 1, sizeof(char));
1261 memcpy(msg, message->data, message->len);
1262 client->ops->say(client, sock->user_data, msg);
1265 SILC_SET_DISCONNECTED(sock);
1266 silc_client_close_connection(client, sock->user_data);
1269 /* Received error message from server. Display it on the screen.
1270 We don't take any action what so ever of the error message. */
1272 void silc_client_error_by_server(SilcClient client,
1273 SilcSocketConnection sock,
1278 msg = silc_calloc(message->len + 1, sizeof(char));
1279 memcpy(msg, message->data, message->len);
1280 client->ops->say(client, sock->user_data, msg);
1284 /* Called when notify is received and some async operation (such as command)
1285 is required before processing the notify message. This calls again the
1286 silc_client_notify_by_server and reprocesses the original notify packet. */
1288 static void silc_client_notify_by_server_pending(void *context)
1290 SilcPacketContext *p = (SilcPacketContext *)context;
1291 silc_client_notify_by_server(p->context, p->sock, p);
1294 /* Destructor for the pending command callback */
1296 static void silc_client_notify_by_server_destructor(void *context)
1298 silc_packet_context_free((SilcPacketContext *)context);
1301 /* Resolve client information from server by Client ID. */
1303 static void silc_client_notify_by_server_resolve(SilcClient client,
1304 SilcClientConnection conn,
1305 SilcPacketContext *packet,
1306 SilcClientID *client_id)
1308 SilcPacketContext *p = silc_packet_context_dup(packet);
1309 SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1311 p->context = (void *)client;
1312 p->sock = conn->sock;
1314 silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, ++conn->cmd_ident,
1315 1, 3, idp->data, idp->len);
1316 silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
1317 silc_client_notify_by_server_destructor,
1318 silc_client_notify_by_server_pending, p);
1319 silc_buffer_free(idp);
1322 /* Received notify message from server */
1324 void silc_client_notify_by_server(SilcClient client,
1325 SilcSocketConnection sock,
1326 SilcPacketContext *packet)
1328 SilcBuffer buffer = packet->buffer;
1329 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1330 SilcNotifyPayload payload;
1331 SilcNotifyType type;
1332 SilcArgumentPayload args;
1334 SilcClientID *client_id = NULL;
1335 SilcChannelID *channel_id = NULL;
1336 SilcClientEntry client_entry;
1337 SilcClientEntry client_entry2;
1338 SilcChannelEntry channel;
1339 SilcChannelUser chu;
1340 SilcIDCacheEntry id_cache = NULL;
1342 unsigned int tmp_len, mode;
1344 payload = silc_notify_payload_parse(buffer);
1348 type = silc_notify_get_type(payload);
1349 args = silc_notify_get_args(payload);
1354 case SILC_NOTIFY_TYPE_NONE:
1355 /* Notify application */
1356 client->ops->notify(client, conn, type,
1357 silc_argument_get_arg_type(args, 1, NULL));
1360 case SILC_NOTIFY_TYPE_INVITE:
1362 * Someone invited me to a channel. Find Client and Channel entries
1363 * for the application.
1367 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1371 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1375 /* Find Client entry and if not found query it */
1376 client_entry = silc_client_get_client_by_id(client, conn, client_id);
1377 if (!client_entry) {
1378 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1382 /* Get Channel ID */
1383 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1387 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1391 /* XXX Will ALWAYS fail because currently we don't have way to resolve
1392 channel information for channel that we're not joined to. */
1393 /* XXX ways to fix: use (extended) LIST command, or define the channel
1394 name to the notfy type when name resolving is not mandatory. */
1395 /* Find channel entry */
1396 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1397 SILC_ID_CHANNEL, &id_cache))
1400 channel = (SilcChannelEntry)id_cache->context;
1402 /* Notify application */
1403 client->ops->notify(client, conn, type, client_entry, channel);
1406 case SILC_NOTIFY_TYPE_JOIN:
1408 * Someone has joined to a channel. Get their ID and nickname and
1409 * cache them for later use.
1413 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1417 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1421 /* Find Client entry and if not found query it */
1422 client_entry = silc_client_get_client_by_id(client, conn, client_id);
1423 if (!client_entry) {
1424 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1428 /* If nickname or username hasn't been resolved, do so */
1429 if (!client_entry->nickname || !client_entry->username) {
1430 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1434 /* Get Channel ID */
1435 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1439 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1443 /* Get channel entry */
1444 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1445 SILC_ID_CHANNEL, &id_cache))
1448 channel = (SilcChannelEntry)id_cache->context;
1450 /* Add client to channel */
1451 chu = silc_calloc(1, sizeof(*chu));
1452 chu->client = client_entry;
1453 silc_list_add(channel->clients, chu);
1455 /* XXX add support for multiple same nicks on same channel. Check
1458 /* Notify application. The channel entry is sent last as this notify
1459 is for channel but application don't know it from the arguments
1461 client->ops->notify(client, conn, type, client_entry, channel);
1464 case SILC_NOTIFY_TYPE_LEAVE:
1466 * Someone has left a channel. We will remove it from the channel but
1467 * we'll keep it in the cache in case we'll need it later.
1471 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1475 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1479 /* Find Client entry */
1481 silc_client_get_client_by_id(client, conn, client_id);
1485 /* Get channel entry */
1486 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1490 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1491 SILC_ID_CHANNEL, &id_cache))
1494 channel = (SilcChannelEntry)id_cache->context;
1496 /* Remove client from channel */
1497 silc_list_start(channel->clients);
1498 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1499 if (chu->client == client_entry) {
1500 silc_list_del(channel->clients, chu);
1506 /* Notify application. The channel entry is sent last as this notify
1507 is for channel but application don't know it from the arguments
1509 client->ops->notify(client, conn, type, client_entry, channel);
1512 case SILC_NOTIFY_TYPE_SIGNOFF:
1514 * Someone left SILC. We'll remove it from all channels and from cache.
1518 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1522 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1526 /* Find Client entry */
1528 silc_client_get_client_by_id(client, conn, client_id);
1532 /* Remove from all channels */
1533 silc_client_remove_from_channels(client, conn, client_entry);
1535 /* Remove from cache */
1536 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1539 /* Get signoff message */
1540 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1544 /* Notify application */
1545 client->ops->notify(client, conn, type, client_entry, tmp);
1548 if (client_entry->nickname)
1549 silc_free(client_entry->nickname);
1550 if (client_entry->server)
1551 silc_free(client_entry->server);
1552 if (client_entry->id)
1553 silc_free(client_entry->id);
1554 if (client_entry->send_key)
1555 silc_cipher_free(client_entry->send_key);
1556 if (client_entry->receive_key)
1557 silc_cipher_free(client_entry->receive_key);
1560 case SILC_NOTIFY_TYPE_TOPIC_SET:
1562 * Someone set the topic on a channel.
1566 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1570 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1574 /* Find Client entry */
1576 silc_client_get_client_by_id(client, conn, client_id);
1581 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1585 /* Get channel entry */
1586 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1590 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1591 SILC_ID_CHANNEL, &id_cache))
1594 channel = (SilcChannelEntry)id_cache->context;
1596 /* Notify application. The channel entry is sent last as this notify
1597 is for channel but application don't know it from the arguments
1599 client->ops->notify(client, conn, type, client_entry, tmp, channel);
1602 case SILC_NOTIFY_TYPE_NICK_CHANGE:
1604 * Someone changed their nickname. If we don't have entry for the new
1605 * ID we will query it and return here after it's done. After we've
1606 * returned we fetch the old entry and free it and notify the
1610 /* Get new Client ID */
1611 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1615 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1620 if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1623 /* Find Client entry and if not found query it */
1625 silc_client_get_client_by_id(client, conn, client_id);
1626 if (!client_entry2) {
1627 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1630 silc_free(client_id);
1632 /* Get old Client ID */
1633 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1637 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1641 /* Find old Client entry */
1643 silc_client_get_client_by_id(client, conn, client_id);
1647 /* Remove the old from cache */
1648 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1651 /* Replace old ID entry with new one on all channels. */
1652 silc_client_replace_from_channels(client, conn, client_entry,
1655 /* Notify application */
1656 client->ops->notify(client, conn, type, client_entry, client_entry2);
1659 if (client_entry->nickname)
1660 silc_free(client_entry->nickname);
1661 if (client_entry->server)
1662 silc_free(client_entry->server);
1663 if (client_entry->id)
1664 silc_free(client_entry->id);
1665 if (client_entry->send_key)
1666 silc_cipher_free(client_entry->send_key);
1667 if (client_entry->receive_key)
1668 silc_cipher_free(client_entry->receive_key);
1671 case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1673 * Someone changed a channel mode
1677 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1681 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1685 /* Find Client entry */
1687 silc_client_get_client_by_id(client, conn, client_id);
1692 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1696 SILC_GET32_MSB(mode, tmp);
1698 /* Get channel entry */
1699 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1703 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1704 SILC_ID_CHANNEL, &id_cache))
1707 channel = (SilcChannelEntry)id_cache->context;
1709 /* Save the new mode */
1710 channel->mode = mode;
1712 /* Notify application. The channel entry is sent last as this notify
1713 is for channel but application don't know it from the arguments
1715 client->ops->notify(client, conn, type, client_entry, mode, channel);
1718 case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1720 * Someone changed user's mode on a channel
1724 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1728 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1732 /* Find Client entry */
1734 silc_client_get_client_by_id(client, conn, client_id);
1739 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1743 SILC_GET32_MSB(mode, tmp);
1745 /* Get target Client ID */
1746 tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1750 silc_free(client_id);
1751 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1755 /* Find target Client entry */
1757 silc_client_get_client_by_id(client, conn, client_id);
1761 /* Get channel entry */
1762 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1766 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1767 SILC_ID_CHANNEL, &id_cache))
1770 channel = (SilcChannelEntry)id_cache->context;
1773 silc_list_start(channel->clients);
1774 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1775 if (chu->client == client_entry) {
1781 /* Notify application. The channel entry is sent last as this notify
1782 is for channel but application don't know it from the arguments
1784 client->ops->notify(client, conn, type, client_entry, mode,
1785 client_entry2, channel);
1788 case SILC_NOTIFY_TYPE_MOTD:
1790 * Received Message of the day
1794 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1798 /* Notify application */
1799 client->ops->notify(client, conn, type, tmp);
1802 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1804 * Router has enforced a new ID to a channel. Let's change the old
1805 * ID to the one provided here.
1808 /* Get the old ID */
1809 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1812 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1816 /* Get the channel entry */
1817 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1818 SILC_ID_CHANNEL, &id_cache))
1821 channel = (SilcChannelEntry)id_cache->context;
1823 /* Free the old ID */
1824 silc_free(channel_id);
1825 silc_free(channel->id);
1827 /* Get the new ID */
1828 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1831 channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1835 id_cache->id = (void *)channel->id;
1837 /* Notify application */
1838 client->ops->notify(client, conn, type, channel, channel);
1841 case SILC_NOTIFY_TYPE_KICKED:
1843 * A client (maybe me) was kicked from a channel
1847 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1851 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1855 /* Find Client entry */
1857 silc_client_get_client_by_id(client, conn, client_id);
1861 /* Get channel entry */
1862 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1866 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1867 SILC_ID_CHANNEL, &id_cache))
1870 channel = (SilcChannelEntry)id_cache->context;
1873 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1875 /* Notify application. The channel entry is sent last as this notify
1876 is for channel but application don't know it from the arguments
1878 client->ops->notify(client, conn, type, client_entry, tmp, channel);
1880 /* If I was kicked from channel, remove the channel */
1881 if (client_entry == conn->local_entry) {
1882 if (conn->current_channel == channel)
1883 conn->current_channel = NULL;
1884 silc_idcache_del_by_id(conn->channel_cache,
1885 SILC_ID_CHANNEL, channel->id);
1886 silc_free(channel->channel_name);
1887 silc_free(channel->id);
1888 silc_free(channel->key);
1889 silc_cipher_free(channel->channel_key);
1899 silc_notify_payload_free(payload);
1901 silc_free(client_id);
1903 silc_free(channel_id);
1906 /* Processes the received new Client ID from server. Old Client ID is
1907 deleted from cache and new one is added. */
1909 void silc_client_receive_new_id(SilcClient client,
1910 SilcSocketConnection sock,
1913 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1914 int connecting = FALSE;
1916 if (!conn->local_entry)
1919 /* Delete old ID from ID cache */
1920 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1922 /* Save the new ID */
1924 silc_free(conn->local_id);
1925 if (conn->local_id_data)
1926 silc_free(conn->local_id_data);
1928 conn->local_id = silc_id_payload_get_id(idp);
1929 conn->local_id_data = silc_id_payload_get_data(idp);
1930 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1932 if (!conn->local_entry)
1933 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1935 conn->local_entry->nickname = conn->nickname;
1936 if (!conn->local_entry->username) {
1937 conn->local_entry->username =
1938 silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1939 sizeof(conn->local_entry->username));
1940 sprintf(conn->local_entry->username, "%s@%s", client->username,
1943 conn->local_entry->server = strdup(conn->remote_host);
1944 conn->local_entry->id = conn->local_id;
1946 /* Put it to the ID cache */
1947 silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1948 conn->local_id, (void *)conn->local_entry, TRUE);
1950 /* Notify application of successful connection. We do it here now that
1951 we've received the Client ID and are allowed to send traffic. */
1953 client->ops->connect(client, conn, TRUE);
1956 /* Processed received Channel ID for a channel. This is called when client
1957 joins to channel and server replies with channel ID. The ID is cached. */
1959 void silc_client_new_channel_id(SilcClient client,
1960 SilcSocketConnection sock,
1962 unsigned int mode, SilcIDPayload idp)
1964 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1965 SilcChannelEntry channel;
1967 SILC_LOG_DEBUG(("New channel ID"));
1969 channel = silc_calloc(1, sizeof(*channel));
1970 channel->channel_name = channel_name;
1971 channel->id = silc_id_payload_get_id(idp);
1972 channel->mode = mode;
1973 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1975 conn->current_channel = channel;
1977 /* Put it to the ID cache */
1978 silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1979 (void *)channel->id, (void *)channel, TRUE);
1982 /* Saves channel key from encoded `key_payload'. This is used when we
1983 receive Channel Key Payload and when we are processing JOIN command
1986 void silc_client_save_channel_key(SilcClientConnection conn,
1987 SilcBuffer key_payload,
1988 SilcChannelEntry channel)
1990 unsigned char *id_string, *key, *cipher;
1991 unsigned int tmp_len;
1993 SilcIDCacheEntry id_cache = NULL;
1994 SilcChannelKeyPayload payload;
1996 payload = silc_channel_key_payload_parse(key_payload);
2000 id_string = silc_channel_key_get_id(payload, &tmp_len);
2002 silc_channel_key_payload_free(payload);
2006 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
2008 silc_channel_key_payload_free(payload);
2014 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2015 SILC_ID_CHANNEL, &id_cache))
2018 /* Get channel entry */
2019 channel = (SilcChannelEntry)id_cache->context;
2023 key = silc_channel_key_get_key(payload, &tmp_len);
2024 cipher = silc_channel_key_get_cipher(payload, NULL);
2025 channel->key_len = tmp_len * 8;
2026 channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
2027 memcpy(channel->key, key, tmp_len);
2029 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
2030 conn->client->ops->say(conn->client, conn,
2031 "Cannot talk to channel: unsupported cipher %s", cipher);
2034 channel->channel_key->cipher->set_key(channel->channel_key->context,
2035 key, channel->key_len);
2037 /* Client is now joined to the channel */
2038 channel->on_channel = TRUE;
2042 silc_channel_key_payload_free(payload);
2045 /* Processes received key for channel. The received key will be used
2046 to protect the traffic on the channel for now on. Client must receive
2047 the key to the channel before talking on the channel is possible.
2048 This is the key that server has generated, this is not the channel
2049 private key, it is entirely local setting. */
2051 void silc_client_receive_channel_key(SilcClient client,
2052 SilcSocketConnection sock,
2055 SILC_LOG_DEBUG(("Received key for channel"));
2058 silc_client_save_channel_key(sock->user_data, packet, NULL);
2061 /* Process received message to a channel (or from a channel, really). This
2062 decrypts the channel message with channel specific key and parses the
2063 channel payload. Finally it displays the message on the screen. */
2065 void silc_client_channel_message(SilcClient client,
2066 SilcSocketConnection sock,
2067 SilcPacketContext *packet)
2069 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2070 SilcBuffer buffer = packet->buffer;
2071 SilcChannelPayload payload = NULL;
2072 SilcChannelID *id = NULL;
2073 SilcChannelEntry channel;
2074 SilcChannelUser chu;
2075 SilcIDCacheEntry id_cache = NULL;
2076 SilcClientID *client_id = NULL;
2078 unsigned int block_len;
2080 SILC_LOG_DEBUG(("Start"));
2083 if (packet->dst_id_type != SILC_ID_CHANNEL)
2086 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2090 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2094 /* Find the channel entry from channels on this connection */
2095 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2096 SILC_ID_CHANNEL, &id_cache))
2099 channel = (SilcChannelEntry)id_cache->context;
2101 /* Decrypt the channel message payload. Push the IV out of the way,
2102 since it is not encrypted (after pushing buffer->tail has the IV). */
2103 block_len = silc_cipher_get_block_len(channel->channel_key);
2104 silc_buffer_push_tail(buffer, block_len);
2105 channel->channel_key->cipher->decrypt(channel->channel_key->context,
2106 buffer->data, buffer->data,
2107 buffer->len, buffer->tail);
2108 silc_buffer_pull_tail(buffer, block_len);
2110 /* Parse the channel message payload */
2111 payload = silc_channel_payload_parse(buffer);
2115 /* Find client entry */
2116 silc_list_start(channel->clients);
2117 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2118 if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2124 /* Pass the message to application */
2125 client->ops->channel_message(client, conn, found ? chu->client : NULL,
2126 channel, silc_channel_get_data(payload, NULL));
2132 silc_free(client_id);
2134 silc_channel_payload_free(payload);
2137 /* Private message received. This processes the private message and
2138 finally displays it on the screen. */
2140 void silc_client_private_message(SilcClient client,
2141 SilcSocketConnection sock,
2142 SilcPacketContext *packet)
2144 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2145 SilcBuffer buffer = packet->buffer;
2146 SilcIDCacheEntry id_cache;
2147 SilcClientID *remote_id = NULL;
2148 SilcClientEntry remote_client;
2149 unsigned short nick_len;
2150 unsigned char *nickname, *message = NULL;
2153 if (packet->src_id_type != SILC_ID_CLIENT)
2157 ret = silc_buffer_unformat(buffer,
2158 SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2163 silc_buffer_pull(buffer, 2 + nick_len);
2165 message = silc_calloc(buffer->len + 1, sizeof(char));
2166 memcpy(message, buffer->data, buffer->len);
2168 remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2173 /* Check whether we know this client already */
2174 if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2175 SILC_ID_CLIENT, &id_cache))
2177 /* Allocate client entry */
2178 remote_client = silc_calloc(1, sizeof(*remote_client));
2179 remote_client->id = remote_id;
2180 silc_parse_nickname(nickname, &remote_client->nickname,
2181 &remote_client->server, &remote_client->num);
2183 /* Save the client to cache */
2184 silc_idcache_add(conn->client_cache, remote_client->nickname,
2185 SILC_ID_CLIENT, remote_client->id, remote_client,
2188 remote_client = (SilcClientEntry)id_cache->context;
2191 /* Pass the private message to application */
2192 client->ops->private_message(client, conn, remote_client, message);
2194 /* See if we are away (gone). If we are away we will reply to the
2195 sender with the set away message. */
2196 if (conn->away && conn->away->away) {
2197 /* If it's me, ignore */
2198 if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2201 /* Send the away message */
2202 silc_client_send_private_message(client, conn, remote_client,
2204 strlen(conn->away->away), TRUE);
2209 silc_free(remote_id);
2212 memset(message, 0, buffer->len);
2215 silc_free(nickname);
2218 /* Removes a client entry from all channel it has joined. This really is
2219 a performance killer (client_entry should have pointers to channel
2222 void silc_client_remove_from_channels(SilcClient client,
2223 SilcClientConnection conn,
2224 SilcClientEntry client_entry)
2226 SilcIDCacheEntry id_cache;
2227 SilcIDCacheList list;
2228 SilcChannelEntry channel;
2229 SilcChannelUser chu;
2231 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2232 SILC_ID_CHANNEL, &list))
2235 silc_idcache_list_first(list, &id_cache);
2236 channel = (SilcChannelEntry)id_cache->context;
2240 /* Remove client from channel */
2241 silc_list_start(channel->clients);
2242 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2243 if (chu->client == client_entry) {
2244 silc_list_del(channel->clients, chu);
2250 if (!silc_idcache_list_next(list, &id_cache))
2253 channel = (SilcChannelEntry)id_cache->context;
2256 silc_idcache_list_free(list);
2259 /* Replaces `old' client entries from all channels to `new' client entry.
2260 This can be called for example when nickname changes and old ID entry
2261 is replaced from ID cache with the new one. If the old ID entry is only
2262 updated, then this fucntion needs not to be called. */
2264 void silc_client_replace_from_channels(SilcClient client,
2265 SilcClientConnection conn,
2266 SilcClientEntry old,
2267 SilcClientEntry new)
2269 SilcIDCacheEntry id_cache;
2270 SilcIDCacheList list;
2271 SilcChannelEntry channel;
2272 SilcChannelUser chu;
2274 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2275 SILC_ID_CHANNEL, &list))
2278 silc_idcache_list_first(list, &id_cache);
2279 channel = (SilcChannelEntry)id_cache->context;
2283 /* Replace client entry */
2284 silc_list_start(channel->clients);
2285 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2286 if (chu->client == old) {
2292 if (!silc_idcache_list_next(list, &id_cache))
2295 channel = (SilcChannelEntry)id_cache->context;
2298 silc_idcache_list_free(list);
2301 /* Parses mode mask and returns the mode as string. */
2303 char *silc_client_chmode(unsigned int mode)
2310 memset(string, 0, sizeof(string));
2312 if (mode & SILC_CHANNEL_MODE_PRIVATE)
2313 strncat(string, "p", 1);
2315 if (mode & SILC_CHANNEL_MODE_SECRET)
2316 strncat(string, "s", 1);
2318 if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2319 strncat(string, "k", 1);
2321 if (mode & SILC_CHANNEL_MODE_INVITE)
2322 strncat(string, "i", 1);
2324 if (mode & SILC_CHANNEL_MODE_TOPIC)
2325 strncat(string, "t", 1);
2327 if (mode & SILC_CHANNEL_MODE_ULIMIT)
2328 strncat(string, "l", 1);
2330 if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2331 strncat(string, "a", 1);
2333 /* Rest of mode is ignored */
2335 return strdup(string);
2338 /* Parses channel user mode mask and returns te mode as string */
2340 char *silc_client_chumode(unsigned int mode)
2347 memset(string, 0, sizeof(string));
2349 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2350 strncat(string, "f", 1);
2352 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2353 strncat(string, "o", 1);
2355 return strdup(string);
2358 /* Parses channel user mode and returns it as special mode character. */
2360 char *silc_client_chumode_char(unsigned int mode)
2367 memset(string, 0, sizeof(string));
2369 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2370 strncat(string, "*", 1);
2372 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2373 strncat(string, "@", 1);
2375 return strdup(string);
2378 /* Function that actually employes the received private message key */
2380 static void silc_client_private_message_key_cb(SilcClient client,
2381 SilcClientConnection conn,
2382 SilcClientEntry *clients,
2383 unsigned int clients_count,
2386 SilcPacketContext *packet = (SilcPacketContext *)context;
2388 unsigned short key_len;
2389 unsigned char *cipher;
2395 /* Parse the private message key payload */
2396 ret = silc_buffer_unformat(packet->buffer,
2397 SILC_STR_UI16_NSTRING(&key, &key_len),
2398 SILC_STR_UI16_STRING(&cipher),
2403 if (key_len > packet->buffer->len)
2406 /* Now take the key in use */
2407 if (!silc_client_add_private_message_key(client, conn, clients[0],
2408 cipher, key, key_len, FALSE))
2411 /* Print some info for application */
2412 client->ops->say(client, conn,
2413 "Received private message key from %s%s%s %s%s%s",
2414 clients[0]->nickname,
2415 clients[0]->server ? "@" : "",
2416 clients[0]->server ? clients[0]->server : "",
2417 clients[0]->username ? "(" : "",
2418 clients[0]->username ? clients[0]->username : "",
2419 clients[0]->username ? ")" : "");
2422 silc_packet_context_free(packet);
2425 /* Processes incoming Private Message Key payload. The libary always
2426 accepts the key and takes it into use. */
2428 void silc_client_private_message_key(SilcClient client,
2429 SilcSocketConnection sock,
2430 SilcPacketContext *packet)
2432 SilcClientID *remote_id;
2434 if (packet->src_id_type != SILC_ID_CLIENT)
2437 remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2442 silc_client_get_client_by_id_resolve(client, sock->user_data, remote_id,
2443 silc_client_private_message_key_cb,
2444 silc_packet_context_dup(packet));
2445 silc_free(remote_id);
2448 /* Adds private message key to the client library. The key will be used to
2449 encrypt all private message between the client and the remote client
2450 indicated by the `client_entry'. If the `key' is NULL and the boolean
2451 value `generate_key' is TRUE the library will generate random key.
2452 The `key' maybe for example pre-shared-key, passphrase or similar.
2453 The `cipher' MAY be provided but SHOULD be NULL to assure that the
2454 requirements of the SILC protocol are met. The API, however, allows
2455 to allocate any cipher.
2457 It is not necessary to set key for normal private message usage. If the
2458 key is not set then the private messages are encrypted using normal
2459 session keys. Setting the private key, however, increases the security.
2461 Returns FALSE if the key is already set for the `client_entry', TRUE
2464 int silc_client_add_private_message_key(SilcClient client,
2465 SilcClientConnection conn,
2466 SilcClientEntry client_entry,
2469 unsigned int key_len,
2472 unsigned char private_key[32];
2475 SilcSKEKeyMaterial *keymat;
2477 assert(client_entry);
2479 /* Return FALSE if key already set */
2480 if (client_entry->send_key && client_entry->receive_key)
2484 cipher = "aes-256-cbc";
2486 /* Check the requested cipher */
2487 if (!silc_cipher_is_supported(cipher))
2490 /* Generate key if not provided */
2491 if (!key && generate_key == TRUE) {
2493 for (i = 0; i < len; i++) private_key[i] = silc_rng_get_byte(client->rng);
2496 client_entry->generated = TRUE;
2500 client_entry->key = silc_calloc(key_len, sizeof(*client_entry->key));
2501 memcpy(client_entry->key, key, key_len);
2502 client_entry->key_len = key_len;
2504 /* Produce the key material as the protocol defines */
2505 keymat = silc_calloc(1, sizeof(*keymat));
2506 if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
2507 client->md5hash, keymat)
2508 != SILC_SKE_STATUS_OK)
2511 /* Allocate the ciphers */
2512 silc_cipher_alloc(cipher, &client_entry->send_key);
2513 silc_cipher_alloc(cipher, &client_entry->receive_key);
2516 silc_cipher_set_key(client_entry->send_key, keymat->send_enc_key,
2517 keymat->enc_key_len);
2518 silc_cipher_set_iv(client_entry->send_key, keymat->send_iv);
2519 silc_cipher_set_key(client_entry->receive_key, keymat->receive_enc_key,
2520 keymat->enc_key_len);
2521 silc_cipher_set_iv(client_entry->receive_key, keymat->receive_iv);
2523 /* Free the key material */
2524 silc_ske_free_key_material(keymat);
2529 /* Same as above but takes the key material from the SKE key material
2530 structure. This structure is received if the application uses the
2531 silc_client_send_key_agreement to negotiate the key material. The
2532 `cipher' SHOULD be provided as it is negotiated also in the SKE
2535 int silc_client_add_private_message_key_ske(SilcClient client,
2536 SilcClientConnection conn,
2537 SilcClientEntry client_entry,
2539 SilcSKEKeyMaterial *key)
2541 assert(client_entry);
2543 /* Return FALSE if key already set */
2544 if (client_entry->send_key && client_entry->receive_key)
2548 cipher = "aes-256-cbc";
2550 /* Check the requested cipher */
2551 if (!silc_cipher_is_supported(cipher))
2554 /* Allocate the ciphers */
2555 silc_cipher_alloc(cipher, &client_entry->send_key);
2556 silc_cipher_alloc(cipher, &client_entry->receive_key);
2559 silc_cipher_set_key(client_entry->send_key, key->send_enc_key,
2561 silc_cipher_set_iv(client_entry->send_key, key->send_iv);
2562 silc_cipher_set_key(client_entry->receive_key, key->receive_enc_key,
2564 silc_cipher_set_iv(client_entry->receive_key, key->receive_iv);
2569 /* Sends private message key payload to the remote client indicated by
2570 the `client_entry'. If the `force_send' is TRUE the packet is sent
2571 immediately. Returns FALSE if error occurs, TRUE otherwise. The
2572 application should call this function after setting the key to the
2575 Note that the key sent using this function is sent to the remote client
2576 through the SILC network. The packet is protected using normal session
2579 int silc_client_send_private_message_key(SilcClient client,
2580 SilcClientConnection conn,
2581 SilcClientEntry client_entry,
2584 SilcSocketConnection sock = conn->sock;
2588 if (!client_entry->send_key || !client_entry->key)
2591 SILC_LOG_DEBUG(("Sending private message key"));
2593 cipher_len = strlen(client_entry->send_key->cipher->name);
2595 /* Create private message key payload */
2596 buffer = silc_buffer_alloc(2 + client_entry->key_len);
2597 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
2598 silc_buffer_format(buffer,
2599 SILC_STR_UI_SHORT(client_entry->key_len),
2600 SILC_STR_UI_XNSTRING(client_entry->key,
2601 client_entry->key_len),
2602 SILC_STR_UI_SHORT(cipher_len),
2603 SILC_STR_UI_XNSTRING(client_entry->send_key->cipher->name,
2607 /* Send the packet */
2608 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE_KEY,
2609 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
2610 buffer->data, buffer->len, force_send);
2616 /* Removes the private message from the library. The key won't be used
2617 after this to protect the private messages with the remote `client_entry'
2618 client. Returns FALSE on error, TRUE otherwise. */
2620 int silc_client_del_private_message_key(SilcClient client,
2621 SilcClientConnection conn,
2622 SilcClientEntry client_entry)
2624 assert(client_entry);
2626 if (!client_entry->send_key && !client_entry->receive_key)
2629 silc_cipher_free(client_entry->send_key);
2630 silc_cipher_free(client_entry->receive_key);
2632 if (client_entry->key) {
2633 memset(client_entry->key, 0, client_entry->key_len);
2634 silc_free(client_entry->key);
2637 client_entry->send_key = NULL;
2638 client_entry->receive_key = NULL;
2639 client_entry->key = NULL;
2644 /* Returns array of set private message keys associated to the connection
2645 `conn'. Returns allocated SilcPrivateMessageKeys array and the array
2646 count to the `key_count' argument. The array must be freed by the caller
2647 by calling the silc_client_free_private_message_keys function. Note:
2648 the keys returned in the array is in raw format. It might not be desired
2649 to show the keys as is. The application might choose not to show the keys
2650 at all or to show the fingerprints of the keys. */
2652 SilcPrivateMessageKeys
2653 silc_client_list_private_message_keys(SilcClient client,
2654 SilcClientConnection conn,
2655 unsigned int *key_count)
2657 SilcPrivateMessageKeys keys;
2658 unsigned int count = 0;
2659 SilcIDCacheEntry id_cache;
2660 SilcIDCacheList list;
2661 SilcClientEntry entry;
2663 if (!silc_idcache_find_by_id(conn->client_cache, SILC_ID_CACHE_ANY,
2664 SILC_ID_CLIENT, &list))
2667 if (!silc_idcache_list_count(list)) {
2668 silc_idcache_list_free(list);
2672 keys = silc_calloc(silc_idcache_list_count(list), sizeof(*keys));
2674 silc_idcache_list_first(list, &id_cache);
2676 entry = (SilcClientEntry)id_cache->context;
2678 if (entry->send_key) {
2679 keys[count].client_entry = entry;
2680 keys[count].cipher = entry->send_key->cipher->name;
2681 keys[count].key = entry->generated == FALSE ? entry->key : NULL;
2682 keys[count].key_len = entry->generated == FALSE ? entry->key_len : 0;
2686 if (!silc_idcache_list_next(list, &id_cache))
2696 /* Frees the SilcPrivateMessageKeys array returned by the function
2697 silc_client_list_private_message_keys. */
2699 void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
2700 unsigned int key_count)
2705 /* Adds private key for channel. This may be set only if the channel's mode
2706 mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
2707 mode is not set. When channel has private key then the messages are
2708 encrypted using that key. All clients on the channel must also know the
2709 key in order to decrypt the messages. However, it is possible to have
2710 several private keys per one channel. In this case only some of the
2711 clients on the channel may now the one key and only some the other key.
2713 The private key for channel is optional. If it is not set then the
2714 channel messages are encrypted using the channel key generated by the
2715 server. However, setting the private key (or keys) for the channel
2716 significantly adds security. If more than one key is set the library
2717 will automatically try all keys at the message decryption phase. Note:
2718 setting many keys slows down the decryption phase as all keys has to
2719 be tried in order to find the correct decryption key. However, setting
2720 a few keys does not have big impact to the decryption performace.
2722 NOTE: that this is entirely local setting. The key set using this function
2723 is not sent to the network at any phase.
2725 NOTE: If the key material was originated by the SKE protocol (using
2726 silc_client_send_key_agreement) then the `key' MUST be the
2727 key->send_enc_key as this is dictated by the SILC protocol. However,
2728 currently it is not expected that the SKE key material would be used
2729 as channel private key. However, this API allows it. */
2731 int silc_client_add_channel_private_key(SilcClient client,
2732 SilcClientConnection conn,
2733 SilcChannelEntry channel,
2736 unsigned int key_len)
2742 /* Removes all private keys from the `channel'. The old channel key is used
2743 after calling this to protect the channel messages. Returns FALSE on
2744 on error, TRUE otherwise. */
2746 int silc_client_del_channel_private_keys(SilcClient client,
2747 SilcClientConnection conn,
2748 SilcChannelEntry channel)
2754 /* Removes and frees private key `key' from the channel `channel'. The `key'
2755 is retrieved by calling the function silc_client_list_channel_private_keys.
2756 The key is not used after this. If the key was last private key then the
2757 old channel key is used hereafter to protect the channel messages. This
2758 returns FALSE on error, TRUE otherwise. */
2760 int silc_client_del_channel_private_key(SilcClient client,
2761 SilcClientConnection conn,
2762 SilcChannelEntry channel,
2763 SilcChannelPrivateKey key)
2769 /* Returns array (pointers) of private keys associated to the `channel'.
2770 The caller must free the array by calling the function
2771 silc_client_free_channel_private_keys. The pointers in the array may be
2772 used to delete the specific key by giving the pointer as argument to the
2773 function silc_client_del_channel_private_key. */
2775 SilcChannelPrivateKey *
2776 silc_client_list_channel_private_keys(SilcClient client,
2777 SilcClientConnection conn,
2778 SilcChannelEntry channel,
2779 unsigned int key_count)
2785 /* Frees the SilcChannelPrivateKey array. */
2787 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
2788 unsigned int key_count)
2793 /* Sends key agreement request to the remote client indicated by the
2794 `client_entry'. If the caller provides the `hostname' and the `port'
2795 arguments then the library will bind the client to that hostname and
2796 that port for the key agreement protocol. It also sends the `hostname'
2797 and the `port' in the key agreement packet to the remote client. This
2798 would indicate that the remote client may initiate the key agreement
2799 protocol to the `hostname' on the `port'.
2801 If the `hostname' and `port' is not provided then empty key agreement
2802 packet is sent to the remote client. The remote client may reply with
2803 the same packet including its hostname and port. If the library receives
2804 the reply from the remote client the `key_agreement' client operation
2805 callback will be called to verify whether the user wants to perform the
2806 key agreement or not.
2808 NOTE: If the application provided the `hostname' and the `port' and the
2809 remote side initiates the key agreement protocol it is not verified
2810 from the user anymore whether the protocol should be executed or not.
2811 By setting the `hostname' and `port' the user gives permission to
2812 perform the protocol (we are responder in this case).
2814 NOTE: If the remote side decides not to initiate the key agreement
2815 or decides not to reply with the key agreement packet then we cannot
2816 perform the key agreement at all. If the key agreement protocol is
2817 performed the `completion' callback with the `context' will be called.
2818 If remote side decides to ignore the request the `completion' will never
2819 be called and the caller is responsible of freeing the `context' memory.
2820 The application can do this by setting, for example, timeout. */
2822 void silc_client_send_key_agreement(SilcClient client,
2823 SilcClientConnection conn,
2824 SilcClientEntry client_entry,
2827 SilcKeyAgreementCallback completion,
2833 /* Performs the actual key agreement protocol. Application may use this
2834 to initiate the key agreement protocol. This can be called for example
2835 after the application has received the `key_agreement' client operation,
2836 and did not return TRUE from it.
2838 The `hostname' is the remote hostname (or IP address) and the `port'
2839 is the remote port. The `completion' callblack with the `context' will
2840 be called after the key agreement protocol.
2842 NOTE: If the application returns TRUE in the `key_agreement' client
2843 operation the library will automatically start the key agreement. In this
2844 case the application must not call this function. However, application
2845 may choose to just ignore the `key_agreement' client operation (and
2846 merely just print information about it on the screen) and call this
2847 function when the user whishes to do so (by, for example, giving some
2848 specific command). Thus, the API provides both, automatic and manual
2849 initiation of the key agreement. Calling this function is the manual
2850 initiation and returning TRUE in the `key_agreement' client operation
2851 is the automatic initiation. */
2853 void silc_client_perform_key_agreement(SilcClient client,
2854 SilcClientConnection conn,
2855 SilcClientEntry client_entry,
2858 SilcKeyAgreementCallback completion,
2864 /* This function can be called to unbind the hostname and the port for
2865 the key agreement protocol. However, this function has effect only
2866 before the key agreement protocol has been performed. After it has
2867 been performed the library will automatically unbind the port. The
2868 `client_entry' is the client to which we sent the key agreement
2871 void silc_client_abort_key_agreement(SilcClient client,
2872 SilcClientConnection conn,
2873 SilcClientEntry client_entry)