updates.
authorPekka Riikonen <priikone@silcnet.org>
Wed, 28 Mar 2001 19:45:57 +0000 (19:45 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Wed, 28 Mar 2001 19:45:57 +0000 (19:45 +0000)
14 files changed:
CHANGES
apps/silc/local_command.c
apps/silcd/packet_send.c
apps/silcd/server.c
doc/draft-riikonen-silc-pp-01.nroff
includes/silcincludes.h
lib/silcclient/client.c
lib/silcclient/client_prvmsg.c
lib/silccore/Makefile.am
lib/silccore/silcchannel.c
lib/silccore/silcchannel.h
lib/silccore/silcprivate.c [new file with mode: 0644]
lib/silccore/silcprivate.h [new file with mode: 0644]
lib/silcutil/silcbuffmt.c

diff --git a/CHANGES b/CHANGES
index 6699e53be784dd5a7e46ee10bc910a75039ee151..0a8babd9850841846a43bdae980fd30fb5c8788c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,16 @@
+Wed Mar 28 20:50:47 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Redefined the Private Message Payload to support private message
+         keys and to support the new private message flags.  Updated
+         the protocol specs.
+
+       * Added new type SilcPrivateMessagePayload and defined an API
+         for it in the lib/silcclient/silcprivate.[ch].
+
+       * Tested private message private keys successfully.  Tested the
+         private message key set, unset and list commands with the new
+         KEY command.
+
 Wed Mar 28 15:52:36 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Added SilcKeyAgreementStatus type to the key agreement routines
 Wed Mar 28 15:52:36 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Added SilcKeyAgreementStatus type to the key agreement routines
index 1938e9f9d2832cc74453736b3e320f07441bcfc1..3527a3ff9c06e3e761a6a2099d7c4cf65cbca2e9 100644 (file)
@@ -417,7 +417,7 @@ SILC_CLIENT_LCMD_FUNC(key)
   if (!strcasecmp(cmd->argv[3], "set")) {
     command = 1;
 
   if (!strcasecmp(cmd->argv[3], "set")) {
     command = 1;
 
-    if (cmd->argc == 3) {
+    if (cmd->argc == 4) {
       if (curr_key && type == 1 && client_entry) {
        silc_client_del_private_message_key(client, conn, client_entry);
        silc_client_add_private_message_key_ske(client, conn, client_entry,
       if (curr_key && type == 1 && client_entry) {
        silc_client_del_private_message_key(client, conn, client_entry);
        silc_client_add_private_message_key_ske(client, conn, client_entry,
@@ -426,13 +426,13 @@ SILC_CLIENT_LCMD_FUNC(key)
       }
     }
 
       }
     }
 
-    if (cmd->argc >= 4) {
+    if (cmd->argc >= 5) {
       if (type == 1 && client_entry) {
        /* Set private message key */
        
        silc_client_del_private_message_key(client, conn, client_entry);
 
       if (type == 1 && client_entry) {
        /* Set private message key */
        
        silc_client_del_private_message_key(client, conn, client_entry);
 
-       if (cmd->argc >= 5)
+       if (cmd->argc >= 6)
          silc_client_add_private_message_key(client, conn, client_entry,
                                              cmd->argv[5], cmd->argv[4],
                                              cmd->argv_lens[4],
          silc_client_add_private_message_key(client, conn, client_entry,
                                              cmd->argv[5], cmd->argv[4],
                                              cmd->argv_lens[4],
@@ -458,9 +458,9 @@ SILC_CLIENT_LCMD_FUNC(key)
          goto out;
        }
 
          goto out;
        }
 
-       if (cmd->argc >= 5)
-         cipher = cmd->argv[5];
        if (cmd->argc >= 6)
        if (cmd->argc >= 6)
+         cipher = cmd->argv[5];
+       if (cmd->argc >= 7)
          hmac = cmd->argv[6];
 
        if (!silc_client_add_channel_private_key(client, conn, channel_entry,
          hmac = cmd->argv[6];
 
        if (!silc_client_add_channel_private_key(client, conn, channel_entry,
@@ -489,10 +489,10 @@ SILC_CLIENT_LCMD_FUNC(key)
       unsigned int keys_count;
       int number;
 
       unsigned int keys_count;
       int number;
 
-      if (cmd->argc == 3)
+      if (cmd->argc == 4)
        silc_client_del_channel_private_keys(client, conn, channel_entry);
 
        silc_client_del_channel_private_keys(client, conn, channel_entry);
 
-      if (cmd->argc > 3) {
+      if (cmd->argc > 4) {
        number = atoi(cmd->argv[4]);
        keys = silc_client_list_channel_private_keys(client, conn, 
                                                     channel_entry,
        number = atoi(cmd->argv[4]);
        keys = silc_client_list_channel_private_keys(client, conn, 
                                                     channel_entry,
@@ -533,7 +533,7 @@ SILC_CLIENT_LCMD_FUNC(key)
       if (nickname[0] == '*') {
        silc_say(client, conn, "Private message keys");
        silc_say(client, conn, 
       if (nickname[0] == '*') {
        silc_say(client, conn, "Private message keys");
        silc_say(client, conn, 
-                "  Client                        Cipher        Key");
+                "  Client                         Cipher         Key");
        for (k = 0; k < keys_count; k++) {
          memset(buf, 0, sizeof(buf));
          strncat(buf, "  ", 2);
        for (k = 0; k < keys_count; k++) {
          memset(buf, 0, sizeof(buf));
          strncat(buf, "  ", 2);
@@ -562,7 +562,7 @@ SILC_CLIENT_LCMD_FUNC(key)
        silc_say(client, conn, "Private message key", 
                 client_entry->nickname);
        silc_say(client, conn, 
        silc_say(client, conn, "Private message key", 
                 client_entry->nickname);
        silc_say(client, conn, 
-                "  Client                        Cipher        Key");
+                "  Client                         Cipher         Key");
        for (k = 0; k < keys_count; k++) {
          if (keys[k].client_entry != client_entry)
            continue;
        for (k = 0; k < keys_count; k++) {
          if (keys[k].client_entry != client_entry)
            continue;
index c4c4a70688fb1856affa88776a7768abf50774eb..f88b63e86a2df6d4b42b196af390642b2aef0377 100644 (file)
@@ -782,11 +782,17 @@ void silc_server_send_private_message(SilcServer server,
     silc_server_packet_send_real(server, dst_sock, FALSE);
 
   } else {
     silc_server_packet_send_real(server, dst_sock, FALSE);
 
   } else {
-    /* Key exist so just send it */
+    /* Key exist so encrypt just header and send it */
     silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
                     + packet->dst_id_len + packet->padlen);
     silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
     silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
     silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
                     + packet->dst_id_len + packet->padlen);
     silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
     silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
+
+    /* Encrypt header */
+    silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, 
+                       SILC_PACKET_HEADER_LEN + packet->src_id_len + 
+                       packet->dst_id_len + packet->padlen);
+
     silc_server_packet_send_real(server, dst_sock, FALSE);
   }
 }
     silc_server_packet_send_real(server, dst_sock, FALSE);
   }
 }
index 96a2433ad82affaf9debd9fa62d4c019d90accec..54dc325a85814406c9108f2e6153185cd7812e27 100644 (file)
@@ -1423,9 +1423,12 @@ static int silc_server_packet_decrypt_check(SilcPacketType packet_type,
 
      all other packets are special packets 
   */
 
      all other packets are special packets 
   */
-  if ((packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
-       !(buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY)) ||
-      packet_type != SILC_PACKET_CHANNEL_MESSAGE || 
+
+  if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
+      (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
+    return FALSE;
+
+  if (packet_type != SILC_PACKET_CHANNEL_MESSAGE || 
       (packet_type == SILC_PACKET_CHANNEL_MESSAGE &&
        parse_ctx->sock->type == SILC_SOCKET_TYPE_ROUTER &&
        server->server_type == SILC_ROUTER))
       (packet_type == SILC_PACKET_CHANNEL_MESSAGE &&
        parse_ctx->sock->type == SILC_SOCKET_TYPE_ROUTER &&
        server->server_type == SILC_ROUTER))
index 29d5713de80e43c081cd188f5009609e7f68e01f..65da1422e14d36309daf917a89c3a4996f055e5d 100644 (file)
@@ -1640,10 +1640,16 @@ diagram represents the Private Message Payload.
 ~                            Nickname                           ~
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 ~                            Nickname                           ~
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|            Flags              |      Message Data Length      |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
 ~                          Message Data                         ~
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
 ~                          Message Data                         ~
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                             Padding                           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 .in 3
 
 .ce
 .in 3
 
 .ce
@@ -1662,9 +1668,24 @@ o Nickname (variable length) - Nickname of the sender of the
   to the Client ID in the SILC Packet Header.  This nickname 
   is merely provided to be displayed by the client.
 
   to the Client ID in the SILC Packet Header.  This nickname 
   is merely provided to be displayed by the client.
 
+o Flags (2 bytes) - This field includes the flags of the
+  private message.  They can indicate a different reason or
+  purpose for the private message.  See section XXX for the
+  defined flags.
+
+o Message Data Length (2 bytes) - Indicates the length of the
+  Message Data field, not includes any other field.
+
 o Message Data (variable length) - The actual message to
   the client.  Rest of the packet is reserved for the message
   data.
 o Message Data (variable length) - The actual message to
   the client.  Rest of the packet is reserved for the message
   data.
+
+o Padding (variable length) - This field is present only
+  when the private message payload is encrypted with private
+  message key.  In this case the padding is applied to make
+  the packet multiple by eight (8), or by the block size of
+  the cipher, which ever is larger.  When encrypted with
+  normal session keys, this field must not be included.
 .in 3
 
 
 .in 3
 
 
index b27765cd3853b0784516bc2001be318606017df0..09da825b65a76b5fa4ef3771f70c8c67405716a6 100644 (file)
 #include "silcnotify.h"
 #include "silcmode.h"
 #include "silcauth.h"
 #include "silcnotify.h"
 #include "silcmode.h"
 #include "silcauth.h"
+#include "silcprivate.h"
 
 /* TRQ (SilcList API and SilcDList API) */
 #include "silclist.h"
 
 /* TRQ (SilcList API and SilcDList API) */
 #include "silclist.h"
index 7637466b0624e4409986bb9e4441f9fa880d7dc5..8bbf3b10bdd4fb91437a52800e96e938ad46b15c 100644 (file)
@@ -692,9 +692,12 @@ static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
 
      all other packets are special packets 
   */
 
      all other packets are special packets 
   */
-  if ((packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
-       !(buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY)) ||
-      packet_type != SILC_PACKET_CHANNEL_MESSAGE)
+
+  if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
+      (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
+    return FALSE;
+
+  if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
     return TRUE;
 
   return FALSE;
     return TRUE;
 
   return FALSE;
index 0234f0232c3fbb11ca02c3837ff9f87f3052bb89..56748bf477e99a66b96e17168e448f8d231e528d 100644 (file)
@@ -42,22 +42,16 @@ void silc_client_send_private_message(SilcClient client,
   SilcSocketConnection sock = conn->sock;
   SilcBuffer buffer;
   SilcPacketContext packetdata;
   SilcSocketConnection sock = conn->sock;
   SilcBuffer buffer;
   SilcPacketContext packetdata;
-  unsigned int nick_len;
   SilcCipher cipher;
   SilcHmac hmac;
 
   SILC_LOG_DEBUG(("Sending private message"));
 
   SilcCipher cipher;
   SilcHmac hmac;
 
   SILC_LOG_DEBUG(("Sending private message"));
 
-  /* Create private message payload */
-  nick_len = strlen(conn->nickname);
-  buffer = silc_buffer_alloc(2 + nick_len + data_len);
-  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
-  silc_buffer_format(buffer,
-                    SILC_STR_UI_SHORT(nick_len),
-                    SILC_STR_UI_XNSTRING(conn->nickname,
-                                         nick_len),
-                    SILC_STR_UI_XNSTRING(data, data_len),
-                    SILC_STR_END);
+  /* Encode private message payload */
+  buffer = silc_private_message_payload_encode(strlen(conn->nickname),
+                                              conn->nickname, 0,
+                                              data_len, data,
+                                              client_entry->send_key);
 
   /* If we don't have private message specific key then private messages
      are just as any normal packet thus call normal packet sending.  If
 
   /* If we don't have private message specific key then private messages
      are just as any normal packet thus call normal packet sending.  If
@@ -101,12 +95,7 @@ void silc_client_send_private_message(SilcClient client,
   
   packetdata.buffer = sock->outbuf;
 
   
   packetdata.buffer = sock->outbuf;
 
-  /* Encrypt payload of the packet. Encrypt with private message specific
-     key */
-  cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
-                         buffer->len, cipher->iv);
-      
-  /* Put the actual encrypted payload data into the buffer. */
+  /* Put the actual encrypted message payload data into the buffer. */
   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
 
   /* Create the outgoing packet */
   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
 
   /* Create the outgoing packet */
@@ -126,9 +115,21 @@ void silc_client_send_private_message(SilcClient client,
   silc_free(packetdata.dst_id);
 
  out:
   silc_free(packetdata.dst_id);
 
  out:
-  silc_free(buffer);
+  silc_buffer_free(buffer);
 }     
 
 }     
 
+static void silc_client_private_message_cb(SilcClient client,
+                                          SilcClientConnection conn,
+                                          SilcClientEntry *clients,
+                                          unsigned int clients_count,
+                                          void *context)
+{
+  SilcPacketContext *packet = (SilcPacketContext *)context;
+
+  silc_client_private_message(client, conn->sock, packet);
+  silc_packet_context_free(packet);
+}
+
 /* Private message received. This processes the private message and
    finally displays it on the screen. */
 
 /* Private message received. This processes the private message and
    finally displays it on the screen. */
 
@@ -137,29 +138,14 @@ void silc_client_private_message(SilcClient client,
                                 SilcPacketContext *packet)
 {
   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
                                 SilcPacketContext *packet)
 {
   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
-  SilcBuffer buffer = packet->buffer;
+  SilcPrivateMessagePayload payload = NULL;
   SilcIDCacheEntry id_cache;
   SilcClientID *remote_id = NULL;
   SilcClientEntry remote_client;
   SilcIDCacheEntry id_cache;
   SilcClientID *remote_id = NULL;
   SilcClientEntry remote_client;
-  unsigned short nick_len;
-  unsigned char *nickname, *message = NULL;
-  int ret;
 
   if (packet->src_id_type != SILC_ID_CLIENT)
     goto out;
 
 
   if (packet->src_id_type != SILC_ID_CLIENT)
     goto out;
 
-  /* Get nickname */
-  ret = silc_buffer_unformat(buffer, 
-                            SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
-                            SILC_STR_END);
-  if (ret == -1)
-    return;
-
-  silc_buffer_pull(buffer, 2 + nick_len);
-
-  message = silc_calloc(buffer->len + 1, sizeof(char));
-  memcpy(message, buffer->data, buffer->len);
-
   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
                             SILC_ID_CLIENT);
   if (!remote_id)
   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
                             SILC_ID_CLIENT);
   if (!remote_id)
@@ -167,24 +153,28 @@ void silc_client_private_message(SilcClient client,
 
   /* Check whether we know this client already */
   if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
 
   /* Check whether we know this client already */
   if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
-                                  SILC_ID_CLIENT, &id_cache))
-    {
-      /* Allocate client entry */
-      remote_client = silc_calloc(1, sizeof(*remote_client));
-      remote_client->id = silc_id_dup(remote_id, SILC_ID_CLIENT);
-      silc_parse_nickname(nickname, &remote_client->nickname, 
-                         &remote_client->server, &remote_client->num);
-      
-      /* Save the client to cache */
-      silc_idcache_add(conn->client_cache, remote_client->nickname,
-                      strlen(remote_client->nickname), SILC_ID_CLIENT, 
-                      remote_client->id, remote_client, TRUE, TRUE);
-    } else {
-      remote_client = (SilcClientEntry)id_cache->context;
-    }
+                                  SILC_ID_CLIENT, &id_cache)) {
+    /* Resolve the client info */
+    silc_client_get_client_by_id_resolve(client, conn, remote_id,
+                                        silc_client_private_message_cb,
+                                        silc_packet_context_dup(packet));
+    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);
+  if (!payload) {
+    silc_free(remote_id);
+    return;
+  }
 
   /* Pass the private message to application */
 
   /* Pass the private message to application */
-  client->ops->private_message(client, conn, remote_client, message);
+  client->ops->private_message(client, conn, remote_client, 
+                              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. */
 
   /* See if we are away (gone). If we are away we will reply to the
      sender with the set away message. */
@@ -200,14 +190,10 @@ void silc_client_private_message(SilcClient client,
   }
 
  out:
   }
 
  out:
+  if (payload)
+    silc_private_message_payload_free(payload);
   if (remote_id)
     silc_free(remote_id);
   if (remote_id)
     silc_free(remote_id);
-
-  if (message) {
-    memset(message, 0, buffer->len);
-    silc_free(message);
-  }
-  silc_free(nickname);
 }
 
 /* Function that actually employes the received private message key */
 }
 
 /* Function that actually employes the received private message key */
index b22ae26401b7803d7b10d5b4a0e986fbac2687e0..73100fa836ac48b60390c1ade1fad0bdf28ebbfb 100644 (file)
@@ -30,7 +30,8 @@ libsilccore_a_SOURCES = \
        silcsockconn.c \
        silcpayload.c \
        silcnotify.c \
        silcsockconn.c \
        silcpayload.c \
        silcnotify.c \
-       silcauth.c
+       silcauth.c \
+       silcprivate.c
 
 EXTRA_DIST = *.h
 
 
 EXTRA_DIST = *.h
 
index 26f7f4dc2fccabb9b6222d71f29dce83b586d13f..74265436e31032d13dfb8a98b77c508ab45976f4 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
 
 
   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2001 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index 1059b156c4a3e697418631d8be1ccd84b221d617..50e40041dfd5488fe580244265fcf2e296889a04 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
 
 
   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2001 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
diff --git a/lib/silccore/silcprivate.c b/lib/silccore/silcprivate.c
new file mode 100644 (file)
index 0000000..45e81d8
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+
+  silcprivate.c
+
+  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+  Copyright (C) 1997 - 2001 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  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
+  GNU General Public License for more details.
+
+*/
+/* Includes the Private Message Payload implementation */
+/* $Id$ */
+
+#include "silcincludes.h"
+#include "silcprivate.h"
+
+/******************************************************************************
+
+                           Private Message Payload
+
+******************************************************************************/
+
+/* Private Message Payload structure. Contents of this structure is parsed
+   from SILC packets. */
+struct SilcPrivateMessagePayloadStruct {
+  unsigned short nickname_len;
+  unsigned char *nickname;
+  unsigned short flags;
+  unsigned short message_len;
+  unsigned char *message;
+};
+
+/* Parses private message payload returning new private mesage payload 
+   structure. This also decrypts the message if the `cipher' is provided. */
+
+SilcPrivateMessagePayload 
+silc_private_message_payload_parse(SilcBuffer buffer, SilcCipher cipher)
+{
+  SilcPrivateMessagePayload new;
+  int ret;
+
+  SILC_LOG_DEBUG(("Parsing private message payload"));
+
+  /* Decrypt the payload */
+  if (cipher)
+    silc_cipher_decrypt(cipher, buffer->data, buffer->data, 
+                       buffer->len, cipher->iv);
+
+  new = silc_calloc(1, sizeof(*new));
+
+  /* Parse the Private Message Payload. Ignore the padding. */
+  ret = silc_buffer_unformat(buffer,
+                            SILC_STR_UI16_NSTRING_ALLOC(&new->nickname, 
+                                                        &new->nickname_len),
+                            SILC_STR_UI_SHORT(&new->flags),
+                            SILC_STR_UI16_NSTRING_ALLOC(&new->message, 
+                                                        &new->message_len),
+                            SILC_STR_END);
+  if (ret == -1)
+    goto err;
+
+  if ((new->message_len < 1 || new->message_len > buffer->len) ||
+      (new->nickname_len < 1 || new->nickname_len > buffer->len)) {
+    SILC_LOG_ERROR(("Incorrect private message payload in packet, "
+                   "packet dropped"));
+    goto err;
+  }
+
+  return new;
+
+ err:
+  silc_private_message_payload_free(new);
+  return NULL;
+}
+
+/* Encodes private message payload into a buffer and returns it.  If
+   the cipher is provided the packet is also encrypted here.  It is provided
+   if the private message private keys are used. */
+
+SilcBuffer silc_private_message_payload_encode(unsigned int nickname_len,
+                                              unsigned char *nickname,
+                                              unsigned short flags,
+                                              unsigned short data_len,
+                                              unsigned char *data,
+                                              SilcCipher cipher)
+{
+  int i;
+  SilcBuffer buffer;
+  unsigned int len, pad_len = 0;
+  unsigned char pad[SILC_PACKET_MAX_PADLEN];
+
+  SILC_LOG_DEBUG(("Encoding private message payload"));
+
+  len = 2 + nickname_len + 4 + data_len;
+
+  if (cipher) {
+    /* Calculate length of padding. */
+    pad_len = SILC_PACKET_PADLEN((len + 2));
+    len += pad_len;
+
+    /* Generate padding */
+    for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte();
+  }
+
+  /* Allocate private message payload buffer */
+  buffer = silc_buffer_alloc(len);
+
+  /* Encode the Channel Message Payload */
+  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+  silc_buffer_format(buffer, 
+                    SILC_STR_UI_SHORT(nickname_len),
+                    SILC_STR_UI_XNSTRING(nickname, nickname_len),
+                    SILC_STR_UI_SHORT(flags),
+                    SILC_STR_UI_SHORT(data_len),
+                    SILC_STR_UI_XNSTRING(data, data_len),
+                    SILC_STR_UI_XNSTRING(pad, pad_len),
+                    SILC_STR_END);
+
+  if (cipher) {
+    /* Encrypt payload of the packet. */
+    silc_cipher_encrypt(cipher, buffer->data, buffer->data, 
+                       buffer->len, cipher->iv);
+    memset(pad, 0, sizeof(pad));
+  }
+
+  return buffer;
+}
+
+/* Free's Private Message Payload */
+
+void silc_private_message_payload_free(SilcPrivateMessagePayload payload)
+{
+  silc_free(payload->nickname);
+  if (payload->message) {
+    memset(payload->message, 0, payload->message_len);
+    silc_free(payload->message);
+  }
+  silc_free(payload);
+}
+
+/* Return nickname */
+
+unsigned char *
+silc_private_message_get_nickname(SilcPrivateMessagePayload payload,
+                                 unsigned int *nickname_len)
+{
+  if (nickname_len)
+    *nickname_len = payload->nickname_len;
+
+  return payload->nickname;
+}
+
+/* Return message */
+
+unsigned char *
+silc_private_message_get_message(SilcPrivateMessagePayload payload,
+                                unsigned int *message_len)
+{
+  if (message_len)
+    *message_len = payload->message_len;
+
+  return payload->message;
+}
+
+/* Return flags */
+
+unsigned short 
+silc_private_message_get_flags(SilcPrivateMessagePayload payload)
+{
+  return payload->flags;
+}
diff --git a/lib/silccore/silcprivate.h b/lib/silccore/silcprivate.h
new file mode 100644 (file)
index 0000000..4cc2872
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+
+  silcprivate.h
+
+  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+  Copyright (C) 1997 - 2001 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  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
+  GNU General Public License for more details.
+
+*/
+
+#ifndef SILCPRIVATE_H
+#define SILCPRIVATE_H
+
+/* Forward declaration of the Private Message Payload. */
+typedef struct SilcPrivateMessagePayloadStruct *SilcPrivateMessagePayload;
+
+/* Prototypes */
+
+SilcPrivateMessagePayload 
+silc_private_message_payload_parse(SilcBuffer buffer, SilcCipher cipher);
+SilcBuffer silc_private_message_payload_encode(unsigned int nickname_len,
+                                              unsigned char *nickname,
+                                              unsigned short flags,
+                                              unsigned short data_len,
+                                              unsigned char *data,
+                                              SilcCipher cipher);
+void silc_private_message_payload_free(SilcPrivateMessagePayload payload);
+unsigned char *
+silc_private_message_get_nickname(SilcPrivateMessagePayload payload,
+                                 unsigned int *nickname_len);
+unsigned char *
+silc_private_message_get_message(SilcPrivateMessagePayload payload,
+                                unsigned int *message_len);
+unsigned short 
+silc_private_message_get_flags(SilcPrivateMessagePayload payload);
+
+#endif
index 08c8e29059574735aae2ef79af1bb965d6197abe..87fa12aef1de526ea2dc106ad05d4374ee2e91b6 100644 (file)
@@ -145,9 +145,6 @@ int silc_buffer_format(SilcBuffer dst, ...)
 
  fail:
   SILC_LOG_DEBUG(("Error occured while formatting data"));
 
  fail:
   SILC_LOG_DEBUG(("Error occured while formatting data"));
-#ifdef SILC_DEBUG
-  assert(FALSE);
-#endif
   return -1;
 
  ok:
   return -1;
 
  ok:
@@ -370,9 +367,6 @@ int silc_buffer_unformat(SilcBuffer src, ...)
 
  fail:
   SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
 
  fail:
   SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
-#ifdef SILC_DEBUG
-  assert(FALSE);
-#endif
   return -1;
 
  ok:
   return -1;
 
  ok: