Added support for using channel private keys without the private
authorPekka Riikonen <priikone@silcnet.org>
Sat, 28 Feb 2004 14:43:28 +0000 (14:43 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sat, 28 Feb 2004 14:43:28 +0000 (14:43 +0000)
key mode on the channel being set.
The channel private key used to decrypt message is now develired
to channel_message client operation.

CHANGES
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/client_ops.h
lib/silcclient/client_channel.c
lib/silcclient/client_ops_example.c
lib/silcclient/command_reply.c
lib/silcclient/silcclient.h

diff --git a/CHANGES b/CHANGES
index 72dbbc609f11f397f618af87402579f8310df6d6..d929e9e2baac193db4a31da4f89a24df662f78ab 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -5,6 +5,15 @@ Sat Feb 28 16:25:09 EET 2004  Pekka Riikonen <priikone@silcnet.org>
          Affected files are lib/silcclient/silcclient.h and
          client_channel.c.
 
+       * Added support for using channel private keys in SILC
+         Client Library even if the private key mode is not set
+         on the channel.  Affected file lib/silcclient/client_channel.c.
+
+       * The channel private key used to decrypt message is now
+         delivered to the application in the 'channel_messageÃ' client
+         operation.  Affected files are lib/silcclient/silcclient.h
+         and client_channel.c.
+
 Fri Feb 27 11:25:26 CET 2004  Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed the JOIN command calling when called with both
index d32c813998b3bb3538c51b9dbcd0094614370c00..3980c45dd147ad7e36a1816adeb0a94189973caf 100644 (file)
@@ -131,7 +131,7 @@ silc_print_nick_change_channel(SILC_SERVER_REC *server, const char *channel,
                   channel, newnick, MSGLEVEL_NICKS))
     return;
 
-  signal_emit("message silc appears", 5, server, channel, 
+  signal_emit("message silc appears", 5, server, channel,
                oldnick, newnick, address);
 }
 
