Addec multiple channel private key support to Irssi SILC client.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 19 Mar 2002 18:41:30 +0000 (18:41 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 19 Mar 2002 18:41:30 +0000 (18:41 +0000)
14 files changed:
CHANGES
TODO
apps/irssi/docs/help/in/key.in
apps/irssi/silc.conf
apps/irssi/src/fe-common/silc/module-formats.c
apps/irssi/src/fe-common/silc/module-formats.h
apps/irssi/src/silc/core/silc-channels.c
apps/irssi/src/silc/core/silc-channels.h
apps/irssi/src/silc/core/silc-servers.c
lib/silcclient/client_channel.c
lib/silcclient/client_prvmsg.c
lib/silcclient/idlist.h
lib/silcclient/silcclient.h
prepare

diff --git a/CHANGES b/CHANGES
index 888671f12ea5f8c8669de2ae0b9f0e1fcc80a3ed..6e419f7f7ca0b63532d288c5ab4866b8d9072fdc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,21 @@
+Tue Mar 19 20:42:41 EET 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added `name' field to SilcChannelPrivateKey to represent
+         application given name for the key.  Moved also the context from
+         lib/silcclient/idlist.h into lib/silcclient/silcclient.h.
+         Added the `name' argument also to the function
+         silc_client_add_channel_private_key.
+
+         Added function silc_client_current_channel_private_key to set the
+         current channel private key in use.
+
+         Added "change" command to KEY command which can be used to change
+         the current channel private key.  Bound the command also to
+         alt+K (Alt+Shift+k).
+
+         Also affected files lib/silcclient/client_channel.c,
+         irssi/src/docs/help/in/key.in, irssi/src/silc/core/silc-channel.c.
+
 Tue Mar 19 16:32:43 CET 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Added silc_rng_get_byte_fast function in to the
diff --git a/TODO b/TODO
index 7ec1bc17ba0786b203e6c3820848c03c7b5a384a..980ff9d4417ccdca139ebe682efd13a074da4c84 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,16 +1,6 @@
 TODO/bugs in Irssi SILC client
 ==============================
 
- o Fix the silc_channels_join to parse the command like, with fe.
-   silc_parse_command_line, because currently it ignores all options,
-   including passphrase which makes autojoin impossible to +a channels.
-   Other important options are ignored too.
-
- o Add local command to switch the channel's private key when channel has
-   several private keys.  Currently sending channel messages with many
-   keys is not possible because changing the key is not possible by the
-   user.
-
  o /cumode for unknown nick does not give any error message.
 
 
index 9e54b7bd7daeae44477b100b5d977aeffae591f4..3d3a716252150d419cf410351e34f1fdb7803df6 100644 (file)
@@ -15,8 +15,8 @@ Types:
   MSG        The command is performed for private messages
              affecting the <nickname>.
 
-  CHANNEL    The command is performed for channel affecting
-             the <channel>.
+  CHANNEL    The command is performed for the channel indicated
+             by <channel> (* matches current channel).
 
 Commands:
 
@@ -27,7 +27,7 @@ Commands:
     negotiated key material is used.  If the negotiation has not
     been performed this command has no effect.
 
-    If the type is `msg' and the <key> is `*' then random key
+    If the type is MSG and the <key> is `*' then random key
     will be generated automatically.  The <cipher> may be set
     for both private message and channel private keys and the
     <hmac> may be set only to the channel private keys.
@@ -44,9 +44,17 @@ Commands:
   list
 
     List all private keys that has been set.  If the type is
-    `msg' and the <nickname> is ´*' then all private message
+    MSG and the <nickname> is ´*' then all private message
     keys that you've set will be listed.
 
+  change     [<number>]
+
+    This command can be used only when type is CHANNEL.  This is
+    used to change the current channel private key.  The <number>
+    may indicate what key is changed.  If it is not provided then
+    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>]]
 
     Send key agreement request to remote client.  If the
