2 silc-channels.c : irssi
4 Copyright (C) 2000 - 2001 Timo Sirainen
5 Pekka Riikonen <priikone@poseidon.pspt.fi>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "net-nonblock.h"
25 #include "net-sendbuffer.h"
35 #include "channels-setup.h"
37 #include "silc-servers.h"
38 #include "silc-channels.h"
39 #include "silc-queries.h"
40 #include "silc-nicklist.h"
41 #include "window-item-def.h"
43 #include "fe-common/core/printtext.h"
44 #include "fe-common/silc/module-formats.h"
46 #include "silc-commands.h"
48 void sig_mime(SILC_SERVER_REC *server, SILC_CHANNEL_REC *channel,
49 const char *blob, const char *enc, const char *type,
53 if (!(IS_SILC_SERVER(server)))
56 printformat_module("fe-common/silc", server,
57 channel == NULL ? NULL : channel->name,
58 MSGLEVEL_CRAP, SILCTXT_MESSAGE_DATA,
59 nick == NULL ? "[<unknown>]" : nick, type);
63 SILC_CHANNEL_REC *silc_channel_create(SILC_SERVER_REC *server,
65 const char *visible_name,
68 SILC_CHANNEL_REC *rec;
70 g_return_val_if_fail(server == NULL || IS_SILC_SERVER(server), NULL);
71 g_return_val_if_fail(name != NULL, NULL);
73 rec = g_new0(SILC_CHANNEL_REC, 1);
74 rec->chat_type = SILC_PROTOCOL;
75 channel_init((CHANNEL_REC *)rec, (SERVER_REC *)server, name, name,
80 static void sig_channel_destroyed(SILC_CHANNEL_REC *channel)
82 if (!IS_SILC_CHANNEL(channel))
84 if (channel->server && channel->server->disconnected)
87 if (channel->server != NULL && !channel->left && !channel->kicked) {
88 /* destroying channel record without actually
89 having left the channel yet */
90 silc_command_exec(channel->server, "LEAVE", channel->name);
94 static void silc_channels_join(SILC_SERVER_REC *server,
95 const char *channels, int automatic)
98 SILC_CHANNEL_REC *chanrec;
100 list = g_strsplit(channels, ",", -1);
101 for (tmp = list; *tmp != NULL; tmp++) {
102 chanrec = silc_channel_find(server, *tmp);
106 silc_command_exec(server, "JOIN", *tmp);
112 static void sig_connected(SILC_SERVER_REC *server)
114 if (IS_SILC_SERVER(server))
115 server->channels_join = (void *) silc_channels_join;
118 /* "server quit" signal from the core to indicate that QUIT command
121 static void sig_server_quit(SILC_SERVER_REC *server, const char *msg)
123 if (IS_SILC_SERVER(server) && server->conn && server->conn->sock)
124 silc_command_exec(server, "QUIT", msg);
127 static void sig_gui_quit(SILC_SERVER_REC *server, const char *msg)
129 silc_client_stop(silc_client);
132 /* Find Irssi channel entry by SILC channel entry */
134 SILC_CHANNEL_REC *silc_channel_find_entry(SILC_SERVER_REC *server,
135 SilcChannelEntry entry)
139 g_return_val_if_fail(IS_SILC_SERVER(server), NULL);
141 for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
142 SILC_CHANNEL_REC *rec = tmp->data;
144 if (rec->entry == entry)
151 /* PART (LEAVE) command. */
153 static void command_part(const char *data, SILC_SERVER_REC *server,
156 SILC_CHANNEL_REC *chanrec;
159 CMD_SILC_SERVER(server);
161 if (!IS_SILC_SERVER(server) || !server->connected)
162 cmd_return_error(CMDERR_NOT_CONNECTED);
164 if (!strcmp(data, "*") || *data == '\0') {
165 if (!IS_SILC_CHANNEL(item))
166 cmd_return_error(CMDERR_NOT_JOINED);
167 data = item->visible_name;
170 chanrec = silc_channel_find(server, data);
172 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
174 memset(userhost, 0, sizeof(userhost));
175 snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
176 server->conn->local_entry->username,
177 server->conn->local_entry->hostname);
178 signal_emit("message part", 5, server, chanrec->name,
179 server->nick, userhost, "");
181 chanrec->left = TRUE;
182 silc_command_exec(server, "LEAVE", chanrec->name);
185 channel_destroy(CHANNEL(chanrec));
188 /* ME local command. */
190 static void command_me(const char *data, SILC_SERVER_REC *server,
193 SILC_CHANNEL_REC *chanrec;
194 char *tmpcmd = "ME", *tmp;
196 unsigned char *message = NULL;
197 unsigned char **argv;
198 SilcUInt32 *argv_lens, *argv_types;
201 CMD_SILC_SERVER(server);
203 if (!IS_SILC_SERVER(server) || !server->connected)
204 cmd_return_error(CMDERR_NOT_CONNECTED);
206 if (!IS_SILC_CHANNEL(item))
207 cmd_return_error(CMDERR_NOT_JOINED);
209 /* Now parse all arguments */
210 tmp = g_strconcat(tmpcmd, " ", data, NULL);
211 silc_parse_command_line(tmp, &argv, &argv_lens,
212 &argv_types, &argc, 2);
216 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
218 chanrec = silc_channel_find(server, item->visible_name);
220 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
222 if (!silc_term_utf8()) {
223 int len = silc_utf8_encoded_len(argv[1], argv_lens[1],
224 SILC_STRING_LANGUAGE);
225 message = silc_calloc(len + 1, sizeof(*message));
226 g_return_if_fail(message != NULL);
227 silc_utf8_encode(argv[1], argv_lens[1], SILC_STRING_LANGUAGE,
231 /* Send the action message */
232 silc_client_send_channel_message(silc_client, server->conn,
233 chanrec->entry, NULL,
234 SILC_MESSAGE_FLAG_ACTION |
235 SILC_MESSAGE_FLAG_UTF8,
236 message ? message : argv[1],
237 message ? strlen(message) : argv_lens[1],
240 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
241 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
242 server->conn->local_entry->nickname, argv[1]);
244 for (i = 0; i < argc; i++)
246 silc_free(argv_lens);
247 silc_free(argv_types);
251 /* ACTION local command. Same as ME but takes the channel as mandatory
254 static void command_action(const char *data, SILC_SERVER_REC *server,
257 SILC_CHANNEL_REC *chanrec;
258 char *tmpcmd = "ME", *tmp;
260 unsigned char *message = NULL;
261 unsigned char **argv;
262 SilcUInt32 *argv_lens, *argv_types;
265 CMD_SILC_SERVER(server);
266 if (!IS_SILC_SERVER(server) || !server->connected)
267 cmd_return_error(CMDERR_NOT_CONNECTED);
269 if (!IS_SILC_CHANNEL(item))
270 cmd_return_error(CMDERR_NOT_JOINED);
272 /* Now parse all arguments */
273 tmp = g_strconcat(tmpcmd, " ", data, NULL);
274 silc_parse_command_line(tmp, &argv, &argv_lens,
275 &argv_types, &argc, 3);
279 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
281 chanrec = silc_channel_find(server, argv[1]);
283 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
285 if (!silc_term_utf8()) {
286 int len = silc_utf8_encoded_len(argv[2], argv_lens[2],
287 SILC_STRING_LANGUAGE);
288 message = silc_calloc(len + 1, sizeof(*message));
289 g_return_if_fail(message != NULL);
290 silc_utf8_encode(argv[2], argv_lens[2], SILC_STRING_LANGUAGE,
294 /* Send the action message */
295 silc_client_send_channel_message(silc_client, server->conn,
296 chanrec->entry, NULL,
297 SILC_MESSAGE_FLAG_ACTION |
298 SILC_MESSAGE_FLAG_UTF8,
299 message ? message : argv[2],
300 message ? strlen(message) : argv_lens[2],
303 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
304 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
305 server->conn->local_entry->nickname, argv[2]);
307 for (i = 0; i < argc; i++)
309 silc_free(argv_lens);
310 silc_free(argv_types);
314 /* NOTICE local command. */
316 static void command_notice(const char *data, SILC_SERVER_REC *server,
319 SILC_CHANNEL_REC *chanrec;
320 char *tmpcmd = "ME", *tmp;
322 unsigned char *message = NULL;
323 unsigned char **argv;
324 SilcUInt32 *argv_lens, *argv_types;
327 CMD_SILC_SERVER(server);
328 if (!IS_SILC_SERVER(server) || !server->connected)
329 cmd_return_error(CMDERR_NOT_CONNECTED);
331 if (!IS_SILC_CHANNEL(item))
332 cmd_return_error(CMDERR_NOT_JOINED);
334 /* Now parse all arguments */
335 tmp = g_strconcat(tmpcmd, " ", data, NULL);
336 silc_parse_command_line(tmp, &argv, &argv_lens,
337 &argv_types, &argc, 2);
341 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
343 chanrec = silc_channel_find(server, item->visible_name);
345 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
347 if (!silc_term_utf8()) {
348 int len = silc_utf8_encoded_len(argv[1], argv_lens[1],
349 SILC_STRING_LANGUAGE);
350 message = silc_calloc(len + 1, sizeof(*message));
351 g_return_if_fail(message != NULL);
352 silc_utf8_encode(argv[1], argv_lens[1], SILC_STRING_LANGUAGE,
356 /* Send the action message */
357 silc_client_send_channel_message(silc_client, server->conn,
358 chanrec->entry, NULL,
359 SILC_MESSAGE_FLAG_NOTICE |
360 SILC_MESSAGE_FLAG_UTF8,
361 message ? message : argv[1],
362 message ? strlen(message) : argv_lens[1],
365 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
366 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE,
367 server->conn->local_entry->nickname, argv[1]);
369 for (i = 0; i < argc; i++)
371 silc_free(argv_lens);
372 silc_free(argv_types);
376 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
379 bool silc_set_away(const char *reason, SILC_SERVER_REC *server)
383 if (!IS_SILC_SERVER(server) || !server->connected)
386 if (*reason == '\0') {
387 /* Remove any possible away message */
388 silc_client_set_away_message(silc_client, server->conn, NULL);
391 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
394 /* Set the away message */
395 silc_client_set_away_message(silc_client, server->conn, (char *)reason);
398 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
399 SILCTXT_SET_AWAY, reason);
402 server->usermode_away = set;
403 g_free_and_null(server->away_reason);
405 server->away_reason = g_strdup((char *)reason);
407 signal_emit("away mode changed", 1, server);
412 static void command_away(const char *data, SILC_SERVER_REC *server,
415 CMD_SILC_SERVER(server);
417 if (!IS_SILC_SERVER(server) || !server->connected)
418 cmd_return_error(CMDERR_NOT_CONNECTED);
420 g_free_and_null(server->away_reason);
421 if ((data) && (*data != '\0'))
422 server->away_reason = g_strdup(data);
424 silc_command_exec(server, "UMODE",
425 (server->away_reason != NULL) ? "+g" : "-g");
429 int type; /* 1 = msg, 2 = channel */
431 SILC_SERVER_REC *server;
434 /* Key agreement callback that is called after the key agreement protocol
435 has been performed. This is called also if error occured during the
436 key agreement protocol. The `key' is the allocated key material and
437 the caller is responsible of freeing it. The `key' is NULL if error
438 has occured. The application can freely use the `key' to whatever
439 purpose it needs. See lib/silcske/silcske.h for the definition of
440 the SilcSKEKeyMaterial structure. */
442 static void keyagr_completion(SilcClient client,
443 SilcClientConnection conn,
444 SilcClientEntry client_entry,
445 SilcKeyAgreementStatus status,
446 SilcSKEKeyMaterial *key,
449 KeyInternal i = (KeyInternal)context;
452 case SILC_KEY_AGREEMENT_OK:
453 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
454 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
457 /* Set the private key for this client */
458 silc_client_del_private_message_key(client, conn, client_entry);
459 silc_client_add_private_message_key_ske(client, conn, client_entry,
460 NULL, NULL, key, i->responder);
461 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
462 SILCTXT_KEY_AGREEMENT_PRIVMSG,
463 client_entry->nickname);
464 silc_ske_free_key_material(key);
469 case SILC_KEY_AGREEMENT_ERROR:
470 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
471 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
474 case SILC_KEY_AGREEMENT_FAILURE:
475 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
476 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
479 case SILC_KEY_AGREEMENT_TIMEOUT:
480 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
481 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
484 case SILC_KEY_AGREEMENT_ABORTED:
485 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
486 SILCTXT_KEY_AGREEMENT_ABORTED, client_entry->nickname);
489 case SILC_KEY_AGREEMENT_ALREADY_STARTED:
490 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
491 SILCTXT_KEY_AGREEMENT_ALREADY_STARTED,
492 client_entry->nickname);
495 case SILC_KEY_AGREEMENT_SELF_DENIED:
496 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
497 SILCTXT_KEY_AGREEMENT_SELF_DENIED);
508 /* Local command KEY. This command is used to set and unset private
509 keys for channels, set and unset private keys for private messages
510 with remote clients and to send key agreement requests and
511 negotiate the key agreement protocol with remote client. The
512 key agreement is supported only to negotiate private message keys,
513 it currently cannot be used to negotiate private keys for channels,
514 as it is not convenient for that purpose. */
517 SILC_SERVER_REC *server;
523 /* Callback to be called after client information is resolved from the
526 static void silc_client_command_key_get_clients(SilcClient client,
527 SilcClientConnection conn,
528 SilcClientEntry *clients,
529 SilcUInt32 clients_count,
532 KeyGetClients internal = (KeyGetClients)context;
535 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s",
537 silc_free(internal->data);
538 silc_free(internal->nick);
543 signal_emit("command key", 3, internal->data, internal->server,
546 silc_free(internal->data);
547 silc_free(internal->nick);
551 static void command_key(const char *data, SILC_SERVER_REC *server,
554 SilcClientConnection conn;
555 SilcClientEntry *entrys, client_entry = NULL;
556 SilcUInt32 entry_count;
557 SILC_CHANNEL_REC *chanrec = NULL;
558 SilcChannelEntry channel_entry = NULL;
559 char *nickname = NULL, *tmp;
560 int command = 0, port = 0, type = 0;
561 char *hostname = NULL;
562 KeyInternal internal = NULL;
564 unsigned char **argv;
565 SilcUInt32 *argv_lens, *argv_types;
566 char *bindhost = NULL;
568 CMD_SILC_SERVER(server);
570 if (!server || !IS_SILC_SERVER(server) || !server->connected)
571 cmd_return_error(CMDERR_NOT_CONNECTED);
575 /* Now parse all arguments */
576 tmp = g_strconcat("KEY", " ", data, NULL);
577 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
581 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
584 if (!strcasecmp(argv[1], "msg"))
586 if (!strcasecmp(argv[1], "channel"))
590 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
593 if (argv[2][0] == '*') {
594 nickname = strdup("*");
596 /* Parse the typed nickname. */
597 if (!silc_parse_userfqdn(argv[2], &nickname, NULL)) {
598 printformat_module("fe-common/silc", server, NULL,
599 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
603 /* Find client entry */
604 entrys = silc_client_get_clients_local(silc_client, conn, nickname,
605 argv[2], &entry_count);
607 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
608 inter->server = server;
609 inter->data = strdup(data);
610 inter->nick = strdup(nickname);
612 silc_client_get_clients(silc_client, conn, nickname, argv[2],
613 silc_client_command_key_get_clients, inter);
616 client_entry = entrys[0];
622 /* Get channel entry */
625 if (argv[2][0] == '*') {
626 if (!conn->current_channel) {
628 cmd_return_error(CMDERR_NOT_JOINED);
630 name = conn->current_channel->channel_name;
635 chanrec = silc_channel_find(server, name);
636 if (chanrec == NULL) {
638 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
640 channel_entry = chanrec->entry;
644 if (!strcasecmp(argv[3], "set")) {
648 char *cipher = NULL, *hmac = NULL;
650 if (type == 1 && client_entry) {
651 /* Set private message key */
652 bool responder = FALSE;
654 silc_client_del_private_message_key(silc_client, conn, client_entry);
657 if (!strcasecmp(argv[5], "-responder"))
663 if (!strcasecmp(argv[6], "-responder"))
669 if (!strcasecmp(argv[7], "-responder"))
673 silc_client_add_private_message_key(silc_client, conn, client_entry,
675 argv[4], argv_lens[4],
677 TRUE : FALSE), responder);
679 /* Send the key to the remote client so that it starts using it
681 /* XXX for now we don't do this. This feature is pretty stupid
682 and should perhaps be removed altogether from SILC.
683 silc_client_send_private_message_key(silc_client, conn,
686 } else if (type == 2) {
687 /* Set private channel key */
688 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
689 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
690 SILCTXT_CH_PRIVATE_KEY_NOMODE,
691 channel_entry->channel_name);
700 if (!silc_client_add_channel_private_key(silc_client, conn,
705 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
706 SILCTXT_CH_PRIVATE_KEY_ERROR,
707 channel_entry->channel_name);
711 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
712 SILCTXT_CH_PRIVATE_KEY_ADD,
713 channel_entry->channel_name);
721 if (!strcasecmp(argv[3], "unset")) {
724 if (type == 1 && client_entry) {
725 /* Unset private message key */
726 silc_client_del_private_message_key(silc_client, conn, client_entry);
727 } else if (type == 2) {
728 /* Unset channel key(s) */
729 SilcChannelPrivateKey *keys;
730 SilcUInt32 keys_count;
734 silc_client_del_channel_private_keys(silc_client, conn,
738 number = atoi(argv[4]);
739 keys = silc_client_list_channel_private_keys(silc_client, conn,
745 if (!number || number > keys_count) {
746 silc_client_free_channel_private_keys(keys, keys_count);
750 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
752 silc_client_free_channel_private_keys(keys, keys_count);
760 if (!strcasecmp(argv[3], "list")) {
764 SilcPrivateMessageKeys keys;
765 SilcUInt32 keys_count;
769 keys = silc_client_list_private_message_keys(silc_client, conn,
774 /* list the private message key(s) */
775 if (nickname[0] == '*') {
776 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
777 SILCTXT_PRIVATE_KEY_LIST);
778 for (k = 0; k < keys_count; k++) {
779 memset(buf, 0, sizeof(buf));
780 strncat(buf, " ", 2);
781 len = strlen(keys[k].client_entry->nickname);
782 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
784 for (i = 0; i < 30 - len; i++)
788 len = strlen(keys[k].cipher);
789 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
791 for (i = 0; i < 14 - len; i++)
796 strcat(buf, "<hidden>");
798 strcat(buf, "*generated*");
800 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
803 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
804 SILCTXT_PRIVATE_KEY_LIST_NICK,
805 client_entry->nickname);
806 for (k = 0; k < keys_count; k++) {
807 if (keys[k].client_entry != client_entry)
810 memset(buf, 0, sizeof(buf));
811 strncat(buf, " ", 2);
812 len = strlen(keys[k].client_entry->nickname);
813 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
815 for (i = 0; i < 30 - len; i++)
819 len = strlen(keys[k].cipher);
820 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
822 for (i = 0; i < 14 - len; i++)
827 strcat(buf, "<hidden>");
829 strcat(buf, "*generated*");
831 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
835 silc_client_free_private_message_keys(keys, keys_count);
837 } else if (type == 2) {
838 SilcChannelPrivateKey *keys;
839 SilcUInt32 keys_count;
843 keys = silc_client_list_channel_private_keys(silc_client, conn,
847 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
848 SILCTXT_CH_PRIVATE_KEY_LIST,
849 channel_entry->channel_name);
854 for (k = 0; k < keys_count; k++) {
855 memset(buf, 0, sizeof(buf));
856 strncat(buf, " ", 2);
858 len = strlen(silc_cipher_get_name(keys[k]->cipher));
859 strncat(buf, silc_cipher_get_name(keys[k]->cipher),
860 len > 16 ? 16 : len);
862 for (i = 0; i < 16 - len; i++)
866 len = strlen(silc_hmac_get_name(keys[k]->hmac));
867 strncat(buf, silc_hmac_get_name(keys[k]->hmac), len > 16 ? 16 : len);
869 for (i = 0; i < 16 - len; i++)
873 strcat(buf, "<hidden>");
875 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
878 silc_client_free_channel_private_keys(keys, keys_count);
884 /* Send command is used to send key agreement */
885 if (!strcasecmp(argv[3], "agreement")) {
891 port = atoi(argv[5]);
893 internal = silc_calloc(1, sizeof(*internal));
894 internal->type = type;
895 internal->server = server;
898 if (settings_get_bool("use_auto_addr")) {
900 hostname = (char *)settings_get_str("auto_public_ip");
902 /* If the hostname isn't set, treat this case as if auto_public_ip
904 if ((hostname) && (*hostname == '\0')) {
907 bindhost = (char *)settings_get_str("auto_bind_ip");
909 /* if the bind_ip isn't set, but the public_ip IS, then assume then
910 public_ip is the same value as the bind_ip. */
911 if ((bindhost) && (*bindhost == '\0'))
913 port = settings_get_int("auto_bind_port");
915 } /* if use_auto_addr */
919 /* Start command is used to start key agreement (after receiving the
920 key_agreement client operation). */
921 if (!strcasecmp(argv[3], "negotiate")) {
927 port = atoi(argv[5]);
929 internal = silc_calloc(1, sizeof(*internal));
930 internal->type = type;
931 internal->server = server;
934 /* Change current channel private key */
935 if (!strcasecmp(argv[3], "change")) {
938 /* Unset channel key(s) */
939 SilcChannelPrivateKey *keys;
940 SilcUInt32 keys_count;
943 keys = silc_client_list_channel_private_keys(silc_client, conn,
951 if (chanrec->cur_key >= keys_count)
952 chanrec->cur_key = 0;
956 number = atoi(argv[4]);
957 if (!number || number > keys_count)
958 chanrec->cur_key = 0;
960 chanrec->cur_key = number - 1;
963 /* Set the current channel private key */
964 silc_client_current_channel_private_key(silc_client, conn,
966 keys[chanrec->cur_key]);
967 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
968 SILCTXT_CH_PRIVATE_KEY_CHANGE, chanrec->cur_key + 1,
969 channel_entry->channel_name);
971 silc_client_free_channel_private_keys(keys, keys_count);
977 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO,
978 "Usage: /KEY msg|channel <nickname|channel> "
979 "set|unset|agreement|negotiate [<arguments>]");
983 if (command == 4 && client_entry) {
984 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
985 SILCTXT_KEY_AGREEMENT, argv[2]);
986 internal->responder = TRUE;
987 silc_client_send_key_agreement(
988 silc_client, conn, client_entry, hostname,
990 settings_get_int("key_exchange_timeout_secs"),
991 keyagr_completion, internal);
997 if (command == 5 && client_entry && hostname) {
998 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
999 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
1000 internal->responder = FALSE;
1001 silc_client_perform_key_agreement(silc_client, conn, client_entry,
1002 hostname, port, keyagr_completion,
1008 silc_free(nickname);
1011 /* Lists locally saved client and server public keys. */
1013 static void command_listkeys(const char *data, SILC_SERVER_REC *server,
1019 void silc_channels_init(void)
1021 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1022 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
1023 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
1024 signal_add("gui exit", (SIGNAL_FUNC) sig_gui_quit);
1025 signal_add("mime", (SIGNAL_FUNC) sig_mime);
1027 command_bind_silc("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
1028 command_bind_silc("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
1029 command_bind_silc("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
1030 command_bind_silc("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
1031 command_bind_silc("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
1032 command_bind_silc("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
1033 /* command_bind_silc("listkeys", MODULE_NAME, (SIGNAL_FUNC) command_listkeys); */
1035 silc_nicklist_init();
1038 void silc_channels_deinit(void)
1040 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1041 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
1042 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
1043 signal_remove("gui exit", (SIGNAL_FUNC) sig_gui_quit);
1044 signal_remove("mime", (SIGNAL_FUNC) sig_mime);
1046 command_unbind("part", (SIGNAL_FUNC) command_part);
1047 command_unbind("me", (SIGNAL_FUNC) command_me);
1048 command_unbind("action", (SIGNAL_FUNC) command_action);
1049 command_unbind("notice", (SIGNAL_FUNC) command_notice);
1050 command_unbind("away", (SIGNAL_FUNC) command_away);
1051 command_unbind("key", (SIGNAL_FUNC) command_key);
1052 /* command_unbind("listkeys", (SIGNAL_FUNC) command_listkeys); */
1054 silc_nicklist_deinit();