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.5 2000/07/06 07:14:36 priikone
24 * Fixes to NAMES command handling.
25 * Fixes when leaving from channel.
27 * Revision 1.4 2000/07/05 06:12:05 priikone
28 * Global cosmetic changes.
30 * Revision 1.3 2000/07/04 08:29:12 priikone
31 * Added support for PING command. The ping times are calculated
32 * and showed to the user.
34 * Revision 1.2 2000/07/03 05:49:48 priikone
35 * Implemented LEAVE command. Minor bug fixes.
37 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
38 * Imported from internal CVS/Added Log headers.
43 #include "clientincludes.h"
45 /* Static function prototypes */
46 static int silc_client_bad_keys(unsigned char key);
47 static void silc_client_process_message(SilcClient client);
48 static char *silc_client_parse_command(unsigned char *buffer);
50 /* Static task callback prototypes */
51 SILC_TASK_CALLBACK(silc_client_update_clock);
52 SILC_TASK_CALLBACK(silc_client_run_commands);
53 SILC_TASK_CALLBACK(silc_client_process_key_press);
54 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
55 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
56 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
57 SILC_TASK_CALLBACK(silc_client_packet_process);
58 SILC_TASK_CALLBACK(silc_client_packet_parse);
60 SilcClientWindow silc_client_create_main_window(SilcClient client);
61 SilcClientWindow silc_client_add_window(SilcClient client,
63 void silc_client_packet_parse_type(SilcClient client,
64 SilcSocketConnection sock,
65 SilcPacketContext *packet);
66 void silc_client_private_message_process(SilcClient client,
67 SilcSocketConnection sock,
68 SilcPacketContext *packet);
70 /* Definitions from version.h */
71 extern char *silc_version;
72 extern char *silc_name;
73 extern char *silc_fullname;
75 /* Allocates new client object. This has to be done before client may
76 work. After calling this one must call silc_client_init to initialize
79 int silc_client_alloc(SilcClient *new_client)
82 *new_client = silc_calloc(1, sizeof(**new_client));
83 (*new_client)->input_buffer = NULL;
84 (*new_client)->screen = NULL;
85 (*new_client)->windows = NULL;
86 (*new_client)->windows_count = 0;
87 (*new_client)->current_win = NULL;
92 /* Free's client object */
94 void silc_client_free(SilcClient client)
101 /* Initializes the client. This makes all the necessary steps to make
102 the client ready to be run. One must call silc_client_run to run the
105 int silc_client_init(SilcClient client)
108 SILC_LOG_DEBUG(("Initializing client"));
111 client->username = silc_get_username();
112 client->realname = silc_get_real_name();
114 /* Register all configured ciphers, PKCS and hash functions. */
115 client->config->client = (void *)client;
116 silc_client_config_register_ciphers(client->config);
117 silc_client_config_register_pkcs(client->config);
118 silc_client_config_register_hashfuncs(client->config);
120 /* Initialize hash functions for client to use */
121 silc_hash_alloc("md5", &client->md5hash);
122 silc_hash_alloc("sha1", &client->sha1hash);
124 /* Initialize none cipher */
125 silc_cipher_alloc("none", &client->none_cipher);
127 /* Initialize random number generator */
128 client->rng = silc_rng_alloc();
129 silc_rng_init(client->rng);
130 silc_math_primegen_init(); /* XXX */
132 /* Load public and private key */
133 if (silc_client_load_keys(client) == FALSE)
136 /* Register the task queues. In SILC we have by default three task queues.
137 One task queue for non-timeout tasks which perform different kind of
138 I/O on file descriptors, timeout task queue for timeout tasks, and,
139 generic non-timeout task queue whose tasks apply to all connections. */
140 silc_task_queue_alloc(&client->io_queue, TRUE);
141 if (!client->io_queue) {
144 silc_task_queue_alloc(&client->timeout_queue, TRUE);
145 if (!client->timeout_queue) {
148 silc_task_queue_alloc(&client->generic_queue, TRUE);
149 if (!client->generic_queue) {
153 /* Initialize the scheduler */
154 silc_schedule_init(client->io_queue, client->timeout_queue,
155 client->generic_queue, 5000);
157 /* Register the main task that is used in client. This received
158 the key pressings. */
159 if (silc_task_register(client->io_queue, fileno(stdin),
160 silc_client_process_key_press,
161 (void *)client, 0, 0,
163 SILC_TASK_PRI_NORMAL) == NULL) {
167 /* Register timeout task that updates clock every minute. */
168 if (silc_task_register(client->timeout_queue, 0,
169 silc_client_update_clock,
171 silc_client_time_til_next_min(), 0,
173 SILC_TASK_PRI_LOW) == NULL) {
177 if (client->config->commands) {
178 /* Run user configured commands with timeout */
179 if (silc_task_register(client->timeout_queue, 0,
180 silc_client_run_commands,
181 (void *)client, 0, 1,
183 SILC_TASK_PRI_LOW) == NULL) {
188 /* Allocate the input buffer used to save typed characters */
189 client->input_buffer = silc_buffer_alloc(SILC_SCREEN_INPUT_WIN_SIZE);
190 silc_buffer_pull_tail(client->input_buffer,
191 SILC_BUFFER_END(client->input_buffer));
193 /* Initialize the screen */
194 client->screen = silc_screen_init();
195 silc_client_create_main_window(client);
196 client->screen->input_buffer = client->input_buffer->data;
197 silc_screen_print_coordinates(client->screen, 0);
202 silc_task_queue_free(client->timeout_queue);
204 silc_task_queue_free(client->io_queue);
209 /* Stops the client. This is called to stop the client and thus to stop
212 void silc_client_stop(SilcClient client)
214 SILC_LOG_DEBUG(("Stopping client"));
216 /* Stop the scheduler, although it might be already stopped. This
217 doesn't hurt anyone. This removes all the tasks and task queues,
219 silc_schedule_stop();
220 silc_schedule_uninit();
222 SILC_LOG_DEBUG(("Client client"));
225 /* Runs the client. */
227 void silc_client_run(SilcClient client)
229 SILC_LOG_DEBUG(("Running client"));
231 /* Start the scheduler, the heart of the SILC client. When this returns
232 the program will be terminated. */
236 /* Creates the main window used in SILC client. This is called always
237 at the initialization of the client. If user wants to create more
238 than one windows a new windows are always created by calling
239 silc_client_add_window. */
241 SilcClientWindow silc_client_create_main_window(SilcClient client)
243 SilcClientWindow win;
246 SILC_LOG_DEBUG(("Creating main window"));
248 assert(client->screen != NULL);
250 win = silc_calloc(1, sizeof(*win));
252 client->screen->u_stat_line.program_name = silc_name;
253 client->screen->u_stat_line.program_version = silc_version;
255 /* Add the pointers */
256 win->nickname = silc_get_username();
257 win->local_id = NULL;
258 win->local_id_data = NULL;
259 win->local_id_data_len = 0;
260 win->remote_host = NULL;
261 win->remote_port = -1;
264 /* Create the actual screen */
265 screen = (void *)silc_screen_create_output_window(client->screen);
266 silc_screen_create_input_window(client->screen);
267 silc_screen_init_upper_status_line(client->screen);
268 silc_screen_init_output_status_line(client->screen);
269 win->screen = screen;
271 client->screen->bottom_line->nickname = win->nickname;
272 silc_screen_print_bottom_line(client->screen, 0);
274 /* Add the window to windows table */
275 client->windows = silc_calloc(1, sizeof(*client->windows));
276 client->windows[client->windows_count] = win;
277 client->windows_count = 1;
279 /* Automatically becomes the current active window */
280 client->current_win = win;
285 /* Allocates and adds new window to the client. This allocates new
286 physical window and internal window for connection specific data.
287 All the connection specific data is always saved into a window
288 since connection is always associated to a active window. */
290 SilcClientWindow silc_client_add_window(SilcClient client,
293 SilcClientWindow win;
295 assert(client->screen != NULL);
297 win = silc_calloc(1, sizeof(*win));
299 /* Add the pointers */
300 win->screen = silc_screen_add_output_window(client->screen);
303 /* Add the window to windows table */
304 client->windows = silc_realloc(client->windows, sizeof(*client->windows)
305 * (client->windows_count + 1));
306 client->windows[client->windows_count] = win;
307 client->windows_count++;
309 if (is_current == TRUE)
310 client->current_win = win;
315 /* The main task on SILC client. This processes the key pressings user
318 SILC_TASK_CALLBACK(silc_client_process_key_press)
320 SilcClient client = (SilcClient)context;
323 /* There is data pending in stdin, this gets it directly */
324 c = wgetch(client->screen->input_win);
325 if (silc_client_bad_keys(c))
328 SILC_LOG_DEBUG(("Pressed key: %d", c));
332 * Special character handling
339 SILC_LOG_DEBUG(("RIGHT"));
340 silc_screen_input_cursor_right(client->screen);
344 SILC_LOG_DEBUG(("LEFT"));
345 silc_screen_input_cursor_left(client->screen);
352 silc_screen_input_backspace(client->screen);
358 /* Insert switch. Turns on/off insert on input window */
359 silc_screen_input_insert(client->screen);
363 /* Enter, Return. User pressed enter we are ready to
364 process the message. */
365 silc_client_process_message(client);
366 silc_screen_input_reset(client->screen);
369 /* Refresh screen, Ctrl^l */
370 silc_screen_refresh_all(client->screen);
375 /* Beginning, Home */
376 silc_screen_input_cursor_home(client->screen);
381 silc_screen_input_cursor_end(client->screen);
399 /* Control codes are printed as reversed */
401 wattron(client->screen->input_win, A_REVERSE);
402 silc_screen_input_print(client->screen, c);
403 wattroff(client->screen->input_win, A_REVERSE);
405 /* Normal character */
406 silc_screen_input_print(client->screen, c);
410 silc_screen_print_coordinates(client->screen, 0);
411 silc_screen_refresh_win(client->screen->input_win);
414 static int silc_client_bad_keys(unsigned char key)
416 /* these are explained in curses.h */
431 case '\E': /* we ignore ESC */
438 /* Processes messages user has typed on the screen. This either sends
439 a packet out to network or if command were written executes it. */
441 static void silc_client_process_message(SilcClient client)
446 SILC_LOG_DEBUG(("Start"));
448 data = client->input_buffer->data;
451 if (data[0] == '/' && data[1] != ' ') {
453 unsigned int argc = 0;
454 unsigned char **argv, *tmpcmd;
455 unsigned int *argv_lens, *argv_types;
456 SilcClientCommand *cmd;
457 SilcClientCommandContext ctx;
459 /* Get the command */
460 tmpcmd = silc_client_parse_command(data);
462 /* Find command match */
463 for (cmd = silc_command_list; cmd->name; cmd++) {
464 if (!strcmp(cmd->name, tmpcmd))
468 if (cmd->name == NULL) {
469 silc_say(client, "Invalid command: %s", tmpcmd);
474 /* Now parse all arguments */
475 silc_client_parse_command_line(data, &argv, &argv_lens,
476 &argv_types, &argc, cmd->max_args);
479 SILC_LOG_DEBUG(("Exeuting command: %s", cmd->name));
481 /* Allocate command context. This and its internals must be free'd
482 by the command routine receiving it. */
483 ctx = silc_calloc(1, sizeof(*ctx));
484 ctx->client = client;
485 ctx->sock = client->current_win->sock;
488 ctx->argv_lens = argv_lens;
489 ctx->argv_types = argv_types;
491 /* Execute command */
495 /* Normal message to a channel */
496 if (len && client->current_win->current_channel &&
497 client->current_win->current_channel->on_channel == TRUE) {
498 silc_print(client, "> %s", data);
499 silc_client_packet_send_to_channel(client,
500 client->current_win->sock,
501 client->current_win->current_channel,
502 data, strlen(data), TRUE);
507 /* Clear the input buffer */
508 silc_buffer_clear(client->input_buffer);
509 silc_buffer_pull_tail(client->input_buffer,
510 SILC_BUFFER_END(client->input_buffer));
513 /* Returns the command fetched from user typed command line */
515 static char *silc_client_parse_command(unsigned char *buffer)
518 const char *cp = buffer;
521 len = strcspn(cp, " ");
522 ret = silc_to_upper((char *)++cp);
528 /* Parses user typed command line. At most `max_args' is taken. Rest
529 of the line will be allocated as the last argument if there are more
530 than `max_args' arguments in the line. Note that the command name
531 is counted as one argument and is saved. */
533 void silc_client_parse_command_line(unsigned char *buffer,
534 unsigned char ***parsed,
535 unsigned int **parsed_lens,
536 unsigned int **parsed_types,
537 unsigned int *parsed_num,
538 unsigned int max_args)
542 const char *cp = buffer;
544 /* Take the '/' away */
547 *parsed = silc_calloc(1, sizeof(**parsed));
548 *parsed_lens = silc_calloc(1, sizeof(**parsed_lens));
550 /* Get the command first */
551 len = strcspn(cp, " ");
552 (*parsed)[0] = silc_to_upper((char *)cp);
553 (*parsed_lens)[0] = len;
557 /* Parse arguments */
558 if (strchr(cp, ' ') || strlen(cp) != 0) {
559 for (i = 1; i < max_args; i++) {
561 if (i != max_args - 1)
562 len = strcspn(cp, " ");
566 *parsed = silc_realloc(*parsed, sizeof(**parsed) * (argc + 1));
567 *parsed_lens = silc_realloc(*parsed_lens,
568 sizeof(**parsed_lens) * (argc + 1));
569 (*parsed)[argc] = silc_calloc(len + 1, sizeof(char));
570 memcpy((*parsed)[argc], cp, len);
571 (*parsed_lens)[argc] = len;
582 /* Save argument types. Protocol defines all argument types but
583 this implementation makes sure that they are always in correct
584 order hence this simple code. */
585 *parsed_types = silc_calloc(argc, sizeof(**parsed_types));
586 for (i = 0; i < argc; i++)
587 (*parsed_types)[i] = i;
592 /* Updates clock on the screen every minute. */
594 SILC_TASK_CALLBACK(silc_client_update_clock)
596 SilcClient client = (SilcClient)context;
598 /* Update the clock on the screen */
599 silc_screen_print_clock(client->screen);
601 /* Re-register this same task */
602 silc_task_register(qptr, 0, silc_client_update_clock, context,
603 silc_client_time_til_next_min(), 0,
607 silc_screen_refresh_win(client->screen->input_win);
610 /* Runs commands user configured in configuration file. This is
611 called when initializing client. */
613 SILC_TASK_CALLBACK(silc_client_run_commands)
615 SilcClient client = (SilcClient)context;
616 SilcClientConfigSectionCommand *cs;
618 SILC_LOG_DEBUG(("Start"));
620 cs = client->config->commands;
622 unsigned int argc = 0;
623 unsigned char **argv, *tmpcmd;
624 unsigned int *argv_lens, *argv_types;
625 SilcClientCommand *cmd;
626 SilcClientCommandContext ctx;
628 /* Get the command */
629 tmpcmd = silc_client_parse_command(cs->command);
631 for (cmd = silc_command_list; cmd->name; cmd++) {
632 if (!strcmp(cmd->name, tmpcmd))
636 if (cmd->name == NULL) {
637 silc_say(client, "Invalid command: %s", tmpcmd);
642 /* Now parse all arguments */
643 silc_client_parse_command_line(cs->command, &argv, &argv_lens,
644 &argv_types, &argc, cmd->max_args);
647 SILC_LOG_DEBUG(("Exeuting command: %s", cmd->name));
649 /* Allocate command context. This and its internals must be free'd
650 by the command routine receiving it. */
651 ctx = silc_calloc(1, sizeof(*ctx));
652 ctx->client = client;
653 ctx->sock = client->current_win->sock;
656 ctx->argv_lens = argv_lens;
657 ctx->argv_types = argv_types;
659 /* Execute command */
666 /* Internal context for connection process. This is needed as we
667 doing asynchronous connecting. */
675 } SilcClientInternalConnectContext;
678 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
682 /* XXX In the future we should give up this non-blocking connect all
683 together and use threads instead. */
684 /* Create connection to server asynchronously */
685 sock = silc_net_create_connection_async(ctx->port, ctx->host);
689 /* Register task that will receive the async connect and will
691 ctx->task = silc_task_register(ctx->client->io_queue, sock,
692 silc_client_connect_to_server_start,
695 SILC_TASK_PRI_NORMAL);
696 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
697 silc_schedule_set_listen_fd(sock, ctx->task->iomask);
704 /* Connects to remote server */
706 int silc_client_connect_to_server(SilcClient client, int port,
709 SilcClientInternalConnectContext *ctx;
711 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
714 silc_say(client, "Connecting to port %d of server %s", port, host);
716 client->current_win->remote_host = strdup(host);
717 client->current_win->remote_port = port;
719 /* Allocate internal context for connection process. This is
720 needed as we are doing async connecting. */
721 ctx = silc_calloc(1, sizeof(*ctx));
722 ctx->client = client;
723 ctx->host = strdup(host);
727 /* Do the actual connecting process */
728 return silc_client_connect_to_server_internal(ctx);
731 /* Start of the connection to the remote server. This is called after
732 succesful TCP/IP connection has been established to the remote host. */
734 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
736 SilcClientInternalConnectContext *ctx =
737 (SilcClientInternalConnectContext *)context;
738 SilcClient client = ctx->client;
739 SilcProtocol protocol;
740 SilcClientKEInternalContext *proto_ctx;
741 int opt, opt_len = sizeof(opt);
743 SILC_LOG_DEBUG(("Start"));
745 /* Check the socket status as it might be in error */
746 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
748 if (ctx->tries < 2) {
749 /* Connection failed but lets try again */
750 silc_say(ctx->client, "Could not connect to server %s: %s",
751 ctx->host, strerror(opt));
752 silc_say(client, "Connecting to port %d of server %s resumed",
753 ctx->port, ctx->host);
755 /* Unregister old connection try */
756 silc_schedule_unset_listen_fd(fd);
757 silc_net_close_connection(fd);
758 silc_task_unregister(client->io_queue, ctx->task);
761 silc_client_connect_to_server_internal(ctx);
764 /* Connection failed and we won't try anymore */
765 silc_say(ctx->client, "Could not connect to server %s: %s",
766 ctx->host, strerror(opt));
767 silc_schedule_unset_listen_fd(fd);
768 silc_net_close_connection(fd);
769 silc_task_unregister(client->io_queue, ctx->task);
775 silc_schedule_unset_listen_fd(fd);
776 silc_task_unregister(client->io_queue, ctx->task);
779 /* Allocate new socket connection object */
780 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER,
781 (void *)client->current_win,
782 &client->current_win->sock);
783 if (client->current_win->sock == NULL) {
784 silc_say(client, "Error: Could not allocate connection socket");
785 silc_net_close_connection(fd);
788 client->current_win->sock->hostname = client->current_win->remote_host;
789 client->current_win->sock->port = client->current_win->remote_port;
791 /* Allocate internal Key Exchange context. This is sent to the
792 protocol as context. */
793 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
794 proto_ctx->client = (void *)client;
795 proto_ctx->sock = client->current_win->sock;
796 proto_ctx->rng = client->rng;
797 proto_ctx->responder = FALSE;
799 /* Perform key exchange protocol. silc_client_connect_to_server_final
800 will be called after the protocol is finished. */
801 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
802 &protocol, (void *)proto_ctx,
803 silc_client_connect_to_server_second);
805 silc_say(client, "Error: Could not start authentication protocol");
808 client->current_win->sock->protocol = protocol;
810 /* Register the connection for network input and output. This sets
811 that scheduler will listen for incoming packets for this connection
812 and sets that outgoing packets may be sent to this connection as well.
813 However, this doesn't set the scheduler for outgoing traffic, it will
814 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
815 later when outgoing data is available. */
816 context = (void *)client;
817 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
819 /* Execute the protocol */
820 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
823 /* Second part of the connecting to the server. This executed
824 authentication protocol. */
826 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
828 SilcProtocol protocol = (SilcProtocol)context;
829 SilcClientKEInternalContext *ctx =
830 (SilcClientKEInternalContext *)protocol->context;
831 SilcClient client = (SilcClient)ctx->client;
832 SilcSocketConnection sock = NULL;
833 SilcClientConnAuthInternalContext *proto_ctx;
835 SILC_LOG_DEBUG(("Start"));
837 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
838 /* Error occured during protocol */
839 SILC_LOG_DEBUG(("Error during KE protocol"));
840 silc_protocol_free(protocol);
842 silc_buffer_free(ctx->packet);
844 silc_ske_free(ctx->ske);
846 silc_free(ctx->dest_id);
848 sock->protocol = NULL;
852 /* Allocate internal context for the authentication protocol. This
853 is sent as context for the protocol. */
854 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
855 proto_ctx->client = (void *)client;
856 proto_ctx->sock = sock = ctx->sock;
857 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
858 proto_ctx->dest_id_type = ctx->dest_id_type;
859 proto_ctx->dest_id = ctx->dest_id;
861 /* Resolve the authentication method to be used in this connection */
862 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
863 if (client->config->conns) {
864 SilcClientConfigSectionConnection *conn = NULL;
866 /* Check if we find a match from user configured connections */
867 conn = silc_client_config_find_connection(client->config,
871 /* Match found. Use the configured authentication method */
872 proto_ctx->auth_meth = conn->auth_meth;
873 if (conn->auth_data) {
874 proto_ctx->auth_data = strdup(conn->auth_data);
875 proto_ctx->auth_data_len = strlen(conn->auth_data);
878 /* No match found. Resolve by sending AUTH_REQUEST to server */
879 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
882 /* XXX Resolve by sending AUTH_REQUEST to server */
883 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
886 /* Free old protocol as it is finished now */
887 silc_protocol_free(protocol);
889 silc_buffer_free(ctx->packet);
891 /* silc_free(ctx->keymat....); */
892 sock->protocol = NULL;
894 /* Allocate the authentication protocol. This is allocated here
895 but we won't start it yet. We will be receiving party of this
896 protocol thus we will wait that connecting party will make
898 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
899 &sock->protocol, (void *)proto_ctx,
900 silc_client_connect_to_server_final);
902 /* Execute the protocol */
903 sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
906 /* Finalizes the connection to the remote SILC server. This is called
907 after authentication protocol has been completed. This send our
908 user information to the server to receive our client ID from
911 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
913 SilcProtocol protocol = (SilcProtocol)context;
914 SilcClientConnAuthInternalContext *ctx =
915 (SilcClientConnAuthInternalContext *)protocol->context;
916 SilcClient client = (SilcClient)ctx->client;
917 SilcClientWindow win = (SilcClientWindow)ctx->sock->user_data;
920 SILC_LOG_DEBUG(("Start"));
922 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
923 /* Error occured during protocol */
924 SILC_LOG_DEBUG(("Error during authentication protocol"));
925 silc_protocol_free(protocol);
927 silc_free(ctx->auth_data);
929 silc_ske_free(ctx->ske);
931 silc_free(ctx->dest_id);
933 win->sock->protocol = NULL;
937 /* Send NEW_CLIENT packet to the server. We will become registered
938 to the SILC network after sending this packet and we will receive
939 client ID from the server. */
940 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
941 strlen(client->realname));
942 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
943 silc_buffer_format(packet,
944 SILC_STR_UI_SHORT(strlen(client->username)),
945 SILC_STR_UI_XNSTRING(client->username,
946 strlen(client->username)),
947 SILC_STR_UI_SHORT(strlen(client->realname)),
948 SILC_STR_UI_XNSTRING(client->realname,
949 strlen(client->realname)),
952 /* Send the packet */
953 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
955 packet->data, packet->len, TRUE);
956 silc_buffer_free(packet);
958 /* Save remote ID. */
959 win->remote_id = ctx->dest_id;
960 win->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_CHANNEL);
961 win->remote_id_data_len = SILC_ID_CHANNEL_LEN;
963 silc_say(client, "Connected to port %d of host %s",
964 win->remote_port, win->remote_host);
966 client->screen->bottom_line->connection = win->remote_host;
967 silc_screen_print_bottom_line(client->screen, 0);
969 silc_protocol_free(protocol);
971 silc_free(ctx->auth_data);
973 silc_ske_free(ctx->ske);
975 silc_free(ctx->dest_id);
977 win->sock->protocol = NULL;
981 SilcPacketContext *packetdata;
982 SilcSocketConnection sock;
984 } SilcClientInternalPacket;
986 SILC_TASK_CALLBACK(silc_client_packet_process)
988 SilcClient client = (SilcClient)context;
989 SilcSocketConnection sock = NULL;
990 int ret, packetlen, paddedlen;
992 SILC_LOG_DEBUG(("Processing packet"));
994 SILC_CLIENT_GET_SOCK(client, fd, sock);
999 if (type == SILC_TASK_WRITE) {
1000 SILC_LOG_DEBUG(("Writing data to connection"));
1002 if (sock->outbuf->data - sock->outbuf->head)
1003 silc_buffer_push(sock->outbuf,
1004 sock->outbuf->data - sock->outbuf->head);
1006 /* Write the packet out to the connection */
1007 ret = silc_packet_write(fd, sock->outbuf);
1009 /* If returned -2 could not write to connection now, will do
1016 SILC_LOG_ERROR(("Packet dropped"));
1018 /* The packet has been sent and now it is time to set the connection
1019 back to only for input. When there is again some outgoing data
1020 available for this connection it will be set for output as well.
1021 This call clears the output setting and sets it only for input. */
1022 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
1023 SILC_UNSET_OUTBUF_PENDING(sock);
1028 /* Packet receiving */
1029 if (type == SILC_TASK_READ) {
1030 SILC_LOG_DEBUG(("Reading data from connection"));
1032 /* Allocate the incoming data buffer if not done already. */
1034 sock->inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
1036 /* Read some data from connection */
1037 ret = silc_packet_read(fd, sock->inbuf);
1039 /* If returned -2 data was not available now, will read it later. */
1045 SILC_LOG_ERROR(("Packet dropped"));
1051 SILC_LOG_DEBUG(("Read EOF"));
1053 /* If connection is disconnecting already we will finally
1054 close the connection */
1055 if (SILC_IS_DISCONNECTING(sock)) {
1056 silc_client_close_connection(client, sock);
1060 silc_say(client, "Connection closed: premature EOF");
1061 SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
1063 silc_client_close_connection(client, sock);
1067 /* Check whether we received a whole packet. If reading went without
1068 errors we either read a whole packet or the read packet is
1069 incorrect and will be dropped. */
1070 SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
1071 if (sock->inbuf->len < paddedlen || (packetlen < SILC_PACKET_MIN_LEN)) {
1072 SILC_LOG_DEBUG(("Received incorrect packet, dropped"));
1073 silc_buffer_clear(sock->inbuf);
1077 /* Decrypt a packet coming from server connection */
1078 if (sock->type == SILC_SOCKET_TYPE_SERVER ||
1079 sock->type == SILC_SOCKET_TYPE_ROUTER) {
1080 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1081 SilcClientInternalPacket *packet;
1085 mac_len = win->hmac->hash->hash->hash_len;
1087 if (sock->inbuf->len - 2 > (paddedlen + mac_len)) {
1088 /* Received possibly many packets at once */
1090 while(sock->inbuf->len > 0) {
1091 SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
1092 if (sock->inbuf->len < paddedlen) {
1093 SILC_LOG_DEBUG(("Received incorrect packet, dropped"));
1098 packet = silc_calloc(1, sizeof(*packet));
1099 packet->client = client;
1100 packet->sock = sock;
1101 packet->packetdata = silc_calloc(1, sizeof(*packet->packetdata));
1102 packet->packetdata->buffer = silc_buffer_alloc(paddedlen + mac_len);
1103 silc_buffer_pull_tail(packet->packetdata->buffer,
1104 SILC_BUFFER_END(packet->packetdata->buffer));
1105 silc_buffer_put(packet->packetdata->buffer, sock->inbuf->data,
1106 paddedlen + mac_len);
1108 SILC_LOG_HEXDUMP(("Incoming packet, len %d",
1109 packet->packetdata->buffer->len),
1110 packet->packetdata->buffer->data,
1111 packet->packetdata->buffer->len);
1112 SILC_LOG_DEBUG(("Packet from server %s, "
1113 "server type %d, packet length %d",
1114 win->remote_host, win->remote_type, paddedlen));
1116 /* If this packet is for the current active connection we will
1117 parse the packet right away to get it quickly on the screen.
1118 Otherwise, it will be parsed with a timeout as the data is
1119 for inactive window (which might not be visible at all). */
1120 if (SILC_CLIENT_IS_CURRENT_WIN(client, win)) {
1121 /* Parse it real soon */
1122 silc_task_register(client->timeout_queue, fd,
1123 silc_client_packet_parse,
1124 (void *)packet, 0, 1,
1126 SILC_TASK_PRI_NORMAL);
1128 /* Parse the packet with timeout */
1129 silc_task_register(client->timeout_queue, fd,
1130 silc_client_packet_parse,
1131 (void *)packet, 0, 200000,
1133 SILC_TASK_PRI_NORMAL);
1136 /* Pull the packet from inbuf thus we'll get the next one
1138 silc_buffer_pull(sock->inbuf, paddedlen);
1140 silc_buffer_pull(sock->inbuf, mac_len);
1142 silc_buffer_clear(sock->inbuf);
1145 /* Received one packet */
1147 SILC_LOG_HEXDUMP(("An incoming packet, len %d", sock->inbuf->len),
1148 sock->inbuf->data, sock->inbuf->len);
1149 SILC_LOG_DEBUG(("Packet from server %s, "
1150 "server type %d, packet length %d",
1151 win->remote_host, win->remote_type, paddedlen));
1153 packet = silc_calloc(1, sizeof(*packet));
1154 packet->client = client;
1155 packet->sock = sock;
1156 packet->packetdata = silc_calloc(1, sizeof(*packet->packetdata));
1157 packet->packetdata->buffer = silc_buffer_copy(sock->inbuf);
1158 silc_buffer_clear(sock->inbuf);
1160 /* If this packet is for the current active connection we will
1161 parse the packet right away to get it quickly on the screen.
1162 Otherwise, it will be parsed with a timeout as the data is
1163 for inactive window (which might not be visible at all). */
1164 if (SILC_CLIENT_IS_CURRENT_WIN(client, win)) {
1165 /* Parse it real soon */
1166 silc_task_register(client->timeout_queue, fd,
1167 silc_client_packet_parse,
1168 (void *)packet, 0, 1,
1170 SILC_TASK_PRI_NORMAL);
1173 /* Parse the packet with timeout */
1174 silc_task_register(client->timeout_queue, fd,
1175 silc_client_packet_parse,
1176 (void *)packet, 0, 200000,
1178 SILC_TASK_PRI_NORMAL);
1185 SILC_LOG_ERROR(("Weird, nothing happened - ignoring"));
1188 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
1189 after packet has been totally decrypted and parsed. */
1191 static int silc_client_packet_check_mac(SilcClient client,
1192 SilcSocketConnection sock,
1195 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1199 int headlen = buffer->data - buffer->head, mac_len;
1200 unsigned char *packet_mac, mac[32];
1202 SILC_LOG_DEBUG(("Verifying MAC"));
1204 mac_len = win->hmac->hash->hash->hash_len;
1206 silc_buffer_push(buffer, headlen);
1208 /* Take mac from packet */
1209 packet_mac = buffer->tail;
1211 /* Make MAC and compare */
1212 memset(mac, 0, sizeof(mac));
1213 silc_hmac_make_with_key(win->hmac,
1214 buffer->data, buffer->len,
1215 win->hmac_key, win->hmac_key_len, mac);
1217 SILC_LOG_HEXDUMP(("PMAC"), packet_mac, mac_len);
1218 SILC_LOG_HEXDUMP(("CMAC"), mac, mac_len);
1220 if (memcmp(mac, packet_mac, mac_len)) {
1221 SILC_LOG_DEBUG(("MAC failed"));
1225 SILC_LOG_DEBUG(("MAC is Ok"));
1226 memset(mac, 0, sizeof(mac));
1228 silc_buffer_pull(buffer, headlen);
1234 /* Decrypts rest of the packet (after decrypting just the SILC header).
1235 After calling this function the packet is ready to be parsed by calling
1236 silc_packet_parse. */
1238 static int silc_client_packet_decrypt_rest(SilcClient client,
1239 SilcSocketConnection sock,
1242 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1243 unsigned int mac_len = 0;
1246 if (win && win->receive_key) {
1248 /* Pull MAC from packet before decryption */
1250 mac_len = win->hmac->hash->hash->hash_len;
1251 if ((buffer->len - mac_len) > SILC_PACKET_MIN_LEN) {
1252 silc_buffer_push_tail(buffer, mac_len);
1254 SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
1259 SILC_LOG_DEBUG(("Decrypting rest of the packet"));
1261 /* Decrypt rest of the packet */
1262 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
1263 silc_packet_decrypt(win->receive_key, buffer, buffer->len);
1264 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
1266 SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
1267 buffer->data, buffer->len);
1273 /* Decrypts rest of the SILC Packet header that has been decrypted partly
1274 already. This decrypts the padding of the packet also. After calling
1275 this function the packet is ready to be parsed by calling function
1276 silc_packet_parse. This is used in special packet reception. */
1278 static int silc_client_packet_decrypt_rest_special(SilcClient client,
1279 SilcSocketConnection sock,
1282 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1283 unsigned int mac_len = 0;
1285 /* Decrypt rest of the header plus padding */
1286 if (win && win->receive_key) {
1287 unsigned short truelen, len1, len2, padlen;
1289 /* Pull MAC from packet before decryption */
1291 mac_len = win->hmac->hash->hash->hash_len;
1292 if ((buffer->len - mac_len) > SILC_PACKET_MIN_LEN) {
1293 silc_buffer_push_tail(buffer, mac_len);
1295 SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
1300 SILC_LOG_DEBUG(("Decrypting rest of the header"));
1302 SILC_GET16_MSB(len1, &buffer->data[4]);
1303 SILC_GET16_MSB(len2, &buffer->data[6]);
1305 truelen = SILC_PACKET_HEADER_LEN + len1 + len2;
1306 padlen = SILC_PACKET_PADLEN(truelen);
1307 len1 = (truelen + padlen) - (SILC_PACKET_MIN_HEADER_LEN - 2);
1309 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
1310 SILC_LOG_HEXDUMP(("XXX"), buffer->data, buffer->len);
1311 silc_packet_decrypt(win->receive_key, buffer, len1);
1312 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
1313 SILC_LOG_HEXDUMP(("XXX"), buffer->data, buffer->len);
1319 /* Parses whole packet, received earlier. */
1321 SILC_TASK_CALLBACK(silc_client_packet_parse)
1323 SilcClientInternalPacket *packet = (SilcClientInternalPacket *)context;
1324 SilcBuffer buffer = packet->packetdata->buffer;
1325 SilcClient client = packet->client;
1326 SilcSocketConnection sock = packet->sock;
1327 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1330 SILC_LOG_DEBUG(("Start"));
1332 /* Decrypt start of the packet header */
1333 if (win && win->receive_key)
1334 silc_packet_decrypt(win->receive_key, buffer, SILC_PACKET_MIN_HEADER_LEN);
1336 /* If the packet type is not any special type lets decrypt rest
1337 of the packet here. */
1338 if (buffer->data[3] != SILC_PACKET_CHANNEL_MESSAGE &&
1339 buffer->data[3] != SILC_PACKET_PRIVATE_MESSAGE) {
1341 /* Normal packet, decrypt rest of the packet */
1342 if (!silc_client_packet_decrypt_rest(client, sock, buffer))
1345 /* Parse the packet. Packet type is returned. */
1346 ret = silc_packet_parse(packet->packetdata);
1347 if (ret == SILC_PACKET_NONE)
1351 if (!silc_client_packet_check_mac(client, sock, buffer))
1354 /* If private message key is not set for private message it is
1355 handled as normal packet. Go back up. */
1356 if (buffer->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
1357 !(buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
1360 /* Packet requires special handling, decrypt rest of the header.
1361 This only decrypts. This does not do any MAC checking, it must
1362 be done individually later when doing the special processing. */
1363 silc_client_packet_decrypt_rest_special(client, sock, buffer);
1365 /* Parse the packet header in special way as this is "special"
1367 ret = silc_packet_parse_special(packet->packetdata);
1368 if (ret == SILC_PACKET_NONE)
1372 /* Parse the incoming packet type */
1373 silc_client_packet_parse_type(client, sock, packet->packetdata);
1376 silc_buffer_clear(packet->packetdata->buffer);
1377 silc_free(packet->packetdata);
1381 /* Parses the packet type and calls what ever routines the packet type
1382 requires. This is done for all incoming packets. */
1384 void silc_client_packet_parse_type(SilcClient client,
1385 SilcSocketConnection sock,
1386 SilcPacketContext *packet)
1388 SilcBuffer buffer = packet->buffer;
1389 SilcPacketType type = packet->type;
1391 SILC_LOG_DEBUG(("Parsing packet type %d", type));
1393 /* Parse the packet type */
1395 case SILC_PACKET_DISCONNECT:
1396 silc_client_disconnected_by_server(client, sock, buffer);
1398 case SILC_PACKET_SUCCESS:
1400 * Success received for something. For now we can have only
1401 * one protocol for connection executing at once hence this
1402 * success message is for whatever protocol is executing currently.
1404 if (sock->protocol) {
1405 sock->protocol->execute(client->timeout_queue, 0,
1406 sock->protocol, sock->sock, 0, 0);
1409 case SILC_PACKET_FAILURE:
1411 * Failure received for some protocol. Set the protocol state to
1412 * error and call the protocol callback. This fill cause error on
1413 * protocol and it will call the final callback.
1415 if (sock->protocol) {
1416 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1417 sock->protocol->execute(client->timeout_queue, 0,
1418 sock->protocol, sock->sock, 0, 0);
1421 case SILC_PACKET_REJECT:
1424 case SILC_PACKET_NOTIFY:
1426 * Received notify message
1428 silc_client_notify_by_server(client, sock, buffer);
1431 case SILC_PACKET_ERROR:
1433 * Received error message
1435 silc_client_error_by_server(client, sock, buffer);
1438 case SILC_PACKET_CHANNEL_MESSAGE:
1440 * Received message to (from, actually) a channel
1442 silc_client_channel_message(client, sock, packet);
1444 case SILC_PACKET_CHANNEL_KEY:
1446 * Received key for a channel. By receiving this key the client will be
1447 * able to talk to the channel it has just joined. This can also be
1448 * a new key for existing channel as keys expire peridiocally.
1450 silc_client_receive_channel_key(client, sock, buffer);
1453 case SILC_PACKET_PRIVATE_MESSAGE:
1455 * Received private message
1458 SilcClientCommandReplyContext ctx;
1459 ctx = silc_calloc(1, sizeof(*ctx));
1460 ctx->client = client;
1462 ctx->context = buffer; /* kludge */
1463 silc_client_command_reply_msg((void *)ctx);
1466 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1468 * Received private message key
1472 case SILC_PACKET_COMMAND_REPLY:
1474 * Recived reply for a command
1476 silc_client_command_reply_process(client, sock, packet);
1479 case SILC_PACKET_KEY_EXCHANGE:
1480 if (sock->protocol) {
1481 SilcClientKEInternalContext *proto_ctx =
1482 (SilcClientKEInternalContext *)sock->protocol->context;
1484 proto_ctx->packet = buffer;
1485 proto_ctx->dest_id_type = packet->src_id_type;
1486 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
1488 /* Let the protocol handle the packet */
1489 sock->protocol->execute(client->timeout_queue, 0,
1490 sock->protocol, sock->sock, 0, 0);
1492 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1493 "protocol active, packet dropped."));
1495 /* XXX Trigger KE protocol?? Rekey actually! */
1499 case SILC_PACKET_KEY_EXCHANGE_1:
1500 if (sock->protocol) {
1503 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1504 "protocol active, packet dropped."));
1507 case SILC_PACKET_KEY_EXCHANGE_2:
1508 if (sock->protocol) {
1509 SilcClientKEInternalContext *proto_ctx =
1510 (SilcClientKEInternalContext *)sock->protocol->context;
1512 if (proto_ctx->packet)
1513 silc_buffer_free(proto_ctx->packet);
1515 proto_ctx->packet = buffer;
1516 proto_ctx->dest_id_type = packet->src_id_type;
1517 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
1519 /* Let the protocol handle the packet */
1520 sock->protocol->execute(client->timeout_queue, 0,
1521 sock->protocol, sock->sock, 0, 0);
1523 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1524 "protocol active, packet dropped."));
1528 case SILC_PACKET_NEW_ID:
1531 * Received new ID from server. This packet is received at
1532 * the connection to the server. New ID is also received when
1533 * user changes nickname but in that case the new ID is received
1534 * as command reply and not as this packet type.
1536 unsigned char *id_string;
1537 unsigned short id_type;
1539 silc_buffer_unformat(buffer,
1540 SILC_STR_UI_SHORT(&id_type),
1541 SILC_STR_UI16_STRING_ALLOC(&id_string),
1544 if ((SilcIdType)id_type != SILC_ID_CLIENT)
1547 silc_client_receive_new_id(client, sock, id_string);
1548 silc_free(id_string);
1553 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1558 /* Internal routine that sends packet or marks packet to be sent. This
1559 is used directly only in special cases. Normal cases should use
1560 silc_server_packet_send. Returns < 0 on error. */
1562 static int silc_client_packet_send_real(SilcClient client,
1563 SilcSocketConnection sock,
1566 /* Send now if forced to do so */
1567 if (force_send == TRUE) {
1569 SILC_LOG_DEBUG(("Forcing packet send, packet sent immediately"));
1570 ret = silc_packet_write(sock->sock, sock->outbuf);
1573 SILC_LOG_ERROR(("Packet dropped"));
1577 SILC_LOG_DEBUG(("Could not force the send, packet put to queue"));
1580 SILC_LOG_DEBUG(("Packet in queue"));
1582 /* Mark that there is some outgoing data available for this connection.
1583 This call sets the connection both for input and output (the input
1584 is set always and this call keeps the input setting, actually).
1585 Actual data sending is performed by silc_client_packet_process. */
1586 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
1588 /* Mark to socket that data is pending in outgoing buffer. This flag
1589 is needed if new data is added to the buffer before the earlier
1590 put data is sent to the network. */
1591 SILC_SET_OUTBUF_PENDING(sock);
1596 /* Prepare outgoing data buffer for packet sending. */
1598 static void silc_client_packet_send_prepare(SilcClient client,
1599 SilcSocketConnection sock,
1600 unsigned int header_len,
1601 unsigned int padlen,
1602 unsigned int data_len)
1606 totlen = header_len + padlen + data_len;
1608 /* Prepare the outgoing buffer for packet sending. */
1609 if (!sock->outbuf) {
1610 /* Allocate new buffer. This is done only once per connection. */
1611 SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
1613 sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
1614 silc_buffer_pull_tail(sock->outbuf, totlen);
1615 silc_buffer_pull(sock->outbuf, header_len + padlen);
1617 if (SILC_IS_OUTBUF_PENDING(sock)) {
1618 /* There is some pending data in the buffer. */
1620 if ((sock->outbuf->end - sock->outbuf->tail) < data_len) {
1621 SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
1622 /* XXX: not done yet */
1624 oldlen = sock->outbuf->len;
1625 silc_buffer_pull_tail(sock->outbuf, totlen);
1626 silc_buffer_pull(sock->outbuf, header_len + padlen + oldlen);
1628 /* Buffer is free for use */
1629 silc_buffer_clear(sock->outbuf);
1630 silc_buffer_pull_tail(sock->outbuf, totlen);
1631 silc_buffer_pull(sock->outbuf, header_len + padlen);
1636 /* Sends packet. This doesn't actually send the packet instead it assembles
1637 it and marks it to be sent. However, if force_send is TRUE the packet
1638 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1639 will be derived from sock argument. Otherwise the valid arguments sent
1642 void silc_client_packet_send(SilcClient client,
1643 SilcSocketConnection sock,
1644 SilcPacketType type,
1646 SilcIdType dst_id_type,
1649 unsigned char *data,
1650 unsigned int data_len,
1653 SilcPacketContext packetdata;
1654 unsigned char *hmac_key = NULL;
1655 unsigned int hmac_key_len = 0;
1656 unsigned char mac[32];
1657 unsigned int mac_len = 0;
1659 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1661 /* Get data used in the packet sending, keys and stuff */
1662 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1663 if (!cipher && ((SilcClientWindow)sock->user_data)->send_key)
1664 cipher = ((SilcClientWindow)sock->user_data)->send_key;
1665 if (!hmac && ((SilcClientWindow)sock->user_data)->hmac) {
1666 hmac = ((SilcClientWindow)sock->user_data)->hmac;
1667 mac_len = hmac->hash->hash->hash_len;
1668 hmac_key = ((SilcClientWindow)sock->user_data)->hmac_key;
1669 hmac_key_len = ((SilcClientWindow)sock->user_data)->hmac_key_len;
1671 if (!dst_id && ((SilcClientWindow)sock->user_data)->remote_id) {
1672 dst_id = ((SilcClientWindow)sock->user_data)->remote_id;
1673 dst_id_type = SILC_ID_SERVER;
1677 /* Set the packet context pointers */
1678 packetdata.flags = 0;
1679 packetdata.type = type;
1680 if (((SilcClientWindow)sock->user_data)->local_id_data)
1681 packetdata.src_id = ((SilcClientWindow)sock->user_data)->local_id_data;
1683 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1684 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1685 packetdata.src_id_type = SILC_ID_CLIENT;
1687 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1688 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
1689 packetdata.dst_id_type = dst_id_type;
1691 packetdata.dst_id = NULL;
1692 packetdata.dst_id_len = 0;
1693 packetdata.dst_id_type = SILC_ID_NONE;
1695 packetdata.rng = client->rng;
1696 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1697 packetdata.src_id_len + packetdata.dst_id_len;
1698 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1700 /* Prepare outgoing data buffer for packet sending */
1701 silc_client_packet_send_prepare(client, sock,
1702 SILC_PACKET_HEADER_LEN +
1703 packetdata.src_id_len +
1704 packetdata.dst_id_len,
1708 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1710 packetdata.buffer = sock->outbuf;
1712 /* Put the data to the buffer */
1713 if (data && data_len)
1714 silc_buffer_put(sock->outbuf, data, data_len);
1716 /* Create the outgoing packet */
1717 silc_packet_assemble(&packetdata);
1719 /* Compute MAC of the packet */
1721 silc_hmac_make_with_key(hmac, sock->outbuf->data, sock->outbuf->len,
1722 hmac_key, hmac_key_len, mac);
1723 silc_buffer_put_tail(sock->outbuf, mac, mac_len);
1724 memset(mac, 0, sizeof(mac));
1727 /* Encrypt the packet */
1729 silc_packet_encrypt(cipher, sock->outbuf, sock->outbuf->len);
1731 /* Pull MAC into the visible data area */
1733 silc_buffer_pull_tail(sock->outbuf, mac_len);
1735 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1736 sock->outbuf->data, sock->outbuf->len);
1738 /* Now actually send the packet */
1739 silc_client_packet_send_real(client, sock, force_send);
1742 /* Sends packet to a channel. Packet to channel is always encrypted
1743 differently from "normal" packets. SILC header of the packet is
1744 encrypted with the next receiver's key and the rest of the packet is
1745 encrypted with the channel specific key. Padding and HMAC is computed
1746 with the next receiver's key. */
1748 void silc_client_packet_send_to_channel(SilcClient client,
1749 SilcSocketConnection sock,
1750 SilcChannelEntry channel,
1751 unsigned char *data,
1752 unsigned int data_len,
1756 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1758 SilcPacketContext packetdata;
1759 unsigned char *hmac_key = NULL;
1760 unsigned int hmac_key_len = 0;
1761 unsigned char mac[32];
1762 unsigned int mac_len = 0;
1763 unsigned char *id_string;
1767 SILC_LOG_DEBUG(("Sending packet to channel"));
1769 if (!channel || !channel->key) {
1770 silc_say(client, "Cannot talk to channel: key does not exist");
1776 for (i = 0; i < 16; i++)
1777 channel->iv[i] = silc_rng_get_byte(client->rng);
1779 silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
1781 /* Encode the channel payload */
1782 payload = silc_channel_encode_payload(strlen(win->nickname), win->nickname,
1783 data_len, data, 16, channel->iv,
1787 "Error: Could not create packet to be sent to the channel");
1791 /* Get data used in packet header encryption, keys and stuff. Rest
1792 of the packet (the payload) is, however, encrypted with the
1793 specified channel key. */
1794 cipher = win->send_key;
1796 mac_len = hmac->hash->hash->hash_len;
1797 hmac_key = win->hmac_key;
1798 hmac_key_len = win->hmac_key_len;
1799 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1801 /* Set the packet context pointers. The destination ID is always
1802 the Channel ID of the channel. Server and router will handle the
1803 distribution of the packet. */
1804 packetdata.flags = 0;
1805 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1806 packetdata.src_id = win->local_id_data;
1807 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1808 packetdata.src_id_type = SILC_ID_CLIENT;
1809 packetdata.dst_id = id_string;
1810 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1811 packetdata.dst_id_type = SILC_ID_CHANNEL;
1812 packetdata.rng = client->rng;
1813 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
1814 packetdata.src_id_len + packetdata.dst_id_len;
1815 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1816 packetdata.src_id_len +
1817 packetdata.dst_id_len));
1819 /* Prepare outgoing data buffer for packet sending */
1820 silc_client_packet_send_prepare(client, sock,
1821 SILC_PACKET_HEADER_LEN +
1822 packetdata.src_id_len +
1823 packetdata.dst_id_len,
1827 packetdata.buffer = sock->outbuf;
1829 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1830 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1831 payload->data, payload->data,
1832 payload->len - 16, /* -IV_LEN */
1835 SILC_LOG_HEXDUMP(("XXX"), payload->data, payload->len);
1837 /* Put the actual encrypted payload data into the buffer. */
1838 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1840 /* Create the outgoing packet */
1841 silc_packet_assemble(&packetdata);
1843 /* Compute MAC of the packet */
1844 silc_hmac_make_with_key(hmac, sock->outbuf->data, sock->outbuf->len,
1845 hmac_key, hmac_key_len, mac);
1846 silc_buffer_put_tail(sock->outbuf, mac, mac_len);
1847 memset(mac, 0, sizeof(mac));
1849 SILC_LOG_HEXDUMP(("XXX"), sock->outbuf->data, sock->outbuf->len);
1851 /* Encrypt the header and padding of the packet. This is encrypted
1852 with normal session key shared with our server. */
1853 silc_packet_encrypt(cipher, sock->outbuf, SILC_PACKET_HEADER_LEN +
1854 packetdata.src_id_len + packetdata.dst_id_len +
1857 /* Pull MAC into the visible data area */
1858 silc_buffer_pull_tail(sock->outbuf, mac_len);
1860 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1861 sock->outbuf->data, sock->outbuf->len);
1863 /* Now actually send the packet */
1864 silc_client_packet_send_real(client, sock, force_send);
1865 silc_buffer_free(payload);
1866 silc_free(id_string);
1869 /* Sends private message to remote client. If private message key has
1870 not been set with this client then the message will be encrypted using
1871 normal session keys. Private messages are special packets in SILC
1872 network hence we need this own function for them. This is similiar
1873 to silc_client_packet_send_to_channel except that we send private
1876 void silc_client_packet_send_private_message(SilcClient client,
1877 SilcSocketConnection sock,
1878 SilcClientEntry client_entry,
1879 unsigned char *data,
1880 unsigned int data_len,
1883 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1885 SilcPacketContext packetdata;
1886 unsigned char *hmac_key = NULL;
1887 unsigned int hmac_key_len = 0;
1888 unsigned char mac[32];
1889 unsigned int mac_len = 0;
1890 unsigned int nick_len;
1894 SILC_LOG_DEBUG(("Sending private message"));
1896 /* Create private message payload */
1897 nick_len = strlen(client->current_win->nickname);
1898 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1899 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1900 silc_buffer_format(buffer,
1901 SILC_STR_UI_SHORT(nick_len),
1902 SILC_STR_UI_XNSTRING(client->current_win->nickname,
1904 SILC_STR_UI_XNSTRING(data, data_len),
1907 /* If we don't have private message specific key then private messages
1908 are just as any normal packet thus call normal packet sending. If
1909 the key exist then the encryption process is a bit different and
1910 will be done in the rest of this function. */
1911 if (!client_entry->send_key) {
1912 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1913 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1914 buffer->data, buffer->len, force_send);
1918 /* We have private message specific key */
1920 /* Get data used in the encryption */
1921 cipher = client_entry->send_key;
1923 mac_len = hmac->hash->hash->hash_len;
1924 hmac_key = win->hmac_key;
1925 hmac_key_len = win->hmac_key_len;
1927 /* Set the packet context pointers. */
1928 packetdata.flags = 0;
1929 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1930 packetdata.src_id = win->local_id_data;
1931 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1932 packetdata.src_id_type = SILC_ID_CLIENT;
1934 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1936 packetdata.dst_id = win->local_id_data;
1937 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1938 packetdata.dst_id_type = SILC_ID_CLIENT;
1939 packetdata.rng = client->rng;
1940 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1941 packetdata.src_id_len + packetdata.dst_id_len;
1942 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1943 packetdata.src_id_len +
1944 packetdata.dst_id_len));
1946 /* Prepare outgoing data buffer for packet sending */
1947 silc_client_packet_send_prepare(client, sock,
1948 SILC_PACKET_HEADER_LEN +
1949 packetdata.src_id_len +
1950 packetdata.dst_id_len,
1954 packetdata.buffer = sock->outbuf;
1956 /* Encrypt payload of the packet. Encrypt with private message specific
1957 key if it exist, otherwise with session key. */
1958 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1959 buffer->len, cipher->iv);
1961 /* Put the actual encrypted payload data into the buffer. */
1962 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1964 /* Create the outgoing packet */
1965 silc_packet_assemble(&packetdata);
1967 /* Compute MAC of the packet */
1968 silc_hmac_make_with_key(hmac, sock->outbuf->data, sock->outbuf->len,
1969 hmac_key, hmac_key_len, mac);
1970 silc_buffer_put_tail(sock->outbuf, mac, mac_len);
1971 memset(mac, 0, sizeof(mac));
1973 SILC_LOG_HEXDUMP(("XXX"), sock->outbuf->data, sock->outbuf->len);
1975 /* Encrypt the header and padding of the packet. */
1976 silc_packet_encrypt(cipher, sock->outbuf, SILC_PACKET_HEADER_LEN +
1977 packetdata.src_id_len + packetdata.dst_id_len +
1980 /* Pull MAC into the visible data area */
1981 silc_buffer_pull_tail(sock->outbuf, mac_len);
1983 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1984 sock->outbuf->data, sock->outbuf->len);
1986 /* Now actually send the packet */
1987 silc_client_packet_send_real(client, sock, force_send);
1988 silc_free(packetdata.dst_id);
1994 /* Closes connection to remote end. Free's all allocated data except
1995 for some information such as nickname etc. that are valid at all time. */
1997 void silc_client_close_connection(SilcClient client,
1998 SilcSocketConnection sock)
2000 SilcClientWindow win;
2003 /* We won't listen for this connection anymore */
2004 silc_schedule_unset_listen_fd(sock->sock);
2006 /* Unregister all tasks */
2007 silc_task_unregister_by_fd(client->io_queue, sock->sock);
2008 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
2010 /* Close the actual connection */
2011 silc_net_close_connection(sock->sock);
2013 silc_say(client, "Closed connection to host %s", sock->hostname ?
2014 sock->hostname : sock->ip);
2016 /* Free everything */
2017 if (sock->user_data) {
2018 win = (SilcClientWindow)sock->user_data;
2020 /* XXX Free all client entries and channel entries. */
2022 /* Clear ID caches */
2023 for (i = 0; i < 96; i++)
2024 silc_idcache_del_all(&win->client_id_cache[i],
2025 win->client_id_cache_count[i]);
2026 for (i = 0; i < 96; i++)
2027 silc_idcache_del_all(&win->channel_id_cache[i],
2028 win->channel_id_cache_count[i]);
2031 if (win->remote_host)
2032 silc_free(win->remote_host);
2034 silc_free(win->local_id);
2035 if (win->local_id_data)
2036 silc_free(win->local_id_data);
2038 silc_cipher_free(win->send_key);
2039 if (win->receive_key)
2040 silc_cipher_free(win->receive_key);
2042 silc_hmac_free(win->hmac);
2043 if (win->hmac_key) {
2044 memset(win->hmac_key, 0, win->hmac_key_len);
2045 silc_free(win->hmac_key);
2049 win->remote_port = 0;
2050 win->remote_type = 0;
2051 win->send_key = NULL;
2052 win->receive_key = NULL;
2054 win->hmac_key = NULL;
2055 win->hmac_key_len = 0;
2056 win->local_id = NULL;
2057 win->local_id_data = NULL;
2058 win->remote_host = NULL;
2059 win->current_channel = NULL;
2062 if (sock->protocol) {
2063 silc_protocol_free(sock->protocol);
2064 sock->protocol = NULL;
2066 silc_socket_free(sock);
2069 /* Called when we receive disconnection packet from server. This
2070 closes our end properly and displays the reason of the disconnection
2073 void silc_client_disconnected_by_server(SilcClient client,
2074 SilcSocketConnection sock,
2079 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
2081 msg = silc_calloc(message->len + 1, sizeof(char));
2082 memcpy(msg, message->data, message->len);
2083 silc_say(client, msg);
2086 SILC_SET_DISCONNECTED(sock);
2087 silc_client_close_connection(client, sock);
2090 /* Received error message from server. Display it on the screen.
2091 We don't take any action what so ever of the error message. */
2093 void silc_client_error_by_server(SilcClient client,
2094 SilcSocketConnection sock,
2099 msg = silc_calloc(message->len + 1, sizeof(char));
2100 memcpy(msg, message->data, message->len);
2101 silc_say(client, msg);
2105 /* Received notify message from server */
2107 void silc_client_notify_by_server(SilcClient client,
2108 SilcSocketConnection sock,
2113 msg = silc_calloc(message->len + 1, sizeof(char));
2114 memcpy(msg, message->data, message->len);
2115 silc_say(client, msg);
2119 /* Processes the received new Client ID from server. Old Client ID is
2120 deleted from cache and new one is added. */
2122 void silc_client_receive_new_id(SilcClient client,
2123 SilcSocketConnection sock,
2124 unsigned char *id_string)
2126 SilcClientWindow win = (SilcClientWindow)sock->user_data;
2127 char *nickname = win->nickname;
2129 #define CIDC(x) win->client_id_cache[(x) - 32]
2130 #define CIDCC(x) win->client_id_cache_count[(x) - 32]
2132 /* Delete old ID from ID cache */
2133 silc_idcache_del_by_id(CIDC(nickname[0]), CIDCC(nickname[0]),
2134 SILC_ID_CLIENT, win->local_id);
2136 /* Save the new ID */
2138 silc_free(win->local_id);
2139 win->local_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
2140 if (win->local_id_data)
2141 silc_free(win->local_id_data);
2142 win->local_id_data =
2143 silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
2144 memcpy(win->local_id_data, id_string, SILC_ID_CLIENT_LEN);
2145 win->local_id_data_len = SILC_ID_CLIENT_LEN;
2146 if (!win->local_entry)
2147 win->local_entry = silc_calloc(1, sizeof(*win->local_entry));
2148 win->local_entry->nickname = win->nickname;
2149 win->local_entry->id = win->local_id;
2151 /* Put it to the ID cache */
2152 CIDCC(nickname[0]) = silc_idcache_add(&CIDC(nickname[0]),
2154 win->nickname, SILC_ID_CLIENT,
2156 (void *)win->local_entry);
2161 /* Processed received Channel ID for a channel. This is called when client
2162 joins to channel and server replies with channel ID. The ID is cached. */
2164 void silc_client_new_channel_id(SilcClient client,
2165 SilcSocketConnection sock,
2168 unsigned char *id_string)
2170 SilcClientWindow win = (SilcClientWindow)sock->user_data;
2172 SilcChannelEntry channel;
2174 SILC_LOG_DEBUG(("New channel ID"));
2176 #define CIDC(x) win->channel_id_cache[(x) - 32]
2177 #define CIDCC(x) win->channel_id_cache_count[(x) - 32]
2179 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
2180 channel = silc_calloc(1, sizeof(*channel));
2181 channel->channel_name = channel_name;
2183 channel->mode = mode;
2184 win->current_channel = channel;
2186 /* Put it to the ID cache */
2187 CIDCC(channel_name[0]) = silc_idcache_add(&CIDC(channel_name[0]),
2188 CIDCC(channel_name[0]),
2189 channel_name, SILC_ID_CHANNEL,
2190 id, (void *)channel);
2195 /* Processes received key for channel. The received key will be used
2196 to protect the traffic on the channel for now on. Client must receive
2197 the key to the channel before talking on the channel is possible.
2198 This is the key that server has generated, this is not the channel
2199 private key, it is entirely local setting. */
2201 void silc_client_receive_channel_key(SilcClient client,
2202 SilcSocketConnection sock,
2206 unsigned char *id_string, *key, *cipher;
2207 unsigned int key_len;
2208 SilcClientWindow win = (SilcClientWindow)sock->user_data;
2210 SilcIDCache *id_cache = NULL;
2211 SilcChannelEntry channel;
2212 SilcChannelKeyPayload payload;
2214 SILC_LOG_DEBUG(("Received key for channel"));
2216 #define CIDC(x) win->channel_id_cache[(x)]
2217 #define CIDCC(x) win->channel_id_cache_count[(x)]
2219 payload = silc_channel_key_parse_payload(packet);
2223 id_string = silc_channel_key_get_id(payload, NULL);
2225 silc_channel_key_free_payload(payload);
2228 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
2230 /* Find channel. XXX: This is bad and slow. */
2231 for (i = 0; i < 96; i++) {
2232 if (CIDC(i) == NULL)
2234 if (silc_idcache_find_by_id(CIDC(i), CIDCC(i), (void *)id,
2235 SILC_ID_CHANNEL, &id_cache))
2243 key = silc_channel_key_get_key(payload, &key_len);
2244 cipher = silc_channel_key_get_cipher(payload, NULL);
2246 channel = (SilcChannelEntry)id_cache->context;
2247 channel->key_len = key_len;
2248 channel->key = silc_calloc(key_len, sizeof(*channel->key));
2249 memcpy(channel->key, key, key_len);
2251 silc_cipher_alloc(cipher, &channel->channel_key);
2252 if (!channel->channel_key) {
2253 silc_say(client, "Cannot talk to channel: unsupported cipher %s", cipher);
2256 channel->channel_key->cipher->set_key(channel->channel_key->context,
2259 /* Client is now joined to the channel */
2260 channel->on_channel = TRUE;
2264 silc_channel_key_free_payload(payload);
2269 /* Process received message to a channel (or from a channel, really). This
2270 decrypts the channel message with channel specific key and parses the
2271 channel payload. Finally it displays the message on the screen. */
2273 void silc_client_channel_message(SilcClient client,
2274 SilcSocketConnection sock,
2275 SilcPacketContext *packet)
2278 SilcClientWindow win = (SilcClientWindow)sock->user_data;
2279 SilcBuffer buffer = packet->buffer;
2280 SilcChannelPayload payload = NULL;
2281 SilcChannelID *id = NULL;
2282 SilcChannelEntry channel;
2283 SilcIDCache *id_cache = NULL;
2285 #define CIDC(x) win->channel_id_cache[(x)]
2286 #define CIDCC(x) win->channel_id_cache_count[(x)]
2289 if (packet->dst_id_type != SILC_ID_CHANNEL)
2292 id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
2294 /* Find the channel entry from channels on this window */
2295 for (i = 0; i < 96; i++) {
2296 if (CIDC(i) == NULL)
2298 if (silc_idcache_find_by_id(CIDC(i), CIDCC(i), (void *)id,
2299 SILC_ID_CHANNEL, &id_cache))
2306 channel = (SilcChannelEntry)id_cache->context;
2308 /* Decrypt the channel message payload. Push the IV out of the way,
2309 since it is not encrypted (after pushing buffer->tail has the IV). */
2310 silc_buffer_push_tail(buffer, 16);
2311 channel->channel_key->cipher->decrypt(channel->channel_key->context,
2312 buffer->data, buffer->data,
2313 buffer->len, buffer->tail);
2314 silc_buffer_pull_tail(buffer, 16);
2316 /* Parse the channel message payload */
2317 payload = silc_channel_parse_payload(buffer);
2321 /* Display the message on screen */
2322 if (packet->src_id_type == SILC_ID_CLIENT)
2323 /* Message from client */
2324 silc_print(client, "<%s> %s", silc_channel_get_nickname(payload, NULL),
2325 silc_channel_get_data(payload, NULL));
2327 /* Message from server */
2328 silc_say(client, "%s", silc_channel_get_data(payload, NULL));
2334 silc_channel_free_payload(payload);