@@ -82,3 +90,10 @@ Commands:
     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.
+
+Examples:
+
+  Set channel private key to current channel, and list all keys:
+
+    /KEY CHANNEL set very_secret_key_this_is
+    /KEY CHANNEL list
index 3ff0538f16eeb13e9e1455b8b39c79222302d999..e8741573fa62039c5001892072a57bde07e8b8bb 100644 (file)
@@ -21,6 +21,13 @@ channels = (
   { name = "#silc"; chatnet = silcnet; autojoin = No; }
 );
 
+#
+# Keyboard bindings (BIND command)
+#
+keyboard = (
+  { key = "meta-K"; id = "command"; data = "key channel * change"; }
+); 
+
 #
 # Your favorite aliases
 #
index 5ee13d6d2cd8c0bdfdc23144d11f710365991eca..6ac3306f20b9d3efe41801fcaab49fa664a86fc2 100644 (file)
@@ -68,6 +68,7 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "channel_private_key_nomode", "Private key mode is not set on channel {channel $0}", 1, { 0 } },
        { "channel_private_key_error", "Could not add private key to channel {channel $0}", 1, { 0 } },
        { "channel_private_key_list", "Channel {channel $0} private keys%:  Cipher           Hmac             Key", 1, { 0 } },
+       { "channel_private_change", "You are using private key n:o $0 on {channel $1}", 2, { 1, 0 } },
        { "private_key_list", "Private message keys%:  Client                         Cipher         Key", 0 },
        { "private_key_list_nick", "Private message keys with {nick $0}%:  Client                         Cipher         Key", 1, { 0 } },
        { "key_agreement", "Requesting key agreement with {nick $0}", 1, { 0 } },
index 62b2db5a2c50f4fc5ac4f8f3e3e8a822cd091fd5..42422e4bd4616d1b206bb06e22c86ed23e45d3b5 100644 (file)
@@ -63,6 +63,7 @@ enum {
   SILCTXT_CH_PRIVATE_KEY_NOMODE,
   SILCTXT_CH_PRIVATE_KEY_ERROR,
   SILCTXT_CH_PRIVATE_KEY_LIST,
+  SILCTXT_CH_PRIVATE_KEY_CHANGE,
   SILCTXT_PRIVATE_KEY_LIST,
   SILCTXT_PRIVATE_KEY_LIST_NICK,
   SILCTXT_KEY_AGREEMENT,
index 1952eb90acbcc9bd4bed1b888c62654d75fa45bc..a0c98fffe1c92f4c2f46345ef147b9168b53dae9 100644 (file)
@@ -450,6 +450,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
   SilcClientConnection conn;
   SilcClientEntry *entrys, client_entry = NULL;
   SilcUInt32 entry_count;
+  SILC_CHANNEL_REC *chanrec = NULL;
   SilcChannelEntry channel_entry = NULL;
   char *nickname = NULL, *tmp;
   int command = 0, port = 0, type = 0;
@@ -525,11 +526,12 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
       name = argv[2];
     }
 
-    channel_entry = silc_client_get_channel(silc_client, conn, name);
-    if (!channel_entry) {
+    chanrec = silc_channel_find(server, name);
+    if (chanrec == NULL) {
       silc_free(nickname);
-      cmd_return_error(CMDERR_NOT_JOINED);
+      cmd_return_error(CMDERR_CHAN_NOT_FOUND);
     }
+    channel_entry = chanrec->entry;
   }
 
   /* Set command */
