Commands:
- set [<key> [<cipher>] [<hmac>]] [-responder]
+ set [<key> [<cipher>] [<hmac>]]
- Set the key into use. If the <key> is provided it is used
- as the key material. If the <key> is not provided the
- negotiated key material is used. If the negotiation has not
- been performed this command has no effect.
+ Set the key into use. The <key> is a pre-shared-key,
+ passphrase or similar shared secret string. Setting
+ the key without first receiving a request from the
+ remote user, this command will send the request to the
+ remote user. The actual key is not sent to network.
- If the type is MSG and the <key> is `*' then random key
- will be generated automatically. The -responder option
- may be used ONLY with MSG type. One of the clients must
- be the responder side. The one being the responder must
- use this option. The clients setting the key must agree
- on which one is the responder.
+ Optionally, the <cipher> and <hmac> may also be set.
unset [<number>]
next key is changed to current channel private key. By default
this command is also bound to Meta-K (Alt+Shift+k) key.
- agreement [<hostname> [<port>]]
+ agreement [<hostname> [<port>] [<TCP|UDP>]]
Send key agreement request to remote client. If the
<hostname> is provided it is sent in the request. The
not provided then the receiver will never initiate the key
agreement. In this case you may start the key agreement
after receiving the reply to the request, by giving the
- negotiate command.
+ negotiate command. By default the key agreement connection
+ is TCP connection. UDP connection may also be defined.
This command may be used to send reply to the remote client.
When receiving empty key agreement you can reply to the
auto_bind_ip is set, silc client will send the auto_bind_ip
variable's value to the remote client.
- negotiate [<hostname> [<port>]]
+ negotiate [<hostname> [<port>] [<TCP|UDP>]]
This may be called to start the key agreement with <nickname>.
This command has effect only if the <nickname> has replied to
your key agreement request. You will see a notify on the
screen when the reply arrives. The <hostname> and <port> is the
hostname and port of the remote client's key agreement server.
+ The request tells the connection protocol used, usually TCP.
+ If UDP was requested it must be provided.
Examples:
/KEY CHANNEL * set very_secret_key_this_is
/KEY CHANNEL * list
- /KEY MSG nickname set secretkey
- /KEY MSG nick set secretkey -responder
- /KEY MSG foo agreement 10.2.1.7 5000
- /KEY MSG bar negotiate 10.2.1.7 5000
+
+ Set private message key with a friend:
+
+ foobar: /KEY MSG friend set secretkey
+ friend: /KEY MSG foobar set secretkey
+
+ Perform key agreement:
+
+ bar: /KEY MSG foo agreement 10.2.1.7 5000
+ foo: /KEY MSG bar negotiate 10.2.1.7 5000
+
+ bar: /KEY MSG foo agreement 10.2.1.7 5000 UDP
+ foo: /KEY MSG bar negotiate 10.2.1.7 5000 UDP
See also: WHOIS, CHANNEL, GETKEY
}
typedef struct {
- int type; /* 1 = msg, 2 = channel */
- bool responder;
SILC_SERVER_REC *server;
+ int type; /* 1 = msg, 2 = channel */
+ SilcBool responder;
} *KeyInternal;
/* Key agreement callback that is called after the key agreement protocol
SilcClientConnection conn,
SilcClientEntry client_entry,
SilcKeyAgreementStatus status,
- SilcSKEKeyMaterial *key,
+ SilcSKEKeyMaterial key,
void *context)
{
KeyInternal i = (KeyInternal)context;
/* Set the private key for this client */
silc_client_del_private_message_key(client, conn, client_entry);
silc_client_add_private_message_key_ske(client, conn, client_entry,
- NULL, NULL, key, i->responder);
+ NULL, NULL, key);
printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
SILCTXT_KEY_AGREEMENT_PRIVMSG,
client_entry->nickname);
break;
case SILC_KEY_AGREEMENT_ERROR:
+ case SILC_KEY_AGREEMENT_NO_MEMORY:
printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
break;
silc_free(i);
}
-#if 0
/* Local command KEY. This command is used to set and unset private
keys for channels, set and unset private keys for private messages
with remote clients and to send key agreement requests and
static void silc_client_command_key_get_clients(SilcClient client,
SilcClientConnection conn,
- SilcClientEntry *clients,
- SilcUInt32 clients_count,
+ SilcStatus status,
+ SilcDList clients,
void *context)
{
KeyGetClients internal = (KeyGetClients)context;
WI_ITEM_REC *item)
{
SilcClientConnection conn;
- SilcClientEntry *entrys, client_entry = NULL;
- SilcUInt32 entry_count;
+ SilcClientEntry client_entry = NULL;
+ SilcDList clients;
SILC_CHANNEL_REC *chanrec = NULL;
SilcChannelEntry channel_entry = NULL;
- char *nickname = NULL, *tmp;
+ char nickname[128 + 1], *tmp;
int command = 0, port = 0, type = 0;
char *hostname = NULL;
KeyInternal internal = NULL;
unsigned char **argv;
SilcUInt32 *argv_lens, *argv_types;
char *bindhost = NULL;
+ SilcChannelEntry ch = NULL;
+ SilcDList ckeys;
+ SilcBool udp = FALSE;
+ int i;
CMD_SILC_SERVER(server);
if (type == 1) {
if (argv[2][0] == '*') {
- nickname = strdup("*");
+ strcpy(nickname, "*");
} else {
/* Parse the typed nickname. */
- if (!silc_parse_userfqdn(argv[2], &nickname, NULL)) {
+ if (!silc_parse_userfqdn(argv[2], nickname, sizeof(nickname), NULL, 0)) {
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
return;
}
/* Find client entry */
- entrys = silc_client_get_clients_local(silc_client, conn, nickname,
- argv[2], &entry_count);
- if (!entrys) {
+ clients = silc_client_get_clients_local(silc_client, conn, nickname,
+ argv[2]);
+ if (!clients) {
KeyGetClients inter = silc_calloc(1, sizeof(*inter));
inter->server = server;
inter->data = strdup(data);
silc_client_command_key_get_clients, inter);
goto out;
}
- client_entry = entrys[0];
- silc_free(entrys);
+
+ client_entry = silc_dlist_get(clients);
+ silc_client_list_free(silc_client, conn, clients);
}
}
if (argc >= 5) {
char *cipher = NULL, *hmac = NULL;
+ if (argc >= 6)
+ cipher = argv[5];
+ if (argc >= 7)
+ hmac = argv[6];
+
if (type == 1 && client_entry) {
/* Set private message key */
- bool responder = FALSE;
-
silc_client_del_private_message_key(silc_client, conn, client_entry);
-
- if (argc >= 6) {
- if (!strcasecmp(argv[5], "-responder"))
- responder = TRUE;
- else
- cipher = argv[5];
- }
- if (argc >= 7) {
- if (!strcasecmp(argv[6], "-responder"))
- responder = TRUE;
- else
- hmac = argv[6];
- }
- if (argc >= 8) {
- if (!strcasecmp(argv[7], "-responder"))
- responder = TRUE;
- }
-
silc_client_add_private_message_key(silc_client, conn, client_entry,
cipher, hmac,
- argv[4], argv_lens[4],
- (argv[4][0] == '*' ?
- TRUE : FALSE), responder);
-
- /* Send the key to the remote client so that it starts using it
- too. */
- /* XXX for now we don't do this. This feature is pretty stupid
- and should perhaps be removed altogether from SILC.
- silc_client_send_private_message_key(silc_client, conn,
- client_entry, TRUE);
- */
+ argv[4], argv_lens[4]);
} else if (type == 2) {
/* Set private channel key */
if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
goto out;
}
- if (argc >= 6)
- cipher = argv[5];
- if (argc >= 7)
- hmac = argv[6];
-
if (!silc_client_add_channel_private_key(silc_client, conn,
channel_entry, NULL,
cipher, hmac,
silc_client_del_private_message_key(silc_client, conn, client_entry);
} else if (type == 2) {
/* Unset channel key(s) */
- SilcChannelPrivateKey *keys;
- SilcUInt32 keys_count;
int number;
if (argc == 4)
if (argc > 4) {
number = atoi(argv[4]);
- keys = silc_client_list_channel_private_keys(silc_client, conn,
- channel_entry,
- &keys_count);
- if (!keys)
+ ckeys = silc_client_list_channel_private_keys(silc_client, conn,
+ channel_entry);
+ if (!ckeys)
goto out;
- if (!number || number > keys_count) {
- silc_client_free_channel_private_keys(keys, keys_count);
+ if (!number || number > silc_dlist_count(ckeys)) {
+ silc_dlist_uninit(ckeys);
goto out;
}
+ for (i = 0; i < number; i++)
+ ch = silc_dlist_get(ckeys);
+ if (!ch)
+ goto out;
+
silc_client_del_channel_private_key(silc_client, conn, channel_entry,
- keys[number - 1]);
- silc_client_free_channel_private_keys(keys, keys_count);
+ ch);
+ silc_dlist_uninit(ckeys);
}
goto out;
}
}
+#if 0
/* List command */
if (!strcasecmp(argv[3], "list")) {
command = 3;
silc_client_free_private_message_keys(keys, keys_count);
} else if (type == 2) {
- SilcChannelPrivateKey *keys;
- SilcUInt32 keys_count;
- int k, i, len;
+ int k, len;
char buf[1024];
- keys = silc_client_list_channel_private_keys(silc_client, conn,
- channel_entry,
- &keys_count);
+ ckeys = silc_client_list_channel_private_keys(silc_client, conn,
+ channel_entry);
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_CH_PRIVATE_KEY_LIST,
channel_entry->channel_name);
- if (!keys)
+ if (!ckeys)
goto out;
for (k = 0; k < keys_count; k++) {
goto out;
}
+#endif /* 0 */
/* Send command is used to send key agreement */
if (!strcasecmp(argv[3], "agreement")) {
if (argc >= 5)
hostname = argv[4];
- if (argc >= 6)
- port = atoi(argv[5]);
+ if (argc >= 6) {
+ if (!strcasecmp(argv[5], "UDP"))
+ udp = TRUE;
+ else
+ port = atoi(argv[5]);
+ }
+ if (argc >= 7)
+ udp = TRUE;
internal = silc_calloc(1, sizeof(*internal));
internal->type = type;
if (!hostname) {
if (settings_get_bool("use_auto_addr")) {
-
hostname = (char *)settings_get_str("auto_public_ip");
/* If the hostname isn't set, treat this case as if auto_public_ip
if (argc >= 5)
hostname = argv[4];
- if (argc >= 6)
- port = atoi(argv[5]);
+ if (argc >= 6) {
+ if (!strcasecmp(argv[5], "UDP"))
+ udp = TRUE;
+ else
+ port = atoi(argv[5]);
+ }
+ if (argc >= 7)
+ udp = TRUE;
internal = silc_calloc(1, sizeof(*internal));
internal->type = type;
command = 6;
if (type == 2) {
/* Unset channel key(s) */
- SilcChannelPrivateKey *keys;
- SilcUInt32 keys_count;
int number;
- keys = silc_client_list_channel_private_keys(silc_client, conn,
- channel_entry,
- &keys_count);
- if (!keys)
+ ckeys = silc_client_list_channel_private_keys(silc_client, conn,
+ channel_entry);
+ if (!ckeys)
goto out;
if (argc == 4) {
chanrec->cur_key++;
- if (chanrec->cur_key >= keys_count)
+ if (chanrec->cur_key >= silc_dlist_count(ckeys))
chanrec->cur_key = 0;
}
if (argc > 4) {
number = atoi(argv[4]);
- if (!number || number > keys_count)
+ if (!number || number > silc_dlist_count(ckeys))
chanrec->cur_key = 0;
else
chanrec->cur_key = number - 1;
}
+ for (i = 0; i < chanrec->cur_key; i++)
+ ch = silc_dlist_get(ckeys);
+ if (!ch)
+ goto out;
+
/* Set the current channel private key */
silc_client_current_channel_private_key(silc_client, conn,
- channel_entry,
- keys[chanrec->cur_key]);
+ channel_entry, ch);
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
- SILCTXT_CH_PRIVATE_KEY_CHANGE, chanrec->cur_key + 1,
+ SILCTXT_CH_PRIVATE_KEY_CHANGE, i + 1,
channel_entry->channel_name);
- silc_client_free_channel_private_keys(keys, keys_count);
+ silc_dlist_uninit(ckeys);
goto out;
}
}
}
if (command == 4 && client_entry) {
+ SilcClientConnectionParams params;
+
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_KEY_AGREEMENT, argv[2]);
internal->responder = TRUE;
+
+ memset(¶ms, 0, sizeof(params));
+ params.local_ip = hostname;
+ params.bind_ip = bindhost;
+ params.local_port = port;
+ params.udp = udp;
+ params.timeout_secs = settings_get_int("key_exchange_timeout_secs");
+
silc_client_send_key_agreement(
- silc_client, conn, client_entry, hostname,
- bindhost, port,
- settings_get_int("key_exchange_timeout_secs"),
+ silc_client, conn, client_entry, ¶ms,
+ irssi_pubkey, irssi_privkey,
keyagr_completion, internal);
if (!hostname)
silc_free(internal);
}
if (command == 5 && client_entry && hostname) {
+ SilcClientConnectionParams params;
+
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
internal->responder = FALSE;
- silc_client_perform_key_agreement(silc_client, conn, client_entry,
+
+ memset(¶ms, 0, sizeof(params));
+ if (udp) {
+ if (settings_get_bool("use_auto_addr")) {
+ params.local_ip = (char *)settings_get_str("auto_public_ip");
+ if ((params.local_ip) && (*params.local_ip == '\0')) {
+ params.local_ip = silc_net_localip();
+ } else {
+ params.bind_ip = (char *)settings_get_str("auto_bind_ip");
+ if ((params.bind_ip) && (*params.bind_ip == '\0'))
+ params.bind_ip = NULL;
+ params.local_port = settings_get_int("auto_bind_port");
+ }
+ }
+ if (!params.local_ip)
+ params.local_ip = silc_net_localip();
+ }
+ params.udp = udp;
+ params.timeout_secs = settings_get_int("key_exchange_timeout_secs");
+
+ silc_client_perform_key_agreement(silc_client, conn, client_entry, ¶ms,
+ irssi_pubkey, irssi_privkey,
hostname, port, keyagr_completion,
internal);
goto out;
}
out:
- silc_free(nickname);
+ return;
}
+#if 0
void silc_list_key(const char *pub_filename, int verbose)
{
SilcPublicKey public_key;
command_bind_silc("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
command_bind_silc("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
command_bind_silc("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
- // command_bind_silc("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
+ command_bind_silc("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
// command_bind("listkeys", MODULE_NAME, (SIGNAL_FUNC) command_listkeys);
//command_set_options("listkeys", "clients servers");
command_unbind("action", (SIGNAL_FUNC) command_action);
command_unbind("notice", (SIGNAL_FUNC) command_notice);
command_unbind("away", (SIGNAL_FUNC) command_away);
- // command_unbind("key", (SIGNAL_FUNC) command_key);
+ command_unbind("key", (SIGNAL_FUNC) command_key);
// command_unbind("listkeys", (SIGNAL_FUNC) command_listkeys);
silc_nicklist_deinit();