Integer type name change.
[silc.git] / lib / silcclient / client_prvmsg.c
index c5a41b11ec70b86e934e30c91bb01e8a2a7aab3f..e472853fecf10f8487623d4d9bfee40fe472caab 100644 (file)
@@ -21,7 +21,8 @@
 /* This file includes the private message sending and receiving routines
    and private message key handling routines. */
 
-#include "clientlibincludes.h"
+#include "silcincludes.h"
+#include "silcclient.h"
 #include "client_internal.h"
 
 /* Sends private message to remote client. If private message key has
@@ -37,7 +38,7 @@ void silc_client_send_private_message(SilcClient client,
                                      SilcClientEntry client_entry,
                                      SilcMessageFlags flags,
                                      unsigned char *data, 
-                                     uint32 data_len, 
+                                     SilcUInt32 data_len, 
                                      int force_send)
 {
   SilcSocketConnection sock = conn->sock;
@@ -45,6 +46,7 @@ void silc_client_send_private_message(SilcClient client,
   SilcPacketContext packetdata;
   SilcCipher cipher;
   SilcHmac hmac;
+  int block_len;
 
   SILC_LOG_DEBUG(("Sending private message"));
 
@@ -69,6 +71,7 @@ void silc_client_send_private_message(SilcClient client,
   /* Get data used in the encryption */
   cipher = client_entry->send_key;
   hmac = conn->hmac_send;
+  block_len = silc_cipher_get_block_len(cipher);
 
   /* Set the packet context pointers. */
   packetdata.flags = SILC_PACKET_FLAG_PRIVMSG_KEY;
