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.12 2000/07/19 07:07:34 priikone
24 * Save packet on private message's command context.
26 * Revision 1.11 2000/07/18 12:20:39 priikone
27 * Added ^U functionality, clears input line (patch form cras).
29 * Revision 1.10 2000/07/18 06:53:15 priikone
30 * Allow partial command strings in comparison.
32 * Revision 1.9 2000/07/14 06:13:19 priikone
33 * Moved all the generic packet sending, encryption, reception,
34 * decryption and processing functions to library as they were
35 * duplicated code with the server. Now client uses the generic
36 * routines which is a lot cleaner.
38 * Revision 1.8 2000/07/12 05:56:32 priikone
39 * Major rewrite of ID Cache system. Support added for the new
42 * Revision 1.7 2000/07/10 05:40:33 priikone
45 * Revision 1.6 2000/07/07 06:54:16 priikone
46 * Print channel name when receiving channel message to non-current
49 * Revision 1.5 2000/07/06 07:14:36 priikone
50 * Fixes to NAMES command handling.
51 * Fixes when leaving from channel.
53 * Revision 1.4 2000/07/05 06:12:05 priikone
54 * Global cosmetic changes.
56 * Revision 1.3 2000/07/04 08:29:12 priikone
57 * Added support for PING command. The ping times are calculated
58 * and showed to the user.
60 * Revision 1.2 2000/07/03 05:49:48 priikone
61 * Implemented LEAVE command. Minor bug fixes.
63 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
64 * Imported from internal CVS/Added Log headers.
69 #include "clientincludes.h"
71 /* Static function prototypes */
72 static int silc_client_bad_keys(unsigned char key);
73 static void silc_client_clear_input(SilcClient client);
74 static void silc_client_process_message(SilcClient client);
75 static char *silc_client_parse_command(unsigned char *buffer);
77 /* Static task callback prototypes */
78 SILC_TASK_CALLBACK(silc_client_update_clock);
79 SILC_TASK_CALLBACK(silc_client_run_commands);
80 SILC_TASK_CALLBACK(silc_client_process_key_press);
81 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
82 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
83 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
84 SILC_TASK_CALLBACK(silc_client_packet_process);
85 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
87 SilcClientWindow silc_client_create_main_window(SilcClient client);
88 SilcClientWindow silc_client_add_window(SilcClient client,
90 void silc_client_packet_parse(SilcPacketParserContext *parser_context);
91 void silc_client_packet_parse_type(SilcClient client,
92 SilcSocketConnection sock,
93 SilcPacketContext *packet);
94 void silc_client_private_message_process(SilcClient client,
95 SilcSocketConnection sock,
96 SilcPacketContext *packet);
98 /* Definitions from version.h */
99 extern char *silc_version;
100 extern char *silc_name;
101 extern char *silc_fullname;
103 /* Allocates new client object. This has to be done before client may
104 work. After calling this one must call silc_client_init to initialize
107 int silc_client_alloc(SilcClient *new_client)
110 *new_client = silc_calloc(1, sizeof(**new_client));
111 (*new_client)->input_buffer = NULL;
112 (*new_client)->screen = NULL;
113 (*new_client)->windows = NULL;
114 (*new_client)->windows_count = 0;
115 (*new_client)->current_win = NULL;
120 /* Free's client object */
122 void silc_client_free(SilcClient client)
129 /* Initializes the client. This makes all the necessary steps to make
130 the client ready to be run. One must call silc_client_run to run the
133 int silc_client_init(SilcClient client)
136 SILC_LOG_DEBUG(("Initializing client"));
139 client->username = silc_get_username();
140 client->realname = silc_get_real_name();
142 /* Register all configured ciphers, PKCS and hash functions. */
143 client->config->client = (void *)client;
144 silc_client_config_register_ciphers(client->config);
145 silc_client_config_register_pkcs(client->config);
146 silc_client_config_register_hashfuncs(client->config);
148 /* Initialize hash functions for client to use */
149 silc_hash_alloc("md5", &client->md5hash);
150 silc_hash_alloc("sha1", &client->sha1hash);
152 /* Initialize none cipher */
153 silc_cipher_alloc("none", &client->none_cipher);
155 /* Initialize random number generator */
156 client->rng = silc_rng_alloc();
157 silc_rng_init(client->rng);
158 silc_math_primegen_init(); /* XXX */
160 /* Load public and private key */
161 if (silc_client_load_keys(client) == FALSE)
164 /* Register the task queues. In SILC we have by default three task queues.
165 One task queue for non-timeout tasks which perform different kind of
166 I/O on file descriptors, timeout task queue for timeout tasks, and,
167 generic non-timeout task queue whose tasks apply to all connections. */
168 silc_task_queue_alloc(&client->io_queue, TRUE);
169 if (!client->io_queue) {
172 silc_task_queue_alloc(&client->timeout_queue, TRUE);
173 if (!client->timeout_queue) {
176 silc_task_queue_alloc(&client->generic_queue, TRUE);
177 if (!client->generic_queue) {
181 /* Initialize the scheduler */
182 silc_schedule_init(client->io_queue, client->timeout_queue,
183 client->generic_queue, 5000);
185 /* Register the main task that is used in client. This received
186 the key pressings. */
187 if (silc_task_register(client->io_queue, fileno(stdin),
188 silc_client_process_key_press,
189 (void *)client, 0, 0,
191 SILC_TASK_PRI_NORMAL) == NULL) {
195 /* Register timeout task that updates clock every minute. */
196 if (silc_task_register(client->timeout_queue, 0,
197 silc_client_update_clock,
199 silc_client_time_til_next_min(), 0,
201 SILC_TASK_PRI_LOW) == NULL) {
205 if (client->config->commands) {
206 /* Run user configured commands with timeout */
207 if (silc_task_register(client->timeout_queue, 0,
208 silc_client_run_commands,
209 (void *)client, 0, 1,
211 SILC_TASK_PRI_LOW) == NULL) {
216 /* Allocate the input buffer used to save typed characters */
217 client->input_buffer = silc_buffer_alloc(SILC_SCREEN_INPUT_WIN_SIZE);
218 silc_buffer_pull_tail(client->input_buffer,
219 SILC_BUFFER_END(client->input_buffer));
221 /* Initialize the screen */
222 client->screen = silc_screen_init();
223 silc_client_create_main_window(client);
224 client->screen->input_buffer = client->input_buffer->data;
225 silc_screen_print_coordinates(client->screen, 0);
230 silc_task_queue_free(client->timeout_queue);
232 silc_task_queue_free(client->io_queue);
237 /* Stops the client. This is called to stop the client and thus to stop
240 void silc_client_stop(SilcClient client)
242 SILC_LOG_DEBUG(("Stopping client"));
244 /* Stop the scheduler, although it might be already stopped. This
245 doesn't hurt anyone. This removes all the tasks and task queues,
247 silc_schedule_stop();
248 silc_schedule_uninit();
250 SILC_LOG_DEBUG(("Client client"));
253 /* Runs the client. */
255 void silc_client_run(SilcClient client)
257 SILC_LOG_DEBUG(("Running client"));
259 /* Start the scheduler, the heart of the SILC client. When this returns
260 the program will be terminated. */
264 /* Creates the main window used in SILC client. This is called always
265 at the initialization of the client. If user wants to create more
266 than one windows a new windows are always created by calling
267 silc_client_add_window. */
269 SilcClientWindow silc_client_create_main_window(SilcClient client)
271 SilcClientWindow win;
274 SILC_LOG_DEBUG(("Creating main window"));
276 assert(client->screen != NULL);
278 client->screen->u_stat_line.program_name = silc_name;
279 client->screen->u_stat_line.program_version = silc_version;
282 win = silc_calloc(1, sizeof(*win));
283 win->nickname = silc_get_username();
284 win->local_id = NULL;
285 win->local_id_data = NULL;
286 win->local_id_data_len = 0;
287 win->remote_host = NULL;
288 win->remote_port = -1;
291 /* Initialize ID caches */
292 win->client_cache = silc_idcache_alloc(0);
293 win->channel_cache = silc_idcache_alloc(0);
294 win->server_cache = silc_idcache_alloc(0);
296 /* Create the actual screen */
297 screen = (void *)silc_screen_create_output_window(client->screen);
298 silc_screen_create_input_window(client->screen);
299 silc_screen_init_upper_status_line(client->screen);
300 silc_screen_init_output_status_line(client->screen);
301 win->screen = screen;
303 client->screen->bottom_line->nickname = win->nickname;
304 silc_screen_print_bottom_line(client->screen, 0);
306 /* Add the window to windows table */
307 client->windows = silc_calloc(1, sizeof(*client->windows));
308 client->windows[client->windows_count] = win;
309 client->windows_count = 1;
311 /* Automatically becomes the current active window */
312 client->current_win = win;
317 /* Allocates and adds new window to the client. This allocates new
318 physical window and internal window for connection specific data.
319 All the connection specific data is always saved into a window
320 since connection is always associated to a active window. */
322 SilcClientWindow silc_client_add_window(SilcClient client,
325 SilcClientWindow win;
327 assert(client->screen != NULL);
329 win = silc_calloc(1, sizeof(*win));
331 /* Add the pointers */
332 win->screen = silc_screen_add_output_window(client->screen);
335 /* Initialize ID caches */
336 win->client_cache = silc_idcache_alloc(0);
337 win->channel_cache = silc_idcache_alloc(0);
338 win->server_cache = silc_idcache_alloc(0);
340 /* Add the window to windows table */
341 client->windows = silc_realloc(client->windows, sizeof(*client->windows)
342 * (client->windows_count + 1));
343 client->windows[client->windows_count] = win;
344 client->windows_count++;
346 if (is_current == TRUE)
347 client->current_win = win;
352 /* The main task on SILC client. This processes the key pressings user
355 SILC_TASK_CALLBACK(silc_client_process_key_press)
357 SilcClient client = (SilcClient)context;
360 /* There is data pending in stdin, this gets it directly */
361 c = wgetch(client->screen->input_win);
362 if (silc_client_bad_keys(c))
365 SILC_LOG_DEBUG(("Pressed key: %d", c));
369 * Special character handling
376 SILC_LOG_DEBUG(("RIGHT"));
377 silc_screen_input_cursor_right(client->screen);
381 SILC_LOG_DEBUG(("LEFT"));
382 silc_screen_input_cursor_left(client->screen);
389 silc_screen_input_backspace(client->screen);
395 /* Insert switch. Turns on/off insert on input window */
396 silc_screen_input_insert(client->screen);
400 /* Enter, Return. User pressed enter we are ready to
401 process the message. */
402 silc_client_process_message(client);
405 /* Refresh screen, Ctrl^l */
406 silc_screen_refresh_all(client->screen);
411 /* Beginning, Home */
412 silc_screen_input_cursor_home(client->screen);
417 silc_screen_input_cursor_end(client->screen);
429 silc_client_clear_input(client);
436 /* Control codes are printed as reversed */
438 wattron(client->screen->input_win, A_REVERSE);
439 silc_screen_input_print(client->screen, c);
440 wattroff(client->screen->input_win, A_REVERSE);
442 /* Normal character */
443 silc_screen_input_print(client->screen, c);
447 silc_screen_print_coordinates(client->screen, 0);
448 silc_screen_refresh_win(client->screen->input_win);
451 static int silc_client_bad_keys(unsigned char key)
453 /* these are explained in curses.h */
468 case '\E': /* we ignore ESC */
475 /* Clears input buffer */
477 static void silc_client_clear_input(SilcClient client)
479 silc_buffer_clear(client->input_buffer);
480 silc_buffer_pull_tail(client->input_buffer,
481 SILC_BUFFER_END(client->input_buffer));
482 silc_screen_input_reset(client->screen);
485 /* Processes messages user has typed on the screen. This either sends
486 a packet out to network or if command were written executes it. */
488 static void silc_client_process_message(SilcClient client)
493 SILC_LOG_DEBUG(("Start"));
495 data = client->input_buffer->data;
498 if (data[0] == '/' && data[1] != ' ') {
500 unsigned int argc = 0;
501 unsigned char **argv, *tmpcmd;
502 unsigned int *argv_lens, *argv_types;
503 SilcClientCommand *cmd;
504 SilcClientCommandContext ctx;
506 /* Get the command */
507 tmpcmd = silc_client_parse_command(data);
509 /* Find command match */
510 for (cmd = silc_command_list; cmd->name; cmd++) {
511 if (!strncmp(cmd->name, tmpcmd, strlen(tmpcmd)))
515 if (cmd->name == NULL) {
516 silc_say(client, "Invalid command: %s", tmpcmd);
521 /* Now parse all arguments */
522 silc_client_parse_command_line(data, &argv, &argv_lens,
523 &argv_types, &argc, cmd->max_args);
526 SILC_LOG_DEBUG(("Exeuting command: %s", cmd->name));
528 /* Allocate command context. This and its internals must be free'd
529 by the command routine receiving it. */
530 ctx = silc_calloc(1, sizeof(*ctx));
531 ctx->client = client;
532 ctx->sock = client->current_win->sock;
535 ctx->argv_lens = argv_lens;
536 ctx->argv_types = argv_types;
538 /* Execute command */
542 /* Normal message to a channel */
543 if (len && client->current_win->current_channel &&
544 client->current_win->current_channel->on_channel == TRUE) {
545 silc_print(client, "> %s", data);
546 silc_client_packet_send_to_channel(client,
547 client->current_win->sock,
548 client->current_win->current_channel,
549 data, strlen(data), TRUE);
554 /* Clear the input buffer */
555 silc_client_clear_input(client);
558 /* Returns the command fetched from user typed command line */
560 static char *silc_client_parse_command(unsigned char *buffer)
563 const char *cp = buffer;
566 len = strcspn(cp, " ");
567 ret = silc_to_upper((char *)++cp);
573 /* Parses user typed command line. At most `max_args' is taken. Rest
574 of the line will be allocated as the last argument if there are more
575 than `max_args' arguments in the line. Note that the command name
576 is counted as one argument and is saved. */
578 void silc_client_parse_command_line(unsigned char *buffer,
579 unsigned char ***parsed,
580 unsigned int **parsed_lens,
581 unsigned int **parsed_types,
582 unsigned int *parsed_num,
583 unsigned int max_args)
587 const char *cp = buffer;
589 /* Take the '/' away */
592 *parsed = silc_calloc(1, sizeof(**parsed));
593 *parsed_lens = silc_calloc(1, sizeof(**parsed_lens));
595 /* Get the command first */
596 len = strcspn(cp, " ");
597 (*parsed)[0] = silc_to_upper((char *)cp);
598 (*parsed_lens)[0] = len;
602 /* Parse arguments */
603 if (strchr(cp, ' ') || strlen(cp) != 0) {
604 for (i = 1; i < max_args; i++) {
606 if (i != max_args - 1)
607 len = strcspn(cp, " ");
611 *parsed = silc_realloc(*parsed, sizeof(**parsed) * (argc + 1));
612 *parsed_lens = silc_realloc(*parsed_lens,
613 sizeof(**parsed_lens) * (argc + 1));
614 (*parsed)[argc] = silc_calloc(len + 1, sizeof(char));
615 memcpy((*parsed)[argc], cp, len);
616 (*parsed_lens)[argc] = len;
627 /* Save argument types. Protocol defines all argument types but
628 this implementation makes sure that they are always in correct
629 order hence this simple code. */
630 *parsed_types = silc_calloc(argc, sizeof(**parsed_types));
631 for (i = 0; i < argc; i++)
632 (*parsed_types)[i] = i;
637 /* Updates clock on the screen every minute. */
639 SILC_TASK_CALLBACK(silc_client_update_clock)
641 SilcClient client = (SilcClient)context;
643 /* Update the clock on the screen */
644 silc_screen_print_clock(client->screen);
646 /* Re-register this same task */
647 silc_task_register(qptr, 0, silc_client_update_clock, context,
648 silc_client_time_til_next_min(), 0,
652 silc_screen_refresh_win(client->screen->input_win);
655 /* Runs commands user configured in configuration file. This is
656 called when initializing client. */
658 SILC_TASK_CALLBACK(silc_client_run_commands)
660 SilcClient client = (SilcClient)context;
661 SilcClientConfigSectionCommand *cs;
663 SILC_LOG_DEBUG(("Start"));
665 cs = client->config->commands;
667 unsigned int argc = 0;
668 unsigned char **argv, *tmpcmd;
669 unsigned int *argv_lens, *argv_types;
670 SilcClientCommand *cmd;
671 SilcClientCommandContext ctx;
673 /* Get the command */
674 tmpcmd = silc_client_parse_command(cs->command);
676 for (cmd = silc_command_list; cmd->name; cmd++) {
677 if (!strcmp(cmd->name, tmpcmd))
681 if (cmd->name == NULL) {
682 silc_say(client, "Invalid command: %s", tmpcmd);
687 /* Now parse all arguments */
688 silc_client_parse_command_line(cs->command, &argv, &argv_lens,
689 &argv_types, &argc, cmd->max_args);
692 SILC_LOG_DEBUG(("Exeuting command: %s", cmd->name));
694 /* Allocate command context. This and its internals must be free'd
695 by the command routine receiving it. */
696 ctx = silc_calloc(1, sizeof(*ctx));
697 ctx->client = client;
698 ctx->sock = client->current_win->sock;
701 ctx->argv_lens = argv_lens;
702 ctx->argv_types = argv_types;
704 /* Execute command */
711 /* Internal context for connection process. This is needed as we
712 doing asynchronous connecting. */
720 } SilcClientInternalConnectContext;
723 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
727 /* XXX In the future we should give up this non-blocking connect all
728 together and use threads instead. */
729 /* Create connection to server asynchronously */
730 sock = silc_net_create_connection_async(ctx->port, ctx->host);
734 /* Register task that will receive the async connect and will
736 ctx->task = silc_task_register(ctx->client->io_queue, sock,
737 silc_client_connect_to_server_start,
740 SILC_TASK_PRI_NORMAL);
741 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
742 silc_schedule_set_listen_fd(sock, ctx->task->iomask);
749 /* Connects to remote server */
751 int silc_client_connect_to_server(SilcClient client, int port,
754 SilcClientInternalConnectContext *ctx;
756 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
759 silc_say(client, "Connecting to port %d of server %s", port, host);
761 client->current_win->remote_host = strdup(host);
762 client->current_win->remote_port = port;
764 /* Allocate internal context for connection process. This is
765 needed as we are doing async connecting. */
766 ctx = silc_calloc(1, sizeof(*ctx));
767 ctx->client = client;
768 ctx->host = strdup(host);
772 /* Do the actual connecting process */
773 return silc_client_connect_to_server_internal(ctx);
776 /* Start of the connection to the remote server. This is called after
777 succesful TCP/IP connection has been established to the remote host. */
779 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
781 SilcClientInternalConnectContext *ctx =
782 (SilcClientInternalConnectContext *)context;
783 SilcClient client = ctx->client;
784 SilcProtocol protocol;
785 SilcClientKEInternalContext *proto_ctx;
786 int opt, opt_len = sizeof(opt);
788 SILC_LOG_DEBUG(("Start"));
790 /* Check the socket status as it might be in error */
791 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
793 if (ctx->tries < 2) {
794 /* Connection failed but lets try again */
795 silc_say(ctx->client, "Could not connect to server %s: %s",
796 ctx->host, strerror(opt));
797 silc_say(client, "Connecting to port %d of server %s resumed",
798 ctx->port, ctx->host);
800 /* Unregister old connection try */
801 silc_schedule_unset_listen_fd(fd);
802 silc_net_close_connection(fd);
803 silc_task_unregister(client->io_queue, ctx->task);
806 silc_client_connect_to_server_internal(ctx);
809 /* Connection failed and we won't try anymore */
810 silc_say(ctx->client, "Could not connect to server %s: %s",
811 ctx->host, strerror(opt));
812 silc_schedule_unset_listen_fd(fd);
813 silc_net_close_connection(fd);
814 silc_task_unregister(client->io_queue, ctx->task);
820 silc_schedule_unset_listen_fd(fd);
821 silc_task_unregister(client->io_queue, ctx->task);
824 /* Allocate new socket connection object */
825 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER,
826 (void *)client->current_win,
827 &client->current_win->sock);
828 if (client->current_win->sock == NULL) {
829 silc_say(client, "Error: Could not allocate connection socket");
830 silc_net_close_connection(fd);
833 client->current_win->sock->hostname = client->current_win->remote_host;
834 client->current_win->sock->port = client->current_win->remote_port;
836 /* Allocate internal Key Exchange context. This is sent to the
837 protocol as context. */
838 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
839 proto_ctx->client = (void *)client;
840 proto_ctx->sock = client->current_win->sock;
841 proto_ctx->rng = client->rng;
842 proto_ctx->responder = FALSE;
844 /* Perform key exchange protocol. silc_client_connect_to_server_final
845 will be called after the protocol is finished. */
846 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
847 &protocol, (void *)proto_ctx,
848 silc_client_connect_to_server_second);
850 silc_say(client, "Error: Could not start authentication protocol");
853 client->current_win->sock->protocol = protocol;
855 /* Register the connection for network input and output. This sets
856 that scheduler will listen for incoming packets for this connection
857 and sets that outgoing packets may be sent to this connection as well.
858 However, this doesn't set the scheduler for outgoing traffic, it will
859 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
860 later when outgoing data is available. */
861 context = (void *)client;
862 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
864 /* Execute the protocol */
865 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
868 /* Second part of the connecting to the server. This executed
869 authentication protocol. */
871 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
873 SilcProtocol protocol = (SilcProtocol)context;
874 SilcClientKEInternalContext *ctx =
875 (SilcClientKEInternalContext *)protocol->context;
876 SilcClient client = (SilcClient)ctx->client;
877 SilcSocketConnection sock = NULL;
878 SilcClientConnAuthInternalContext *proto_ctx;
880 SILC_LOG_DEBUG(("Start"));
882 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
883 /* Error occured during protocol */
884 SILC_LOG_DEBUG(("Error during KE protocol"));
885 silc_protocol_free(protocol);
887 silc_ske_free(ctx->ske);
889 silc_free(ctx->dest_id);
890 ctx->sock->protocol = NULL;
895 /* Allocate internal context for the authentication protocol. This
896 is sent as context for the protocol. */
897 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
898 proto_ctx->client = (void *)client;
899 proto_ctx->sock = sock = ctx->sock;
900 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
901 proto_ctx->dest_id_type = ctx->dest_id_type;
902 proto_ctx->dest_id = ctx->dest_id;
904 /* Resolve the authentication method to be used in this connection */
905 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
906 if (client->config->conns) {
907 SilcClientConfigSectionConnection *conn = NULL;
909 /* Check if we find a match from user configured connections */
910 conn = silc_client_config_find_connection(client->config,
914 /* Match found. Use the configured authentication method */
915 proto_ctx->auth_meth = conn->auth_meth;
916 if (conn->auth_data) {
917 proto_ctx->auth_data = strdup(conn->auth_data);
918 proto_ctx->auth_data_len = strlen(conn->auth_data);
921 /* No match found. Resolve by sending AUTH_REQUEST to server */
922 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
925 /* XXX Resolve by sending AUTH_REQUEST to server */
926 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
929 /* Free old protocol as it is finished now */
930 silc_protocol_free(protocol);
932 silc_buffer_free(ctx->packet);
934 /* silc_free(ctx->keymat....); */
935 sock->protocol = NULL;
937 /* Allocate the authentication protocol. This is allocated here
938 but we won't start it yet. We will be receiving party of this
939 protocol thus we will wait that connecting party will make
941 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
942 &sock->protocol, (void *)proto_ctx,
943 silc_client_connect_to_server_final);
945 /* Execute the protocol */
946 sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
949 /* Finalizes the connection to the remote SILC server. This is called
950 after authentication protocol has been completed. This send our
951 user information to the server to receive our client ID from
954 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
956 SilcProtocol protocol = (SilcProtocol)context;
957 SilcClientConnAuthInternalContext *ctx =
958 (SilcClientConnAuthInternalContext *)protocol->context;
959 SilcClient client = (SilcClient)ctx->client;
960 SilcClientWindow win = (SilcClientWindow)ctx->sock->user_data;
963 SILC_LOG_DEBUG(("Start"));
965 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
966 /* Error occured during protocol */
967 SILC_LOG_DEBUG(("Error during authentication protocol"));
968 silc_protocol_free(protocol);
970 silc_free(ctx->auth_data);
972 silc_ske_free(ctx->ske);
974 silc_free(ctx->dest_id);
976 win->sock->protocol = NULL;
980 /* Send NEW_CLIENT packet to the server. We will become registered
981 to the SILC network after sending this packet and we will receive
982 client ID from the server. */
983 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
984 strlen(client->realname));
985 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
986 silc_buffer_format(packet,
987 SILC_STR_UI_SHORT(strlen(client->username)),
988 SILC_STR_UI_XNSTRING(client->username,
989 strlen(client->username)),
990 SILC_STR_UI_SHORT(strlen(client->realname)),
991 SILC_STR_UI_XNSTRING(client->realname,
992 strlen(client->realname)),
995 /* Send the packet */
996 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
998 packet->data, packet->len, TRUE);
999 silc_buffer_free(packet);
1001 /* Save remote ID. */
1002 win->remote_id = ctx->dest_id;
1003 win->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_CHANNEL);
1004 win->remote_id_data_len = SILC_ID_CHANNEL_LEN;
1006 silc_say(client, "Connected to port %d of host %s",
1007 win->remote_port, win->remote_host);
1009 client->screen->bottom_line->connection = win->remote_host;
1010 silc_screen_print_bottom_line(client->screen, 0);
1012 silc_protocol_free(protocol);
1014 silc_free(ctx->auth_data);
1016 silc_ske_free(ctx->ske);
1018 silc_free(ctx->dest_id);
1020 win->sock->protocol = NULL;
1023 /* Internal routine that sends packet or marks packet to be sent. This
1024 is used directly only in special cases. Normal cases should use
1025 silc_server_packet_send. Returns < 0 on error. */
1027 static int silc_client_packet_send_real(SilcClient client,
1028 SilcSocketConnection sock,
1033 /* Send the packet */
1034 ret = silc_packet_send(sock, force_send);
1038 /* Mark that there is some outgoing data available for this connection.
1039 This call sets the connection both for input and output (the input
1040 is set always and this call keeps the input setting, actually).
1041 Actual data sending is performed by silc_client_packet_process. */
1042 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
1044 /* Mark to socket that data is pending in outgoing buffer. This flag
1045 is needed if new data is added to the buffer before the earlier
1046 put data is sent to the network. */
1047 SILC_SET_OUTBUF_PENDING(sock);
1052 /* Packet processing callback. This is used to send and receive packets
1053 from network. This is generic task. */
1055 SILC_TASK_CALLBACK(silc_client_packet_process)
1057 SilcClient client = (SilcClient)context;
1058 SilcSocketConnection sock = NULL;
1059 SilcClientWindow win;
1062 SILC_LOG_DEBUG(("Processing packet"));
1064 SILC_CLIENT_GET_SOCK(client, fd, sock);
1068 win = (SilcClientWindow)sock->user_data;
1070 /* Packet sending */
1071 if (type == SILC_TASK_WRITE) {
1072 SILC_LOG_DEBUG(("Writing data to connection"));
1074 if (sock->outbuf->data - sock->outbuf->head)
1075 silc_buffer_push(sock->outbuf,
1076 sock->outbuf->data - sock->outbuf->head);
1078 ret = silc_client_packet_send_real(client, sock, TRUE);
1080 /* If returned -2 could not write to connection now, will do
1085 /* The packet has been sent and now it is time to set the connection
1086 back to only for input. When there is again some outgoing data
1087 available for this connection it will be set for output as well.
1088 This call clears the output setting and sets it only for input. */
1089 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
1090 SILC_UNSET_OUTBUF_PENDING(sock);
1092 silc_buffer_clear(sock->outbuf);
1096 /* Packet receiving */
1097 if (type == SILC_TASK_READ) {
1098 SILC_LOG_DEBUG(("Reading data from connection"));
1100 /* Read data from network */
1101 ret = silc_packet_receive(sock);
1107 SILC_LOG_DEBUG(("Read EOF"));
1109 /* If connection is disconnecting already we will finally
1110 close the connection */
1111 if (SILC_IS_DISCONNECTING(sock)) {
1112 silc_client_close_connection(client, sock);
1116 silc_say(client, "Connection closed: premature EOF");
1117 SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
1119 silc_client_close_connection(client, sock);
1123 /* Process the packet. This will call the parser that will then
1124 decrypt and parse the packet. */
1125 if (!silc_packet_receive_process(sock, win->receive_key, win->hmac,
1126 silc_client_packet_parse, client)) {
1127 silc_buffer_clear(sock->inbuf);
1133 /* Parses whole packet, received earlier. */
1135 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
1137 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
1138 SilcClient client = (SilcClient)parse_ctx->context;
1139 SilcPacketContext *packet = parse_ctx->packet;
1140 SilcBuffer buffer = packet->buffer;
1141 SilcSocketConnection sock = parse_ctx->sock;
1142 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1145 SILC_LOG_DEBUG(("Start"));
1147 /* Decrypt the received packet */
1148 ret = silc_packet_decrypt(win->receive_key, win->hmac, buffer, packet);
1153 /* Parse the packet. Packet type is returned. */
1154 ret = silc_packet_parse(packet);
1156 /* Parse the packet header in special way as this is "special"
1158 ret = silc_packet_parse_special(packet);
1161 if (ret == SILC_PACKET_NONE)
1164 /* Parse the incoming packet type */
1165 silc_client_packet_parse_type(client, sock, packet);
1168 silc_buffer_clear(buffer);
1170 silc_free(parse_ctx);
1173 /* Parser callback called by silc_packet_receive_process. Thie merely
1174 registers timeout that will handle the actual parsing when appropriate. */
1176 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
1178 SilcClient client = (SilcClient)parser_context->context;
1179 SilcClientWindow win = (SilcClientWindow)parser_context->sock->user_data;
1181 /* If this packet is for the current active connection we will
1182 parse the packet right away to get it quickly on the screen.
1183 Otherwise, it will be parsed with a timeout as the data is
1184 for inactive window (which might not be visible at all). */
1185 if (SILC_CLIENT_IS_CURRENT_WIN(client, win)) {
1186 /* Parse it real soon */
1187 silc_task_register(client->timeout_queue, parser_context->sock->sock,
1188 silc_client_packet_parse_real,
1189 (void *)parser_context, 0, 1,
1191 SILC_TASK_PRI_NORMAL);
1193 /* Parse the packet with timeout */
1194 silc_task_register(client->timeout_queue, parser_context->sock->sock,
1195 silc_client_packet_parse_real,
1196 (void *)parser_context, 0, 200000,
1198 SILC_TASK_PRI_NORMAL);
1202 /* Parses the packet type and calls what ever routines the packet type
1203 requires. This is done for all incoming packets. */
1205 void silc_client_packet_parse_type(SilcClient client,
1206 SilcSocketConnection sock,
1207 SilcPacketContext *packet)
1209 SilcBuffer buffer = packet->buffer;
1210 SilcPacketType type = packet->type;
1212 SILC_LOG_DEBUG(("Parsing packet type %d", type));
1214 /* Parse the packet type */
1216 case SILC_PACKET_DISCONNECT:
1217 silc_client_disconnected_by_server(client, sock, buffer);
1219 case SILC_PACKET_SUCCESS:
1221 * Success received for something. For now we can have only
1222 * one protocol for connection executing at once hence this
1223 * success message is for whatever protocol is executing currently.
1225 if (sock->protocol) {
1226 sock->protocol->execute(client->timeout_queue, 0,
1227 sock->protocol, sock->sock, 0, 0);
1230 case SILC_PACKET_FAILURE:
1232 * Failure received for some protocol. Set the protocol state to
1233 * error and call the protocol callback. This fill cause error on
1234 * protocol and it will call the final callback.
1236 if (sock->protocol) {
1237 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1238 sock->protocol->execute(client->timeout_queue, 0,
1239 sock->protocol, sock->sock, 0, 0);
1242 case SILC_PACKET_REJECT:
1245 case SILC_PACKET_NOTIFY:
1247 * Received notify message
1249 silc_client_notify_by_server(client, sock, buffer);
1252 case SILC_PACKET_ERROR:
1254 * Received error message
1256 silc_client_error_by_server(client, sock, buffer);
1259 case SILC_PACKET_CHANNEL_MESSAGE:
1261 * Received message to (from, actually) a channel
1263 silc_client_channel_message(client, sock, packet);
1265 case SILC_PACKET_CHANNEL_KEY:
1267 * Received key for a channel. By receiving this key the client will be
1268 * able to talk to the channel it has just joined. This can also be
1269 * a new key for existing channel as keys expire peridiocally.
1271 silc_client_receive_channel_key(client, sock, buffer);
1274 case SILC_PACKET_PRIVATE_MESSAGE:
1276 * Received private message
1279 SilcClientCommandReplyContext ctx;
1280 ctx = silc_calloc(1, sizeof(*ctx));
1281 ctx->client = client;
1283 ctx->packet = packet;
1284 silc_client_command_reply_msg((void *)ctx);
1287 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1289 * Received private message key
1293 case SILC_PACKET_COMMAND_REPLY:
1295 * Recived reply for a command
1297 silc_client_command_reply_process(client, sock, packet);
1300 case SILC_PACKET_KEY_EXCHANGE:
1301 if (sock->protocol) {
1302 SilcClientKEInternalContext *proto_ctx =
1303 (SilcClientKEInternalContext *)sock->protocol->context;
1305 proto_ctx->packet = buffer;
1306 proto_ctx->dest_id_type = packet->src_id_type;
1307 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
1309 /* Let the protocol handle the packet */
1310 sock->protocol->execute(client->timeout_queue, 0,
1311 sock->protocol, sock->sock, 0, 0);
1313 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1314 "protocol active, packet dropped."));
1316 /* XXX Trigger KE protocol?? Rekey actually! */
1320 case SILC_PACKET_KEY_EXCHANGE_1:
1321 if (sock->protocol) {
1324 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1325 "protocol active, packet dropped."));
1328 case SILC_PACKET_KEY_EXCHANGE_2:
1329 if (sock->protocol) {
1330 SilcClientKEInternalContext *proto_ctx =
1331 (SilcClientKEInternalContext *)sock->protocol->context;
1333 if (proto_ctx->packet)
1334 silc_buffer_free(proto_ctx->packet);
1336 proto_ctx->packet = buffer;
1337 proto_ctx->dest_id_type = packet->src_id_type;
1338 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
1340 /* Let the protocol handle the packet */
1341 sock->protocol->execute(client->timeout_queue, 0,
1342 sock->protocol, sock->sock, 0, 0);
1344 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1345 "protocol active, packet dropped."));
1349 case SILC_PACKET_NEW_ID:
1352 * Received new ID from server. This packet is received at
1353 * the connection to the server. New ID is also received when
1354 * user changes nickname but in that case the new ID is received
1355 * as command reply and not as this packet type.
1357 unsigned char *id_string;
1358 unsigned short id_type;
1360 silc_buffer_unformat(buffer,
1361 SILC_STR_UI_SHORT(&id_type),
1362 SILC_STR_UI16_STRING_ALLOC(&id_string),
1365 if ((SilcIdType)id_type != SILC_ID_CLIENT)
1368 silc_client_receive_new_id(client, sock, id_string);
1369 silc_free(id_string);
1374 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1379 /* Sends packet. This doesn't actually send the packet instead it assembles
1380 it and marks it to be sent. However, if force_send is TRUE the packet
1381 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1382 will be derived from sock argument. Otherwise the valid arguments sent
1385 void silc_client_packet_send(SilcClient client,
1386 SilcSocketConnection sock,
1387 SilcPacketType type,
1389 SilcIdType dst_id_type,
1392 unsigned char *data,
1393 unsigned int data_len,
1396 SilcPacketContext packetdata;
1398 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1400 /* Get data used in the packet sending, keys and stuff */
1401 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1402 if (!cipher && ((SilcClientWindow)sock->user_data)->send_key)
1403 cipher = ((SilcClientWindow)sock->user_data)->send_key;
1405 if (!hmac && ((SilcClientWindow)sock->user_data)->hmac)
1406 hmac = ((SilcClientWindow)sock->user_data)->hmac;
1408 if (!dst_id && ((SilcClientWindow)sock->user_data)->remote_id) {
1409 dst_id = ((SilcClientWindow)sock->user_data)->remote_id;
1410 dst_id_type = SILC_ID_SERVER;
1414 /* Set the packet context pointers */
1415 packetdata.flags = 0;
1416 packetdata.type = type;
1417 if (((SilcClientWindow)sock->user_data)->local_id_data)
1418 packetdata.src_id = ((SilcClientWindow)sock->user_data)->local_id_data;
1420 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1421 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1422 packetdata.src_id_type = SILC_ID_CLIENT;
1424 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1425 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
1426 packetdata.dst_id_type = dst_id_type;
1428 packetdata.dst_id = NULL;
1429 packetdata.dst_id_len = 0;
1430 packetdata.dst_id_type = SILC_ID_NONE;
1432 packetdata.rng = client->rng;
1433 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1434 packetdata.src_id_len + packetdata.dst_id_len;
1435 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1437 /* Prepare outgoing data buffer for packet sending */
1438 silc_packet_send_prepare(sock,
1439 SILC_PACKET_HEADER_LEN +
1440 packetdata.src_id_len +
1441 packetdata.dst_id_len,
1445 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1447 packetdata.buffer = sock->outbuf;
1449 /* Put the data to the buffer */
1450 if (data && data_len)
1451 silc_buffer_put(sock->outbuf, data, data_len);
1453 /* Create the outgoing packet */
1454 silc_packet_assemble(&packetdata);
1456 /* Encrypt the packet */
1458 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1460 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1461 sock->outbuf->data, sock->outbuf->len);
1463 /* Now actually send the packet */
1464 silc_client_packet_send_real(client, sock, force_send);
1467 /* Sends packet to a channel. Packet to channel is always encrypted
1468 differently from "normal" packets. SILC header of the packet is
1469 encrypted with the next receiver's key and the rest of the packet is
1470 encrypted with the channel specific key. Padding and HMAC is computed
1471 with the next receiver's key. */
1473 void silc_client_packet_send_to_channel(SilcClient client,
1474 SilcSocketConnection sock,
1475 SilcChannelEntry channel,
1476 unsigned char *data,
1477 unsigned int data_len,
1481 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1483 SilcPacketContext packetdata;
1486 unsigned char *id_string;
1488 SILC_LOG_DEBUG(("Sending packet to channel"));
1490 if (!channel || !channel->key) {
1491 silc_say(client, "Cannot talk to channel: key does not exist");
1497 for (i = 0; i < 16; i++)
1498 channel->iv[i] = silc_rng_get_byte(client->rng);
1500 silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
1502 /* Encode the channel payload */
1503 payload = silc_channel_encode_payload(strlen(win->nickname), win->nickname,
1504 data_len, data, 16, channel->iv,
1508 "Error: Could not create packet to be sent to the channel");
1512 /* Get data used in packet header encryption, keys and stuff. Rest
1513 of the packet (the payload) is, however, encrypted with the
1514 specified channel key. */
1515 cipher = win->send_key;
1517 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1519 /* Set the packet context pointers. The destination ID is always
1520 the Channel ID of the channel. Server and router will handle the
1521 distribution of the packet. */
1522 packetdata.flags = 0;
1523 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1524 packetdata.src_id = win->local_id_data;
1525 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1526 packetdata.src_id_type = SILC_ID_CLIENT;
1527 packetdata.dst_id = id_string;
1528 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1529 packetdata.dst_id_type = SILC_ID_CHANNEL;
1530 packetdata.rng = client->rng;
1531 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
1532 packetdata.src_id_len + packetdata.dst_id_len;
1533 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1534 packetdata.src_id_len +
1535 packetdata.dst_id_len));
1537 /* Prepare outgoing data buffer for packet sending */
1538 silc_packet_send_prepare(sock,
1539 SILC_PACKET_HEADER_LEN +
1540 packetdata.src_id_len +
1541 packetdata.dst_id_len,
1545 packetdata.buffer = sock->outbuf;
1547 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1548 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1549 payload->data, payload->data,
1550 payload->len - 16, /* -IV_LEN */
1553 /* Put the actual encrypted payload data into the buffer. */
1554 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1556 /* Create the outgoing packet */
1557 silc_packet_assemble(&packetdata);
1559 /* Encrypt the header and padding of the packet. This is encrypted
1560 with normal session key shared with our server. */
1561 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1562 packetdata.src_id_len + packetdata.dst_id_len +
1565 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1566 sock->outbuf->data, sock->outbuf->len);
1568 /* Now actually send the packet */
1569 silc_client_packet_send_real(client, sock, force_send);
1570 silc_buffer_free(payload);
1571 silc_free(id_string);
1574 /* Sends private message to remote client. If private message key has
1575 not been set with this client then the message will be encrypted using
1576 normal session keys. Private messages are special packets in SILC
1577 network hence we need this own function for them. This is similiar
1578 to silc_client_packet_send_to_channel except that we send private
1581 void silc_client_packet_send_private_message(SilcClient client,
1582 SilcSocketConnection sock,
1583 SilcClientEntry client_entry,
1584 unsigned char *data,
1585 unsigned int data_len,
1588 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1590 SilcPacketContext packetdata;
1591 unsigned int nick_len;
1595 SILC_LOG_DEBUG(("Sending private message"));
1597 /* Create private message payload */
1598 nick_len = strlen(client->current_win->nickname);
1599 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1600 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1601 silc_buffer_format(buffer,
1602 SILC_STR_UI_SHORT(nick_len),
1603 SILC_STR_UI_XNSTRING(client->current_win->nickname,
1605 SILC_STR_UI_XNSTRING(data, data_len),
1608 /* If we don't have private message specific key then private messages
1609 are just as any normal packet thus call normal packet sending. If
1610 the key exist then the encryption process is a bit different and
1611 will be done in the rest of this function. */
1612 if (!client_entry->send_key) {
1613 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1614 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1615 buffer->data, buffer->len, force_send);
1619 /* We have private message specific key */
1621 /* Get data used in the encryption */
1622 cipher = client_entry->send_key;
1625 /* Set the packet context pointers. */
1626 packetdata.flags = 0;
1627 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1628 packetdata.src_id = win->local_id_data;
1629 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1630 packetdata.src_id_type = SILC_ID_CLIENT;
1632 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1634 packetdata.dst_id = win->local_id_data;
1635 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1636 packetdata.dst_id_type = SILC_ID_CLIENT;
1637 packetdata.rng = client->rng;
1638 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1639 packetdata.src_id_len + packetdata.dst_id_len;
1640 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1641 packetdata.src_id_len +
1642 packetdata.dst_id_len));
1644 /* Prepare outgoing data buffer for packet sending */
1645 silc_packet_send_prepare(sock,
1646 SILC_PACKET_HEADER_LEN +
1647 packetdata.src_id_len +
1648 packetdata.dst_id_len,
1652 packetdata.buffer = sock->outbuf;
1654 /* Encrypt payload of the packet. Encrypt with private message specific
1655 key if it exist, otherwise with session key. */
1656 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1657 buffer->len, cipher->iv);
1659 /* Put the actual encrypted payload data into the buffer. */
1660 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1662 /* Create the outgoing packet */
1663 silc_packet_assemble(&packetdata);
1665 /* Encrypt the header and padding of the packet. */
1666 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1667 packetdata.src_id_len + packetdata.dst_id_len +
1670 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1671 sock->outbuf->data, sock->outbuf->len);
1673 /* Now actually send the packet */
1674 silc_client_packet_send_real(client, sock, force_send);
1675 silc_free(packetdata.dst_id);
1681 /* Closes connection to remote end. Free's all allocated data except
1682 for some information such as nickname etc. that are valid at all time. */
1684 void silc_client_close_connection(SilcClient client,
1685 SilcSocketConnection sock)
1687 SilcClientWindow win;
1689 /* We won't listen for this connection anymore */
1690 silc_schedule_unset_listen_fd(sock->sock);
1692 /* Unregister all tasks */
1693 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1694 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1696 /* Close the actual connection */
1697 silc_net_close_connection(sock->sock);
1699 silc_say(client, "Closed connection to host %s", sock->hostname ?
1700 sock->hostname : sock->ip);
1702 /* Free everything */
1703 if (sock->user_data) {
1704 win = (SilcClientWindow)sock->user_data;
1706 /* XXX Free all client entries and channel entries. */
1708 /* Clear ID caches */
1709 silc_idcache_del_all(win->client_cache);
1710 silc_idcache_del_all(win->channel_cache);
1713 if (win->remote_host)
1714 silc_free(win->remote_host);
1716 silc_free(win->local_id);
1717 if (win->local_id_data)
1718 silc_free(win->local_id_data);
1720 silc_cipher_free(win->send_key);
1721 if (win->receive_key)
1722 silc_cipher_free(win->receive_key);
1724 silc_hmac_free(win->hmac);
1725 if (win->hmac_key) {
1726 memset(win->hmac_key, 0, win->hmac_key_len);
1727 silc_free(win->hmac_key);
1731 win->remote_port = 0;
1732 win->remote_type = 0;
1733 win->send_key = NULL;
1734 win->receive_key = NULL;
1736 win->hmac_key = NULL;
1737 win->hmac_key_len = 0;
1738 win->local_id = NULL;
1739 win->local_id_data = NULL;
1740 win->remote_host = NULL;
1741 win->current_channel = NULL;
1744 if (sock->protocol) {
1745 silc_protocol_free(sock->protocol);
1746 sock->protocol = NULL;
1748 silc_socket_free(sock);
1751 /* Called when we receive disconnection packet from server. This
1752 closes our end properly and displays the reason of the disconnection
1755 void silc_client_disconnected_by_server(SilcClient client,
1756 SilcSocketConnection sock,
1761 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1763 msg = silc_calloc(message->len + 1, sizeof(char));
1764 memcpy(msg, message->data, message->len);
1765 silc_say(client, msg);
1768 SILC_SET_DISCONNECTED(sock);
1769 silc_client_close_connection(client, sock);
1772 /* Received error message from server. Display it on the screen.
1773 We don't take any action what so ever of the error message. */
1775 void silc_client_error_by_server(SilcClient client,
1776 SilcSocketConnection sock,
1781 msg = silc_calloc(message->len + 1, sizeof(char));
1782 memcpy(msg, message->data, message->len);
1783 silc_say(client, msg);
1787 /* Received notify message from server */
1789 void silc_client_notify_by_server(SilcClient client,
1790 SilcSocketConnection sock,
1795 msg = silc_calloc(message->len + 1, sizeof(char));
1796 memcpy(msg, message->data, message->len);
1797 silc_say(client, msg);
1801 /* Processes the received new Client ID from server. Old Client ID is
1802 deleted from cache and new one is added. */
1804 void silc_client_receive_new_id(SilcClient client,
1805 SilcSocketConnection sock,
1806 unsigned char *id_string)
1808 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1810 /* Delete old ID from ID cache */
1811 silc_idcache_del_by_id(win->client_cache, SILC_ID_CLIENT, win->local_id);
1813 /* Save the new ID */
1815 silc_free(win->local_id);
1816 win->local_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
1817 if (win->local_id_data)
1818 silc_free(win->local_id_data);
1819 win->local_id_data =
1820 silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1821 memcpy(win->local_id_data, id_string, SILC_ID_CLIENT_LEN);
1822 win->local_id_data_len = SILC_ID_CLIENT_LEN;
1823 if (!win->local_entry)
1824 win->local_entry = silc_calloc(1, sizeof(*win->local_entry));
1825 win->local_entry->nickname = win->nickname;
1826 win->local_entry->id = win->local_id;
1828 /* Put it to the ID cache */
1829 silc_idcache_add(win->client_cache, win->nickname, SILC_ID_CLIENT,
1830 win->local_id, (void *)win->local_entry, TRUE);
1833 /* Processed received Channel ID for a channel. This is called when client
1834 joins to channel and server replies with channel ID. The ID is cached. */
1836 void silc_client_new_channel_id(SilcClient client,
1837 SilcSocketConnection sock,
1840 unsigned char *id_string)
1842 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1844 SilcChannelEntry channel;
1846 SILC_LOG_DEBUG(("New channel ID"));
1848 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1849 channel = silc_calloc(1, sizeof(*channel));
1850 channel->channel_name = channel_name;
1852 channel->mode = mode;
1853 win->current_channel = channel;
1855 /* Put it to the ID cache */
1856 silc_idcache_add(win->channel_cache, channel_name, SILC_ID_CHANNEL,
1857 (void *)id, (void *)channel, TRUE);
1860 /* Processes received key for channel. The received key will be used
1861 to protect the traffic on the channel for now on. Client must receive
1862 the key to the channel before talking on the channel is possible.
1863 This is the key that server has generated, this is not the channel
1864 private key, it is entirely local setting. */
1866 void silc_client_receive_channel_key(SilcClient client,
1867 SilcSocketConnection sock,
1870 unsigned char *id_string, *key, *cipher;
1871 unsigned int key_len;
1872 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1874 SilcIDCacheEntry id_cache = NULL;
1875 SilcChannelEntry channel;
1876 SilcChannelKeyPayload payload;
1878 SILC_LOG_DEBUG(("Received key for channel"));
1880 payload = silc_channel_key_parse_payload(packet);
1884 id_string = silc_channel_key_get_id(payload, NULL);
1886 silc_channel_key_free_payload(payload);
1889 id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1892 if (!silc_idcache_find_by_id_one(win->channel_cache, (void *)id,
1893 SILC_ID_CHANNEL, &id_cache))
1897 key = silc_channel_key_get_key(payload, &key_len);
1898 cipher = silc_channel_key_get_cipher(payload, NULL);
1900 channel = (SilcChannelEntry)id_cache->context;
1901 channel->key_len = key_len;
1902 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1903 memcpy(channel->key, key, key_len);
1905 silc_cipher_alloc(cipher, &channel->channel_key);
1906 if (!channel->channel_key) {
1907 silc_say(client, "Cannot talk to channel: unsupported cipher %s", cipher);
1910 channel->channel_key->cipher->set_key(channel->channel_key->context,
1913 /* Client is now joined to the channel */
1914 channel->on_channel = TRUE;
1918 silc_channel_key_free_payload(payload);
1921 /* Process received message to a channel (or from a channel, really). This
1922 decrypts the channel message with channel specific key and parses the
1923 channel payload. Finally it displays the message on the screen. */
1925 void silc_client_channel_message(SilcClient client,
1926 SilcSocketConnection sock,
1927 SilcPacketContext *packet)
1929 SilcClientWindow win = (SilcClientWindow)sock->user_data;
1930 SilcBuffer buffer = packet->buffer;
1931 SilcChannelPayload payload = NULL;
1932 SilcChannelID *id = NULL;
1933 SilcChannelEntry channel;
1934 SilcIDCacheEntry id_cache = NULL;
1937 if (packet->dst_id_type != SILC_ID_CHANNEL)
1940 id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1942 /* Find the channel entry from channels on this window */
1943 if (!silc_idcache_find_by_id_one(win->channel_cache, (void *)id,
1944 SILC_ID_CHANNEL, &id_cache))
1947 channel = (SilcChannelEntry)id_cache->context;
1949 /* Decrypt the channel message payload. Push the IV out of the way,
1950 since it is not encrypted (after pushing buffer->tail has the IV). */
1951 silc_buffer_push_tail(buffer, 16);
1952 channel->channel_key->cipher->decrypt(channel->channel_key->context,
1953 buffer->data, buffer->data,
1954 buffer->len, buffer->tail);
1955 silc_buffer_pull_tail(buffer, 16);
1957 /* Parse the channel message payload */
1958 payload = silc_channel_parse_payload(buffer);
1962 /* Display the message on screen */
1963 if (packet->src_id_type == SILC_ID_CLIENT) {
1964 /* Message from client */
1965 if (channel == win->current_channel)
1966 silc_print(client, "<%s> %s",
1967 silc_channel_get_nickname(payload, NULL),
1968 silc_channel_get_data(payload, NULL));
1970 silc_print(client, "<%s:%s> %s",
1971 silc_channel_get_nickname(payload, NULL),
1972 channel->channel_name,
1973 silc_channel_get_data(payload, NULL));
1975 /* Message from server */
1976 silc_say(client, "%s", silc_channel_get_data(payload, NULL));
1983 silc_channel_free_payload(payload);