@@ -576,7 +578,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
          hmac = argv[6];
 
        if (!silc_client_add_channel_private_key(silc_client, conn, 
-                                                channel_entry,
+                                                channel_entry, NULL,
                                                 cipher, hmac,
                                                 argv[4],
                                                 argv_lens[4])) {
@@ -776,22 +778,18 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
        
         hostname = (char *)settings_get_str("auto_public_ip");
 
-/* If the hostname isn't set, treat this case as if auto_public_ip wasn't
- * set.
- */
+       /* If the hostname isn't set, treat this case as if auto_public_ip 
+          wasn't set. */
         if ((hostname) && (*hostname == '\0')) {
            hostname = NULL;
-        }
-        else {
+        } else {
           bindhost = (char *)settings_get_str("auto_bind_ip");
             
-/* if the bind_ip isn't set, but the public_ip IS, then assume then
- * public_ip is the same value as the bind_ip.
- */
-          if ((bindhost) && (*bindhost == '\0')) {
+         /* if the bind_ip isn't set, but the public_ip IS, then assume then
+            public_ip is the same value as the bind_ip. */
+          if ((bindhost) && (*bindhost == '\0'))
             bindhost = hostname;
-          }
-           port = settings_get_int("auto_bind_port");
+         port = settings_get_int("auto_bind_port");
         }
       }  /* if use_auto_addr */
     }
@@ -812,6 +810,48 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
     internal->server = server;
   }
 