@@ -83,7 +86,7 @@ void silc_client_send_private_message(SilcClient client,
     packetdata.src_id_len + packetdata.dst_id_len;
   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
                                          packetdata.src_id_len +
-                                         packetdata.dst_id_len));
+                                         packetdata.dst_id_len), block_len);
 
   /* Prepare outgoing data buffer for packet sending */
   silc_packet_send_prepare(sock, 
@@ -99,11 +102,12 @@ void silc_client_send_private_message(SilcClient client,
   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
 
   /* Create the outgoing packet */
-  silc_packet_assemble(&packetdata);
+  silc_packet_assemble(&packetdata, cipher);
 
   /* Encrypt the header and padding of the packet. */
   cipher = conn->send_key;
-  silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
+  silc_packet_encrypt(cipher, hmac, conn->psn_send++,
+                     sock->outbuf, SILC_PACKET_HEADER_LEN + 
                      packetdata.src_id_len + packetdata.dst_id_len +
                      packetdata.padlen);
 
@@ -111,7 +115,7 @@ void silc_client_send_private_message(SilcClient client,
                   sock->outbuf->data, sock->outbuf->len);
 
   /* Now actually send the packet */
-  silc_client_packet_send_real(client, sock, force_send, FALSE);
+  silc_client_packet_send_real(client, sock, force_send);
   silc_free(packetdata.dst_id);
 
  out:
@@ -121,11 +125,16 @@ void silc_client_send_private_message(SilcClient client,
 static void silc_client_private_message_cb(SilcClient client,
                                           SilcClientConnection conn,
                                           SilcClientEntry *clients,
-                                          uint32 clients_count,
+                                          SilcUInt32 clients_count,
                                           void *context)
 {
   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);
 }
@@ -139,7 +148,6 @@ void silc_client_private_message(SilcClient client,
 {
   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
   SilcPrivateMessagePayload payload = NULL;
-  SilcIDCacheEntry id_cache;
   SilcClientID *remote_id = NULL;
   SilcClientEntry remote_client;
   SilcMessageFlags flags;
@@ -153,10 +161,16 @@ void silc_client_private_message(SilcClient client,
     goto out;
 
   /* Check whether we know this client already */
-  if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)remote_id, 
-                                      NULL, NULL, 
-                                      silc_hash_client_id_compare, NULL,
-                                      &id_cache)) {
+  remote_client = silc_client_get_client_by_id(client, conn, remote_id);
+  if (!remote_client || !remote_client->nickname) {
+    if (remote_client) {
+      if (remote_client->status & SILC_CLIENT_STATUS_RESOLVING) {
+       remote_client->status &= ~SILC_CLIENT_STATUS_RESOLVING;
+       goto out;
+      }
+      remote_client->status |= SILC_CLIENT_STATUS_RESOLVING;
+    }
+
     /* Resolve the client info */
     silc_client_get_client_by_id_resolve(client, conn, remote_id,
                                         silc_client_private_message_cb,
@@ -164,11 +178,10 @@ void silc_client_private_message(SilcClient client,
     return;
   }
 
-  remote_client = (SilcClientEntry)id_cache->context;
-
   /* 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);
+  payload = silc_private_message_payload_parse(packet->buffer->data,
+                                              packet->buffer->len,
+                                              remote_client->receive_key);
   if (!payload) {
     silc_free(remote_id);
     return;
@@ -177,9 +190,10 @@ void silc_client_private_message(SilcClient client,
   flags = silc_private_message_get_flags(payload);
 
   /* Pass the private message to application */
-  client->ops->private_message(client, conn, remote_client, flags,
-                              silc_private_message_get_message(payload, 
-                                                               NULL));
+  client->internal->ops->private_message(
+                                client, conn, remote_client, flags,
+                                silc_private_message_get_message(payload, 
+                                                                 NULL));
 
   /* See if we are away (gone). If we are away we will reply to the
      sender with the set away message. */
@@ -199,8 +213,7 @@ void silc_client_private_message(SilcClient client,
  out:
   if (payload)
     silc_private_message_payload_free(payload);
-  if (remote_id)
-    silc_free(remote_id);
+  silc_free(remote_id);
 }
 
 /* Function that actually employes the received private message key */
@@ -208,12 +221,12 @@ void silc_client_private_message(SilcClient client,
 static void silc_client_private_message_key_cb(SilcClient client,
                                               SilcClientConnection conn,
                                               SilcClientEntry *clients,
-                                              uint32 clients_count,
+                                              SilcUInt32 clients_count,
                                               void *context)
 {
   SilcPacketContext *packet = (SilcPacketContext *)context;
   unsigned char *key;
-  uint16 key_len;
+  SilcUInt16 key_len;
   unsigned char *cipher;
   int ret;
 
@@ -233,18 +246,19 @@ 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 */
-  client->ops->say(client, conn, 
-                  "Received private message key from %s%s%s %s%s%s", 
-                  clients[0]->nickname,
-                  clients[0]->server ? "@" : "",
-                  clients[0]->server ? clients[0]->server : "",
-                  clients[0]->username ? "(" : "",
-                  clients[0]->username ? clients[0]->username : "",
-                  clients[0]->username ? ")" : "");
+  client->internal->ops->say(
+                    client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
+                    "Received private message key from %s%s%s %s%s%s", 
+                    clients[0]->nickname,
+                    clients[0]->server ? "@" : "",
+                    clients[0]->server ? clients[0]->server : "",
+                    clients[0]->username ? "(" : "",
+                    clients[0]->username ? clients[0]->username : "",
+                    clients[0]->username ? ")" : "");
 
  out:
   silc_packet_context_free(packet);
@@ -282,6 +296,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. 
@@ -294,11 +313,12 @@ int silc_client_add_private_message_key(SilcClient client,
                                        SilcClientEntry client_entry,
                                        char *cipher,
                                        unsigned char *key,
-                                       uint32 key_len,
-                                       int generate_key)
+                                       SilcUInt32 key_len,
+                                       bool generate_key,
+                                       bool responder)
 {
   unsigned char private_key[32];
-  uint32 len;
+  SilcUInt32 len;
   int i;
   SilcSKEKeyMaterial *keymat;
 
@@ -309,7 +329,7 @@ int silc_client_add_private_message_key(SilcClient client,
     return FALSE;
 
   if (!cipher)
-    cipher = "aes-256-cbc";
+    cipher = SILC_DEFAULT_CIPHER;
 
   /* Check the requested cipher */
   if (!silc_cipher_is_supported(cipher))
@@ -325,14 +345,13 @@ int silc_client_add_private_message_key(SilcClient client,
   }
 
   /* Save the key */
-  client_entry->key = silc_calloc(key_len, sizeof(*client_entry->key));
-  memcpy(client_entry->key, key, key_len);
+  client_entry->key = silc_memdup(key, key_len);
   client_entry->key_len = key_len;
 
   /* Produce the key material as the protocol defines */
   keymat = silc_calloc(1, sizeof(*keymat));
   if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16, 
-                                        client->md5hash, keymat) 
+                                        client->internal->md5hash, keymat) 
       != SILC_SKE_STATUS_OK)
     return FALSE;
 
@@ -341,12 +360,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 +392,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);
 
@@ -373,7 +402,7 @@ int silc_client_add_private_message_key_ske(SilcClient client,
     return FALSE;
 
   if (!cipher)
-    cipher = "aes-256-cbc";
+    cipher = SILC_DEFAULT_CIPHER;
 
   /* Check the requested cipher */
   if (!silc_cipher_is_supported(cipher))
@@ -384,12 +413,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;
 }
@@ -480,10 +518,10 @@ int silc_client_del_private_message_key(SilcClient client,
 SilcPrivateMessageKeys
 silc_client_list_private_message_keys(SilcClient client,
                                      SilcClientConnection conn,
-                                     uint32 *key_count)
+                                     SilcUInt32 *key_count)
 {
   SilcPrivateMessageKeys keys;
-  uint32 count = 0;
+  SilcUInt32 count = 0;
   SilcIDCacheEntry id_cache;
   SilcIDCacheList list;
   SilcClientEntry entry;
@@ -524,7 +562,7 @@ silc_client_list_private_message_keys(SilcClient client,
    silc_client_list_private_message_keys. */
 
 void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
-                                          uint32 key_count)
+                                          SilcUInt32 key_count)
 {
   silc_free(keys);
 }