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.10 2000/07/18 06:53:15 priikone
24 * Allow partial command strings in comparison.
26 * Revision 1.9 2000/07/14 06:13:19 priikone
27 * Moved all the generic packet sending, encryption, reception,
28 * decryption and processing functions to library as they were
29 * duplicated code with the server. Now client uses the generic
30 * routines which is a lot cleaner.
32 * Revision 1.8 2000/07/12 05:56:32 priikone
33 * Major rewrite of ID Cache system. Support added for the new
36 * Revision 1.7 2000/07/10 05:40:33 priikone
39 * Revision 1.6 2000/07/07 06:54:16 priikone
40 * Print channel name when receiving channel message to non-current
43 * Revision 1.5 2000/07/06 07:14:36 priikone
44 * Fixes to NAMES command handling.
45 * Fixes when leaving from channel.
47 * Revision 1.4 2000/07/05 06:12:05 priikone
48 * Global cosmetic changes.
50 * Revision 1.3 2000/07/04 08:29:12 priikone
51 * Added support for PING command. The ping times are calculated
52 * and showed to the user.
54 * Revision 1.2 2000/07/03 05:49:48 priikone
55 * Implemented LEAVE command. Minor bug fixes.
57 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
58 * Imported from internal CVS/Added Log headers.
63 #include "clientincludes.h"
65 /* Static function prototypes */
66 static int silc_client_bad_keys(unsigned char key);
67 static void silc_client_process_message(SilcClient client);
68 static char *silc_client_parse_command(unsigned char *buffer);
70 /* Static task callback prototypes */
71 SILC_TASK_CALLBACK(silc_client_update_clock);
72 SILC_TASK_CALLBACK(silc_client_run_commands);
73 SILC_TASK_CALLBACK(silc_client_process_key_press);
74 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
75 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
76 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
77 SILC_TASK_CALLBACK(silc_client_packet_process);
78 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
80 SilcClientWindow silc_client_create_main_window(SilcClient client);
81 SilcClientWindow silc_client_add_window(SilcClient client,
83 void silc_client_packet_parse(SilcPacketParserContext *parser_context);
84 void silc_client_packet_parse_type(SilcClient client,
85 SilcSocketConnection sock,
86 SilcPacketContext *packet);
87 void silc_client_private_message_process(SilcClient client,
88 SilcSocketConnection sock,
89 SilcPacketContext *packet);
91 /* Definitions from version.h */
92 extern char *silc_version;
93 extern char *silc_name;
94 extern char *silc_fullname;
96 /* Allocates new client object. This has to be done before client may
97 work. After calling this one must call silc_client_init to initialize
100 int silc_client_alloc(SilcClient *new_client)
103 *new_client = silc_calloc(1, sizeof(**new_client));
104 (*new_client)->input_buffer = NULL;
105 (*new_client)->screen = NULL;
106 (*new_client)->windows = NULL;
107 (*new_client)->windows_count = 0;
108 (*new_client)->current_win = NULL;
113 /* Free's client object */
115 void silc_client_free(SilcClient client)
122 /* Initializes the client. This makes all the necessary steps to make
123 the client ready to be run. One must call silc_client_run to run the
126 int silc_client_init(SilcClient client)
129 SILC_LOG_DEBUG(("Initializing client"));
132 client->username = silc_get_username();
133 client->realname = silc_get_real_name();
135 /* Register all configured ciphers, PKCS and hash functions. */
136 client->config->client = (void *)client;
137 silc_client_config_register_ciphers(client->config);
138 silc_client_config_register_pkcs(client->config);
139 silc_client_config_register_hashfuncs(client->config);
141 /* Initialize hash functions for client to use */
142 silc_hash_alloc("md5", &client->md5hash);
143 silc_hash_alloc("sha1", &client->sha1hash);
145 /* Initialize none cipher */
146 silc_cipher_alloc("none", &client->none_cipher);
148 /* Initialize random number generator */
149 client->rng = silc_rng_alloc();
150 silc_rng_init(client->rng);
151 silc_math_primegen_init(); /* XXX */
153 /* Load public and private key */
154 if (silc_client_load_keys(client) == FALSE)
157 /* Register the task queues. In SILC we have by default three task queues.
158 One task queue for non-timeout tasks which perform different kind of
159 I/O on file descriptors, timeout task queue for timeout tasks, and,
160 generic non-timeout task queue whose tasks apply to all connections. */
161 silc_task_queue_alloc(&client->io_queue, TRUE);
162 if (!client->io_queue) {
165 silc_task_queue_alloc(&client->timeout_queue, TRUE);
166 if (!client->timeout_queue) {
169 silc_task_queue_alloc(&client->generic_queue, TRUE);
170 if (!client->generic_queue) {
174 /* Initialize the scheduler */
175 silc_schedule_init(client->io_queue, client->timeout_queue,
176 client->generic_queue, 5000);
178 /* Register the main task that is used in client. This received
179 the key pressings. */
180 if (silc_task_register(client->io_queue, fileno(stdin),
181 silc_client_process_key_press,
182 (void *)client, 0, 0,
184 SILC_TASK_PRI_NORMAL) == NULL) {
188 /* Register timeout task that updates clock every minute. */
189 if (silc_task_register(client->timeout_queue, 0,
190 silc_client_update_clock,
192 silc_client_time_til_next_min(), 0,
194 SILC_TASK_PRI_LOW) == NULL) {
198 if (client->config->commands) {
199 /* Run user configured commands with timeout */
200 if (silc_task_register(client->timeout_queue, 0,
201 silc_client_run_commands,
202 (void *)client, 0, 1,
204 SILC_TASK_PRI_LOW) == NULL) {
209 /* Allocate the input buffer used to save typed characters */
210 client->input_buffer = silc_buffer_alloc(SILC_SCREEN_INPUT_WIN_SIZE);
211 silc_buffer_pull_tail(client->input_buffer,
212 SILC_BUFFER_END(client->input_buffer));
214 /* Initialize the screen */
215 client->screen = silc_screen_init();
216 silc_client_create_main_window(client);
217 client->screen->input_buffer = client->input_buffer->data;
218 silc_screen_print_coordinates(client->screen, 0);
223 silc_task_queue_free(client->timeout_queue);
225 silc_task_queue_free(client->io_queue);
230 /* Stops the client. This is called to stop the client and thus to stop
233 void silc_client_stop(SilcClient client)
235 SILC_LOG_DEBUG(("Stopping client"));
237 /* Stop the scheduler, although it might be already stopped. This
238 doesn't hurt anyone. This removes all the tasks and task queues,
240 silc_schedule_stop();
241 silc_schedule_uninit();
243 SILC_LOG_DEBUG(("Client client"));
246 /* Runs the client. */
248 void silc_client_run(SilcClient client)
250 SILC_LOG_DEBUG(("Running client"));
252 /* Start the scheduler, the heart of the SILC client. When this returns
253 the program will be terminated. */
257 /* Creates the main window used in SILC client. This is called always
258 at the initialization of the client. If user wants to create more
259 than one windows a new windows are always created by calling
260 silc_client_add_window. */
262 SilcClientWindow silc_client_create_main_window(SilcClient client)
264 SilcClientWindow win;
267 SILC_LOG_DEBUG(("Creating main window"));
269 assert(client->screen != NULL);
271 client->screen->u_stat_line.program_name = silc_name;
272 client->screen->u_stat_line.program_version = silc_version;
275 win = silc_calloc(1, sizeof(*win));
276 win->nickname = silc_get_username();
277 win->local_id = NULL;
278 win->local_id_data = NULL;
279 win->local_id_data_len = 0;
280 win->remote_host = NULL;
281 win->remote_port = -1;
284 /* Initialize ID caches */
285 win->client_cache = silc_idcache_alloc(0);
286 win->channel_cache = silc_idcache_alloc(0);
287 win->server_cache = silc_idcache_alloc(0);
289 /* Create the actual screen */
290 screen = (void *)silc_screen_create_output_window(client->screen);
291 silc_screen_create_input_window(client->screen);
292 silc_screen_init_upper_status_line(client->screen);
293 silc_screen_init_output_status_line(client->screen);
294 win->screen = screen;
296 client->screen->bottom_line->nickname = win->nickname;
297 silc_screen_print_bottom_line(client->screen, 0);
299 /* Add the window to windows table */
300 client->windows = silc_calloc(1, sizeof(*client->windows));
301 client->windows[client->windows_count] = win;
302 client->windows_count = 1;
304 /* Automatically becomes the current active window */
305 client->current_win = win;
310 /* Allocates and adds new window to the client. This allocates new
311 physical window and internal window for connection specific data.
312 All the connection specific data is always saved into a window
313 since connection is always associated to a active window. */
315 SilcClientWindow silc_client_add_window(SilcClient client,
318 SilcClientWindow win;
320 assert(client->screen != NULL);
322 win = silc_calloc(1, sizeof(*win));
324 /* Add the pointers */
325 win->screen = silc_screen_add_output_window(client->screen);
328 /* Initialize ID caches */
329 win->client_cache = silc_idcache_alloc(0);
330 win->channel_cache = silc_idcache_alloc(0);
331 win->server_cache = silc_idcache_alloc(0);
333 /* Add the window to windows table */
334 client->windows = silc_realloc(client->windows, sizeof(*client->windows)
335 * (client->windows_count + 1));
336 client->windows[client->windows_count] = win;
337 client->windows_count++;
339 if (is_current == TRUE)
340 client->current_win = win;
345 /* The main task on SILC client. This processes the key pressings user
348 SILC_TASK_CALLBACK(silc_client_process_key_press)
350 SilcClient client = (SilcClient)context;
353 /* There is data pending in stdin, this gets it directly */
354 c = wgetch(client->screen->input_win);
355 if (silc_client_bad_keys(c))
358 SILC_LOG_DEBUG(("Pressed key: %d", c));
362 * Special character handling
369 SILC_LOG_DEBUG(("RIGHT"));
370 silc_screen_input_cursor_right(client->screen);
374 SILC_LOG_DEBUG(("LEFT"));
375 silc_screen_input_cursor_left(client->screen);
382 silc_screen_input_backspace(client->screen);
388 /* Insert switch. Turns on/off insert on input window */
389 silc_screen_input_insert(client->screen);
393 /* Enter, Return. User pressed enter we are ready to
394 process the message. */
395 silc_client_process_message(client);
396 silc_screen_input_reset(client->screen);
399 /* Refresh screen, Ctrl^l */
400 silc_screen_refresh_all(client->screen);
405 /* Beginning, Home */
406 silc_screen_input_cursor_home(client->screen);
411 silc_screen_input_cursor_end(client->screen);
429 /* Control codes are printed as reversed */
431 wattron(client->screen->input_win, A_REVERSE);
432 silc_screen_input_print(client->screen, c);
433 wattroff(client->screen->input_win, A_REVERSE);
435 /* Normal character */
436 silc_screen_input_print(client->screen, c);
440 silc_screen_print_coordinates(client->screen, 0);
441 silc_screen_refresh_win(client->screen->input_win);
444 static int silc_client_bad_keys(unsigned char key)
446 /* these are explained in curses.h */
461 case '\E': /* we ignore ESC */
468 /* Processes messages user has typed on the screen. This either sends
469 a packet out to network or if command were written executes it. */
471 static void silc_client_process_message(SilcClient client)
476 SILC_LOG_DEBUG(("Start"));
478 data = client->input_buffer->data;
481 if (data[0] == '/' && data[1] != ' ') {
483 unsigned int argc = 0;
484 unsigned char **argv, *tmpcmd;
485 unsigned int *argv_lens, *argv_types;
486 SilcClientCommand *cmd;
487 SilcClientCommandContext ctx;
489 /* Get the command */
490 tmpcmd = silc_client_parse_command(data);
492 /* Find command match */
493 for (cmd = silc_command_list; cmd->name; cmd++) {
494 if (!strncmp(cmd->name, tmpcmd, strlen(tmpcmd)))
498 if (cmd->name == NULL) {
499 silc_say(client, "Invalid command: %s", tmpcmd);
504 /* Now parse all arguments */
505 silc_client_parse_command_line(data, &argv, &argv_lens,
506 &argv_types, &argc, cmd->max_args);
509 SILC_LOG_DEBUG(("Exeuting command: %s", cmd->name));
511 /* Allocate command context. This and its internals must be free'd
512 by the command routine receiving it. */
513 ctx = silc_calloc(1, sizeof(*ctx));
514 ctx->client = client;
515 ctx->sock = client->current_win->sock;
518 ctx->argv_lens = argv_lens;
519 ctx->argv_types = argv_types;
521 /* Execute command */
525 /* Normal message to a channel */
526 if (len && client->current_win->current_channel &&
527 client->current_win->current_channel->on_channel == TRUE) {
528 silc_print(client, "> %s", data);
529 silc_client_packet_send_to_channel(client,
530 client->current_win->sock,
531 client->current_win->current_channel,
532 data, strlen(data), TRUE);
537 /* Clear the input buffer */
538 silc_buffer_clear(client->input_buffer);
539 silc_buffer_pull_tail(client->input_buffer,
540 SILC_BUFFER_END(client->input_buffer));
543 /* Returns the command fetched from user typed command line */
545 static char *silc_client_parse_command(unsigned char *buffer)
548 const char *cp = buffer;
551 len = strcspn(cp, " ");
552 ret = silc_to_upper((char *)++cp);
558 /* Parses user typed command line. At most `max_args' is taken. Rest
559 of the line will be allocated as the last argument if there are more
560 than `max_args' arguments in the line. Note that the command name
561 is counted as one argument and is saved. */
563 void silc_client_parse_command_line(unsigned char *buffer,
564 unsigned char ***parsed,
565 unsigned int **parsed_lens,
566 unsigned int **parsed_types,
567 unsigned int *parsed_num,
568 unsigned int max_args)
572 const char *cp = buffer;
574 /* Take the '/' away */
577 *parsed = silc_calloc(1, sizeof(**parsed));
578 *parsed_lens = silc_calloc(1, sizeof(**parsed_lens));
580 /* Get the command first */
581 len = strcspn(cp, " ");
582 (*parsed)[0] = silc_to_upper((char *)cp);
583 (*parsed_lens)[0] = len;
587 /* Parse arguments */
588 if (strchr(cp, ' ') || strlen(cp) != 0) {
589 for (i = 1; i < max_args; i++) {
591 if (i != max_args - 1)
592 len = strcspn(cp, " ");
596 *parsed = silc_realloc(*parsed, sizeof(**parsed) * (argc + 1));
597 *parsed_lens = silc_realloc(*parsed_lens,
598 sizeof(**parsed_lens) * (argc + 1));
599 (*parsed)[argc] = silc_calloc(len + 1, sizeof(char));
600 memcpy((*parsed)[argc], cp, len);
601 (*parsed_lens)[argc] = len;
612 /* Save argument types. Protocol defines all argument types but
613 this implementation makes sure that they are always in correct
614 order hence this simple code. */
615 *parsed_types = silc_calloc(argc, sizeof(**parsed_types));
616 for (i = 0; i < argc; i++)
617 (*parsed_types)[i] = i;
622 /* Updates clock on the screen every minute. */
624 SILC_TASK_CALLBACK(silc_client_update_clock)
626 SilcClient client = (SilcClient)context;
628 /* Update the clock on the screen */
629 silc_screen_print_clock(client->screen);
631 /* Re-register this same task */
632 silc_task_register(qptr, 0, silc_client_update_clock, context,
633 silc_client_time_til_next_min(), 0,
637 silc_screen_refresh_win(client->screen->input_win);
640 /* Runs commands user configured in configuration file. This is
641 called when initializing client. */
643 SILC_TASK_CALLBACK(silc_client_run_commands)
645 SilcClient client = (SilcClient)context;
646 SilcClientConfigSectionCommand *cs;
648 SILC_LOG_DEBUG(("Start"));
650 cs = client->config->commands;
652 unsigned int argc = 0;
653 unsigned char **argv, *tmpcmd;
654 unsigned int *argv_lens, *argv_types;
655 SilcClientCommand *cmd;
656 SilcClientCommandContext ctx;
658 /* Get the command */
659 tmpcmd = silc_client_parse_command(cs->command);
661 for (cmd = silc_command_list; cmd->name; cmd++) {
662 if (!strcmp(cmd->name, tmpcmd))
666 if (cmd->name == NULL) {
667 silc_say(client, "Invalid command: %s", tmpcmd);
672 /* Now parse all arguments */
673 silc_client_parse_command_line(cs->command, &argv, &argv_lens,
674 &argv_types, &argc, cmd->max_args);
677 SILC_LOG_DEBUG(("Exeuting command: %s", cmd->name));
679 /* Allocate command context. This and its internals must be free'd
680 by the command routine receiving it. */
681 ctx = silc_calloc(1, sizeof(*ctx));
682 ctx->client = client;
683 ctx->sock = client->current_win->sock;
686 ctx->argv_lens = argv_lens;
687 ctx->argv_types = argv_types;
689 /* Execute command */
696 /* Internal context for connection process. This is needed as we
697 doing asynchronous connecting. */
705 } SilcClientInternalConnectContext;
708 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
712 /* XXX In the future we should give up this non-blocking connect all
713 together and use threads instead. */
714 /* Create connection to server asynchronously */
715 sock = silc_net_create_connection_async(ctx->port, ctx->host);
719 /* Register task that will receive the async connect and will
721 ctx->task = silc_task_register(ctx->client->io_queue, sock,
722 silc_client_connect_to_server_start,
725 SILC_TASK_PRI_NORMAL);
726 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
727 silc_schedule_set_listen_fd(sock, ctx->task->iomask);
734 /* Connects to remote server */
736 int silc_client_connect_to_server(SilcClient client, int port,
739 SilcClientInternalConnectContext *ctx;
741 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
744 silc_say(client, "Connecting to port %d of server %s", port, host);
746 client->current_win->remote_host = strdup(host);
747 client->current_win->remote_port = port;
749 /* Allocate internal context for connection process. This is
750 needed as we are doing async connecting. */
751 ctx = silc_calloc(1, sizeof(*ctx));
752 ctx->client = client;
753 ctx->host = strdup(host);
757 /* Do the actual connecting process */
758 return silc_client_connect_to_server_internal(ctx);
761 /* Start of the connection to the remote server. This is called after
762 succesful TCP/IP connection has been established to the remote host. */
764 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
766 SilcClientInternalConnectContext *ctx =
767 (SilcClientInternalConnectContext *)context;
768 SilcClient client = ctx->client;
769 SilcProtocol protocol;
770 SilcClientKEInternalContext *proto_ctx;
771 int opt, opt_len = sizeof(opt);
773 SILC_LOG_DEBUG(("Start"));
775 /* Check the socket status as it might be in error */
776 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
778 if (ctx->tries < 2) {
779 /* Connection failed but lets try again */
780 silc_say(ctx->client, "Could not connect to server %s: %s",
781 ctx->host, strerror(opt));
782 silc_say(client, "Connecting to port %d of server %s resumed",
783 ctx->port, ctx->host);
785 /* Unregister old connection try */
786 silc_schedule_unset_listen_fd(fd);
787 silc_net_close_connection(fd);
788 silc_task_unregister(client->io_queue, ctx->task);
791 silc_client_connect_to_server_internal(ctx);
794 /* Connection failed and we won't try anymore */
795 silc_say(ctx->client, "Could not connect to server %s: %s",
796 ctx->host, strerror(opt));
797 silc_schedule_unset_listen_fd(fd);
798 silc_net_close_connection(fd);
799 silc_task_unregister(client->io_queue, ctx->task);
805 silc_schedule_unset_listen_fd(fd);
806 silc_task_unregister(client->io_queue, ctx->task);
809 /* Allocate new socket connection object */
810 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER,
811 (void *)client->current_win,
812 &client->current_win->sock);
813 if (client->current_win->sock == NULL) {
814 silc_say(client, "Error: Could not allocate connection socket");
815 silc_net_close_connection(fd);
818 client->current_win->sock->hostname = client->current_win->remote_host;
819 client->current_win->sock->port = client->current_win->remote_port;
821 /* Allocate internal Key Exchange context. This is sent to the
822 protocol as context. */
823 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
824 proto_ctx->client = (void *)client;
825 proto_ctx->sock = client->current_win->sock;
826 proto_ctx->rng = client->rng;
827 proto_ctx->responder = FALSE;
829 /* Perform key exchange protocol. silc_client_connect_to_server_final
830 will be called after the protocol is finished. */
831 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
832 &protocol, (void *)proto_ctx,
833 silc_client_connect_to_server_second);
835 silc_say(client, "Error: Could not start authentication protocol");
838 client->current_win->sock->protocol = protocol;
840 /* Register the connection for network input and output. This sets
841 that scheduler will listen for incoming packets for this connection
842 and sets that outgoing packets may be sent to this connection as well.
843 However, this doesn't set the scheduler for outgoing traffic, it will
844 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
845 later when outgoing data is available. */
846 context = (void *)client;
847 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
849 /* Execute the protocol */
850 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
853 /* Second part of the connecting to the server. This executed
854 authentication protocol. */
856 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
858 SilcProtocol protocol = (SilcProtocol)context;
859 SilcClientKEInternalContext *ctx =
860 (SilcClientKEInternalContext *)protocol->context;
861 SilcClient client = (SilcClient)ctx->client;
862 SilcSocketConnection sock = NULL;
863 SilcClientConnAuthInternalContext *proto_ctx;
865 SILC_LOG_DEBUG(("Start"));
867 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
868 /* Error occured during protocol */
869 SILC_LOG_DEBUG(("Error during KE protocol"));
870 silc_protocol_free(protocol);
872 silc_ske_free(ctx->ske);
874 silc_free(ctx->dest_id);
875 ctx->sock->protocol = NULL;
880 /* Allocate internal context for the authentication protocol. This
881 is sent as context for the protocol. */
882 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
883 proto_ctx->client = (void *)client;
884 proto_ctx->sock = sock = ctx->sock;
885 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
886 proto_ctx->dest_id_type = ctx->dest_id_type;
887 proto_ctx->dest_id = ctx->dest_id;
889 /* Resolve the authentication method to be used in this connection */
890 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
891 if (client->config->conns) {
892 SilcClientConfigSectionConnection *conn = NULL;
894 /* Check if we find a match from user configured connections */
895 conn = silc_client_config_find_connection(client->config,
899 /* Match found. Use the configured authentication method */
900 proto_ctx->auth_meth = conn->auth_meth;
901 if (conn->auth_data) {
902 proto_ctx->auth_data = strdup(conn->auth_data);
903 proto_ctx->auth_data_len = strlen(conn->auth_data);
906 /* No match found. Resolve by sending AUTH_REQUEST to server */
907 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
910 /* XXX Resolve by sending AUTH_REQUEST to server */
911 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
914 /* Free old protocol as it is finished now */
915 silc_protocol_free(protocol);
917 silc_buffer_free(ctx->packet);
919 /* silc_free(ctx->keymat....); */
920 sock->protocol = NULL;
922 /* Allocate the authentication protocol. This is allocated here
923 but we won't start it yet. We will be receiving party of this
924 protocol thus we will wait that connecting party will make
926 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
927 &sock->protocol, (void *)proto_ctx,
928 silc_client_connect_to_server_final);
930 /* Execute the protocol */
931 sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
934 /* Finalizes the connection to the remote SILC server. This is called
935 after authentication protocol has been completed. This send our
936 user information to the server to receive our client ID from
939 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
941 SilcProtocol protocol = (SilcProtocol)context;
942 SilcClientConnAuthInternalContext *ctx =
943 (SilcClientConnAuthInternalContext *)protocol->context;
944 SilcClient client = (SilcClient)ctx->client;
945 SilcClientWindow win = (SilcClientWindow)ctx->sock->user_data;
948 SILC_LOG_DEBUG(("Start"));
950 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
951 /* Error occured during protocol */
952 SILC_LOG_DEBUG(("Error during authentication protocol"));
953 silc_protocol_free(protocol);
955 silc_free(ctx->auth_data);
957 silc_ske_free(ctx->ske);
959 silc_free(ctx->dest_id);
961 win->sock->protocol = NULL;
965 /* Send NEW_CLIENT packet to the server. We will become registered
966 to the SILC network after sending this packet and we will receive
967 client ID from the server. */
968 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
969 strlen(client->realname));
970 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
971 silc_buffer_format(packet,
972 SILC_STR_UI_SHORT(strlen(client->username)),
973 SILC_STR_UI_XNSTRING(client->username,
974 strlen(client->username)),
975 SILC_STR_UI_SHORT(strlen(client->realname)),
976 SILC_STR_UI_XNSTRING(client->realname,
977 strlen(client->realname)),
980 /* Send the packet */
981 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
983 packet->data, packet->len, TRUE);
984 silc_buffer_free(packet);
986 /* Save remote ID. */
987 win->remote_id = ctx->dest_id;
988 win->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_CHANNEL);
989 win->remote_id_data_len = SILC_ID_CHANNEL_LEN;
991 silc_say(client, "Connected to port %d of host %s",
992 win->remote_port, win->remote_host);
994 client->screen->bottom_line->connection = win->remote_host;
995 silc_screen_print_bottom_line(client->screen, 0);
997 silc_protocol_free(protocol);
999 silc_free(ctx->auth_data);
1001 silc_ske_free(ctx->ske);
1003 silc_free(ctx->dest_id);
1005 win->sock->protocol = NULL;
1008 /* Internal routine that sends packet or marks packet to be sent. This
1009 is used directly only in special cases. Normal cases should use
1010 silc_server_packet_send. Returns < 0 on error. */
1012 static int silc_client_packet_send_real(SilcClient client,
1013 SilcSocketConnection sock,
1018 /* Send the packet */
1019 ret = silc_packet_send(sock, force_send);
1023 /* Mark that there is some outgoing data available for this connection.
1024 This call sets the connection both for input and output (the input
1025 is set always and this call keeps the input setting, actually).
1026 Actual data sending is performed by silc_client_packet_process. */
1027 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
1029 /* Mark to socket that data is pending in outgoing buffer. This flag
1030 is needed if new data is added to the buffer before the earlier
1031 put data is sent to the network. */
1032 SILC_SET_OUTBUF_PENDING(sock);
1037 /* Packet processing callback. This is used to send and receive packets
1038 from network. This is generic task. */
1040 SILC_TASK_CALLBACK(silc_client_packet_process)
1042 SilcClient client = (SilcClient)context;
1043 SilcSocketConnection sock = NULL;
1044 SilcClientWindow win;
1047 SILC_LOG_DEBUG(("Processing packet"));
1049 SILC_CLIENT_GET_SOCK(client, fd, sock);
1053 win = (SilcClientWindow)sock->user_data;
1055 /* Packet sending */
1056 if (type == SILC_TASK_WRITE) {
1057 SILC_LOG_DEBUG(("Writing data to connection"));
1059 if (sock->outbuf->data - sock->outbuf->head)
1060 silc_buffer_push(sock->outbuf,
1061 sock->outbuf->data - sock->outbuf->head);
1063 ret = silc_client_packet_send_real(client, sock, TRUE);
1065 /* If returned -2 could not write to connection now, will do
1070 /* The packet has been sent and now it is time to set the connection
1071 back to only for input. When there is again some outgoing data
1072 available for this connection it will be set for output as well.
1073 This call clears the output setting and sets it only for input. */
1074 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
1075 SILC_UNSET_OUTBUF_PENDING(sock);
1077 silc_buffer_clear(sock->outbuf);
1081 /* Packet receiving */
1082 if (type == SILC_TASK_READ) {
1083 SILC_LOG_DEBUG(("Reading data from connection"));
1085 /* Read data from network */
1086 ret = silc_packet_receive(sock);
1092 SILC_LOG_DEBUG(("Read EOF"));
1094 /* If connection is disconnecting already we will finally
1095 close the connection */
1096 if (SILC_IS_DISCONNECTING(sock)) {
1097 silc_client_close_connection(client, sock);
1101 silc_say(client, "Connection closed: premature EOF");
1102 SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
1104 silc_client_close_connection(client, sock);
1108 /* Process the packet. This will call the parser that will then
1109 decrypt and parse the packet. */
1110 if (!silc_packet_receive_process(sock, win->receive_key, win->hmac,
1111 silc_client_packet_parse, client)) {
1112 silc_buffer_clear(sock->inbuf);
1118 /* Parses whole packet, received earlier. */
1120 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
1122 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
1123 SilcClient client = (SilcClient)parse_ctx->context;
1124 SilcPacketContext *packet = parse_ctx->packet;
1125 SilcBuffer buffer = packet->buffer;
1126 SilcSocketConnection sock = parse_ctx->sock;
1127 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1130 SILC_LOG_DEBUG(("Start"));
1132 /* Decrypt the received packet */
1133 ret = silc_packet_decrypt(win->receive_key, win->hmac, buffer, packet);
1138 /* Parse the packet. Packet type is returned. */
1139 ret = silc_packet_parse(packet);
1141 /* Parse the packet header in special way as this is "special"
1143 ret = silc_packet_parse_special(packet);
1146 if (ret == SILC_PACKET_NONE)
1149 /* Parse the incoming packet type */
1150 silc_client_packet_parse_type(client, sock, packet);
1153 silc_buffer_clear(buffer);
1155 silc_free(parse_ctx);
1158 /* Parser callback called by silc_packet_receive_process. Thie merely
1159 registers timeout that will handle the actual parsing when appropriate. */
1161 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
1163 SilcClient client = (SilcClient)parser_context->context;
1164 SilcClientWindow win = (SilcClientWindow)parser_context->sock->user_data;
1166 /* If this packet is for the current active connection we will
1167 parse the packet right away to get it quickly on the screen.
1168 Otherwise, it will be parsed with a timeout as the data is
1169 for inactive window (which might not be visible at all). */
1170 if (SILC_CLIENT_IS_CURRENT_WIN(client, win)) {
1171 /* Parse it real soon */
1172 silc_task_register(client->timeout_queue, parser_context->sock->sock,
1173 silc_client_packet_parse_real,
1174 (void *)parser_context, 0, 1,
1176 SILC_TASK_PRI_NORMAL);
1178 /* Parse the packet with timeout */
1179 silc_task_register(client->timeout_queue, parser_context->sock->sock,
1180 silc_client_packet_parse_real,
1181 (void *)parser_context, 0, 200000,
1183 SILC_TASK_PRI_NORMAL);
1187 /* Parses the packet type and calls what ever routines the packet type
1188 requires. This is done for all incoming packets. */
1190 void silc_client_packet_parse_type(SilcClient client,
1191 SilcSocketConnection sock,
1192 SilcPacketContext *packet)
1194 SilcBuffer buffer = packet->buffer;
1195 SilcPacketType type = packet->type;
1197 SILC_LOG_DEBUG(("Parsing packet type %d", type));
1199 /* Parse the packet type */
1201 case SILC_PACKET_DISCONNECT:
1202 silc_client_disconnected_by_server(client, sock, buffer);
1204 case SILC_PACKET_SUCCESS:
1206 * Success received for something. For now we can have only
1207 * one protocol for connection executing at once hence this
1208 * success message is for whatever protocol is executing currently.
1210 if (sock->protocol) {
1211 sock->protocol->execute(client->timeout_queue, 0,
1212 sock->protocol, sock->sock, 0, 0);
1215 case SILC_PACKET_FAILURE:
1217 * Failure received for some protocol. Set the protocol state to
1218 * error and call the protocol callback. This fill cause error on
1219 * protocol and it will call the final callback.
1221 if (sock->protocol) {
1222 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1223 sock->protocol->execute(client->timeout_queue, 0,
1224 sock->protocol, sock->sock, 0, 0);
1227 case SILC_PACKET_REJECT:
1230 case SILC_PACKET_NOTIFY:
1232 * Received notify message
1234 silc_client_notify_by_server(client, sock, buffer);
1237 case SILC_PACKET_ERROR:
1239 * Received error message
1241 silc_client_error_by_server(client, sock, buffer);
1244 case SILC_PACKET_CHANNEL_MESSAGE:
1246 * Received message to (from, actually) a channel
1248 silc_client_channel_message(client, sock, packet);
1250 case SILC_PACKET_CHANNEL_KEY:
1252 * Received key for a channel. By receiving this key the client will be
1253 * able to talk to the channel it has just joined. This can also be
1254 * a new key for existing channel as keys expire peridiocally.
1256 silc_client_receive_channel_key(client, sock, buffer);
1259 case SILC_PACKET_PRIVATE_MESSAGE:
1261 * Received private message
1264 SilcClientCommandReplyContext ctx;
1265 ctx = silc_calloc(1, sizeof(*ctx));
1266 ctx->client = client;
1268 ctx->context = buffer; /* kludge */
1269 silc_client_command_reply_msg((void *)ctx);
1272 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1274 * Received private message key
1278 case SILC_PACKET_COMMAND_REPLY:
1280 * Recived reply for a command
1282 silc_client_command_reply_process(client, sock, packet);
1285 case SILC_PACKET_KEY_EXCHANGE:
1286 if (sock->protocol) {
1287 SilcClientKEInternalContext *proto_ctx =
1288 (SilcClientKEInternalContext *)sock->protocol->context;
1290 proto_ctx->packet = buffer;
1291 proto_ctx->dest_id_type = packet->src_id_type;
1292 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
1294 /* Let the protocol handle the packet */
1295 sock->protocol->execute(client->timeout_queue, 0,
1296 sock->protocol, sock->sock, 0, 0);
1298 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1299 "protocol active, packet dropped."));
1301 /* XXX Trigger KE protocol?? Rekey actually! */
1305 case SILC_PACKET_KEY_EXCHANGE_1:
1306 if (sock->protocol) {
1309 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1310 "protocol active, packet dropped."));
1313 case SILC_PACKET_KEY_EXCHANGE_2:
1314 if (sock->protocol) {
1315 SilcClientKEInternalContext *proto_ctx =
1316 (SilcClientKEInternalContext *)sock->protocol->context;
1318 if (proto_ctx->packet)
1319 silc_buffer_free(proto_ctx->packet);
1321 proto_ctx->packet = buffer;
1322 proto_ctx->dest_id_type = packet->src_id_type;
1323 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
1325 /* Let the protocol handle the packet */
1326 sock->protocol->execute(client->timeout_queue, 0,
1327 sock->protocol, sock->sock, 0, 0);
1329 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1330 "protocol active, packet dropped."));
1334 case SILC_PACKET_NEW_ID:
1337 * Received new ID from server. This packet is received at
1338 * the connection to the server. New ID is also received when
1339 * user changes nickname but in that case the new ID is received
1340 * as command reply and not as this packet type.
1342 unsigned char *id_string;
1343 unsigned short id_type;
1345 silc_buffer_unformat(buffer,
1346 SILC_STR_UI_SHORT(&id_type),
1347 SILC_STR_UI16_STRING_ALLOC(&id_string),
1350 if ((SilcIdType)id_type != SILC_ID_CLIENT)
1353 silc_client_receive_new_id(client, sock, id_string);
1354 silc_free(id_string);
1359 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1364 /* Sends packet. This doesn't actually send the packet instead it assembles
1365 it and marks it to be sent. However, if force_send is TRUE the packet
1366 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1367 will be derived from sock argument. Otherwise the valid arguments sent
1370 void silc_client_packet_send(SilcClient client,
1371 SilcSocketConnection sock,
1372 SilcPacketType type,
1374 SilcIdType dst_id_type,
1377 unsigned char *data,
1378 unsigned int data_len,
1381 SilcPacketContext packetdata;
1383 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1385 /* Get data used in the packet sending, keys and stuff */
1386 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1387 if (!cipher && ((SilcClientWindow)sock->user_data)->send_key)
1388 cipher = ((SilcClientWindow)sock->user_data)->send_key;
1390 if (!hmac && ((SilcClientWindow)sock->user_data)->hmac)
1391 hmac = ((SilcClientWindow)sock->user_data)->hmac;
1393 if (!dst_id && ((SilcClientWindow)sock->user_data)->remote_id) {
1394 dst_id = ((SilcClientWindow)sock->user_data)->remote_id;
1395 dst_id_type = SILC_ID_SERVER;
1399 /* Set the packet context pointers */
1400 packetdata.flags = 0;
1401 packetdata.type = type;
1402 if (((SilcClientWindow)sock->user_data)->local_id_data)
1403 packetdata.src_id = ((SilcClientWindow)sock->user_data)->local_id_data;
1405 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1406 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1407 packetdata.src_id_type = SILC_ID_CLIENT;
1409 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1410 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
1411 packetdata.dst_id_type = dst_id_type;
1413 packetdata.dst_id = NULL;
1414 packetdata.dst_id_len = 0;
1415 packetdata.dst_id_type = SILC_ID_NONE;
1417 packetdata.rng = client->rng;
1418 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1419 packetdata.src_id_len + packetdata.dst_id_len;
1420 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1422 /* Prepare outgoing data buffer for packet sending */
1423 silc_packet_send_prepare(sock,
1424 SILC_PACKET_HEADER_LEN +
1425 packetdata.src_id_len +
1426 packetdata.dst_id_len,
1430 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1432 packetdata.buffer = sock->outbuf;
1434 /* Put the data to the buffer */
1435 if (data && data_len)
1436 silc_buffer_put(sock->outbuf, data, data_len);
1438 /* Create the outgoing packet */
1439 silc_packet_assemble(&packetdata);
1441 /* Encrypt the packet */
1443 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1445 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1446 sock->outbuf->data, sock->outbuf->len);
1448 /* Now actually send the packet */
1449 silc_client_packet_send_real(client, sock, force_send);
1452 /* Sends packet to a channel. Packet to channel is always encrypted
1453 differently from "normal" packets. SILC header of the packet is
1454 encrypted with the next receiver's key and the rest of the packet is
1455 encrypted with the channel specific key. Padding and HMAC is computed
1456 with the next receiver's key. */
1458 void silc_client_packet_send_to_channel(SilcClient client,
1459 SilcSocketConnection sock,
1460 SilcChannelEntry channel,
1461 unsigned char *data,
1462 unsigned int data_len,
1466 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1468 SilcPacketContext packetdata;
1471 unsigned char *id_string;
1473 SILC_LOG_DEBUG(("Sending packet to channel"));
1475 if (!channel || !channel->key) {
1476 silc_say(client, "Cannot talk to channel: key does not exist");
1482 for (i = 0; i < 16; i++)
1483 channel->iv[i] = silc_rng_get_byte(client->rng);
1485 silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
1487 /* Encode the channel payload */
1488 payload = silc_channel_encode_payload(strlen(win->nickname), win->nickname,
1489 data_len, data, 16, channel->iv,
1493 "Error: Could not create packet to be sent to the channel");
1497 /* Get data used in packet header encryption, keys and stuff. Rest
1498 of the packet (the payload) is, however, encrypted with the
1499 specified channel key. */
1500 cipher = win->send_key;
1502 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1504 /* Set the packet context pointers. The destination ID is always
1505 the Channel ID of the channel. Server and router will handle the
1506 distribution of the packet. */
1507 packetdata.flags = 0;
1508 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1509 packetdata.src_id = win->local_id_data;
1510 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1511 packetdata.src_id_type = SILC_ID_CLIENT;
1512 packetdata.dst_id = id_string;
1513 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1514 packetdata.dst_id_type = SILC_ID_CHANNEL;
1515 packetdata.rng = client->rng;
1516 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
1517 packetdata.src_id_len + packetdata.dst_id_len;
1518 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1519 packetdata.src_id_len +
1520 packetdata.dst_id_len));
1522 /* Prepare outgoing data buffer for packet sending */
1523 silc_packet_send_prepare(sock,
1524 SILC_PACKET_HEADER_LEN +
1525 packetdata.src_id_len +
1526 packetdata.dst_id_len,
1530 packetdata.buffer = sock->outbuf;
1532 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1533 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1534 payload->data, payload->data,
1535 payload->len - 16, /* -IV_LEN */
1538 /* Put the actual encrypted payload data into the buffer. */
1539 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1541 /* Create the outgoing packet */
1542 silc_packet_assemble(&packetdata);
1544 /* Encrypt the header and padding of the packet. This is encrypted
1545 with normal session key shared with our server. */
1546 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1547 packetdata.src_id_len + packetdata.dst_id_len +
1550 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1551 sock->outbuf->data, sock->outbuf->len);
1553 /* Now actually send the packet */
1554 silc_client_packet_send_real(client, sock, force_send);
1555 silc_buffer_free(payload);
1556 silc_free(id_string);
1559 /* Sends private message to remote client. If private message key has
1560 not been set with this client then the message will be encrypted using
1561 normal session keys. Private messages are special packets in SILC
1562 network hence we need this own function for them. This is similiar
1563 to silc_client_packet_send_to_channel except that we send private
1566 void silc_client_packet_send_private_message(SilcClient client,
1567 SilcSocketConnection sock,
1568 SilcClientEntry client_entry,
1569 unsigned char *data,
1570 unsigned int data_len,
1573 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1575 SilcPacketContext packetdata;
1576 unsigned int nick_len;
1580 SILC_LOG_DEBUG(("Sending private message"));
1582 /* Create private message payload */
1583 nick_len = strlen(client->current_win->nickname);
1584 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1585 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1586 silc_buffer_format(buffer,
1587 SILC_STR_UI_SHORT(nick_len),
1588 SILC_STR_UI_XNSTRING(client->current_win->nickname,
1590 SILC_STR_UI_XNSTRING(data, data_len),
1593 /* If we don't have private message specific key then private messages
1594 are just as any normal packet thus call normal packet sending. If
1595 the key exist then the encryption process is a bit different and
1596 will be done in the rest of this function. */
1597 if (!client_entry->send_key) {
1598 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1599 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1600 buffer->data, buffer->len, force_send);
1604 /* We have private message specific key */
1606 /* Get data used in the encryption */
1607 cipher = client_entry->send_key;
1610 /* Set the packet context pointers. */
1611 packetdata.flags = 0;
1612 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1613 packetdata.src_id = win->local_id_data;
1614 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1615 packetdata.src_id_type = SILC_ID_CLIENT;
1617 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1619 packetdata.dst_id = win->local_id_data;
1620 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1621 packetdata.dst_id_type = SILC_ID_CLIENT;
1622 packetdata.rng = client->rng;
1623 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1624 packetdata.src_id_len + packetdata.dst_id_len;
1625 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1626 packetdata.src_id_len +
1627 packetdata.dst_id_len));
1629 /* Prepare outgoing data buffer for packet sending */
1630 silc_packet_send_prepare(sock,
1631 SILC_PACKET_HEADER_LEN +
1632 packetdata.src_id_len +
1633 packetdata.dst_id_len,
1637 packetdata.buffer = sock->outbuf;
1639 /* Encrypt payload of the packet. Encrypt with private message specific
1640 key if it exist, otherwise with session key. */
1641 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1642 buffer->len, cipher->iv);
1644 /* Put the actual encrypted payload data into the buffer. */
1645 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1647 /* Create the outgoing packet */
1648 silc_packet_assemble(&packetdata);
1650 /* Encrypt the header and padding of the packet. */
1651 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1652 packetdata.src_id_len + packetdata.dst_id_len +
1655 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1656 sock->outbuf->data, sock->outbuf->len);
1658 /* Now actually send the packet */
1659 silc_client_packet_send_real(client, sock, force_send);
1660 silc_free(packetdata.dst_id);
1666 /* Closes connection to remote end. Free's all allocated data except
1667 for some information such as nickname etc. that are valid at all time. */
1669 void silc_client_close_connection(SilcClient client,
1670 SilcSocketConnection sock)
1672 SilcClientWindow win;
1674 /* We won't listen for this connection anymore */
1675 silc_schedule_unset_listen_fd(sock->sock);
1677 /* Unregister all tasks */
1678 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1679 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1681 /* Close the actual connection */
1682 silc_net_close_connection(sock->sock);
1684 silc_say(client, "Closed connection to host %s", sock->hostname ?
1685 sock->hostname : sock->ip);
1687 /* Free everything */
1688 if (sock->user_data) {
1689 win = (SilcClientWindow)sock->user_data;
1691 /* XXX Free all client entries and channel entries. */
1693 /* Clear ID caches */
1694 silc_idcache_del_all(win->client_cache);
1695 silc_idcache_del_all(win->channel_cache);
1698 if (win->remote_host)
1699 silc_free(win->remote_host);
1701 silc_free(win->local_id);
1702 if (win->local_id_data)
1703 silc_free(win->local_id_data);
1705 silc_cipher_free(win->send_key);
1706 if (win->receive_key)
1707 silc_cipher_free(win->receive_key);
1709 silc_hmac_free(win->hmac);
1710 if (win->hmac_key) {
1711 memset(win->hmac_key, 0, win->hmac_key_len);
1712 silc_free(win->hmac_key);
1716 win->remote_port = 0;
1717 win->remote_type = 0;
1718 win->send_key = NULL;
1719 win->receive_key = NULL;
1721 win->hmac_key = NULL;
1722 win->hmac_key_len = 0;
1723 win->local_id = NULL;
1724 win->local_id_data = NULL;
1725 win->remote_host = NULL;
1726 win->current_channel = NULL;
1729 if (sock->protocol) {
1730 silc_protocol_free(sock->protocol);
1731 sock->protocol = NULL;
1733 silc_socket_free(sock);
1736 /* Called when we receive disconnection packet from server. This
1737 closes our end properly and displays the reason of the disconnection
1740 void silc_client_disconnected_by_server(SilcClient client,
1741 SilcSocketConnection sock,
1746 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1748 msg = silc_calloc(message->len + 1, sizeof(char));
1749 memcpy(msg, message->data, message->len);
1750 silc_say(client, msg);
1753 SILC_SET_DISCONNECTED(sock);
1754 silc_client_close_connection(client, sock);
1757 /* Received error message from server. Display it on the screen.
1758 We don't take any action what so ever of the error message. */
1760 void silc_client_error_by_server(SilcClient client,
1761 SilcSocketConnection sock,
1766 msg = silc_calloc(message->len + 1, sizeof(char));
1767 memcpy(msg, message->data, message->len);
1768 silc_say(client, msg);
1772 /* Received notify message from server */
1774 void silc_client_notify_by_server(SilcClient client,
1775 SilcSocketConnection sock,
1780 msg = silc_calloc(message->len + 1, sizeof(char));
1781 memcpy(msg, message->data, message->len);
1782 silc_say(client, msg);
1786 /* Processes the received new Client ID from server. Old Client ID is
1787 deleted from cache and new one is added. */
1789 void silc_client_receive_new_id(SilcClient client,
1790 SilcSocketConnection sock,
1791 unsigned char *id_string)
1793 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1795 /* Delete old ID from ID cache */
1796 silc_idcache_del_by_id(win->client_cache, SILC_ID_CLIENT, win->local_id);
1798 /* Save the new ID */
1800 silc_free(win->local_id);
1801 win->local_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
1802 if (win->local_id_data)
1803 silc_free(win->local_id_data);
1804 win->local_id_data =
1805 silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1806 memcpy(win->local_id_data, id_string, SILC_ID_CLIENT_LEN);
1807 win->local_id_data_len = SILC_ID_CLIENT_LEN;
1808 if (!win->local_entry)
1809 win->local_entry = silc_calloc(1, sizeof(*win->local_entry));
1810 win->local_entry->nickname = win->nickname;
1811 win->local_entry->id = win->local_id;
1813 /* Put it to the ID cache */
1814 silc_idcache_add(win->client_cache, win->nickname, SILC_ID_CLIENT,
1815 win->local_id, (void *)win->local_entry, TRUE);
1818 /* Processed received Channel ID for a channel. This is called when client
1819 joins to channel and server replies with channel ID. The ID is cached. */
1821 void silc_client_new_channel_id(SilcClient client,
1822 SilcSocketConnection sock,
1825 unsigned char *id_string)
1827 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1829 SilcChannelEntry channel;
1831 SILC_LOG_DEBUG(("New channel ID"));
1833 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1834 channel = silc_calloc(1, sizeof(*channel));
1835 channel->channel_name = channel_name;
1837 channel->mode = mode;
1838 win->current_channel = channel;
1840 /* Put it to the ID cache */
1841 silc_idcache_add(win->channel_cache, channel_name, SILC_ID_CHANNEL,
1842 (void *)id, (void *)channel, TRUE);
1845 /* Processes received key for channel. The received key will be used
1846 to protect the traffic on the channel for now on. Client must receive
1847 the key to the channel before talking on the channel is possible.
1848 This is the key that server has generated, this is not the channel
1849 private key, it is entirely local setting. */
1851 void silc_client_receive_channel_key(SilcClient client,
1852 SilcSocketConnection sock,
1855 unsigned char *id_string, *key, *cipher;
1856 unsigned int key_len;
1857 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1859 SilcIDCacheEntry id_cache = NULL;
1860 SilcChannelEntry channel;
1861 SilcChannelKeyPayload payload;
1863 SILC_LOG_DEBUG(("Received key for channel"));
1865 payload = silc_channel_key_parse_payload(packet);
1869 id_string = silc_channel_key_get_id(payload, NULL);
1871 silc_channel_key_free_payload(payload);
1874 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1877 if (!silc_idcache_find_by_id_one(win->channel_cache, (void *)id,
1878 SILC_ID_CHANNEL, &id_cache))
1882 key = silc_channel_key_get_key(payload, &key_len);
1883 cipher = silc_channel_key_get_cipher(payload, NULL);
1885 channel = (SilcChannelEntry)id_cache->context;
1886 channel->key_len = key_len;
1887 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1888 memcpy(channel->key, key, key_len);
1890 silc_cipher_alloc(cipher, &channel->channel_key);
1891 if (!channel->channel_key) {
1892 silc_say(client, "Cannot talk to channel: unsupported cipher %s", cipher);
1895 channel->channel_key->cipher->set_key(channel->channel_key->context,
1898 /* Client is now joined to the channel */
1899 channel->on_channel = TRUE;
1903 silc_channel_key_free_payload(payload);
1906 /* Process received message to a channel (or from a channel, really). This
1907 decrypts the channel message with channel specific key and parses the
1908 channel payload. Finally it displays the message on the screen. */
1910 void silc_client_channel_message(SilcClient client,
1911 SilcSocketConnection sock,
1912 SilcPacketContext *packet)
1914 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1915 SilcBuffer buffer = packet->buffer;
1916 SilcChannelPayload payload = NULL;
1917 SilcChannelID *id = NULL;
1918 SilcChannelEntry channel;
1919 SilcIDCacheEntry id_cache = NULL;
1922 if (packet->dst_id_type != SILC_ID_CHANNEL)
1925 id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1927 /* Find the channel entry from channels on this window */
1928 if (!silc_idcache_find_by_id_one(win->channel_cache, (void *)id,
1929 SILC_ID_CHANNEL, &id_cache))
1932 channel = (SilcChannelEntry)id_cache->context;
1934 /* Decrypt the channel message payload. Push the IV out of the way,
1935 since it is not encrypted (after pushing buffer->tail has the IV). */
1936 silc_buffer_push_tail(buffer, 16);
1937 channel->channel_key->cipher->decrypt(channel->channel_key->context,
1938 buffer->data, buffer->data,
1939 buffer->len, buffer->tail);
1940 silc_buffer_pull_tail(buffer, 16);
1942 /* Parse the channel message payload */
1943 payload = silc_channel_parse_payload(buffer);
1947 /* Display the message on screen */
1948 if (packet->src_id_type == SILC_ID_CLIENT) {
1949 /* Message from client */
1950 if (channel == win->current_channel)
1951 silc_print(client, "<%s> %s",
1952 silc_channel_get_nickname(payload, NULL),
1953 silc_channel_get_data(payload, NULL));
1955 silc_print(client, "<%s:%s> %s",
1956 silc_channel_get_nickname(payload, NULL),
1957 channel->channel_name,
1958 silc_channel_get_data(payload, NULL));
1960 /* Message from server */
1961 silc_say(client, "%s", silc_channel_get_data(payload, NULL));
1968 silc_channel_free_payload(payload);