+  /* Change current channel private key */
+  if (!strcasecmp(argv[3], "change")) {
+    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)
+       goto out;
+
+      if (argc == 4) {
+       chanrec->cur_key++;
+       if (chanrec->cur_key >= keys_count)
+         chanrec->cur_key = 0;
+      }
+
+      if (argc > 4) {
+       number = atoi(argv[4]);
+       if (!number || number > keys_count)
+         chanrec->cur_key = 0;
+       else
+         chanrec->cur_key = number - 1;
+      }
+
+      /* Set the current channel private key */
+      silc_client_current_channel_private_key(silc_client, conn, 
+                                             channel_entry, 
+                                             keys[chanrec->cur_key]);
+      printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                        SILCTXT_CH_PRIVATE_KEY_CHANGE, chanrec->cur_key + 1,
+                        channel_entry->channel_name);
+
+      silc_client_free_channel_private_keys(keys, keys_count);
+      goto out;
+    }
+  }
+
   if (command == 0) {
     silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO,
             "Usage: /KEY msg|channel <nickname|channel> "
index 8a286b733efe8c5575c07513bb47b9da07397d28..b572712c4b8c0cf30d5e8445262424ba544643bb 100644 (file)
@@ -19,6 +19,7 @@ typedef struct {
   GSList *banlist;             /* list of bans */
   GSList *ebanlist;            /* list of ban exceptions */
   GSList *invitelist;          /* invite list */
+  SilcUInt32 cur_key;
   SilcChannelEntry entry;
 } SILC_CHANNEL_REC;
 
index 03ccd79f7426e2c27bc9a24706e65bac7b7556c1..dcd9bb34ff94856cd113f9cecf96ee1f1ef890ca 100644 (file)
@@ -295,7 +295,7 @@ char *silc_server_get_channels(SILC_SERVER_REC *server)
 /* SYNTAX: INVITE <channel> [<nickname>[@hostname>] */
 /* SYNTAX: INVITE <channel> [+|-[<nickname>[@<server>[!<username>[@hostname>]]]]] */
 /* SYNTAX: KEY MSG <nickname> set|unset|list|agreement|negotiate [<arguments>] */
-/* SYNTAX: KEY CHANNEL <channel> set|unset|list [<arguments>] */
+/* SYNTAX: KEY CHANNEL <channel> set|unset|list|change [<arguments>] */
 /* SYNTAX: KICK <channel> <nickname>[@<hostname>] [<comment>] */
 /* SYNTAX: KILL <nickname>[@<hostname>] [<comment>] */
 /* SYNTAX: OPER <username> [-pubkey] */
index 485decf0867e70e8fec29bfba533bcf6f4d2364e..ff2f6d026a92cf69472661ce93e7218a736ab30b 100644 (file)
@@ -471,6 +471,7 @@ void silc_client_receive_channel_key(SilcClient client,
 int silc_client_add_channel_private_key(SilcClient client,
                                        SilcClientConnection conn,
                                        SilcChannelEntry channel,
+                                       const char *name,
                                        char *cipher,
                                        char *hmac,
                                        unsigned char *key,
@@ -520,6 +521,7 @@ int silc_client_add_channel_private_key(SilcClient client,
 
   /* Save the key */
   entry = silc_calloc(1, sizeof(*entry));
+  entry->name = name ? strdup(name) : NULL;
   entry->key = silc_memdup(keymat->send_enc_key, keymat->enc_key_len / 8);
   entry->key_len = keymat->enc_key_len / 8;
 
@@ -565,6 +567,7 @@ int silc_client_del_channel_private_keys(SilcClient client,
     silc_dlist_del(channel->private_keys, entry);
     memset(entry->key, 0, entry->key_len);
     silc_free(entry->key);
+    silc_free(entry->name);
     silc_cipher_free(entry->cipher);
     silc_hmac_free(entry->hmac);
     silc_free(entry);
@@ -603,6 +606,7 @@ int silc_client_del_channel_private_key(SilcClient client,
       silc_dlist_del(channel->private_keys, entry);
       memset(entry->key, 0, entry->key_len);
       silc_free(entry->key);
+      silc_free(entry->name);
       silc_cipher_free(entry->cipher);
       silc_hmac_free(entry->hmac);
       silc_free(entry);
@@ -658,6 +662,18 @@ void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
   silc_free(keys);
 }
 
+/* Sets the `key' to be used as current channel private key on the
+   `channel'.  Packet sent after calling this function will be secured
+   with `key'. */
+
+void silc_client_current_channel_private_key(SilcClient client,
+                                            SilcClientConnection conn,
+                                            SilcChannelEntry channel,
+                                            SilcChannelPrivateKey key)
+{
+  channel->curr_key = key;
+}
+
 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the 
    channel indicated by the `channel'. NULL if client is not joined on
    the channel. */
index 2ef43aec9245307d993752a0ae37fff1a546ec80..c229b4509655c111fe43e21c6f0fc45d8922a6d7 100644 (file)
@@ -71,7 +71,7 @@ void silc_client_send_private_message(SilcClient client,
   /* We have private message specific key */
 
   /* Get data used in the encryption */
-  cipher = client_entry->send_key;
+  cipher = conn->send_key;
   hmac = conn->hmac_send;
   block_len = silc_cipher_get_block_len(cipher);
 
@@ -103,7 +103,6 @@ void silc_client_send_private_message(SilcClient client,
   }
 
   /* Encrypt the header and padding of the packet. */
-  cipher = conn->send_key;
   silc_packet_encrypt(cipher, hmac, conn->psn_send++,
                      (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN + 
                      packetdata.src_id_len + packetdata.dst_id_len +
index ef48ed54fbdbacf53af102c48af8a412c6b83c5a..7d680741f73c2f9b554784423e72c0d1a2afea2b 100644 (file)
@@ -61,14 +61,6 @@ struct SilcChannelUserStruct {
   SilcChannelEntry channel;
 };
 
-/* Structure to hold one channel private key. */
-struct SilcChannelPrivateKeyStruct {
-  SilcCipher cipher;                 /* The cipher and key */
-  SilcHmac hmac;                     /* The HMAC and hmac key */
-  unsigned char *key;                /* The key data */
-  SilcUInt32 key_len;                /* The key length */
-};
-
 /* Channel entry context. This is allocate for every channel client has
    joined to. This includes for example the channel specific keys */
 struct SilcChannelEntryStruct {
index 2dcb7a58a8aaf9bf9c05b1d984a5f303d1afe741..1e069138a4b53a51c70a7eed51f7c75c4af4082d 100644 (file)
@@ -68,7 +68,6 @@ typedef struct SilcClientCommandStruct *SilcClientCommand;
 typedef struct SilcClientCommandContextStruct *SilcClientCommandContext;
 typedef struct SilcClientCommandReplyContextStruct 
                                            *SilcClientCommandReplyContext;
-typedef struct SilcChannelPrivateKeyStruct *SilcChannelPrivateKey;
 typedef struct SilcChannelUserStruct *SilcChannelUser;
 
 /* General definitions */
@@ -150,6 +149,27 @@ typedef struct {
 } *SilcPrivateMessageKeys;
 /***/
 
+/****s* silcclient/SilcClientAPI/SilcChannelPrivateKey
+ *
+ * NAME
+ *
+ *    typedef struct { ... } SilcChannelPrivateKey;
+ *
+ * DESCRIPTION
+ *
+ *    Structure to hold one channel private key. The array of this structure
+ *    is returned by silc_client_list_channel_private_keys function.
+ *
+ * SOURCE
+ */
+typedef struct SilcChannelPrivateKeyStruct {
+  char *name;                        /* Application given name */
+  SilcCipher cipher;                 /* The cipher and key */
+  SilcHmac hmac;                     /* The HMAC and hmac key */
+  unsigned char *key;                /* The key data */
+  SilcUInt32 key_len;                /* The key length */
+} *SilcChannelPrivateKey;
+/***/
 
 /****f* silcclient/SilcClientAPI/SilcAskPassphrase
  *
@@ -1471,6 +1491,7 @@ void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
  *    int silc_client_add_channel_private_key(SilcClient client,
  *                                            SilcClientConnection conn,
  *                                            SilcChannelEntry channel,
+ *                                            const char *name,
  *                                            char *cipher,
  *                                            char *hmac,
  *                                            unsigned char *key,
@@ -1485,6 +1506,7 @@ void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
  *    key in order to decrypt the messages. However, it is possible to have
  *    several private keys per one channel. In this case only some of the
  *    clients on the channel may know the one key and only some the other key.
+ *    The `name' can be application given name for the key.
  *
  *    The private key for channel is optional. If it is not set then the
  *    channel messages are encrypted using the channel key generated by the
@@ -1510,6 +1532,7 @@ void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
 int silc_client_add_channel_private_key(SilcClient client,
                                        SilcClientConnection conn,
                                        SilcChannelEntry channel,
+                                       const char *name,
                                        char *cipher,
                                        char *hmac,
                                        unsigned char *key,
@@ -1598,6 +1621,27 @@ silc_client_list_channel_private_keys(SilcClient client,
 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
                                           SilcUInt32 key_count);
 
+/****f* silcclient/SilcClientAPI/silc_client_current_channel_private_key
+ *
+ * SYNOPSIS
+ *
+ *    void silc_client_current_channel_private_key(SilcClient client,
+ *                                                 SilcClientConnection conn,
+ *                                                 SilcChannelEntry channel,
+ *                                                 SilcChannelPrivateKey key);
+ *
+ * DESCRIPTION
+ *
+ *    Sets the `key' to be used as current channel private key on the
+ *    `channel'.  Packet sent after calling this function will be secured
+ *    with `key'.
+ *
+ ***/
+void silc_client_current_channel_private_key(SilcClient client,
+                                            SilcClientConnection conn,
+                                            SilcChannelEntry channel,
+                                            SilcChannelPrivateKey key);
+
 
 /* Key Agreement routines (client_keyagr.c) */
 
diff --git a/prepare b/prepare
index e7e4ab8e875cef7b8509b04b197346d1c0cfd526..d3fc25bd10c83c936cae66a8ae9af30ab627ac2b 100755 (executable)
--- a/prepare
+++ b/prepare
@@ -37,7 +37,7 @@
 # SILC Distribution versions. Set here or give the version on the command
 # line as argument.
 #
-SILC_VERSION=0.8                       # Base version
+SILC_VERSION=0.8.1                     # Base version
 
 #############################################################################