@@ -364,6 +364,7 @@ void silc_emit_mime_sig(SILC_SERVER_REC *server, WI_ITEM_REC *item,
 void silc_channel_message(SilcClient client, SilcClientConnection conn,
                          SilcClientEntry sender, SilcChannelEntry channel,
                          SilcMessagePayload payload,
+                         SilcChannelPrivateKey key,
                          SilcMessageFlags flags, const unsigned char *message,
                          SilcUInt32 message_len)
 {
@@ -559,23 +560,23 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
       silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
                        cp, message_len);
       if (flags & SILC_MESSAGE_FLAG_SIGNED)
-        signal_emit("message silc signed_private_action", 6, server, cp, 
+        signal_emit("message silc signed_private_action", 6, server, cp,
                    sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL, 
+                   sender->username ? userhost : NULL,
                    NULL, verified);
       else
-        signal_emit("message silc private_action", 5, server, cp, 
+        signal_emit("message silc private_action", 5, server, cp,
                    sender->nickname ? sender->nickname : "[<unknown>]",
                    sender->username ? userhost : NULL, NULL);
       silc_free(dm);
     } else {
       if (flags & SILC_MESSAGE_FLAG_SIGNED)
-        signal_emit("message silc signed_private_action", 6, server, message, 
+        signal_emit("message silc signed_private_action", 6, server, message,
                    sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL, 
+                   sender->username ? userhost : NULL,
                    NULL, verified);
       else
-        signal_emit("message silc private_action", 5, server, message, 
+        signal_emit("message silc private_action", 5, server, message,
                    sender->nickname ? sender->nickname : "[<unknown>]",
                    sender->username ? userhost : NULL, NULL);
     }
@@ -591,23 +592,23 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
       silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
                        cp, message_len);
       if (flags & SILC_MESSAGE_FLAG_SIGNED)
-        signal_emit("message silc signed_private_notice", 6, server, cp, 
+        signal_emit("message silc signed_private_notice", 6, server, cp,
                    sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL, 
+                   sender->username ? userhost : NULL,
                    NULL, verified);
       else
-        signal_emit("message silc private_notice", 5, server, cp, 
+        signal_emit("message silc private_notice", 5, server, cp,
                    sender->nickname ? sender->nickname : "[<unknown>]",
                    sender->username ? userhost : NULL, NULL);
       silc_free(dm);
     } else {
       if (flags & SILC_MESSAGE_FLAG_SIGNED)
-        signal_emit("message silc signed_private_notice", 6, server, message, 
+        signal_emit("message silc signed_private_notice", 6, server, message,
                    sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL, 
+                   sender->username ? userhost : NULL,
                    NULL, verified);
       else
-        signal_emit("message silc private_notice", 5, server, message, 
+        signal_emit("message silc private_notice", 5, server, message,
                    sender->nickname ? sender->nickname : "[<unknown>]",
                    sender->username ? userhost : NULL, NULL);
     }
@@ -634,7 +635,7 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
                  sender->username ? userhost : NULL);
       silc_free(dm);
       return;
-    } 
+    }
 
     if (flags & SILC_MESSAGE_FLAG_SIGNED)
       signal_emit("message signed_private", 5, server, message,
@@ -644,7 +645,7 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
       signal_emit("message private", 4, server, message,
               sender->nickname ? sender->nickname : "[<unknown>]",
               sender->username ? userhost : NULL);
-  } 
+  }
 }
 
 /* Notify message to the client. The notify arguments are sent in the
@@ -750,7 +751,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
 
     client_entry = va_arg(va, SilcClientEntry);
     channel = va_arg(va, SilcChannelEntry);
-    
+
     memset(buf, 0, sizeof(buf));
     if (client_entry->username)
       snprintf(buf, sizeof(buf) - 1, "%s@%s",
@@ -808,9 +809,9 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
     /*
      * Changed topic.
      */
-    
+
     SILC_LOG_DEBUG(("Notify: TOPIC_SET"));
-    
+
     idtype = va_arg(va, int);
     entry = va_arg(va, void *);
     tmp = va_arg(va, char *);
@@ -820,14 +821,14 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
 
     chanrec = silc_channel_find_entry(server, channel);
     if (chanrec != NULL) {
-    
+
       g_free_not_null(chanrec->topic);
-    
+
       chanrec->topic = *tmp == '\0' ? NULL : g_strdup(tmp);
       signal_emit("channel topic changed", 1, chanrec);
-    
+
     }
-    
+
     if (idtype == SILC_ID_CLIENT) {
       client_entry = (SilcClientEntry)entry;
       memset(buf, 0, sizeof(buf));
@@ -845,7 +846,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
       signal_emit("message topic", 5, server, channel->channel_name,
                  tmp, channel->channel_name, channel->channel_name);
     }
-    
+
     silc_free(tmp);
     break;
 
@@ -1230,7 +1231,7 @@ void silc_connect(SilcClient client, SilcClientConnection conn,
   switch (status) {
   case SILC_CLIENT_CONN_SUCCESS:
     /* We have successfully connected to server */
-    if ((client->nickname != NULL) && 
+    if ((client->nickname != NULL) &&
         (strcmp(client->nickname, client->username)))
       silc_queue_enable(conn); /* enable queueing until we have our nick */
     server->connected = TRUE;
@@ -2403,7 +2404,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
        return;
 
       /* Print the channel public key list */
-      signal_emit("message silc pubkeys", 3, 
+      signal_emit("message silc pubkeys", 3,
                        server, channel_entry, channel_pubkeys);
     }
     break;
index db982e0954e49f20c3f4793dd4a25f6fe9665fd8..d9c181822a50034fa1731a333c3a4d07ff2ecaf0 100644 (file)
@@ -10,7 +10,7 @@
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
-  
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 #include "silc-servers.h"
 
-void silc_say(SilcClient client, SilcClientConnection conn, 
+void silc_say(SilcClient client, SilcClientConnection conn,
              SilcClientMessageType type, char *msg, ...);
 void silc_say_error(char *msg, ...);
 void silc_channel_message(SilcClient client, SilcClientConnection conn,
-                         SilcClientEntry sender, 
-                         SilcChannelEntry channel, 
+                         SilcClientEntry sender,
+                         SilcChannelEntry channel,
                          SilcMessagePayload payload,
-                         SilcMessageFlags flags, 
+                         SilcChannelPrivateKey key,
+                         SilcMessageFlags flags,
                          const unsigned char *message,
                          SilcUInt32 message_len);
 void silc_private_message(SilcClient client, SilcClientConnection conn,
-                         SilcClientEntry sender, 
+                         SilcClientEntry sender,
                          SilcMessagePayload payload,
-                         SilcMessageFlags flags, 
+                         SilcMessageFlags flags,
                          const unsigned char *message,
                          SilcUInt32 message_len);
-void silc_notify(SilcClient client, SilcClientConnection conn, 
+void silc_notify(SilcClient client, SilcClientConnection conn,
                 SilcNotifyType type, ...);
-void silc_command(SilcClient client, SilcClientConnection conn, 
+void silc_command(SilcClient client, SilcClientConnection conn,
                  SilcClientCommandContext cmd_context, bool success,
                  SilcCommand command, SilcStatus status);
 void silc_command_reply(SilcClient client, SilcClientConnection conn,
@@ -54,13 +55,13 @@ void silc_disconnect(SilcClient client, SilcClientConnection conn,
 void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
                         SilcAskPassphrase completion, void *context);
 void silc_verify_public_key(SilcClient client, SilcClientConnection conn,
-                           SilcSocketType conn_type, unsigned char *pk, 
+                           SilcSocketType conn_type, unsigned char *pk,
                            SilcUInt32 pk_len, SilcSKEPKType pk_type,
                            SilcVerifyPublicKey completion, void *context);
 void silc_get_auth_method(SilcClient client, SilcClientConnection conn,
                          char *hostname, SilcUInt16 port,
                          SilcGetAuthMeth completion, void *context);
-void silc_failure(SilcClient client, SilcClientConnection conn, 
+void silc_failure(SilcClient client, SilcClientConnection conn,
                  SilcProtocol protocol, void *failure);
 bool silc_key_agreement(SilcClient client, SilcClientConnection conn,
                        SilcClientEntry client_entry, const char *hostname,
@@ -74,7 +75,7 @@ silc_detach(SilcClient client, SilcClientConnection conn,
             const unsigned char *detach_data, SilcUInt32 detach_data_len);
 char *
 silc_unescape_data(const char *escaped_data, SilcUInt32 *length);
-char * 
+char *
 silc_escape_data(const char *data, SilcUInt32 len);
 
 char *
index f372a989c27285b6a162b5c90c9bdc6d0a14170f..b052ea23cf561512b0fd86a2a4d28809160a28a0 100644 (file)
@@ -73,16 +73,18 @@ bool silc_client_send_channel_message(SilcClient client,
     return FALSE;
 
   /* Take the key to be used */
-  if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
+  if (channel->private_keys) {
     if (key) {
       /* Use key application specified */
       cipher = key->cipher;
       hmac = key->hmac;
-    } else if (channel->curr_key) {
+    } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
+              channel->curr_key) {
       /* Use current private key */
       cipher = channel->curr_key->cipher;
       hmac = channel->curr_key->hmac;
-    } else if (!channel->curr_key && channel->private_keys) {
+    } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
+              !channel->curr_key && channel->private_keys) {
       /* Use just some private key since we don't know what to use
         and private keys are set. */
       silc_dlist_start(channel->private_keys);
@@ -184,6 +186,7 @@ bool silc_client_send_channel_message(SilcClient client,
 typedef struct {
   SilcMessagePayload payload;
   SilcChannelID *channel_id;
+  SilcChannelPrivateKey key;
 } *SilcChannelClientResolve;
 
 static void silc_client_channel_message_cb(SilcClient client,
@@ -218,7 +221,7 @@ static void silc_client_channel_message_cb(SilcClient client,
     /* Pass the message to application */
     client->internal->ops->channel_message(
                            client, conn, clients[0], channel, res->payload,
-                           silc_message_get_flags(res->payload),
+                           res->key, silc_message_get_flags(res->payload),
                            message, message_len);
   }
 
@@ -245,6 +248,7 @@ void silc_client_channel_message(SilcClient client,
   SilcClientID *client_id = NULL;
   unsigned char *message;
   SilcUInt32 message_len;
+  SilcChannelPrivateKey key = NULL;
 
   SILC_LOG_DEBUG(("Received channel message"));
 
@@ -268,7 +272,7 @@ void silc_client_channel_message(SilcClient client,
   /* If there is no channel private key then just decrypt the message
      with the channel key. If private keys are set then just go through
      all private keys and check what decrypts correctly. */
-  if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
+  if (!channel->private_keys) {
     /* Parse the channel message payload. This also decrypts the payload */
     payload = silc_message_payload_parse(buffer->data, buffer->len, FALSE,
                                         FALSE, channel->channel_key,
@@ -304,22 +308,28 @@ void silc_client_channel_message(SilcClient client,
       if (!payload)
        goto out;
     }
-  } else if (channel->private_keys) {
-    SilcChannelPrivateKey entry;
-
-    silc_dlist_start(channel->private_keys);
-    while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
-      /* Parse the message payload. This also decrypts the payload */
-      payload = silc_message_payload_parse(buffer->data, buffer->len,
-                                          FALSE, FALSE,
-                                          entry->cipher, entry->hmac);
-      if (payload)
-       break;
-    }
-    if (entry == SILC_LIST_END)
-      goto out;
   } else {
-    goto out;
+    /* If the private key mode, however is not set on the channel then
+       try the actual channel key first before trying private keys. */
+    if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
+      payload = silc_message_payload_parse(buffer->data, buffer->len, FALSE,
+                                          FALSE, channel->channel_key,
+                                          channel->hmac);
+
+    if (!payload) {
+      silc_dlist_start(channel->private_keys);
+      while ((key = silc_dlist_get(channel->private_keys))
+            != SILC_LIST_END) {
+       /* Parse the message payload. This also decrypts the payload */
+       payload = silc_message_payload_parse(buffer->data, buffer->len,
+                                            FALSE, FALSE,
+                                            key->cipher, key->hmac);
+       if (payload)
+         break;
+      }
+      if (key == SILC_LIST_END)
+       goto out;
+    }
   }
 
   /* Find client entry */
@@ -330,6 +340,7 @@ void silc_client_channel_message(SilcClient client,
     SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
     res->payload = payload;
     res->channel_id = id;
+    res->key = key;
     silc_client_get_client_by_id_resolve(client, conn, client_id, NULL,
                                         silc_client_channel_message_cb,
                                         res);
@@ -343,7 +354,7 @@ void silc_client_channel_message(SilcClient client,
   /* Pass the message to application */
   client->internal->ops->channel_message(
                             client, conn, client_entry, channel, payload,
-                            silc_message_get_flags(payload),
+                            key, silc_message_get_flags(payload),
                             message, message_len);
 
  out:
@@ -485,13 +496,12 @@ void silc_client_receive_channel_key(SilcClient client,
   silc_client_save_channel_key(client, sock->user_data, packet, NULL);
 }
 
-/* Adds private key for channel. This may be set only if the channel's mode
-   mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
-   mode is not set. When channel has private key then the messages are
-   encrypted using that key. All clients on the channel must also know the
-   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.
+/* Adds private key for channel. When channel has private key then the
+   messages are encrypted using that key. All clients on the channel must
+   also know the 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.
 
    If `cipher' and/or `hmac' is NULL then default values will be used
    (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
@@ -530,9 +540,6 @@ bool silc_client_add_channel_private_key(SilcClient client,
 
   assert(client && channel);
 
-  if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
-    return FALSE;
-
   if (!cipher)
     cipher = SILC_DEFAULT_CIPHER;
   if (!hmac)
@@ -551,20 +558,6 @@ bool silc_client_add_channel_private_key(SilcClient client,
       != SILC_SKE_STATUS_OK)
     return FALSE;
 
-  /* Remove the current key, if it exists. */
-  if (channel->channel_key) {
-    silc_cipher_free(channel->channel_key);
-    memset(channel->key, 0, channel->key_len / 8);
-    silc_free(channel->key);
-    channel->channel_key = NULL;
-    channel->key = NULL;
-    channel->key_len = 0;
-  }
-  if (channel->hmac) {
-    silc_hmac_free(channel->hmac);
-    channel->hmac = NULL;
-  }
-
   if (!channel->private_keys)
     channel->private_keys = silc_dlist_init();
 
index 19b9acc14fdc856291da82e83f43c54b5f13938e..4fe166a873b54004f30519bb3ffd58b1dfd550ce 100644 (file)
@@ -31,15 +31,16 @@ silc_say(SilcClient client, SilcClientConnection conn,
 static void
 silc_channel_message(SilcClient client, SilcClientConnection conn,
                     SilcClientEntry sender, SilcChannelEntry channel,
-                    SilcMessagePayload payload, SilcMessageFlags flags,
-                    const unsigned char *message, SilcUInt32 message_len)
+                    SilcMessagePayload payload, SilcChannelPrivateKey key,
+                    SilcMessageFlags flags, const unsigned char *message,
+                    SilcUInt32 message_len)
 {
 
 }
 
 
 /* Private message to the client. The `sender' is the sender of the
-   message. The message is `message'and maybe NULL.  The `flags'  
+   message. The message is `message'and maybe NULL.  The `flags'
    indicates message flags  and it is used to determine how the message
    can be interpreted (like it may tell the message is multimedia
    message). */
index 6cb2c1d771a74dcedb4c68adb5d5113d80d00fb0..4e226e810d6bdfeb5e631bb6af61b6a873a7c49e 100644 (file)
@@ -1124,7 +1124,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
                   client_mode_list->head);
 
   /* Save channel key */
-  if (keyp && !(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
+  if (keyp)
     silc_client_save_channel_key(cmd->client, conn, keyp, channel);
 
   /* Get founder key */
index 592dbd23ce29843c2ca7ac79ab745cb92bc47870..5fa200659e29521f255bda1358054ec128865bac 100644 (file)
@@ -580,7 +580,8 @@ typedef struct {
      (like it may tell the message is multimedia message). */
   void (*channel_message)(SilcClient client, SilcClientConnection conn,
                          SilcClientEntry sender, SilcChannelEntry channel,
-                         SilcMessagePayload payload, SilcMessageFlags flags,
+                         SilcMessagePayload payload,
+                         SilcChannelPrivateKey key, SilcMessageFlags flags,
                          const unsigned char *message,
                          SilcUInt32 message_len);
 
@@ -2030,15 +2031,14 @@ void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
  *
  * DESCRIPTION
  *
- *    Adds private key for channel. This may be set only if the channel's mode
- *    mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
- *    mode is not set. When channel has private key then the messages are
- *    encrypted using that key. All clients on the channel must also know the
- *    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.  This returns
- *    the created key to the 'ret_key' pointer if it is non-NULL;
+ *    Adds private key for channel. When channel has private key then the
+ *    messages are encrypted using that key. All clients on the channel
+ *    must also know the 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.  This returns the created key to the 'ret_key'
+ *    pointer if it is non-NULL;
  *
  *    If `cipher' and/or `hmac' is NULL then default values will be used
  *    (aes-256-cbc for cipher and hmac-sha1-96 for hmac).