updates.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 26 Jun 2001 21:16:17 +0000 (21:16 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 26 Jun 2001 21:16:17 +0000 (21:16 +0000)
CHANGES
apps/irssi/src/silc/core/silc-channels.c
lib/silcclient/client_keyagr.c
lib/silcclient/client_prvmsg.c
lib/silcclient/silcapi.h
lib/silccore/silcprivate.c

diff --git a/CHANGES b/CHANGES
index 9c06a57778f88cc5016f19fd686cf375f3a0c827..9ef4147d4525fdcc94d07f0e8f11cf7384321651 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,21 @@
+Wed Jun 27 00:10:33 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed a fatal bug in private message sending and reception
+         encryption and decryption when using private message keys.
+         The implementation was incorrect and did not follow the
+         specification.  It causd that some of the message were
+         lost since it did not use the sending and receiving keys
+         as the protocol suggests.  This has been fixed and will cause
+         incompatibilities with older clients when sending private
+         message encrypted with private message keys.  Affected files
+         lib/silcclient/client_prvmsg.c, lib/silcclient/client_keyagr.c
+         and various other in Irssi SILC Client.
+
+         Added `responder' boolean argument to the functions
+         silc_client_add_private_message_key[_ske] to indicate when
+         the key is added as responder or initiator of the key
+         negotiation.
+
 Tue Jun 26 19:23:07 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
 
        * Removed the silc_ske_check_version function and created
@@ -20,6 +38,11 @@ Tue Jun 26 19:23:07 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
          is in process when we get timeout.  Affected file is
          lib/silcclient/client_keyagr.c.
 
+       * Do not resolve the client ID forever if it returns in the
+         first time that such client does not exist.  This was done
+         for example with private message.  Affected file is
+         lib/silcclient/client_prvmsg.c.
+
 Mon Jun 25 21:42:51 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
 
        * Do not add regex.h for WIN32.  The affected file
index cf3fc6ba055e6650eaabfb44e2b0bd99b106060a..ead74959c8bd6287016db399995632e6a4b73b04 100644 (file)
@@ -688,6 +688,7 @@ static void command_away(const char *data, SILC_SERVER_REC *server,
 
 typedef struct {
   int type;                    /* 1 = msg, 2 = channel */
+  bool responder;
   SILC_SERVER_REC *server;
 } *KeyInternal;
 
@@ -717,7 +718,7 @@ static void keyagr_completion(SilcClient client,
       /* 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, key);
+                                             NULL, key, i->responder);
       printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
                         SILCTXT_KEY_AGREEMENT_PRIVMSG, 
                         client_entry->nickname);
@@ -889,13 +890,13 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
                                              argv[5], argv[4],
                                              argv_lens[4],
                                              (argv[4][0] == '*' ?
-                                              TRUE : FALSE));
+                                              TRUE : FALSE), FALSE);
        else
          silc_client_add_private_message_key(silc_client, conn, client_entry,
                                              NULL, argv[4],
                                              argv_lens[4],
                                              (argv[4][0] == '*' ?
-                                              TRUE : FALSE));
+                                              TRUE : FALSE), FALSE);
 
        /* Send the key to the remote client so that it starts using it
           too. */
@@ -1135,14 +1136,18 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
   if (command == 4 && client_entry) {
     printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
                       SILCTXT_KEY_AGREEMENT, argv[2]);
+    internal->responder = TRUE;
     silc_client_send_key_agreement(silc_client, conn, client_entry, hostname, 
                                   port, 120, keyagr_completion, internal);
+    if (!hostname)
+      silc_free(internal);
     goto out;
   }
 
   if (command == 5 && client_entry && hostname) {
     printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
                       SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
+    internal->responder = FALSE;
     silc_client_perform_key_agreement(silc_client, conn, client_entry, 
                                      hostname, port, keyagr_completion, 
                                      internal);
index 1540b9dc7162206fecbcebb257f5e748bee1142f..6be73f8900ad1c4d14dbbfca47499126ee9d79ad 100644 (file)
@@ -283,6 +283,10 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
    If remote side decides to ignore the request the `completion' will be
    called after the specified timeout, `timeout_secs'. 
 
+   NOTE: If the `hostname' and the `port' was not provided the `completion'
+   will not be called at all since this does nothing more than sending
+   a packet to the remote host.
+
    NOTE: There can be only one active key agreement for one client entry.
    Before setting new one, the old one must be finished (it is finished
    after calling the completion callback) or the function 
index c5a41b11ec70b86e934e30c91bb01e8a2a7aab3f..5b465df210a454534a44321317b590b5fa2ab31d 100644 (file)
@@ -126,6 +126,11 @@ static void silc_client_private_message_cb(SilcClient client,
 {
   SilcPacketContext *packet = (SilcPacketContext *)context;
 
+  if (!clients) {
+    silc_packet_context_free(packet);
+    return;
+  }
+
   silc_client_private_message(client, conn->sock, packet);
   silc_packet_context_free(packet);
 }
@@ -168,7 +173,7 @@ void silc_client_private_message(SilcClient client,
 
   /* Parse the payload and decrypt it also if private message key is set */
   payload = silc_private_message_payload_parse(packet->buffer,
-                                              remote_client->send_key);
+                                              remote_client->receive_key);
   if (!payload) {
     silc_free(remote_id);
     return;
@@ -233,7 +238,7 @@ static void silc_client_private_message_key_cb(SilcClient client,
 
   /* Now take the key in use */
   if (!silc_client_add_private_message_key(client, conn, clients[0],
-                                          cipher, key, key_len, FALSE))
+                                          cipher, key, key_len, FALSE, TRUE))
     goto out;
 
   /* Print some info for application */
@@ -282,6 +287,11 @@ void silc_client_private_message_key(SilcClient client,
    requirements of the SILC protocol are met. The API, however, allows
    to allocate any cipher.
 
+   If `responder' is TRUE then the sending and receiving keys will be
+   set according the client being the receiver of the private key.  If
+   FALSE the client is being the sender (or negotiator) of the private
+   key.
+
    It is not necessary to set key for normal private message usage. If the
    key is not set then the private messages are encrypted using normal
    session keys. Setting the private key, however, increases the security. 
@@ -295,7 +305,8 @@ int silc_client_add_private_message_key(SilcClient client,
                                        char *cipher,
                                        unsigned char *key,
                                        uint32 key_len,
-                                       int generate_key)
+                                       bool generate_key,
+                                       bool responder)
 {
   unsigned char private_key[32];
   uint32 len;
@@ -341,12 +352,21 @@ int silc_client_add_private_message_key(SilcClient client,
   silc_cipher_alloc(cipher, &client_entry->receive_key);
 
   /* Set the keys */
-  silc_cipher_set_key(client_entry->send_key, keymat->send_enc_key,
-                     keymat->enc_key_len);
-  silc_cipher_set_iv(client_entry->send_key, keymat->send_iv);
-  silc_cipher_set_key(client_entry->receive_key, keymat->receive_enc_key,
-                     keymat->enc_key_len);
-  silc_cipher_set_iv(client_entry->receive_key, keymat->receive_iv);
+  if (responder == TRUE) {
+    silc_cipher_set_key(client_entry->send_key, keymat->receive_enc_key,
+                       keymat->enc_key_len);
+    silc_cipher_set_iv(client_entry->send_key, keymat->receive_iv);
+    silc_cipher_set_key(client_entry->receive_key, keymat->send_enc_key,
+                       keymat->enc_key_len);
+    silc_cipher_set_iv(client_entry->receive_key, keymat->send_iv);
+  } else {
+    silc_cipher_set_key(client_entry->send_key, keymat->send_enc_key,
+                       keymat->enc_key_len);
+    silc_cipher_set_iv(client_entry->send_key, keymat->send_iv);
+    silc_cipher_set_key(client_entry->receive_key, keymat->receive_enc_key,
+                       keymat->enc_key_len);
+    silc_cipher_set_iv(client_entry->receive_key, keymat->receive_iv);
+  }
 
   /* Free the key material */
   silc_ske_free_key_material(keymat);
@@ -364,7 +384,8 @@ int silc_client_add_private_message_key_ske(SilcClient client,
                                            SilcClientConnection conn,
                                            SilcClientEntry client_entry,
                                            char *cipher,
-                                           SilcSKEKeyMaterial *key)
+                                           SilcSKEKeyMaterial *key,
+                                           bool responder)
 {
   assert(client_entry);
 
@@ -384,12 +405,21 @@ int silc_client_add_private_message_key_ske(SilcClient client,
   silc_cipher_alloc(cipher, &client_entry->receive_key);
 
   /* Set the keys */
-  silc_cipher_set_key(client_entry->send_key, key->send_enc_key,
-                     key->enc_key_len);
-  silc_cipher_set_iv(client_entry->send_key, key->send_iv);
-  silc_cipher_set_key(client_entry->receive_key, key->receive_enc_key,
-                     key->enc_key_len);
-  silc_cipher_set_iv(client_entry->receive_key, key->receive_iv);
+  if (responder == TRUE) {
+    silc_cipher_set_key(client_entry->send_key, key->receive_enc_key,
+                       key->enc_key_len);
+    silc_cipher_set_iv(client_entry->send_key, key->receive_iv);
+    silc_cipher_set_key(client_entry->receive_key, key->send_enc_key,
+                       key->enc_key_len);
+    silc_cipher_set_iv(client_entry->receive_key, key->send_iv);
+  } else {
+    silc_cipher_set_key(client_entry->send_key, key->send_enc_key,
+                       key->enc_key_len);
+    silc_cipher_set_iv(client_entry->send_key, key->send_iv);
+    silc_cipher_set_key(client_entry->receive_key, key->receive_enc_key,
+                       key->enc_key_len);
+    silc_cipher_set_iv(client_entry->receive_key, key->receive_iv);
+  }
 
   return TRUE;
 }
index c1f46d258fd4f01e6dc7dd3eace21ab997d90d7c..45506527d2eb43095eee4eb4cdace19246b7c9f6 100644 (file)
@@ -910,7 +910,8 @@ void silc_client_command_pending(SilcClientConnection conn,
  *                                            char *cipher,
  *                                            unsigned char *key,
  *                                            uint32 key_len,
- *                                            int generate_key);
+ *                                            bool generate_key,
+ *                                            bool responder);
  *
  * DESCRIPTION
  *
@@ -923,6 +924,11 @@ void silc_client_command_pending(SilcClientConnection conn,
  *    requirements of the SILC protocol are met. The API, however, allows
  *    to allocate any cipher.
  *
+ *    If `responder' is TRUE then the sending and receiving keys will be
+ *    set according the client being the receiver of the private key.  If
+ *    FALSE the client is being the sender (or negotiator) of the private
+ *    key.
+ *
  *    It is not necessary to set key for normal private message usage. If the
  *    key is not set then the private messages are encrypted using normal
  *    session keys. Setting the private key, however, increases the security. 
@@ -937,7 +943,8 @@ int silc_client_add_private_message_key(SilcClient client,
                                        char *cipher,
                                        unsigned char *key,
                                        uint32 key_len,
-                                       int generate_key);
+                                       bool generate_key,
+                                       bool responder);
 
 /****f* silcclient/SilcClientAPI/silc_client_add_private_message_key_ske
  *
@@ -951,18 +958,19 @@ int silc_client_add_private_message_key(SilcClient client,
  *
  * DESCRIPTION
  *
- *    Same as above but takes the key material from the SKE key material
- *    structure. This structure is received if the application uses the
- *    silc_client_send_key_agreement to negotiate the key material. The
- *    `cipher' SHOULD be provided as it is negotiated also in the SKE
- *    protocol. 
+ *    Same as silc_client_add_private_message_key but takes the key material
+ *    from the SKE key material structure. This structure is received if
+ *    the application uses the silc_client_send_key_agreement to negotiate
+ *    the key material. The `cipher' SHOULD be provided as it is negotiated
+ *    also in the SKE protocol. 
  *
  ***/
 int silc_client_add_private_message_key_ske(SilcClient client,
                                            SilcClientConnection conn,
                                            SilcClientEntry client_entry,
                                            char *cipher,
-                                           SilcSKEKeyMaterial *key);
+                                           SilcSKEKeyMaterial *key,
+                                           bool responder);
 
 /****f* silcclient/SilcClientAPI/silc_client_send_private_message_key
  *
@@ -1238,6 +1246,10 @@ void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
  *    If remote side decides to ignore the request the `completion' will be
  *    called after the specified timeout, `timeout_secs'. 
  *
+ *    NOTE: If the `hostname' and the `port' was not provided the `completion'
+ *    will not be called at all since this does nothing more than sending
+ *    a packet to the remote host.
+ *
  *    NOTE: There can be only one active key agreement for one client entry.
  *    Before setting new one, the old one must be finished (it is finished
  *    after calling the completion callback) or the function 
index 48a31b65f72d1429b9eb008e43a6400c685b2cef..c828a8f77facb87c5608fd4643b14710d2a0cf3f 100644 (file)
@@ -61,8 +61,10 @@ silc_private_message_payload_parse(SilcBuffer buffer, SilcCipher cipher)
                             SILC_STR_UI16_NSTRING_ALLOC(&new->message, 
                                                         &new->message_len),
                             SILC_STR_END);
-  if (ret == -1)
+  if (ret == -1) {
+    SILC_LOG_ERROR(("Incorrect private message payload"));
     goto err;
+  }
 
   if ((new->message_len < 1 || new->message_len > buffer->len)) {
     SILC_LOG_ERROR(("Incorrect private message payload in packet, "