5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
23 * Revision 1.3 2000/07/04 08:29:12 priikone
24 * Added support for PING command. The ping times are calculated
25 * and showed to the user.
27 * Revision 1.2 2000/07/03 05:49:48 priikone
28 * Implemented LEAVE command. Minor bug fixes.
30 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
31 * Importet from internal CVS/Added Log headers.
36 #include "clientincludes.h"
38 /* Static function prototypes */
39 static int silc_client_bad_keys(unsigned char key);
40 static void silc_client_process_message(SilcClient client);
41 static char *silc_client_parse_command(unsigned char *buffer);
43 /* Static task callback prototypes */
44 SILC_TASK_CALLBACK(silc_client_update_clock);
45 SILC_TASK_CALLBACK(silc_client_run_commands);
46 SILC_TASK_CALLBACK(silc_client_process_key_press);
47 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
48 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
49 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
50 SILC_TASK_CALLBACK(silc_client_packet_process);
51 SILC_TASK_CALLBACK(silc_client_packet_parse);
53 SilcClientWindow silc_client_create_main_window(SilcClient client);
54 SilcClientWindow silc_client_add_window(SilcClient client,
56 void silc_client_packet_parse_type(SilcClient client,
57 SilcSocketConnection sock,
58 SilcPacketContext *packet);
59 void silc_client_private_message_process(SilcClient client,
60 SilcSocketConnection sock,
61 SilcPacketContext *packet);
63 /* Definitions from version.h */
64 extern char *silc_version;
65 extern char *silc_name;
66 extern char *silc_fullname;
68 /* Allocates new client object. This has to be done before client may
69 work. After calling this one must call silc_client_init to initialize
72 int silc_client_alloc(SilcClient *new_client)
75 *new_client = silc_calloc(1, sizeof(**new_client));
76 if (*new_client == NULL) {
77 SILC_LOG_ERROR(("Could not allocate new client object"));
81 (*new_client)->input_buffer = NULL;
82 (*new_client)->screen = NULL;
83 (*new_client)->windows = NULL;
84 (*new_client)->windows_count = 0;
85 (*new_client)->current_win = NULL;
90 /* Free's client object */
92 void silc_client_free(SilcClient client)
99 /* Initializes the client. This makes all the necessary steps to make
100 the client ready to be run. One must call silc_client_run to run the
103 int silc_client_init(SilcClient client)
106 SILC_LOG_DEBUG(("Initializing client"));
109 client->username = silc_get_username();
110 client->realname = silc_get_real_name();
112 /* Register all configured ciphers, PKCS and hash functions. */
113 client->config->client = (void *)client;
114 silc_client_config_register_ciphers(client->config);
115 silc_client_config_register_pkcs(client->config);
116 silc_client_config_register_hashfuncs(client->config);
118 /* Initialize hash functions for client to use */
119 silc_hash_alloc("md5", &client->md5hash);
120 silc_hash_alloc("sha1", &client->sha1hash);
122 /* Initialize none cipher */
123 silc_cipher_alloc("none", &client->none_cipher);
125 /* Initialize random number generator */
126 client->rng = silc_rng_alloc();
127 silc_rng_init(client->rng);
128 silc_math_primegen_init(); /* XXX */
133 unsigned char *src, *dst, *dec;
137 payload_len = 4 + strlen("pekka riikonen");
138 packet = silc_buffer_alloc(payload_len);
139 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
140 silc_buffer_format(packet,
141 SILC_STR_UI_SHORT(payload_len),
142 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
143 SILC_STR_UI_XNSTRING("pekka riikonen",
144 strlen("pekka riikonen")),
147 silc_cipher_alloc("twofish", &twofish);
148 twofish->cipher->set_key(twofish->context, "1234567890123456", 16);
149 twofish->set_iv(twofish, "6543210987654321");
150 SILC_LOG_HEXDUMP(("source: len %d", packet->len),
151 packet->data, packet->len );
152 silc_packet_encrypt(twofish, packet, packet->len);
153 SILC_LOG_HEXDUMP(("encrypted"), packet->data, packet->len);
154 silc_packet_decrypt(twofish, packet, packet->len);
155 SILC_LOG_HEXDUMP(("decrypted"), packet->data, packet->len);
160 SilcCipher cipher1, cipher2;
161 unsigned char *src, *dst, *dec;
162 int len = strlen("12345678901234561234567890123456123456789012345612345678901234561234567890123456");
164 src = silc_calloc(len + 1, sizeof(unsigned char));
165 dst = silc_calloc(len + 1, sizeof(unsigned char));
166 dec = silc_calloc(len + 1, sizeof(unsigned char));
168 memcpy(src, "12345678901234561234567890123456123456789012345612345678901234561234567890123456", len);
170 silc_cipher_alloc("twofish", &cipher1);
171 cipher1->cipher->set_key(cipher1->context, "1234567890123456", 128);
172 cipher1->set_iv(cipher1, "6543210987654321");
174 silc_cipher_alloc("twofish", &cipher2);
175 cipher2->cipher->set_key(cipher2->context, "1234567890123456", 128);
176 cipher2->set_iv(cipher2, "6543210987654321");
178 SILC_LOG_HEXDUMP(("source: %d", len), src, len);
179 cipher1->cipher->encrypt(cipher1->context, src, src, len, cipher1->iv);
180 SILC_LOG_HEXDUMP(("encrypted"), src, len);
181 cipher2->set_iv(cipher2, "6543210987654321");
182 cipher2->cipher->decrypt(cipher2->context, src, src, len, cipher2->iv);
183 SILC_LOG_HEXDUMP(("decrypted"), src, len);
188 /* Register the task queues. In SILC we have by default three task queues.
189 One task queue for non-timeout tasks which perform different kind of
190 I/O on file descriptors, timeout task queue for timeout tasks, and,
191 generic non-timeout task queue whose tasks apply to all connections. */
192 silc_task_queue_alloc(&client->io_queue, TRUE);
193 if (!client->io_queue) {
196 silc_task_queue_alloc(&client->timeout_queue, TRUE);
197 if (!client->timeout_queue) {
200 silc_task_queue_alloc(&client->generic_queue, TRUE);
201 if (!client->generic_queue) {
205 /* Initialize the scheduler */
206 silc_schedule_init(client->io_queue, client->timeout_queue,
207 client->generic_queue, 5000);
209 /* Register the main task that is used in client. This received
210 the key pressings. */
211 if (silc_task_register(client->io_queue, fileno(stdin),
212 silc_client_process_key_press,
213 (void *)client, 0, 0,
215 SILC_TASK_PRI_NORMAL) == NULL) {
219 /* Register timeout task that updates clock every minute. */
220 if (silc_task_register(client->timeout_queue, 0,
221 silc_client_update_clock,
223 silc_client_time_til_next_min(), 0,
225 SILC_TASK_PRI_LOW) == NULL) {
229 if (client->config->commands) {
230 /* Run user configured commands with timeout */
231 if (silc_task_register(client->timeout_queue, 0,
232 silc_client_run_commands,
233 (void *)client, 0, 1,
235 SILC_TASK_PRI_LOW) == NULL) {
240 /* Allocate the input buffer used to save typed characters */
241 client->input_buffer = silc_buffer_alloc(SILC_SCREEN_INPUT_WIN_SIZE);
242 silc_buffer_pull_tail(client->input_buffer,
243 SILC_BUFFER_END(client->input_buffer));
245 /* Initialize the screen */
246 client->screen = silc_screen_init();
247 silc_client_create_main_window(client);
248 client->screen->input_buffer = client->input_buffer->data;
249 silc_screen_print_coordinates(client->screen, 0);
254 silc_task_queue_free(client->timeout_queue);
256 silc_task_queue_free(client->io_queue);
261 /* Stops the client. This is called to stop the client and thus to stop
264 void silc_client_stop(SilcClient client)
266 SILC_LOG_DEBUG(("Stopping client"));
268 /* Stop the scheduler, although it might be already stopped. This
269 doesn't hurt anyone. This removes all the tasks and task queues,
271 silc_schedule_stop();
272 silc_schedule_uninit();
274 SILC_LOG_DEBUG(("Client client"));
277 /* Runs the client. */
279 void silc_client_run(SilcClient client)
281 SILC_LOG_DEBUG(("Running client"));
283 /* Start the scheduler, the heart of the SILC client. When this returns
284 the program will be terminated. */
288 /* Creates the main window used in SILC client. This is called always
289 at the initialization of the client. If user wants to create more
290 than one windows a new windows are always created by calling
291 silc_client_add_window. */
293 SilcClientWindow silc_client_create_main_window(SilcClient client)
295 SilcClientWindow win;
298 SILC_LOG_DEBUG(("Creating main window"));
300 assert(client->screen != NULL);
302 win = silc_calloc(1, sizeof(*win));
304 SILC_LOG_ERROR(("Could not allocate new window"));
308 client->screen->u_stat_line.program_name = silc_name;
309 client->screen->u_stat_line.program_version = silc_version;
311 /* Add the pointers */
312 win->nickname = silc_get_username();
313 win->local_id = NULL;
314 win->local_id_data = NULL;
315 win->local_id_data_len = 0;
316 win->remote_host = NULL;
317 win->remote_port = -1;
320 /* Create the actual screen */
321 screen = (void *)silc_screen_create_output_window(client->screen);
322 silc_screen_create_input_window(client->screen);
323 silc_screen_init_upper_status_line(client->screen);
324 silc_screen_init_output_status_line(client->screen);
325 win->screen = screen;
327 client->screen->bottom_line->nickname = win->nickname;
328 silc_screen_print_bottom_line(client->screen, 0);
330 /* Add the window to windows table */
331 client->windows = silc_calloc(1, sizeof(*client->windows));
332 client->windows[client->windows_count] = win;
333 client->windows_count = 1;
335 /* Automatically becomes the current active window */
336 client->current_win = win;
341 /* Allocates and adds new window to the client. This allocates new
342 physical window and internal window for connection specific data.
343 All the connection specific data is always saved into a window
344 since connection is always associated to a active window. */
346 SilcClientWindow silc_client_add_window(SilcClient client,
349 SilcClientWindow win;
351 assert(client->screen != NULL);
353 win = silc_calloc(1, sizeof(*win));
355 SILC_LOG_ERROR(("Could not allocate new window"));
359 /* Add the pointers */
360 win->screen = silc_screen_add_output_window(client->screen);
363 /* Add the window to windows table */
364 client->windows = silc_realloc(client->windows, sizeof(*client->windows)
365 * (client->windows_count + 1));
366 client->windows[client->windows_count] = win;
367 client->windows_count++;
369 if (is_current == TRUE)
370 client->current_win = win;
375 /* The main task on SILC client. This processes the key pressings user
378 SILC_TASK_CALLBACK(silc_client_process_key_press)
380 SilcClient client = (SilcClient)context;
383 /* There is data pending in stdin, this gets it directly */
384 c = wgetch(client->screen->input_win);
385 if (silc_client_bad_keys(c))
388 SILC_LOG_DEBUG(("Pressed key: %d", c));
392 * Special character handling
399 SILC_LOG_DEBUG(("RIGHT"));
400 silc_screen_input_cursor_right(client->screen);
404 SILC_LOG_DEBUG(("LEFT"));
405 silc_screen_input_cursor_left(client->screen);
412 silc_screen_input_backspace(client->screen);
418 /* Insert switch. Turns on/off insert on input window */
419 silc_screen_input_insert(client->screen);
423 /* Enter, Return. User pressed enter we are ready to
424 process the message. */
425 silc_client_process_message(client);
426 silc_screen_input_reset(client->screen);
429 /* Refresh screen, Ctrl^l */
430 silc_screen_refresh_all(client->screen);
435 /* Beginning, Home */
436 silc_screen_input_cursor_home(client->screen);
441 silc_screen_input_cursor_end(client->screen);
459 /* Control codes are printed as reversed */
461 wattron(client->screen->input_win, A_REVERSE);
462 silc_screen_input_print(client->screen, c);
463 wattroff(client->screen->input_win, A_REVERSE);
465 /* Normal character */
466 silc_screen_input_print(client->screen, c);
470 silc_screen_print_coordinates(client->screen, 0);
471 silc_screen_refresh_win(client->screen->input_win);
474 static int silc_client_bad_keys(unsigned char key)
476 /* these are explained in curses.h */
491 case '\E': /* we ignore ESC */
498 /* Processes messages user has typed on the screen. This either sends
499 a packet out to network or if command were written executes it. */
501 static void silc_client_process_message(SilcClient client)
506 SILC_LOG_DEBUG(("Start"));
508 data = client->input_buffer->data;
511 if (data[0] == '/' && data[1] != ' ') {
513 unsigned int argc = 0;
514 unsigned char **argv, *tmpcmd;
515 unsigned int *argv_lens, *argv_types;
516 SilcClientCommand *cmd;
517 SilcClientCommandContext ctx;
519 /* Get the command */
520 tmpcmd = silc_client_parse_command(data);
522 /* Find command match */
523 for (cmd = silc_command_list; cmd->name; cmd++) {
524 if (!strcmp(cmd->name, tmpcmd))
528 if (cmd->name == NULL) {
529 silc_say(client, "Invalid command: %s", tmpcmd);
534 /* Now parse all arguments */
535 silc_client_parse_command_line(data, &argv, &argv_lens,
536 &argv_types, &argc, cmd->max_args);
539 SILC_LOG_DEBUG(("Exeuting command: %s", cmd->name));
541 /* Allocate command context. This and its internals must be free'd
542 by the command routine receiving it. */
543 ctx = silc_calloc(1, sizeof(*ctx));
544 ctx->client = client;
545 ctx->sock = client->current_win->sock;
548 ctx->argv_lens = argv_lens;
549 ctx->argv_types = argv_types;
551 /* Execute command */
555 /* Normal message to a channel */
556 if (len && client->current_win->current_channel &&
557 client->current_win->current_channel->on_channel == TRUE) {
558 silc_print(client, "> %s", data);
559 silc_client_packet_send_to_channel(client,
560 client->current_win->sock,
561 client->current_win->current_channel,
562 data, strlen(data), TRUE);
567 /* Clear the input buffer */
568 silc_buffer_clear(client->input_buffer);
569 silc_buffer_pull_tail(client->input_buffer,
570 SILC_BUFFER_END(client->input_buffer));
573 /* Returns the command fetched from user typed command line */
575 static char *silc_client_parse_command(unsigned char *buffer)
578 const char *cp = buffer;
581 len = strcspn(cp, " ");
582 ret = silc_to_upper((char *)++cp);
588 /* Parses user typed command line. At most `max_args' is taken. Rest
589 of the line will be allocated as the last argument if there are more
590 than `max_args' arguments in the line. Note that the command name
591 is counted as one argument and is saved. */
593 void silc_client_parse_command_line(unsigned char *buffer,
594 unsigned char ***parsed,
595 unsigned int **parsed_lens,
596 unsigned int **parsed_types,
597 unsigned int *parsed_num,
598 unsigned int max_args)
602 const char *cp = buffer;
604 /* Take the '/' away */
607 *parsed = silc_calloc(1, sizeof(**parsed));
608 *parsed_lens = silc_calloc(1, sizeof(**parsed_lens));
610 /* Get the command first */
611 len = strcspn(cp, " ");
612 (*parsed)[0] = silc_to_upper((char *)cp);
613 (*parsed_lens)[0] = len;
617 /* Parse arguments */
618 if (strchr(cp, ' ') || strlen(cp) != 0) {
619 for (i = 1; i < max_args; i++) {
621 if (i != max_args - 1)
622 len = strcspn(cp, " ");
626 *parsed = silc_realloc(*parsed, sizeof(**parsed) * (argc + 1));
627 *parsed_lens = silc_realloc(*parsed_lens,
628 sizeof(**parsed_lens) * (argc + 1));
629 (*parsed)[argc] = silc_calloc(len + 1, sizeof(char));
630 memcpy((*parsed)[argc], cp, len);
631 (*parsed_lens)[argc] = len;
642 /* Save argument types. Protocol defines all argument types but
643 this implementation makes sure that they are always in correct
644 order hence this simple code. */
645 *parsed_types = silc_calloc(argc, sizeof(**parsed_types));
646 for (i = 0; i < argc; i++)
647 (*parsed_types)[i] = i;
652 /* Updates clock on the screen every minute. */
654 SILC_TASK_CALLBACK(silc_client_update_clock)
656 SilcClient client = (SilcClient)context;
658 /* Update the clock on the screen */
659 silc_screen_print_clock(client->screen);
661 /* Re-register this same task */
662 silc_task_register(qptr, 0, silc_client_update_clock, context,
663 silc_client_time_til_next_min(), 0,
667 silc_screen_refresh_win(client->screen->input_win);
670 /* Runs commands user configured in configuration file. This is
671 called when initializing client. */
673 SILC_TASK_CALLBACK(silc_client_run_commands)
675 SilcClient client = (SilcClient)context;
676 SilcClientConfigSectionCommand *cs;
678 SILC_LOG_DEBUG(("Start"));
680 cs = client->config->commands;
682 unsigned int argc = 0;
683 unsigned char **argv, *tmpcmd;
684 unsigned int *argv_lens, *argv_types;
685 SilcClientCommand *cmd;
686 SilcClientCommandContext ctx;
688 /* Get the command */
689 tmpcmd = silc_client_parse_command(cs->command);
691 for (cmd = silc_command_list; cmd->name; cmd++) {
692 if (!strcmp(cmd->name, tmpcmd))
696 if (cmd->name == NULL) {
697 silc_say(client, "Invalid command: %s", tmpcmd);
702 /* Now parse all arguments */
703 silc_client_parse_command_line(cs->command, &argv, &argv_lens,
704 &argv_types, &argc, cmd->max_args);
707 SILC_LOG_DEBUG(("Exeuting command: %s", cmd->name));
709 /* Allocate command context. This and its internals must be free'd
710 by the command routine receiving it. */
711 ctx = silc_calloc(1, sizeof(*ctx));
712 ctx->client = client;
713 ctx->sock = client->current_win->sock;
716 ctx->argv_lens = argv_lens;
717 ctx->argv_types = argv_types;
719 /* Execute command */
726 /* Internal context for connection process. This is needed as we
727 doing asynchronous connecting. */
735 } SilcClientInternalConnectContext;
738 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
742 /* XXX In the future we should give up this non-blocking connect all
743 together and use threads instead. */
744 /* Create connection to server asynchronously */
745 sock = silc_net_create_connection_async(ctx->port, ctx->host);
749 /* Register task that will receive the async connect and will
751 ctx->task = silc_task_register(ctx->client->io_queue, sock,
752 silc_client_connect_to_server_start,
755 SILC_TASK_PRI_NORMAL);
756 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
757 silc_schedule_set_listen_fd(sock, ctx->task->iomask);
764 /* Connects to remote server */
766 int silc_client_connect_to_server(SilcClient client, int port,
769 SilcClientInternalConnectContext *ctx;
771 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
774 silc_say(client, "Connecting to port %d of server %s", port, host);
776 client->current_win->remote_host = strdup(host);
777 client->current_win->remote_port = port;
779 /* Allocate internal context for connection process. This is
780 needed as we are doing async connecting. */
781 ctx = silc_calloc(1, sizeof(*ctx));
782 ctx->client = client;
783 ctx->host = strdup(host);
787 /* Do the actual connecting process */
788 return silc_client_connect_to_server_internal(ctx);
791 /* Start of the connection to the remote server. This is called after
792 succesful TCP/IP connection has been established to the remote host. */
794 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
796 SilcClientInternalConnectContext *ctx =
797 (SilcClientInternalConnectContext *)context;
798 SilcClient client = ctx->client;
799 SilcProtocol protocol;
800 SilcClientKEInternalContext *proto_ctx;
801 int opt, opt_len = sizeof(opt);
803 SILC_LOG_DEBUG(("Start"));
805 /* Check the socket status as it might be in error */
806 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
808 if (ctx->tries < 2) {
809 /* Connection failed but lets try again */
810 silc_say(ctx->client, "Could not connect to server %s: %s",
811 ctx->host, strerror(opt));
812 silc_say(client, "Connecting to port %d of server %s resumed",
813 ctx->port, ctx->host);
815 /* Unregister old connection try */
816 silc_schedule_unset_listen_fd(fd);
817 silc_net_close_connection(fd);
818 silc_task_unregister(client->io_queue, ctx->task);
821 silc_client_connect_to_server_internal(ctx);
824 /* Connection failed and we won't try anymore */
825 silc_say(ctx->client, "Could not connect to server %s: %s",
826 ctx->host, strerror(opt));
827 silc_schedule_unset_listen_fd(fd);
828 silc_net_close_connection(fd);
829 silc_task_unregister(client->io_queue, ctx->task);
835 silc_schedule_unset_listen_fd(fd);
836 silc_task_unregister(client->io_queue, ctx->task);
839 /* Allocate new socket connection object */
840 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER,
841 (void *)client->current_win,
842 &client->current_win->sock);
843 if (client->current_win->sock == NULL) {
844 silc_say(client, "Error: Could not allocate connection socket");
845 silc_net_close_connection(fd);
848 client->current_win->sock->hostname = client->current_win->remote_host;
849 client->current_win->sock->port = client->current_win->remote_port;
851 /* Allocate internal Key Exchange context. This is sent to the
852 protocol as context. */
853 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
854 proto_ctx->client = (void *)client;
855 proto_ctx->sock = client->current_win->sock;
856 proto_ctx->rng = client->rng;
857 proto_ctx->responder = FALSE;
859 /* Perform key exchange protocol. silc_client_connect_to_server_final
860 will be called after the protocol is finished. */
861 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
862 &protocol, (void *)proto_ctx,
863 silc_client_connect_to_server_second);
865 silc_say(client, "Error: Could not start authentication protocol");
868 client->current_win->sock->protocol = protocol;
870 /* Register the connection for network input and output. This sets
871 that scheduler will listen for incoming packets for this connection
872 and sets that outgoing packets may be sent to this connection as well.
873 However, this doesn't set the scheduler for outgoing traffic, it will
874 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
875 later when outgoing data is available. */
876 context = (void *)client;
877 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
879 /* Execute the protocol */
880 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
883 /* Second part of the connecting to the server. This executed
884 authentication protocol. */
886 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
888 SilcProtocol protocol = (SilcProtocol)context;
889 SilcClientKEInternalContext *ctx =
890 (SilcClientKEInternalContext *)protocol->context;
891 SilcClient client = (SilcClient)ctx->client;
892 SilcSocketConnection sock = NULL;
893 SilcClientConnAuthInternalContext *proto_ctx;
895 SILC_LOG_DEBUG(("Start"));
897 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
898 /* Error occured during protocol */
899 SILC_LOG_DEBUG(("Error during KE protocol"));
900 silc_protocol_free(protocol);
902 silc_buffer_free(ctx->packet);
904 silc_ske_free(ctx->ske);
906 silc_free(ctx->dest_id);
908 sock->protocol = NULL;
912 /* Allocate internal context for the authentication protocol. This
913 is sent as context for the protocol. */
914 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
915 proto_ctx->client = (void *)client;
916 proto_ctx->sock = sock = ctx->sock;
917 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
918 proto_ctx->dest_id_type = ctx->dest_id_type;
919 proto_ctx->dest_id = ctx->dest_id;
921 /* Resolve the authentication method to be used in this connection */
922 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
923 if (client->config->conns) {
924 SilcClientConfigSectionConnection *conn = NULL;
926 /* Check if we find a match from user configured connections */
927 conn = silc_client_config_find_connection(client->config,
931 /* Match found. Use the configured authentication method */
932 proto_ctx->auth_meth = conn->auth_meth;
933 if (conn->auth_data) {
934 proto_ctx->auth_data = strdup(conn->auth_data);
935 proto_ctx->auth_data_len = strlen(conn->auth_data);
938 /* No match found. Resolve by sending AUTH_REQUEST to server */
939 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
942 /* XXX Resolve by sending AUTH_REQUEST to server */
943 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
946 /* Free old protocol as it is finished now */
947 silc_protocol_free(protocol);
949 silc_buffer_free(ctx->packet);
951 /* silc_free(ctx->keymat....); */
952 sock->protocol = NULL;
954 /* Allocate the authentication protocol. This is allocated here
955 but we won't start it yet. We will be receiving party of this
956 protocol thus we will wait that connecting party will make
958 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
959 &sock->protocol, (void *)proto_ctx,
960 silc_client_connect_to_server_final);
962 /* Execute the protocol */
963 sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
966 /* Finalizes the connection to the remote SILC server. This is called
967 after authentication protocol has been completed. This send our
968 user information to the server to receive our client ID from
971 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
973 SilcProtocol protocol = (SilcProtocol)context;
974 SilcClientConnAuthInternalContext *ctx =
975 (SilcClientConnAuthInternalContext *)protocol->context;
976 SilcClient client = (SilcClient)ctx->client;
977 SilcClientWindow win = (SilcClientWindow)ctx->sock->user_data;
980 SILC_LOG_DEBUG(("Start"));
982 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
983 /* Error occured during protocol */
984 SILC_LOG_DEBUG(("Error during authentication protocol"));
985 silc_protocol_free(protocol);
987 silc_free(ctx->auth_data);
989 silc_ske_free(ctx->ske);
991 silc_free(ctx->dest_id);
993 win->sock->protocol = NULL;
997 /* Send NEW_CLIENT packet to the server. We will become registered
998 to the SILC network after sending this packet and we will receive
999 client ID from the server. */
1000 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
1001 strlen(client->realname));
1002 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1003 silc_buffer_format(packet,
1004 SILC_STR_UI_SHORT(strlen(client->username)),
1005 SILC_STR_UI_XNSTRING(client->username,
1006 strlen(client->username)),
1007 SILC_STR_UI_SHORT(strlen(client->realname)),
1008 SILC_STR_UI_XNSTRING(client->realname,
1009 strlen(client->realname)),
1012 /* Send the packet */
1013 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
1014 NULL, 0, NULL, NULL,
1015 packet->data, packet->len, TRUE);
1016 silc_buffer_free(packet);
1018 /* Save remote ID. */
1019 win->remote_id = ctx->dest_id;
1020 win->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_CHANNEL);
1021 win->remote_id_data_len = SILC_ID_CHANNEL_LEN;
1023 silc_say(client, "Connected to port %d of host %s",
1024 win->remote_port, win->remote_host);
1026 client->screen->bottom_line->connection = win->remote_host;
1027 silc_screen_print_bottom_line(client->screen, 0);
1029 silc_protocol_free(protocol);
1031 silc_free(ctx->auth_data);
1033 silc_ske_free(ctx->ske);
1035 silc_free(ctx->dest_id);
1037 win->sock->protocol = NULL;
1041 SilcPacketContext *packetdata;
1042 SilcSocketConnection sock;
1044 } SilcClientInternalPacket;
1046 SILC_TASK_CALLBACK(silc_client_packet_process)
1048 SilcClient client = (SilcClient)context;
1049 SilcSocketConnection sock = NULL;
1050 int ret, packetlen, paddedlen;
1052 SILC_LOG_DEBUG(("Processing packet"));
1054 SILC_CLIENT_GET_SOCK(client, fd, sock);
1058 /* Packet sending */
1059 if (type == SILC_TASK_WRITE) {
1060 SILC_LOG_DEBUG(("Writing data to connection"));
1062 if (sock->outbuf->data - sock->outbuf->head)
1063 silc_buffer_push(sock->outbuf,
1064 sock->outbuf->data - sock->outbuf->head);
1066 /* Write the packet out to the connection */
1067 ret = silc_packet_write(fd, sock->outbuf);
1069 /* If returned -2 could not write to connection now, will do
1076 SILC_LOG_ERROR(("Packet dropped"));
1078 /* The packet has been sent and now it is time to set the connection
1079 back to only for input. When there is again some outgoing data
1080 available for this connection it will be set for output as well.
1081 This call clears the output setting and sets it only for input. */
1082 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
1083 SILC_UNSET_OUTBUF_PENDING(sock);
1088 /* Packet receiving */
1089 if (type == SILC_TASK_READ) {
1090 SILC_LOG_DEBUG(("Reading data from connection"));
1092 /* Allocate the incoming data buffer if not done already. */
1094 sock->inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
1096 /* Read some data from connection */
1097 ret = silc_packet_read(fd, sock->inbuf);
1099 /* If returned -2 data was not available now, will read it later. */
1105 SILC_LOG_ERROR(("Packet dropped"));
1111 SILC_LOG_DEBUG(("Read EOF"));
1113 /* If connection is disconnecting already we will finally
1114 close the connection */
1115 if (SILC_IS_DISCONNECTING(sock)) {
1116 silc_client_close_connection(client, sock);
1120 silc_say(client, "Connection closed: premature EOF");
1121 SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
1123 silc_client_close_connection(client, sock);
1127 /* Check whether we received a whole packet. If reading went without
1128 errors we either read a whole packet or the read packet is
1129 incorrect and will be dropped. */
1130 SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
1131 if (sock->inbuf->len < paddedlen || (packetlen < SILC_PACKET_MIN_LEN)) {
1132 SILC_LOG_DEBUG(("Received incorrect packet, dropped"));
1133 silc_buffer_clear(sock->inbuf);
1137 /* Decrypt a packet coming from server connection */
1138 if (sock->type == SILC_SOCKET_TYPE_SERVER ||
1139 sock->type == SILC_SOCKET_TYPE_ROUTER) {
1140 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1141 SilcClientInternalPacket *packet;
1145 mac_len = win->hmac->hash->hash->hash_len;
1147 if (sock->inbuf->len - 2 > (paddedlen + mac_len)) {
1148 /* Received possibly many packets at once */
1150 while(sock->inbuf->len > 0) {
1151 SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
1152 if (sock->inbuf->len < paddedlen) {
1153 SILC_LOG_DEBUG(("Received incorrect packet, dropped"));
1158 packet = silc_calloc(1, sizeof(*packet));
1159 packet->client = client;
1160 packet->sock = sock;
1161 packet->packetdata = silc_calloc(1, sizeof(*packet->packetdata));
1162 packet->packetdata->buffer = silc_buffer_alloc(paddedlen + mac_len);
1163 silc_buffer_pull_tail(packet->packetdata->buffer,
1164 SILC_BUFFER_END(packet->packetdata->buffer));
1165 silc_buffer_put(packet->packetdata->buffer, sock->inbuf->data,
1166 paddedlen + mac_len);
1168 SILC_LOG_HEXDUMP(("Incoming packet, len %d",
1169 packet->packetdata->buffer->len),
1170 packet->packetdata->buffer->data,
1171 packet->packetdata->buffer->len);
1172 SILC_LOG_DEBUG(("Packet from server %s, "
1173 "server type %d, packet length %d",
1174 win->remote_host, win->remote_type, paddedlen));
1176 /* If this packet is for the current active connection we will
1177 parse the packet right away to get it quickly on the screen.
1178 Otherwise, it will be parsed with a timeout as the data is
1179 for inactive window (which might not be visible at all). */
1180 if (SILC_CLIENT_IS_CURRENT_WIN(client, win)) {
1181 /* Parse it real soon */
1182 silc_task_register(client->timeout_queue, fd,
1183 silc_client_packet_parse,
1184 (void *)packet, 0, 1,
1186 SILC_TASK_PRI_NORMAL);
1188 /* Parse the packet with timeout */
1189 silc_task_register(client->timeout_queue, fd,
1190 silc_client_packet_parse,
1191 (void *)packet, 0, 200000,
1193 SILC_TASK_PRI_NORMAL);
1196 /* Pull the packet from inbuf thus we'll get the next one
1198 silc_buffer_pull(sock->inbuf, paddedlen);
1200 silc_buffer_pull(sock->inbuf, mac_len);
1202 silc_buffer_clear(sock->inbuf);
1205 /* Received one packet */
1207 SILC_LOG_HEXDUMP(("An incoming packet, len %d", sock->inbuf->len),
1208 sock->inbuf->data, sock->inbuf->len);
1209 SILC_LOG_DEBUG(("Packet from server %s, "
1210 "server type %d, packet length %d",
1211 win->remote_host, win->remote_type, paddedlen));
1213 packet = silc_calloc(1, sizeof(*packet));
1214 packet->client = client;
1215 packet->sock = sock;
1216 packet->packetdata = silc_calloc(1, sizeof(*packet->packetdata));
1217 packet->packetdata->buffer = silc_buffer_copy(sock->inbuf);
1218 silc_buffer_clear(sock->inbuf);
1220 /* If this packet is for the current active connection we will
1221 parse the packet right away to get it quickly on the screen.
1222 Otherwise, it will be parsed with a timeout as the data is
1223 for inactive window (which might not be visible at all). */
1224 if (SILC_CLIENT_IS_CURRENT_WIN(client, win)) {
1225 /* Parse it real soon */
1226 silc_task_register(client->timeout_queue, fd,
1227 silc_client_packet_parse,
1228 (void *)packet, 0, 1,
1230 SILC_TASK_PRI_NORMAL);
1233 /* Parse the packet with timeout */
1234 silc_task_register(client->timeout_queue, fd,
1235 silc_client_packet_parse,
1236 (void *)packet, 0, 200000,
1238 SILC_TASK_PRI_NORMAL);
1245 SILC_LOG_ERROR(("Weird, nothing happened - ignoring"));
1248 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
1249 after packet has been totally decrypted and parsed. */
1251 static int silc_client_packet_check_mac(SilcClient client,
1252 SilcSocketConnection sock,
1255 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1259 int headlen = buffer->data - buffer->head, mac_len;
1260 unsigned char *packet_mac, mac[32];
1262 SILC_LOG_DEBUG(("Verifying MAC"));
1264 mac_len = win->hmac->hash->hash->hash_len;
1266 silc_buffer_push(buffer, headlen);
1268 /* Take mac from packet */
1269 packet_mac = buffer->tail;
1271 /* Make MAC and compare */
1272 memset(mac, 0, sizeof(mac));
1273 silc_hmac_make_with_key(win->hmac,
1274 buffer->data, buffer->len,
1275 win->hmac_key, win->hmac_key_len, mac);
1277 SILC_LOG_HEXDUMP(("PMAC"), packet_mac, mac_len);
1278 SILC_LOG_HEXDUMP(("CMAC"), mac, mac_len);
1280 if (memcmp(mac, packet_mac, mac_len)) {
1281 SILC_LOG_DEBUG(("MAC failed"));
1285 SILC_LOG_DEBUG(("MAC is Ok"));
1286 memset(mac, 0, sizeof(mac));
1288 silc_buffer_pull(buffer, headlen);
1294 /* Decrypts rest of the packet (after decrypting just the SILC header).
1295 After calling this function the packet is ready to be parsed by calling
1296 silc_packet_parse. */
1298 static int silc_client_packet_decrypt_rest(SilcClient client,
1299 SilcSocketConnection sock,
1302 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1303 unsigned int mac_len = 0;
1306 if (win && win->receive_key) {
1308 /* Pull MAC from packet before decryption */
1310 mac_len = win->hmac->hash->hash->hash_len;
1311 if ((buffer->len - mac_len) > SILC_PACKET_MIN_LEN) {
1312 silc_buffer_push_tail(buffer, mac_len);
1314 SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
1319 SILC_LOG_DEBUG(("Decrypting rest of the packet"));
1321 /* Decrypt rest of the packet */
1322 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
1323 silc_packet_decrypt(win->receive_key, buffer, buffer->len);
1324 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
1326 SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
1327 buffer->data, buffer->len);
1333 /* Decrypts rest of the SILC Packet header that has been decrypted partly
1334 already. This decrypts the padding of the packet also. After calling
1335 this function the packet is ready to be parsed by calling function
1336 silc_packet_parse. This is used in special packet reception. */
1338 static int silc_client_packet_decrypt_rest_special(SilcClient client,
1339 SilcSocketConnection sock,
1342 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1343 unsigned int mac_len = 0;
1345 /* Decrypt rest of the header plus padding */
1346 if (win && win->receive_key) {
1347 unsigned short truelen, len1, len2, padlen;
1349 /* Pull MAC from packet before decryption */
1351 mac_len = win->hmac->hash->hash->hash_len;
1352 if ((buffer->len - mac_len) > SILC_PACKET_MIN_LEN) {
1353 silc_buffer_push_tail(buffer, mac_len);
1355 SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
1360 SILC_LOG_DEBUG(("Decrypting rest of the header"));
1362 SILC_GET16_MSB(len1, &buffer->data[4]);
1363 SILC_GET16_MSB(len2, &buffer->data[6]);
1365 truelen = SILC_PACKET_HEADER_LEN + len1 + len2;
1366 padlen = SILC_PACKET_PADLEN(truelen);
1367 len1 = (truelen + padlen) - (SILC_PACKET_MIN_HEADER_LEN - 2);
1369 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
1370 SILC_LOG_HEXDUMP(("XXX"), buffer->data, buffer->len);
1371 silc_packet_decrypt(win->receive_key, buffer, len1);
1372 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
1373 SILC_LOG_HEXDUMP(("XXX"), buffer->data, buffer->len);
1379 /* Parses whole packet, received earlier. */
1381 SILC_TASK_CALLBACK(silc_client_packet_parse)
1383 SilcClientInternalPacket *packet = (SilcClientInternalPacket *)context;
1384 SilcBuffer buffer = packet->packetdata->buffer;
1385 SilcClient client = packet->client;
1386 SilcSocketConnection sock = packet->sock;
1387 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1390 SILC_LOG_DEBUG(("Start"));
1392 /* Decrypt start of the packet header */
1393 if (win && win->receive_key)
1394 silc_packet_decrypt(win->receive_key, buffer, SILC_PACKET_MIN_HEADER_LEN);
1396 /* If the packet type is not any special type lets decrypt rest
1397 of the packet here. */
1398 if (buffer->data[3] != SILC_PACKET_CHANNEL_MESSAGE &&
1399 buffer->data[3] != SILC_PACKET_PRIVATE_MESSAGE) {
1401 /* Normal packet, decrypt rest of the packet */
1402 if (!silc_client_packet_decrypt_rest(client, sock, buffer))
1405 /* Parse the packet. Packet type is returned. */
1406 ret = silc_packet_parse(packet->packetdata);
1407 if (ret == SILC_PACKET_NONE)
1411 if (!silc_client_packet_check_mac(client, sock, buffer))
1414 /* If private message key is not set for private message it is
1415 handled as normal packet. Go back up. */
1416 if (buffer->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
1417 !(buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
1420 /* Packet requires special handling, decrypt rest of the header.
1421 This only decrypts. This does not do any MAC checking, it must
1422 be done individually later when doing the special processing. */
1423 silc_client_packet_decrypt_rest_special(client, sock, buffer);
1425 /* Parse the packet header in special way as this is "special"
1427 ret = silc_packet_parse_special(packet->packetdata);
1428 if (ret == SILC_PACKET_NONE)
1432 /* Parse the incoming packet type */
1433 silc_client_packet_parse_type(client, sock, packet->packetdata);
1436 silc_buffer_clear(packet->packetdata->buffer);
1437 silc_free(packet->packetdata);
1441 /* Parses the packet type and calls what ever routines the packet type
1442 requires. This is done for all incoming packets. */
1444 void silc_client_packet_parse_type(SilcClient client,
1445 SilcSocketConnection sock,
1446 SilcPacketContext *packet)
1448 SilcBuffer buffer = packet->buffer;
1449 SilcPacketType type = packet->type;
1451 SILC_LOG_DEBUG(("Parsing packet type %d", type));
1453 /* Parse the packet type */
1455 case SILC_PACKET_DISCONNECT:
1456 silc_client_disconnected_by_server(client, sock, buffer);
1458 case SILC_PACKET_SUCCESS:
1460 * Success received for something. For now we can have only
1461 * one protocol for connection executing at once hence this
1462 * success message is for whatever protocol is executing currently.
1464 if (sock->protocol) {
1465 sock->protocol->execute(client->timeout_queue, 0,
1466 sock->protocol, sock->sock, 0, 0);
1469 case SILC_PACKET_FAILURE:
1471 * Failure received for some protocol. Set the protocol state to
1472 * error and call the protocol callback. This fill cause error on
1473 * protocol and it will call the final callback.
1475 if (sock->protocol) {
1476 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1477 sock->protocol->execute(client->timeout_queue, 0,
1478 sock->protocol, sock->sock, 0, 0);
1481 case SILC_PACKET_REJECT:
1484 case SILC_PACKET_NOTIFY:
1486 * Received notify message
1488 silc_client_notify_by_server(client, sock, buffer);
1491 case SILC_PACKET_ERROR:
1493 * Received error message
1495 silc_client_error_by_server(client, sock, buffer);
1498 case SILC_PACKET_CHANNEL_MESSAGE:
1500 * Received message to (from, actually) a channel
1502 silc_client_channel_message(client, sock, packet);
1504 case SILC_PACKET_CHANNEL_KEY:
1506 * Received key for a channel. By receiving this key the client will be
1507 * able to talk to the channel it has just joined. This can also be
1508 * a new key for existing channel as keys expire peridiocally.
1510 silc_client_receive_channel_key(client, sock, buffer);
1513 case SILC_PACKET_PRIVATE_MESSAGE:
1515 * Received private message
1518 SilcClientCommandReplyContext ctx;
1519 ctx = silc_calloc(1, sizeof(*ctx));
1520 ctx->client = client;
1522 ctx->context = buffer; /* kludge */
1523 silc_client_command_reply_msg((void *)ctx);
1526 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1528 * Received private message key
1532 case SILC_PACKET_COMMAND_REPLY:
1534 * Recived reply for a command
1536 silc_client_command_reply_process(client, sock, packet);
1539 case SILC_PACKET_KEY_EXCHANGE:
1540 if (sock->protocol) {
1541 SilcClientKEInternalContext *proto_ctx =
1542 (SilcClientKEInternalContext *)sock->protocol->context;
1544 proto_ctx->packet = buffer;
1545 proto_ctx->dest_id_type = packet->src_id_type;
1546 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
1548 /* Let the protocol handle the packet */
1549 sock->protocol->execute(client->timeout_queue, 0,
1550 sock->protocol, sock->sock, 0, 0);
1552 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1553 "protocol active, packet dropped."));
1555 /* XXX Trigger KE protocol?? Rekey actually! */
1559 case SILC_PACKET_KEY_EXCHANGE_1:
1560 if (sock->protocol) {
1563 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1564 "protocol active, packet dropped."));
1567 case SILC_PACKET_KEY_EXCHANGE_2:
1568 if (sock->protocol) {
1569 SilcClientKEInternalContext *proto_ctx =
1570 (SilcClientKEInternalContext *)sock->protocol->context;
1572 if (proto_ctx->packet)
1573 silc_buffer_free(proto_ctx->packet);
1575 proto_ctx->packet = buffer;
1576 proto_ctx->dest_id_type = packet->src_id_type;
1577 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
1579 /* Let the protocol handle the packet */
1580 sock->protocol->execute(client->timeout_queue, 0,
1581 sock->protocol, sock->sock, 0, 0);
1583 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1584 "protocol active, packet dropped."));
1588 case SILC_PACKET_NEW_ID:
1591 * Received new ID from server. This packet is received at
1592 * the connection to the server. New ID is also received when
1593 * user changes nickname but in that case the new ID is received
1594 * as command reply and not as this packet type.
1596 unsigned char *id_string;
1597 unsigned short id_type;
1599 silc_buffer_unformat(buffer,
1600 SILC_STR_UI_SHORT(&id_type),
1601 SILC_STR_UI16_STRING_ALLOC(&id_string),
1604 if ((SilcIdType)id_type != SILC_ID_CLIENT)
1607 silc_client_receive_new_id(client, sock, id_string);
1608 silc_free(id_string);
1613 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1618 /* Internal routine that sends packet or marks packet to be sent. This
1619 is used directly only in special cases. Normal cases should use
1620 silc_server_packet_send. Returns < 0 on error. */
1622 static int silc_client_packet_send_real(SilcClient client,
1623 SilcSocketConnection sock,
1626 /* Send now if forced to do so */
1627 if (force_send == TRUE) {
1629 SILC_LOG_DEBUG(("Forcing packet send, packet sent immediately"));
1630 ret = silc_packet_write(sock->sock, sock->outbuf);
1633 SILC_LOG_ERROR(("Packet dropped"));
1637 SILC_LOG_DEBUG(("Could not force the send, packet put to queue"));
1640 SILC_LOG_DEBUG(("Packet in queue"));
1642 /* Mark that there is some outgoing data available for this connection.
1643 This call sets the connection both for input and output (the input
1644 is set always and this call keeps the input setting, actually).
1645 Actual data sending is performed by silc_client_packet_process. */
1646 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
1648 /* Mark to socket that data is pending in outgoing buffer. This flag
1649 is needed if new data is added to the buffer before the earlier
1650 put data is sent to the network. */
1651 SILC_SET_OUTBUF_PENDING(sock);
1656 /* Prepare outgoing data buffer for packet sending. */
1658 static void silc_client_packet_send_prepare(SilcClient client,
1659 SilcSocketConnection sock,
1660 unsigned int header_len,
1661 unsigned int padlen,
1662 unsigned int data_len)
1666 totlen = header_len + padlen + data_len;
1668 /* Prepare the outgoing buffer for packet sending. */
1669 if (!sock->outbuf) {
1670 /* Allocate new buffer. This is done only once per connection. */
1671 SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
1673 sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
1674 silc_buffer_pull_tail(sock->outbuf, totlen);
1675 silc_buffer_pull(sock->outbuf, header_len + padlen);
1677 if (SILC_IS_OUTBUF_PENDING(sock)) {
1678 /* There is some pending data in the buffer. */
1680 if ((sock->outbuf->end - sock->outbuf->tail) < data_len) {
1681 SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
1682 /* XXX: not done yet */
1684 oldlen = sock->outbuf->len;
1685 silc_buffer_pull_tail(sock->outbuf, totlen);
1686 silc_buffer_pull(sock->outbuf, header_len + padlen + oldlen);
1688 /* Buffer is free for use */
1689 silc_buffer_clear(sock->outbuf);
1690 silc_buffer_pull_tail(sock->outbuf, totlen);
1691 silc_buffer_pull(sock->outbuf, header_len + padlen);
1696 /* Sends packet. This doesn't actually send the packet instead it assembles
1697 it and marks it to be sent. However, if force_send is TRUE the packet
1698 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1699 will be derived from sock argument. Otherwise the valid arguments sent
1702 void silc_client_packet_send(SilcClient client,
1703 SilcSocketConnection sock,
1704 SilcPacketType type,
1706 SilcIdType dst_id_type,
1709 unsigned char *data,
1710 unsigned int data_len,
1713 SilcPacketContext packetdata;
1714 unsigned char *hmac_key = NULL;
1715 unsigned int hmac_key_len = 0;
1716 unsigned char mac[32];
1717 unsigned int mac_len = 0;
1719 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1721 /* Get data used in the packet sending, keys and stuff */
1722 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1723 if (!cipher && ((SilcClientWindow)sock->user_data)->send_key)
1724 cipher = ((SilcClientWindow)sock->user_data)->send_key;
1725 if (!hmac && ((SilcClientWindow)sock->user_data)->hmac) {
1726 hmac = ((SilcClientWindow)sock->user_data)->hmac;
1727 mac_len = hmac->hash->hash->hash_len;
1728 hmac_key = ((SilcClientWindow)sock->user_data)->hmac_key;
1729 hmac_key_len = ((SilcClientWindow)sock->user_data)->hmac_key_len;
1731 if (!dst_id && ((SilcClientWindow)sock->user_data)->remote_id) {
1732 dst_id = ((SilcClientWindow)sock->user_data)->remote_id;
1733 dst_id_type = SILC_ID_SERVER;
1737 /* Set the packet context pointers */
1738 packetdata.flags = 0;
1739 packetdata.type = type;
1740 if (((SilcClientWindow)sock->user_data)->local_id_data)
1741 packetdata.src_id = ((SilcClientWindow)sock->user_data)->local_id_data;
1743 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1744 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1745 packetdata.src_id_type = SILC_ID_CLIENT;
1747 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1748 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
1749 packetdata.dst_id_type = dst_id_type;
1751 packetdata.dst_id = NULL;
1752 packetdata.dst_id_len = 0;
1753 packetdata.dst_id_type = SILC_ID_NONE;
1755 packetdata.rng = client->rng;
1756 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1757 packetdata.src_id_len + packetdata.dst_id_len;
1758 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1760 /* Prepare outgoing data buffer for packet sending */
1761 silc_client_packet_send_prepare(client, sock,
1762 SILC_PACKET_HEADER_LEN +
1763 packetdata.src_id_len +
1764 packetdata.dst_id_len,
1768 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1770 packetdata.buffer = sock->outbuf;
1772 /* Put the data to the buffer */
1773 if (data && data_len)
1774 silc_buffer_put(sock->outbuf, data, data_len);
1776 /* Create the outgoing packet */
1777 silc_packet_assemble(&packetdata);
1779 /* Compute MAC of the packet */
1781 silc_hmac_make_with_key(hmac, sock->outbuf->data, sock->outbuf->len,
1782 hmac_key, hmac_key_len, mac);
1783 silc_buffer_put_tail(sock->outbuf, mac, mac_len);
1784 memset(mac, 0, sizeof(mac));
1787 /* Encrypt the packet */
1789 silc_packet_encrypt(cipher, sock->outbuf, sock->outbuf->len);
1791 /* Pull MAC into the visible data area */
1793 silc_buffer_pull_tail(sock->outbuf, mac_len);
1795 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1796 sock->outbuf->data, sock->outbuf->len);
1798 /* Now actually send the packet */
1799 silc_client_packet_send_real(client, sock, force_send);
1802 /* Sends packet to a channel. Packet to channel is always encrypted
1803 differently from "normal" packets. SILC header of the packet is
1804 encrypted with the next receiver's key and the rest of the packet is
1805 encrypted with the channel specific key. Padding and HMAC is computed
1806 with the next receiver's key. */
1808 void silc_client_packet_send_to_channel(SilcClient client,
1809 SilcSocketConnection sock,
1810 SilcChannelEntry channel,
1811 unsigned char *data,
1812 unsigned int data_len,
1816 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1818 SilcPacketContext packetdata;
1819 unsigned char *hmac_key = NULL;
1820 unsigned int hmac_key_len = 0;
1821 unsigned char mac[32];
1822 unsigned int mac_len = 0;
1823 unsigned char *id_string;
1827 SILC_LOG_DEBUG(("Sending packet to channel"));
1829 if (!channel || !channel->key) {
1830 silc_say(client, "Cannot talk to channel: key does not exist");
1836 for (i = 0; i < 16; i++)
1837 channel->iv[i] = silc_rng_get_byte(client->rng);
1839 silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
1841 /* Encode the channel payload */
1842 payload = silc_channel_encode_payload(strlen(win->nickname), win->nickname,
1843 data_len, data, 16, channel->iv,
1847 "Error: Could not create packet to be sent to the channel");
1851 /* Get data used in packet header encryption, keys and stuff. Rest
1852 of the packet (the payload) is, however, encrypted with the
1853 specified channel key. */
1854 cipher = win->send_key;
1856 mac_len = hmac->hash->hash->hash_len;
1857 hmac_key = win->hmac_key;
1858 hmac_key_len = win->hmac_key_len;
1859 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1861 /* Set the packet context pointers. The destination ID is always
1862 the Channel ID of the channel. Server and router will handle the
1863 distribution of the packet. */
1864 packetdata.flags = 0;
1865 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1866 packetdata.src_id = win->local_id_data;
1867 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1868 packetdata.src_id_type = SILC_ID_CLIENT;
1869 packetdata.dst_id = id_string;
1870 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1871 packetdata.dst_id_type = SILC_ID_CHANNEL;
1872 packetdata.rng = client->rng;
1873 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
1874 packetdata.src_id_len + packetdata.dst_id_len;
1875 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1876 packetdata.src_id_len +
1877 packetdata.dst_id_len));
1879 /* Prepare outgoing data buffer for packet sending */
1880 silc_client_packet_send_prepare(client, sock,
1881 SILC_PACKET_HEADER_LEN +
1882 packetdata.src_id_len +
1883 packetdata.dst_id_len,
1887 packetdata.buffer = sock->outbuf;
1889 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1890 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1891 payload->data, payload->data,
1892 payload->len - 16, /* -IV_LEN */
1895 SILC_LOG_HEXDUMP(("XXX"), payload->data, payload->len);
1897 /* Put the actual encrypted payload data into the buffer. */
1898 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1900 /* Create the outgoing packet */
1901 silc_packet_assemble(&packetdata);
1903 /* Compute MAC of the packet */
1904 silc_hmac_make_with_key(hmac, sock->outbuf->data, sock->outbuf->len,
1905 hmac_key, hmac_key_len, mac);
1906 silc_buffer_put_tail(sock->outbuf, mac, mac_len);
1907 memset(mac, 0, sizeof(mac));
1909 SILC_LOG_HEXDUMP(("XXX"), sock->outbuf->data, sock->outbuf->len);
1911 /* Encrypt the header and padding of the packet. This is encrypted
1912 with normal session key shared with our server. */
1913 silc_packet_encrypt(cipher, sock->outbuf, SILC_PACKET_HEADER_LEN +
1914 packetdata.src_id_len + packetdata.dst_id_len +
1917 /* Pull MAC into the visible data area */
1918 silc_buffer_pull_tail(sock->outbuf, mac_len);
1920 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1921 sock->outbuf->data, sock->outbuf->len);
1923 /* Now actually send the packet */
1924 silc_client_packet_send_real(client, sock, force_send);
1925 silc_buffer_free(payload);
1926 silc_free(id_string);
1929 /* Sends private message to remote client. If private message key has
1930 not been set with this client then the message will be encrypted using
1931 normal session keys. Private messages are special packets in SILC
1932 network hence we need this own function for them. This is similiar
1933 to silc_client_packet_send_to_channel except that we send private
1936 void silc_client_packet_send_private_message(SilcClient client,
1937 SilcSocketConnection sock,
1938 SilcClientEntry client_entry,
1939 unsigned char *data,
1940 unsigned int data_len,
1943 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1945 SilcPacketContext packetdata;
1946 unsigned char *hmac_key = NULL;
1947 unsigned int hmac_key_len = 0;
1948 unsigned char mac[32];
1949 unsigned int mac_len = 0;
1950 unsigned int nick_len;
1954 SILC_LOG_DEBUG(("Sending private message"));
1956 /* Create private message payload */
1957 nick_len = strlen(client->current_win->nickname);
1958 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1959 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1960 silc_buffer_format(buffer,
1961 SILC_STR_UI_SHORT(nick_len),
1962 SILC_STR_UI_XNSTRING(client->current_win->nickname,
1964 SILC_STR_UI_XNSTRING(data, data_len),
1967 /* If we don't have private message specific key then private messages
1968 are just as any normal packet thus call normal packet sending. If
1969 the key exist then the encryption process is a bit different and
1970 will be done in the rest of this function. */
1971 if (!client_entry->send_key) {
1972 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1973 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1974 buffer->data, buffer->len, force_send);
1978 /* We have private message specific key */
1980 /* Get data used in the encryption */
1981 cipher = client_entry->send_key;
1983 mac_len = hmac->hash->hash->hash_len;
1984 hmac_key = win->hmac_key;
1985 hmac_key_len = win->hmac_key_len;
1987 /* Set the packet context pointers. */
1988 packetdata.flags = 0;
1989 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1990 packetdata.src_id = win->local_id_data;
1991 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1992 packetdata.src_id_type = SILC_ID_CLIENT;
1994 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1996 packetdata.dst_id = win->local_id_data;
1997 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1998 packetdata.dst_id_type = SILC_ID_CLIENT;
1999 packetdata.rng = client->rng;
2000 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
2001 packetdata.src_id_len + packetdata.dst_id_len;
2002 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
2003 packetdata.src_id_len +
2004 packetdata.dst_id_len));
2006 /* Prepare outgoing data buffer for packet sending */
2007 silc_client_packet_send_prepare(client, sock,
2008 SILC_PACKET_HEADER_LEN +
2009 packetdata.src_id_len +
2010 packetdata.dst_id_len,
2014 packetdata.buffer = sock->outbuf;
2016 /* Encrypt payload of the packet. Encrypt with private message specific
2017 key if it exist, otherwise with session key. */
2018 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
2019 buffer->len, cipher->iv);
2021 /* Put the actual encrypted payload data into the buffer. */
2022 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
2024 /* Create the outgoing packet */
2025 silc_packet_assemble(&packetdata);
2027 /* Compute MAC of the packet */
2028 silc_hmac_make_with_key(hmac, sock->outbuf->data, sock->outbuf->len,
2029 hmac_key, hmac_key_len, mac);
2030 silc_buffer_put_tail(sock->outbuf, mac, mac_len);
2031 memset(mac, 0, sizeof(mac));
2033 SILC_LOG_HEXDUMP(("XXX"), sock->outbuf->data, sock->outbuf->len);
2035 /* Encrypt the header and padding of the packet. */
2036 silc_packet_encrypt(cipher, sock->outbuf, SILC_PACKET_HEADER_LEN +
2037 packetdata.src_id_len + packetdata.dst_id_len +
2040 /* Pull MAC into the visible data area */
2041 silc_buffer_pull_tail(sock->outbuf, mac_len);
2043 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
2044 sock->outbuf->data, sock->outbuf->len);
2046 /* Now actually send the packet */
2047 silc_client_packet_send_real(client, sock, force_send);
2048 silc_free(packetdata.dst_id);
2054 /* Closes connection to remote end. Free's all allocated data except
2055 for some information such as nickname etc. that are valid at all time. */
2057 void silc_client_close_connection(SilcClient client,
2058 SilcSocketConnection sock)
2060 SilcClientWindow win;
2063 /* We won't listen for this connection anymore */
2064 silc_schedule_unset_listen_fd(sock->sock);
2066 /* Unregister all tasks */
2067 silc_task_unregister_by_fd(client->io_queue, sock->sock);
2068 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
2070 /* Close the actual connection */
2071 silc_net_close_connection(sock->sock);
2073 silc_say(client, "Closed connection to host %s", sock->hostname ?
2074 sock->hostname : sock->ip);
2076 /* Free everything */
2077 if (sock->user_data) {
2078 win = (SilcClientWindow)sock->user_data;
2080 /* Clear ID caches */
2081 for (i = 0; i < 96; i++)
2082 silc_idcache_del_all(&win->client_id_cache[i],
2083 win->client_id_cache_count[i]);
2084 for (i = 0; i < 96; i++)
2085 silc_idcache_del_all(&win->channel_id_cache[i],
2086 win->channel_id_cache_count[i]);
2089 if (win->remote_host)
2090 silc_free(win->remote_host);
2092 silc_free(win->local_id);
2093 if (win->local_id_data)
2094 silc_free(win->local_id_data);
2096 silc_cipher_free(win->send_key);
2097 if (win->receive_key)
2098 silc_cipher_free(win->receive_key);
2099 if (win->public_key)
2100 silc_pkcs_free(win->public_key);
2102 silc_hmac_free(win->hmac);
2103 if (win->hmac_key) {
2104 memset(win->hmac_key, 0, win->hmac_key_len);
2105 silc_free(win->hmac_key);
2109 win->remote_port = 0;
2110 win->remote_type = 0;
2111 win->send_key = NULL;
2112 win->receive_key = NULL;
2113 win->public_key = NULL;
2115 win->hmac_key = NULL;
2116 win->hmac_key_len = 0;
2117 win->local_id = NULL;
2118 win->local_id_data = NULL;
2119 win->remote_host = NULL;
2122 if (sock->protocol) {
2123 silc_protocol_free(sock->protocol);
2124 sock->protocol = NULL;
2126 silc_socket_free(sock);
2129 /* Called when we receive disconnection packet from server. This
2130 closes our end properly and displays the reason of the disconnection
2133 void silc_client_disconnected_by_server(SilcClient client,
2134 SilcSocketConnection sock,
2139 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
2141 msg = silc_calloc(message->len + 1, sizeof(char));
2142 memcpy(msg, message->data, message->len);
2143 silc_say(client, msg);
2146 SILC_SET_DISCONNECTED(sock);
2147 silc_client_close_connection(client, sock);
2150 /* Received error message from server. Display it on the screen.
2151 We don't take any action what so ever of the error message. */
2153 void silc_client_error_by_server(SilcClient client,
2154 SilcSocketConnection sock,
2159 msg = silc_calloc(message->len + 1, sizeof(char));
2160 memcpy(msg, message->data, message->len);
2161 silc_say(client, msg);
2165 /* Received notify message from server */
2167 void silc_client_notify_by_server(SilcClient client,
2168 SilcSocketConnection sock,
2173 msg = silc_calloc(message->len + 1, sizeof(char));
2174 memcpy(msg, message->data, message->len);
2175 silc_say(client, msg);
2179 /* Processes the received new Client ID from server. Old Client ID is
2180 deleted from cache and new one is added. */
2182 void silc_client_receive_new_id(SilcClient client,
2183 SilcSocketConnection sock,
2184 unsigned char *id_string)
2186 SilcClientWindow win = (SilcClientWindow)sock->user_data;
2187 char *nickname = win->nickname;
2189 #define CIDC(x) win->client_id_cache[(x) - 32]
2190 #define CIDCC(x) win->client_id_cache_count[(x) - 32]
2192 /* Delete old ID from ID cache */
2193 silc_idcache_del_by_id(CIDC(nickname[0]), CIDCC(nickname[0]),
2194 SILC_ID_CLIENT, win->local_id);
2196 /* Save the new ID */
2198 silc_free(win->local_id);
2199 win->local_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
2200 if (win->local_id_data)
2201 silc_free(win->local_id_data);
2202 win->local_id_data =
2203 silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
2204 memcpy(win->local_id_data, id_string, SILC_ID_CLIENT_LEN);
2205 win->local_id_data_len = SILC_ID_CLIENT_LEN;
2206 if (!win->local_entry)
2207 win->local_entry = silc_calloc(1, sizeof(*win->local_entry));
2208 win->local_entry->nickname = win->nickname;
2209 win->local_entry->id = win->local_id;
2211 /* Put it to the ID cache */
2212 CIDCC(nickname[0]) = silc_idcache_add(&CIDC(nickname[0]),
2214 win->nickname, SILC_ID_CLIENT,
2216 (void *)win->local_entry);
2221 /* Processed received Channel ID for a channel. This is called when client
2222 joins to channel and server replies with channel ID. The ID is cached. */
2224 void silc_client_new_channel_id(SilcClient client,
2225 SilcSocketConnection sock,
2228 unsigned char *id_string)
2230 SilcClientWindow win = (SilcClientWindow)sock->user_data;
2232 SilcChannelEntry channel;
2234 SILC_LOG_DEBUG(("New channel ID"));
2236 #define CIDC(x) win->channel_id_cache[(x) - 32]
2237 #define CIDCC(x) win->channel_id_cache_count[(x) - 32]
2239 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
2240 channel = silc_calloc(1, sizeof(*channel));
2241 channel->channel_name = channel_name;
2243 channel->mode = mode;
2244 win->current_channel = channel;
2246 /* Put it to the ID cache */
2247 CIDCC(channel_name[0]) = silc_idcache_add(&CIDC(channel_name[0]),
2248 CIDCC(channel_name[0]),
2249 channel_name, SILC_ID_CHANNEL,
2250 id, (void *)channel);
2255 /* Processes received key for channel. The received key will be used
2256 to protect the traffic on the channel for now on. Client must receive
2257 the key to the channel before talking on the channel is possible.
2258 This is the key that server has generated, this is not the channel
2259 private key, it is entirely local setting. */
2261 void silc_client_receive_channel_key(SilcClient client,
2262 SilcSocketConnection sock,
2266 unsigned char *id_string, *key, *cipher;
2267 unsigned int key_len;
2268 SilcClientWindow win = (SilcClientWindow)sock->user_data;
2270 SilcIDCache *id_cache = NULL;
2271 SilcChannelEntry channel;
2272 SilcChannelKeyPayload payload;
2274 SILC_LOG_DEBUG(("Received key for channel"));
2276 #define CIDC(x) win->channel_id_cache[(x)]
2277 #define CIDCC(x) win->channel_id_cache_count[(x)]
2279 payload = silc_channel_key_parse_payload(packet);
2283 id_string = silc_channel_key_get_id(payload, NULL);
2285 silc_channel_key_free_payload(payload);
2288 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
2290 /* Find channel. XXX: This is bad and slow. */
2291 for (i = 0; i < 96; i++) {
2292 if (CIDC(i) == NULL)
2294 if (silc_idcache_find_by_id(CIDC(i), CIDCC(i), (void *)id,
2295 SILC_ID_CHANNEL, &id_cache))
2303 key = silc_channel_key_get_key(payload, &key_len);
2304 cipher = silc_channel_key_get_cipher(payload, NULL);
2306 channel = (SilcChannelEntry)id_cache->context;
2307 channel->key_len = key_len;
2308 channel->key = silc_calloc(key_len, sizeof(*channel->key));
2309 memcpy(channel->key, key, key_len);
2311 silc_cipher_alloc(cipher, &channel->channel_key);
2312 if (!channel->channel_key) {
2313 silc_say(client, "Cannot talk to channel: unsupported cipher %s", cipher);
2316 channel->channel_key->cipher->set_key(channel->channel_key->context,
2319 /* Client is now joined to the channel */
2320 channel->on_channel = TRUE;
2324 silc_channel_key_free_payload(payload);
2329 /* Process received message to a channel (or from a channel, really). This
2330 decrypts the channel message with channel specific key and parses the
2331 channel payload. Finally it displays the message on the screen. */
2333 void silc_client_channel_message(SilcClient client,
2334 SilcSocketConnection sock,
2335 SilcPacketContext *packet)
2338 SilcClientWindow win = (SilcClientWindow)sock->user_data;
2339 SilcBuffer buffer = packet->buffer;
2340 SilcChannelPayload payload = NULL;
2341 SilcChannelID *id = NULL;
2342 SilcChannelEntry channel;
2343 SilcIDCache *id_cache = NULL;
2345 #define CIDC(x) win->channel_id_cache[(x)]
2346 #define CIDCC(x) win->channel_id_cache_count[(x)]
2349 if (packet->dst_id_type != SILC_ID_CHANNEL)
2352 id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
2354 /* Find the channel entry from channels on this window */
2355 for (i = 0; i < 96; i++) {
2356 if (CIDC(i) == NULL)
2358 if (silc_idcache_find_by_id(CIDC(i), CIDCC(i), (void *)id,
2359 SILC_ID_CHANNEL, &id_cache))
2366 channel = (SilcChannelEntry)id_cache->context;
2368 /* Decrypt the channel message payload. Push the IV out of the way,
2369 since it is not encrypted (after pushing buffer->tail has the IV). */
2370 silc_buffer_push_tail(buffer, 16);
2371 channel->channel_key->cipher->decrypt(channel->channel_key->context,
2372 buffer->data, buffer->data,
2373 buffer->len, buffer->tail);
2374 silc_buffer_pull_tail(buffer, 16);
2376 /* Parse the channel message payload */
2377 payload = silc_channel_parse_payload(buffer);
2381 /* Display the message on screen */
2382 if (packet->src_id_type == SILC_ID_CLIENT)
2383 /* Message from client */
2384 silc_print(client, "<%s> %s", silc_channel_get_nickname(payload, NULL),
2385 silc_channel_get_data(payload, NULL));
2387 /* Message from server */
2388 silc_say(client, "%s", silc_channel_get_data(payload, NULL));
2394 silc_channel_free_payload(payload);