Protocol version 1.2 integrations
authorPekka Riikonen <priikone@silcnet.org>
Sun, 10 Nov 2002 20:30:49 +0000 (20:30 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 10 Nov 2002 20:30:49 +0000 (20:30 +0000)
51 files changed:
CHANGES
apps/irssi/docs/help/in/key.in
apps/irssi/docs/help/in/kill.in
apps/irssi/src/fe-common/silc/module-formats.c
apps/irssi/src/silc/core/silc-channels.c
apps/irssi/src/silc/core/silc-queries.c
apps/irssi/src/silc/core/silc-servers.c
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/server.c
apps/silcd/server_backup.c
apps/silcd/server_internal.h
apps/silcd/server_query.c
doc/draft-riikonen-presence-attrs-01.nroff
doc/draft-riikonen-silc-commands-04.nroff
doc/draft-riikonen-silc-flags-payloads-01.nroff
doc/draft-riikonen-silc-pp-06.nroff
doc/draft-riikonen-silc-spec-06.nroff
includes/silcincludes.h.in
includes/silcversion.h
lib/silcclient/client.c
lib/silcclient/client_channel.c
lib/silcclient/client_internal.h
lib/silcclient/client_prvmsg.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/silcclient.h
lib/silccore/silcargument.c
lib/silccore/silcargument.h
lib/silccore/silcattrs.c
lib/silccore/silcattrs.h
lib/silccore/silcauth.c
lib/silccore/silcauth.h
lib/silccore/silcchannel.c
lib/silccore/silcchannel.h
lib/silccore/silcchannel_i.h [new file with mode: 0644]
lib/silccore/silcpacket.c
lib/silccore/silcpacket.h
lib/silccore/silcprivate.c
lib/silccore/silcprivate.h
lib/silccore/silcprivate_i.h [new file with mode: 0644]
lib/silccore/silcstatus.h
lib/silccrypt/silchmac.h
lib/silccrypt/silcpkcs.c
lib/silccrypt/silcpkcs.h
lib/silcutil/silcbuffmt.c
lib/silcutil/silcutil.c
lib/silcutil/stacktrace.h
prepare

diff --git a/CHANGES b/CHANGES
index d265e7f84516a3634e6d153d788a1da9fc5f1b7f..a456d060e6cc5a3eab5849f1ba3714cf45c8fb7e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,42 @@
+Sun Nov 10 12:20:56 EET 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added support for rekey before 2^32 sequence number wraps.
+         Affected files in server and client library.
+
+       * Padding must be at least 8 bytes now.  Implemented and updated
+         protocol specs.
+
+       * Compute maximum padding for authentication packets to make
+         passphrase approximation attacks impossible.  Affected files
+         in client library and in server.
+
+       * Fixed PING command sending in client library and handling in
+         server.  The server ID must be ID Payload, not raw ID data.
+         Affected files in server and client library.
+
+       * Defined that all public keys sent in commands and notify
+         payloads are actually Public Key Payloads not raw public key
+         data.  Updated protocol specs and implemented.
+
+       * Updated protocol version to 1.2.  Updated specs and code.
+
+       * Added ERR_UNSUPPORTED_PUBLIC_KEY and ERR_OPERATION_ALLOWED
+         status types.  Updated specs and the code.
+
+       * Added support for normal client to kill its own entries from
+         the network.  Updated protocol specs and the code.
+
+       * Defined the SILC_MESSAGE_FLAG_SIGNED.  Updated protocol specs
+         and added initial implementation.
+
+       * Added MAC field to the Private Message Payload to protect
+         against chosen ciphertext attacks.  Updated the protocol specs
+         and implemented.
+
+       * Added idle and signon fields to the ATTRIBUTE_SERVICE
+         attribute to indicate the user's current idle and signon time
+         of a service.  Updated protocol specs and implemented.
+
 Thu Nov  7 19:21:10 EET 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Added "do_not_bind" argument to silc_client_file_send what
index 3d3a716252150d419cf410351e34f1fdb7803df6..92f9699941d31bc647c071e8a07eb30fa4597648 100644 (file)
@@ -20,7 +20,7 @@ Types:
 
 Commands:
 
-  set        [<key> [<cipher>] [<hmac>]]
+  set        [<key> [<cipher>] [<hmac>]] [-responder]
 
     Set the key into use.  If the <key> is provided it is used
     as the key material.  If the <key> is not provided the
@@ -28,9 +28,11 @@ Commands:
     been performed this command has no effect.
 
     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.
+    will be generated automatically.  The -responder option
+    may be used ONLY with MSG type.  One of the clients must
+    be the responder side.  The one being the responder must
+    use this option.  The clients setting the key must agree
+    on which one is the responder.
 
   unset      [<number>]
 
@@ -97,3 +99,7 @@ Examples:
 
     /KEY CHANNEL set very_secret_key_this_is
     /KEY CHANNEL list
+    /KEY MSG nickname set secretkey
+    /KEY MSG nick set secretkey -responder
+    /KEY MSG foo agreement 10.2.1.7 5000
+    /KEY MSG bar negotiate 10.2.1.7 5000
index 8b3b91cd1701634f67f9ae9d358198d29eb5cedb..96b6b6cafc6f9a60842cdea6b801853cdce83e1b 100644 (file)
@@ -1,11 +1,30 @@
 
 @SYNTAX:kill@
 
-This is operator command. KILL is used to forcibly remove
-a client from the network. It works similarly to KICK expect
-that the client is removed from the entire network.  In general,
-KILL is useful only as a warning tool for abusive users and
-it has only temporary effects.
+This command can be used for two purpose:  SILC operator may use it
+to remove a client from the network, or user may use it to remove
+its own client entries from the network.
+
+If you are not SILC operator you cannot use this command to remove
+anybody else except yourself from the network.  Only SILC operator
+is able to kill other clients from the network.  When killing your
+own client entry you must provide -pubkey argument to the command.
+For killing your own client from network you also must be connected
+to the same server as your own client entry (the client entry may
+be for example detached client entry).  When using this command as
+SILC operator -pubkey has no effect.
+
+Examples:
+
+       /KILL myself -pubkey
+
+               Kill yourself with nickname "myself" from network.
+
+       /SILCOPER user
+       /KILL someclient You have been killed
+
+               Become SILC operator and kill client named
+                "someclient", with comment "You have been killed".
 
 See also: OPER, SILCOPER
 
index c1521c31c558d91606b21c5e75c82998506103e7..ecd8fafd22c046461ec1316bad802a6cbb537d0f 100644 (file)
@@ -159,7 +159,7 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "attr_allow",       " Sending allowed    : $0", 1, { 0 } },
        { "attr_vcard_file",  " Business card      : $0", 1, { 0 } },
        { "attr_services",    " Services used      : $0", 1, { 0 } },
-       { "attr_service",     " Service            : port [$0] address [$1] logged in [$2]", 3, { 0, 0, 0 } },
+       { "attr_service",     " Service            : port [$0] address [$1] logged in [$2] login time [$3] idle [$4]", 5, { 0, 0, 0, 0, 0 } },
        { "attr_status_mood", " User's mood        : $0", 1, { 0 } },
        { "attr_status_text", " User's message     : $0", 1, { 0 } },
        { "attr_status_message",      " User's message     : $0", 1, { 0 } },
index 005763bf6439d0b636f2b89c72ecfb6b7508a0d2..a720ecdb88e427bc4151fe484fdd36ab6735abae 100644 (file)
@@ -424,7 +424,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, i->responder);
+                                             NULL, NULL, key, i->responder);
       printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
                         SILCTXT_KEY_AGREEMENT_PRIVMSG, 
                         client_entry->nickname);
@@ -612,23 +612,36 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
     command = 1;
 
     if (argc >= 5) {
+      char *cipher = NULL, *hmac = NULL;
+
       if (type == 1 && client_entry) {
        /* Set private message key */
+       bool responder = FALSE;
        
        silc_client_del_private_message_key(silc_client, conn, client_entry);
 
-       if (argc >= 6)
-         silc_client_add_private_message_key(silc_client, conn, client_entry,
-                                             argv[5], argv[4],
-                                             argv_lens[4],
-                                             (argv[4][0] == '*' ?
-                                              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), FALSE);
+       if (argc >= 6) {
+         if (!strcasecmp(argv[5], "-responder"))
+           responder = TRUE;
+         else
+           cipher = argv[5];
+       }
+       if (argc >= 7) {
+         if (!strcasecmp(argv[6], "-responder"))
+           responder = TRUE;
+         else
+           hmac = argv[6];
+       }
+       if (argc >= 8) {
+         if (!strcasecmp(argv[7], "-responder"))
+           responder = TRUE;
+       }
+
+       silc_client_add_private_message_key(silc_client, conn, client_entry,
+                                           cipher, hmac,
+                                           argv[4], argv_lens[4],
+                                           (argv[4][0] == '*' ?
+                                            TRUE : FALSE), responder);
 
        /* Send the key to the remote client so that it starts using it
           too. */
@@ -639,8 +652,6 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
        */
       } else if (type == 2) {
        /* Set private channel key */
-       char *cipher = NULL, *hmac = NULL;
-
        if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
          printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                             SILCTXT_CH_PRIVATE_KEY_NOMODE, 
index e4a03ae881c3b8c167c6ab77e8338cedb2ee0b72..c946f56ddac8320926d1e35895fcd4811d694dc8 100644 (file)
@@ -323,6 +323,7 @@ void silc_query_attributes_default(SilcClient client,
       silc_strncat(service.address, sizeof(service.address), *entry,
                   strlen(*entry));
       service.status = TRUE;
+      service.idle = 0;
       silc_client_attribute_add(silc_client, conn,
                                SILC_ATTRIBUTE_SERVICE, &service,
                                sizeof(service));
@@ -609,9 +610,10 @@ void silc_query_attributes_print(SILC_SERVER_REC *server,
        if (!silc_attribute_get_object(attr, (void *)&service,
                                       sizeof(service)))
          continue;
-       snprintf(tmp, sizeof(tmp) - 1, "%s:%d (logged %s)",
+       snprintf(tmp, sizeof(tmp) - 1, "%s:%d (logged %s) idle %d seconds",
                 service.address, (unsigned int)service.port,
-                service.status ? "in" : "out");
+                service.status ? "in" : "out",
+                service.idle);
        printformat_module("fe-common/silc", server, NULL,
                           MSGLEVEL_CRAP, SILCTXT_ATTR_SERVICES, tmp);
       }
index 77ae7d8d5b0683cef27aea216b32bd3e7ac0117f..4d68aeb0ad0cde2bd8433f716275ea84a31e6ddf 100644 (file)
@@ -414,7 +414,7 @@ char *silc_server_get_channels(SILC_SERVER_REC *server)
 /* SYNTAX: KEY MSG <nickname> set|unset|list|agreement|negotiate [<arguments>] */
 /* SYNTAX: KEY CHANNEL <channel> set|unset|list|change [<arguments>] */
 /* SYNTAX: KICK <channel> <nickname>[@<hostname>] [<comment>] */
-/* SYNTAX: KILL <nickname>[@<hostname>] [<comment>] */
+/* SYNTAX: KILL <nickname>[@<hostname>] [<comment>] [-pubkey] */
 /* SYNTAX: OPER <username> [-pubkey] */
 /* SYNTAX: SILCOPER <username> [-pubkey] */
 /* SYNTAX: TOPIC <channel> [<topic>] */
index 06fbd9fb1f6dbf13ce104fa57c66d025c7f3ccee..13aaad03de9fec43d8980af7c51f30202147841c 100644 (file)
@@ -1086,7 +1086,7 @@ SILC_SERVER_CMD_FUNC(invite)
     /* Get the client entry */
     dest = silc_server_query_client(server, dest_id, FALSE, &resolve);
     if (!dest) {
-      if (server->server_type != SILC_SERVER || !resolve) {
+      if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
        silc_server_command_send_status_reply(
                                        cmd, SILC_COMMAND_INVITE,
                                        SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
@@ -1299,28 +1299,34 @@ SILC_SERVER_CMD_FUNC(kill)
   SilcServer server = cmd->server;
   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
   SilcClientEntry remote_client;
-  SilcClientID *client_id;
-  unsigned char *tmp, *comment;
-  SilcUInt32 tmp_len, tmp_len2;
-  bool local;
+  SilcClientID *client_id = NULL;
+  unsigned char *tmp, *comment, *auth;
+  SilcUInt32 tmp_len, tmp_len2, auth_len;
 
-  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
+  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
 
   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
-  /* KILL command works only on router */
-  if (server->server_type != SILC_ROUTER) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
-                                         SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
-    goto out;
-  }
+  /* Get authentication payload if present */
+  auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
 
-  /* Check whether client has the permissions. */
-  if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
-                                         SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
-    goto out;
+  if (!auth) {
+    /* Router operator killing */
+
+    /* KILL command works only on router */
+    if (server->server_type != SILC_ROUTER) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
+      goto out;
+    }
+
+    /* Check whether client has the permissions. */
+    if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
+      goto out;
+    }
   }
 
   /* Get the client ID */
@@ -1342,11 +1348,9 @@ SILC_SERVER_CMD_FUNC(kill)
   /* Get the client entry */
   remote_client = silc_idlist_find_client_by_id(server->local_list, 
                                                client_id, TRUE, NULL);
-  local = TRUE;
   if (!remote_client) {
     remote_client = silc_idlist_find_client_by_id(server->global_list, 
                                                  client_id, TRUE, NULL);
-    local = FALSE;
     if (!remote_client) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
@@ -1357,23 +1361,64 @@ SILC_SERVER_CMD_FUNC(kill)
 
   /* Get comment */
   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
-  if (tmp_len2 > 128)
+  if (comment && tmp_len2 > 128) {
     tmp_len2 = 128;
+    comment[127] = '\0';
+  }
 
-  /* Send reply to the sender */
-  silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
-                                       SILC_STATUS_OK, 0);
+  /* If authentication data is provided then verify that killing is
+     actually allowed */
+  if (auth && auth_len) {
+    SilcSocketConnection sock;
 
-  /* Check if anyone is watching this nickname */
-  if (server->server_type == SILC_ROUTER)
-    silc_server_check_watcher_list(server, client, NULL,
-                                  SILC_NOTIFY_TYPE_KILLED);
+    if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                           SILC_STATUS_ERR_OPERATION_ALLOWED,
+                                           0);
+      goto out;
+    }
 
-  /* Now do the killing */
-  silc_server_kill_client(server, remote_client, comment, client->id,
-                         SILC_ID_CLIENT);
+    /* Verify the signature */
+    if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
+                              remote_client->data.public_key, 0,
+                              server->sha1hash, remote_client->id,
+                              SILC_ID_CLIENT)) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                           SILC_STATUS_ERR_AUTH_FAILED,
+                                           0);
+      goto out;
+    }
+
+    /* Send reply to the sender */
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                         SILC_STATUS_OK, 0);
+
+    /* Do normal signoff for the destination client */
+    sock = remote_client->connection;
+    silc_server_free_client_data(server, NULL, remote_client, TRUE,
+                                comment ? comment :
+                                (unsigned char *)"Killed");
+    if (sock)
+      silc_server_close_connection(server, sock);
+  } else {
+    /* Router operator killing */
+
+    /* Send reply to the sender */
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                         SILC_STATUS_OK, 0);
+
+    /* Check if anyone is watching this nickname */
+    if (server->server_type == SILC_ROUTER)
+      silc_server_check_watcher_list(server, client, NULL,
+                                    SILC_NOTIFY_TYPE_KILLED);
+
+    /* Now do the killing */
+    silc_server_kill_client(server, remote_client, comment, client->id,
+                           SILC_ID_CLIENT);
+  }
 
  out:
+  silc_free(client_id);
   silc_server_command_free(cmd);
 }
 
@@ -1545,20 +1590,24 @@ SILC_SERVER_CMD_FUNC(ping)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcUInt32 len;
+  SilcUInt32 tmp_len;
   unsigned char *tmp;
+  SilcServerID *server_id = NULL;
 
-  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 2);
+  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
 
   /* Get Server ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
   if (!tmp) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
                                          SILC_STATUS_ERR_NO_SERVER_ID, 0);
     goto out;
   }
+  server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+  if (!server_id)
+    goto out;
 
-  if (!memcmp(tmp, server->id_string, server->id_string_len)) {
+  if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
     /* Send our reply */
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
                                          SILC_STATUS_OK, 0);
@@ -1569,6 +1618,7 @@ SILC_SERVER_CMD_FUNC(ping)
   }
 
  out:
+  silc_free(server_id);
   silc_server_command_free(cmd);
 }
 
@@ -1590,7 +1640,7 @@ SILC_SERVER_CMD_FUNC(stats)
   /* Get Server ID */
   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
   if (!tmp) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
                                          SILC_STATUS_ERR_NO_SERVER_ID, 0);
     goto out;
   }
@@ -1600,7 +1650,7 @@ SILC_SERVER_CMD_FUNC(stats)
 
   /* The ID must be ours */
   if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
                                          SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
     silc_free(server_id);
     goto out;
@@ -1693,8 +1743,7 @@ static void silc_server_command_join_channel(SilcServer server,
   char check[512], check2[512];
   bool founder = FALSE;
   bool resolve;
-  unsigned char *fkey = NULL;
-  SilcUInt32 fkey_len = 0;
+  SilcBuffer fkey = NULL;
   const char *cipher;
 
   SILC_LOG_DEBUG(("Joining client to channel"));
@@ -1711,10 +1760,7 @@ static void silc_server_command_join_channel(SilcServer server,
     client = silc_server_query_client(server, client_id, FALSE, 
                                      &resolve);
     if (!client) {
-      if (cmd->pending)
-       goto out;
-
-      if (!resolve) {
+      if (!resolve || cmd->pending) {
        silc_server_command_send_status_reply(
                                         cmd, SILC_COMMAND_JOIN,
                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
@@ -1935,7 +1981,7 @@ static void silc_server_command_join_channel(SilcServer server,
   }
 
   if (channel->founder_key)
-    fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
+    fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
 
   reply = 
     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
@@ -1964,7 +2010,8 @@ static void silc_server_command_join_channel(SilcServer server,
                                         13, user_list->data, user_list->len,
                                         14, mode_list->data, 
                                         mode_list->len,
-                                        15, fkey, fkey_len);
+                                        15, fkey ? fkey->data : NULL,
+                                        fkey ? fkey->len : 0);
 
   /* Send command reply */
   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
@@ -2008,7 +2055,8 @@ static void silc_server_command_join_channel(SilcServer server,
                                         SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
                                         clidp->data, clidp->len,
                                         mode, 4, clidp->data, clidp->len,
-                                        fkey, fkey_len);
+                                        fkey ? fkey->data : NULL,
+                                        fkey ? fkey->len : 0);
     }
   }
 
@@ -2025,7 +2073,7 @@ static void silc_server_command_join_channel(SilcServer server,
   silc_buffer_free(keyp);
   silc_buffer_free(user_list);
   silc_buffer_free(mode_list);
-  silc_free(fkey);
+  silc_buffer_free(fkey);
 
  out:
   silc_free(passphrase);
@@ -2510,8 +2558,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   bool set_mask = FALSE;
   SilcPublicKey founder_key = NULL;
-  unsigned char *fkey = NULL;
-  SilcUInt32 fkey_len = 0;
+  SilcBuffer fkey = NULL;
 
   if (!client) {
     silc_server_command_free(cmd);
@@ -2837,7 +2884,7 @@ SILC_SERVER_CMD_FUNC(cmode)
         }
 
        founder_key = channel->founder_key;
-       fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
+       fkey = silc_pkcs_public_key_payload_encode(founder_key);
         if (!fkey) {
          silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                                SILC_STATUS_ERR_AUTH_FAILED,
@@ -2871,7 +2918,8 @@ SILC_SERVER_CMD_FUNC(cmode)
                                     hmac, hmac ? strlen(hmac) : 0,
                                     passphrase, passphrase ? 
                                     strlen(passphrase) : 0,
-                                    fkey, fkey_len);
+                                    fkey ? fkey->data : NULL,
+                                    fkey ? fkey->len : 0);
 
   /* Set CMODE notify type to network */
   silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
@@ -2892,7 +2940,7 @@ SILC_SERVER_CMD_FUNC(cmode)
 
  out:
   channel->mode = old_mask;
-  silc_free(fkey);
+  silc_buffer_free(fkey);
   silc_free(channel_id);
   silc_server_command_free(cmd);
 }
@@ -2916,8 +2964,7 @@ SILC_SERVER_CMD_FUNC(cumode)
   int notify = FALSE;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   SilcPublicKey founder_key = NULL;
-  unsigned char *fkey = NULL;
-  SilcUInt32 fkey_len = 0;
+  SilcBuffer fkey = NULL;
 
   if (!client)
     goto out;
@@ -3063,7 +3110,7 @@ SILC_SERVER_CMD_FUNC(cumode)
 
       notify = TRUE;
       founder_key = channel->founder_key;
-      fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
+      fkey = silc_pkcs_public_key_payload_encode(founder_key);
       if (!fkey) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                              SILC_STATUS_ERR_AUTH_FAILED, 0);
@@ -3232,7 +3279,8 @@ SILC_SERVER_CMD_FUNC(cumode)
                                       idp->data, idp->len,
                                       tmp_mask, 4, 
                                       tmp_id, tmp_len,
-                                      fkey, fkey_len);
+                                      fkey ? fkey->data : NULL,
+                                      fkey ? fkey->len : 0);
 
     /* Set CUMODE notify type to network */
     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
@@ -3256,7 +3304,7 @@ SILC_SERVER_CMD_FUNC(cumode)
  out:
   silc_free(channel_id);
   silc_free(client_id);
-  silc_free(fkey);
+  silc_buffer_free(fkey);
   silc_server_command_free(cmd);
 }
 
@@ -4277,8 +4325,8 @@ SILC_SERVER_CMD_FUNC(getkey)
   SilcServerID *server_id = NULL;
   SilcIDPayload idp = NULL;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
-  unsigned char *tmp, *pkdata;
-  SilcUInt32 tmp_len, pklen;
+  unsigned char *tmp;
+  SilcUInt32 tmp_len;
   SilcBuffer pk = NULL;
   SilcIdType id_type;
   SilcPublicKey public_key;
@@ -4353,22 +4401,8 @@ SILC_SERVER_CMD_FUNC(getkey)
        send it back. If they key does not exist then do not send it, 
        send just OK reply */
     public_key = client->data.public_key;
-    if (!public_key) {
-      pkdata = NULL;
-      pklen = 0;
-    } else {
-      tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
-      pk = silc_buffer_alloc(4 + tmp_len);
-      silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
-      silc_buffer_format(pk,
-                        SILC_STR_UI_SHORT(tmp_len),
-                        SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
-                        SILC_STR_UI_XNSTRING(tmp, tmp_len),
-                        SILC_STR_END);
-      silc_free(tmp);
-      pkdata = pk->data;
-      pklen = pk->len;
-    }
+    if (public_key)
+      pk = silc_pkcs_public_key_payload_encode(public_key);
   } else if (id_type == SILC_ID_SERVER) {
     server_id = silc_id_payload_get_id(idp);
 
@@ -4419,42 +4453,26 @@ SILC_SERVER_CMD_FUNC(getkey)
     public_key = (!server_entry->data.public_key ? 
                  (server_entry == server->id_entry ? server->public_key :
                   NULL) : server_entry->data.public_key);
-    if (!public_key) {
-      pkdata = NULL;
-      pklen = 0;
-    } else {
-      tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
-      pk = silc_buffer_alloc(4 + tmp_len);
-      silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
-      silc_buffer_format(pk,
-                        SILC_STR_UI_SHORT(tmp_len),
-                        SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
-                        SILC_STR_UI_XNSTRING(tmp, tmp_len),
-                        SILC_STR_END);
-      silc_free(tmp);
-      pkdata = pk->data;
-      pklen = pk->len;
-    }
+    if (public_key)
+      pk = silc_pkcs_public_key_payload_encode(public_key);
   } else {
     goto out;
   }
 
   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
-                                               SILC_STATUS_OK, 0, ident, 
-                                               pkdata ? 2 : 1,
+                                               SILC_STATUS_OK, 0, ident, 2,
                                                2, tmp, tmp_len,
-                                               3, pkdata, pklen);
+                                               3, pk ? pk->data : NULL,
+                                               pk ? pk->len : 0);
   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
                          packet->data, packet->len, FALSE);
   silc_buffer_free(packet);
 
-  if (pk)
-    silc_buffer_free(pk);
-
  out:
   if (idp)
     silc_id_payload_free(idp);
+  silc_buffer_free(pk);
   silc_free(client_id);
   silc_free(server_id);
   silc_server_command_free(cmd);
index 6a4713d6a07c3ca239766f95ecf990a5ecbcf3d3..d02b62ff0015112480e57e9c4018a7b2e3a5ef42 100644 (file)
@@ -939,7 +939,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
   /* Get founder key */
   tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
   if (tmp)
-    silc_pkcs_public_key_decode(tmp, len, &founder_key);
+    silc_pkcs_public_key_payload_decode(tmp, len, &founder_key);
 
   /* See whether we already have the channel. */
   entry = silc_idlist_find_channel_by_name(server->local_list, 
@@ -1205,10 +1205,8 @@ SILC_SERVER_CMD_REPLY_FUNC(getkey)
   SilcServerEntry server_entry = NULL;
   SilcClientID *client_id = NULL;
   SilcServerID *server_id = NULL;
-  SilcSKEPKType type;
-  unsigned char *tmp, *pk;
+  unsigned char *tmp;
   SilcUInt32 len;
-  SilcUInt16 pk_len;
   SilcIDPayload idp = NULL;
   SilcIdType id_type;
   SilcPublicKey public_key = NULL;
@@ -1227,16 +1225,8 @@ SILC_SERVER_CMD_REPLY_FUNC(getkey)
   if (!tmp)
     goto out;
 
-  /* Decode the public key */
-
-  SILC_GET16_MSB(pk_len, tmp);
-  SILC_GET16_MSB(type, tmp + 2);
-  pk = tmp + 4;
-
-  if (type != SILC_SKE_PK_TYPE_SILC)
-    goto out;
-
-  if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
+  /* Decode the public key payload */
+  if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
     goto out;
 
   id_type = silc_id_payload_get_type(idp);
index feb4e0198c0a8392c312be0e3d3f81f900ab78e4..b715828dd5e4cb34ac46d9351ac22634d7929fe3 100644 (file)
@@ -612,7 +612,8 @@ void silc_server_notify(SilcServer server,
        if (channel->founder_key)
          silc_pkcs_public_key_free(channel->founder_key);
        channel->founder_key = NULL;
-       silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
+       silc_pkcs_public_key_payload_decode(tmp, tmp_len,
+                                           &channel->founder_key);
       }
 
       break;
@@ -718,7 +719,7 @@ void silc_server_notify(SilcServer server,
       if (channel->founder_key)
        silc_pkcs_public_key_free(channel->founder_key);
       channel->founder_key = NULL;
-      silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
+      silc_pkcs_public_key_payload_decode(tmp, tmp_len, &channel->founder_key);
 
       if (!channel->founder_key || 
          (client && client->data.public_key && 
@@ -938,8 +939,8 @@ void silc_server_notify(SilcServer server,
        if (channel->founder_key) {
          /* Get public key that must be present in notify */
          tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
-         if (!tmp || !silc_pkcs_public_key_decode(tmp, tmp_len,
-                                                  &founder_key)) {
+         if (!tmp || !silc_pkcs_public_key_payload_decode(tmp, tmp_len,
+                                                          &founder_key)) {
            chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
            silc_server_force_cumode_change(server, sock, channel, chl, mode);
            notify_sent = TRUE;
index 2a5118cc015acbcc89ae1c35bd6734c6aade264f..9113f68840de7bc55d4db9fc02b7ec9f4372b512 100644 (file)
@@ -181,6 +181,12 @@ void silc_server_packet_send_dest(SilcServer server,
     hmac = idata->hmac_send;
     sequence = idata->psn_send++;
     block_len = silc_cipher_get_block_len(cipher);
+
+    /* Check for mandatory rekey */
+    if (sequence == SILC_SERVER_REKEY_THRESHOLD)
+      silc_schedule_task_add(server->schedule, sock->sock,
+                            silc_server_rekey_callback, sock, 0, 1,
+                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
   }
 
   /* Set the packet context pointers */
@@ -197,7 +203,10 @@ void silc_server_packet_send_dest(SilcServer server,
                                            packetdata.dst_id_len));
   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
     packetdata.src_id_len + dst_id_len;
-  packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
+  if (type == SILC_PACKET_CONNECTION_AUTH)
+    SILC_PACKET_PADLEN_MAX(packetdata.truelen, block_len, packetdata.padlen);
+  else
+    SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
 
   /* Create the outgoing packet */
   if (!silc_packet_assemble(&packetdata, NULL, cipher, hmac, sock,
@@ -272,6 +281,12 @@ void silc_server_packet_send_srcdest(SilcServer server,
     hmac = idata->hmac_send;
     sequence = idata->psn_send++;
     block_len = silc_cipher_get_block_len(cipher);
+
+    /* Check for mandatory rekey */
+    if (sequence == SILC_SERVER_REKEY_THRESHOLD)
+      silc_schedule_task_add(server->schedule, sock->sock,
+                            silc_server_rekey_callback, sock, 0, 1,
+                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
   }
 
   if (dst_id) {
@@ -298,7 +313,7 @@ void silc_server_packet_send_srcdest(SilcServer server,
                                            dst_id_len));
   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
     packetdata.src_id_len + dst_id_len;
-  packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
+  SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
 
   /* Create the outgoing packet */
   if (!silc_packet_assemble(&packetdata, NULL, cipher, hmac, sock, data,
@@ -364,6 +379,12 @@ void silc_server_packet_broadcast(SilcServer server,
     /* Now actually send the packet */
     silc_server_packet_send_real(server, sock, TRUE);
     silc_free(id);
+
+    /* Check for mandatory rekey */
+    if (idata->psn_send == SILC_SERVER_REKEY_THRESHOLD)
+      silc_schedule_task_add(server->schedule, sock->sock,
+                            silc_server_rekey_callback, sock, 0, 1,
+                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
     return;
   }
 
@@ -402,6 +423,12 @@ void silc_server_packet_route(SilcServer server,
 
   /* Now actually send the packet */
   silc_server_packet_send_real(server, sock, TRUE);
+
+  /* Check for mandatory rekey */
+  if (idata->psn_send == SILC_SERVER_REKEY_THRESHOLD)
+    silc_schedule_task_add(server->schedule, sock->sock,
+                          silc_server_rekey_callback, sock, 0, 1,
+                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 }
 
 /* This routine can be used to send a packet to table of clients provided
@@ -513,11 +540,11 @@ silc_server_packet_send_to_channel_real(SilcServer server,
 
   block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
   if (channel_message)
-    packet->padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
-                                        packet->src_id_len +
-                                        packet->dst_id_len), block_len);
+    SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
+                       packet->src_id_len +
+                       packet->dst_id_len), block_len, packet->padlen);
   else
-    packet->padlen = SILC_PACKET_PADLEN(packet->truelen, block_len);
+    SILC_PACKET_PADLEN(packet->truelen, block_len, packet->padlen);
 
   /* Put the data to buffer, assemble and encrypt the packet. The packet
      is encrypted with normal session key shared with the client, unless
@@ -1045,6 +1072,12 @@ void silc_server_send_private_message(SilcServer server,
 
   /* Send the packet */
   silc_server_packet_send_real(server, dst_sock, FALSE);
+
+  /* Check for mandatory rekey */
+  if (sequence == SILC_SERVER_REKEY_THRESHOLD)
+    silc_schedule_task_add(server->schedule, dst_sock->sock,
+                          silc_server_rekey_callback, dst_sock, 0, 1,
+                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 }
 
 /* Sends current motd to client */
@@ -1237,14 +1270,13 @@ void silc_server_send_notify_cmode(SilcServer server,
                                   const char *passphrase,
                                   SilcPublicKey founder_key)
 {
-  SilcBuffer idp;
-  unsigned char mode[4], *key = NULL;
-  SilcUInt32 key_len = 0;
+  SilcBuffer idp, fkey = NULL;
+  unsigned char mode[4];
 
   idp = silc_id_payload_encode((void *)id, id_type);
   SILC_PUT32_MSB(mode_mask, mode);
   if (founder_key)
-    key = silc_pkcs_public_key_encode(founder_key, &key_len);
+    fkey = silc_pkcs_public_key_payload_encode(founder_key);
 
   silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
                               SILC_ID_CHANNEL, SILC_NOTIFY_TYPE_CMODE_CHANGE,
@@ -1254,8 +1286,8 @@ void silc_server_send_notify_cmode(SilcServer server,
                               hmac, hmac ? strlen(hmac) : 0,
                               passphrase, passphrase ? 
                               strlen(passphrase) : 0,
-                              key, key_len);
-  silc_free(key);
+                              fkey ? fkey->data : NULL, fkey ? fkey->len : 0);
+  silc_buffer_free(fkey),
   silc_buffer_free(idp);
 }
 
@@ -1272,15 +1304,14 @@ void silc_server_send_notify_cumode(SilcServer server,
                                    SilcClientID *target,
                                    SilcPublicKey founder_key)
 {
-  SilcBuffer idp1, idp2;
-  unsigned char mode[4], *key = NULL;
-  SilcUInt32 key_len = 0;
+  SilcBuffer idp1, idp2, fkey = NULL;
+  unsigned char mode[4];
 
   idp1 = silc_id_payload_encode((void *)id, id_type);
   idp2 = silc_id_payload_encode((void *)target, SILC_ID_CLIENT);
   SILC_PUT32_MSB(mode_mask, mode);
   if (founder_key)
-    key = silc_pkcs_public_key_encode(founder_key, &key_len);
+    fkey = silc_pkcs_public_key_payload_encode(founder_key);
 
   silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
                               SILC_ID_CHANNEL, 
@@ -1288,8 +1319,8 @@ void silc_server_send_notify_cumode(SilcServer server,
                               idp1->data, idp1->len,
                               mode, 4,
                               idp2->data, idp2->len,
-                              key, key_len);
-  silc_free(key);
+                              fkey ? fkey->data : NULL, fkey ? fkey->len : 0);
+  silc_buffer_free(fkey);
   silc_buffer_free(idp1);
   silc_buffer_free(idp2);
 }
@@ -1917,6 +1948,12 @@ void silc_server_relay_packet(SilcServer server,
 
   silc_buffer_pull(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
                   + packet->dst_id_len + packet->padlen);
+
+  /* Check for mandatory rekey */
+  if (sequence == SILC_SERVER_REKEY_THRESHOLD)
+    silc_schedule_task_add(server->schedule, dst_sock->sock,
+                          silc_server_rekey_callback, dst_sock, 0, 1,
+                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 }
 
 /* Routine used to send the connection authentication packet. */
index 502f3cbaae17c86a5e23afb20b4bb7a33a69c209..5656be0baa762b28fc7de32b4bbfe867504d7c98 100644 (file)
@@ -43,7 +43,6 @@ SILC_TASK_CALLBACK(silc_server_free_client_data_timeout);
 SILC_TASK_CALLBACK(silc_server_timeout_remote);
 SILC_TASK_CALLBACK(silc_server_channel_key_rekey);
 SILC_TASK_CALLBACK(silc_server_failure_callback);
-SILC_TASK_CALLBACK(silc_server_rekey_callback);
 SILC_TASK_CALLBACK(silc_server_get_stats);
 
 /* Allocates a new SILC server object. This has to be done before the server
@@ -4233,10 +4232,9 @@ void silc_server_announce_get_channel_users(SilcServer server,
   SilcChannelClientEntry chl;
   SilcHashTableList htl;
   SilcBuffer chidp, clidp, csidp;
-  SilcBuffer tmp;
+  SilcBuffer tmp, fkey = NULL;
   int len;
-  unsigned char mode[4], *fkey = NULL;
-  SilcUInt32 fkey_len = 0;
+  unsigned char mode[4];
   char *hmac;
 
   SILC_LOG_DEBUG(("Start"));
@@ -4248,7 +4246,7 @@ void silc_server_announce_get_channel_users(SilcServer server,
   SILC_PUT32_MSB(channel->mode, mode);
   hmac = channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) : NULL;
   if (channel->founder_key)
-    fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
+    fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
   tmp = 
     silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CMODE_CHANGE,
                                       6, csidp->data, csidp->len,
@@ -4258,7 +4256,8 @@ void silc_server_announce_get_channel_users(SilcServer server,
                                       channel->passphrase,
                                       channel->passphrase ?
                                       strlen(channel->passphrase) : 0,
-                                      fkey, fkey_len);
+                                      fkey ? fkey->data : NULL,
+                                      fkey ? fkey->len : 0);
   len = tmp->len;
   *channel_modes =
     silc_buffer_realloc(*channel_modes,
@@ -4270,9 +4269,8 @@ void silc_server_announce_get_channel_users(SilcServer server,
   silc_buffer_put(*channel_modes, tmp->data, tmp->len);
   silc_buffer_pull(*channel_modes, len);
   silc_buffer_free(tmp);
-  silc_free(fkey);
+  silc_buffer_free(fkey);
   fkey = NULL;
-  fkey_len = 0;
 
   /* Now find all users on the channel */
   silc_hash_table_list(channel->user_list, &htl);
@@ -4299,12 +4297,13 @@ void silc_server_announce_get_channel_users(SilcServer server,
     /* CUMODE notify for mode change on the channel */
     SILC_PUT32_MSB(chl->mode, mode);
     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && channel->founder_key)
-      fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
+      fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
     tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CUMODE_CHANGE,
                                             4, csidp->data, csidp->len,
                                             mode, sizeof(mode),
                                             clidp->data, clidp->len,
-                                            fkey, fkey_len);
+                                            fkey ? fkey->data : NULL,
+                                            fkey ? fkey->len : 0);
     len = tmp->len;
     *channel_users_modes =
       silc_buffer_realloc(*channel_users_modes,
@@ -4317,9 +4316,8 @@ void silc_server_announce_get_channel_users(SilcServer server,
     silc_buffer_put(*channel_users_modes, tmp->data, tmp->len);
     silc_buffer_pull(*channel_users_modes, len);
     silc_buffer_free(tmp);
-    silc_free(fkey);
+    silc_buffer_free(fkey);
     fkey = NULL;
-    fkey_len = 0;
     silc_buffer_free(clidp);
   }
   silc_hash_table_list_reset(&htl);
@@ -5011,7 +5009,7 @@ SilcBuffer silc_server_get_client_channel_list(SilcServer server,
 /* A timeout callback for the re-key. We will be the initiator of the
    re-key protocol. */
 
-SILC_TASK_CALLBACK(silc_server_rekey_callback)
+SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_callback)
 {
   SilcServer server = app_context;
   SilcSocketConnection sock = (SilcSocketConnection)context;
index 12479fff6c49866e925aaa14e9fe9dfc46ec3438..88da61f8c36115e9b1da493e83dc27db0c3482ac 100644 (file)
@@ -333,6 +333,12 @@ void silc_server_backup_broadcast(SilcServer server,
 
     /* Now actually send the packet */
     silc_server_packet_send_real(server, sock, FALSE);
+
+    /* Check for mandatory rekey */
+    if (idata->psn_send == SILC_SERVER_REKEY_THRESHOLD)
+      silc_schedule_task_add(server->schedule, sender->sock,
+                            silc_server_rekey_callback, sender, 0, 1,
+                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
   }
 }
 
index 1fb5201e81c1848ea8359b83bb1386ed9228eca6..406d4338f1e5fa6b291a6a7fa65b2fca5f3d6673 100644 (file)
@@ -152,6 +152,9 @@ typedef struct {
   SilcUInt32 failure;
 } *SilcServerFailureContext;
 
+/* Rekey must be performed at the lastest when this many packets is sent */
+#define SILC_SERVER_REKEY_THRESHOLD 0xfffffe00
+
 /* Macros */
 
 /* Return pointer to the primary router connection */
@@ -228,6 +231,7 @@ do {                                                \
 
 /* Prototypes */
 SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final);
+SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_callback);
 void silc_server_watcher_list_destroy(void *key, void *context,
                                      void *user_context);
 
index cf309e77d5ae392ab939d5fe9f50c2fa32970ede..dd79c597f08a22c8675c8eb12e31b1aea9bd725a 100644 (file)
@@ -1573,6 +1573,8 @@ SilcBuffer silc_server_query_reply_attrs(SilcServer server,
       silc_strncat(service.address, sizeof(service.address),
                   server->server_name, strlen(server->server_name));
       service.status = !(client_entry->mode & SILC_UMODE_DETACHED);
+      if (client_entry->connection)
+       service.idle = time(NULL) - client_entry->data.last_receive;
       buffer = silc_attribute_payload_encode(buffer, attribute,
                                             SILC_ATTRIBUTE_FLAG_VALID,
                                             &service, sizeof(service));
index d938e68ffafc3083c2612f91852828ed41b134e3..2736584a924e725e58f57146ba08307cc6d706ab 100644 (file)
@@ -8,7 +8,7 @@
 .ds RF FORMFEED[Page %]
 .ds CF
 .ds LH Internet Draft
-.ds RH 15 May 2002
+.ds RH XXX
 .ds CH
 .na
 .hy 0
@@ -16,8 +16,8 @@
 .nf
 Network Working Group                                        P. Riikonen
 Internet-Draft
-draft-riikonen-presence-attrs-00.txt                         15 May 2002
-Expires: 15 November 2002
+draft-riikonen-presence-attrs-00.txt                         XXX
+Expires: XXX
 
 .in 3
 
@@ -306,8 +306,9 @@ multiple same attributes in the packet.
 2    ATTRIBUTE_SERVICE
 
      This attribute indicates a service in the Internet that the user
-     is currently using or has logged in.  The value of this attribute
-     is as follows:
+     is currently using or has logged in.  It also shows when the user
+     started using the service, and how long user has been idle in the
+     service.  The value of this attribute is as follows:
 
      Length       Type       Value
      4 bytes      integer    Service Port (IANA specified)
@@ -316,6 +317,9 @@ multiple same attributes in the packet.
                              0x01 (true) it means the user is online
                              in the service.  Set to 0x00 (false) when
                              out of reach.
+     variable     string     Signon date and time, UTC date, format as
+                             in ISO 8601
+     4 bytes      integer    Idle time
 
 
 3    ATTRIBUTE_STATUS_MOOD
@@ -542,7 +546,8 @@ multiple same attributes in the packet.
 
      The procedure producing the signature and encoding it are done
      in the manner defined in their respective definitions, see the
-     provided references.
+     provided references.  Also the hash function used with the
+     signature procedure is defined by the public key/certificate type.
 
 
 15   ATTRIBUTE_SERVER_DIGITAL_SIGNATURE
@@ -628,4 +633,4 @@ Finland
 
 EMail: priikone@iki.fi
 
-This Internet-Draft expires 15 November 2002
+This Internet-Draft expires XXX
index b9359734953e81033d458a4c7132d2c36b84d684..0dfaabeb8b956c9513eb28b546e33e14da639711 100644 (file)
@@ -74,8 +74,9 @@ Table of Contents
   1.1 Requirements Terminology ..................................  2
 2 SILC Commands .................................................  2
   2.1 SILC Commands Syntax ......................................  2
-  2.2 SILC Commands List ........................................  4
-  2.3 SILC Command Status Payload ............................... 40
+  2.2 SILC Command Argument Idioms ..............................  2
+  2.3 SILC Commands List ........................................  4
+  2.4 SILC Command Status Payload ............................... 40
 3 SILC Status Types ............................................. 41
 4 Security Considerations ....................................... 47
 5 References .................................................... 47
@@ -196,18 +197,30 @@ Status messages:
 Every command reply also defines set of status message that it
 may return inside the <Status Payload>.  All status messages
 are defined in the section 2.3 SILC Command Status Payload
-
+The status messages defined with the command are recommendations.
+It is possible to return other status messages not listes with
+the command reply definition.
 .in 3
-Every command that has some kind of ID as argument (for example
-<Client ID>) are actually ID Payloads, defined in [SILC2] that includes
-the type of the ID, length of the ID and the actual ID data.  This
-way variable length ID's can be sent as arguments.  Also note that
-all passphrases that may be sent in commands MUST be UTF-8 [RFC2279]
-encoded.
 
 
 .ti 0
-2.2 SILC Commands List
+2.2 SILC Command Argument Idioms
+
+All commands that has an ID as argument (for example <Client ID>) are
+actually ID Payloads, defined in [SILC2] that includes the type of the
+ID, length of the ID and the actual ID data.  This way variable length
+ID's can be sent as arguments.
+
+All passphrases that may be sent in commands as arguments MUST be
+UTF-8 [RFC2279] encoded.
+
+All public keys and certificates that are sent as arguments are actually
+Public Key Payloads [SILC2].  This way it is possible to send different
+kind of public keys and certificate types as arguments.
+
+
+.ti 0
+2.3 SILC Commands List
 
 This section lists all SILC commands, however, it is expected that a
 implementation and especially client implementation has many more
@@ -660,15 +673,22 @@ List of all defined commands in SILC follows.
 
     9   SILC_COMMAND_KILL
 
-        Max Arguments:  2
-            Arguments:  (1) <Client ID>  (2) [<comment>]
+        Max Arguments:  3
+            Arguments:  (1) <Client ID>         (2) [<comment>]
+                        (3) [<auth payload>]
+
+        This command can be used by SILC operators to remove a client from
+        SILC network.  It also can be used by a normal client to remove
+        its own client from network by providing correct authentication
+        data.
+
+        Router operator killing a client:
 
-        This command is used by SILC operators to remove a client from
-        SILC network.  The removing has temporary effects and client may
-        reconnect to SILC network.  The <Client ID> is the client to be
-        removed from SILC.  The <comment> argument may be provided to 
-        give to the removed client some information why it was removed
-        from the network.
+        The removing has temporary effects and client may reconnect to
+        SILC network.  The <Client ID> is the client to be removed from SILC.
+        The <comment> argument may be provided to give to the removed client
+        some information why it was removed from the network.  The killer
+        MUST have SILC operator privileges.
 
         When killing a client the router MUST first send notify type
         SILC_NOTIFY_TYPE_KILLED to all channels the client has joined.
@@ -677,6 +697,19 @@ List of all defined commands in SILC follows.
         router.  Finally, the router MUST send the same notify type 
         directly to the client which was killed.
 
+        Normal client killing by authentication:
+
+        When normal client executes this command the <Client ID> is the
+        destination client to be removed from the network.  The client
+        MUST provide the <auth payload> which includes a digital signature
+        that MUST be verified with the public key of the client indicated
+        by <Client ID>.  The <Client ID> MUST be local client to the server.
+        If the signature verification is successful the server sends
+        SILC_NOTIFY_TYPE_SIGNOFF to network and to the destination client.
+        The SILC_NOTIFY_TYPE_KILLED MUST NOT be used in this case.  If the
+        verification fails the destination client remains in network.
+        The hash function used in <auth payload> computing is SHA1.
+
         Reply messages to the command:
 
         Max Arguments:  1
@@ -829,12 +862,10 @@ List of all defined commands in SILC follows.
         The <username> is the username set in the server configurations
         as operator.  The <authentication payload> is the data that the
         client is authenticated against.  It may be passphrase prompted
-        for user on client's screen or it may be public key or certificate
-        authentication data (data signed with private key).  The public
-        key that server will use to verify the signature found in the
-        payload should be verified.  It is recommended that the public
-        key is saved locally in the server and server would not use
-        any public keys received during the SKE.
+        for user on client's screen or it may be public key authentication
+        based on digital signatures.  The public key used to verify the
+        signature should be locally saved in the server, and server should
+        not use public key received during the SKE to verify this signature.
 
         After changing the mode the server MUST send the notify type
         SILC_NOTIFY_TYPE_UMODE_CHANGE to its primary router.
@@ -942,7 +973,7 @@ List of all defined commands in SILC follows.
         channel.  The <Client ID list> is formed by adding the ID Payloads
         one after the other.  The <client mode list> is formed by adding
         32 bit MSB first order values one after the other.  The <founder
-        pubkey> is the public key of the channel founder.
+        pubkey> is the public key (or certificate) of the channel founder.
 
         Client receives the channel key in the reply message as well
         inside <Channel Key Payload>.
@@ -1943,7 +1974,7 @@ List of all defined commands in SILC follows.
 
 
 .ti 0
-2.3.1 SILC Command Status Payload
+2.4 SILC Command Status Payload
 
 Command Status Payload is sent in command reply messages to indicate
 the status of the command.  The payload is one of argument in the
@@ -2014,7 +2045,7 @@ All Status messages are described in the next section.
 
 
 .ti 0
-2.3.2 SILC Status Types
+3 SILC Status Types
 
 Status messages are returned in SILC protocol in command reply
 packet and in notify packet.  The SILC_PACKET_COMMAND_REPLY is
@@ -2296,11 +2327,21 @@ List of all defined status types:
         "Operation timed out".  Operation or service request timed
         out, and thus was not processed.
 
+   55   SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY
+
+        "Unsupported public key type".  The public key or certificate
+        type is not supported in this implementation.
+
+   56   SILC_STATUS_ERR_OPERATION_ALLOWED
+
+        "Operation is not allowed".  A operation, for example a command,
+        is not allowed or it's execution is not allowed.
+
 .in 3
 
 
 .ti 0
-3 Security Considerations
+4 Security Considerations
 
 Security is central to the design of this protocol, and these security
 considerations permeate the specification.  Common security considerations
@@ -2310,7 +2351,7 @@ security of this protocol.
 
 
 .ti 0
-4 References
+5 References
 
 [SILC1]      Riikonen, P., "Secure Internet Live Conferencing (SILC),
              Protocol Specification", Internet Draft, May 2002.
@@ -2382,7 +2423,7 @@ security of this protocol.
 
 
 .ti 0
-5 Author's Address
+6 Author's Address
 
 .nf
 Pekka Riikonen
index fb9d84b67665efe4032da80177c1bb623ff92216..cb0240d82b8259f3b037e61cff2e6d3a249260af 100644 (file)
@@ -8,7 +8,7 @@
 .ds RF FORMFEED[Page %]
 .ds CF
 .ds LH Internet Draft
-.ds RH 15 May 2002
+.ds RH XXX
 .ds CH
 .na
 .hy 0
 .nf
 Network Working Group                                        P. Riikonen
 Internet-Draft
-draft-riikonen-flags-payloads-00.txt                         15 May 2002
-Expires: 15 November 2002
+draft-riikonen-flags-payloads-01.txt                         XXX
+Expires: 20 April 2003
 
 .in 3
 
 .ce 2
 SILC Message Flag Payloads
-<draft-riikonen-flags-payloads-00.txt>
+<draft-riikonen-flags-payloads-01.txt>
 
 .ti 0
 Status of this Memo
@@ -178,7 +178,106 @@ additional payload.
 .ti 0
 3.3 SILC_MESSAGE_FLAG_SIGNED
 
-Not defined yet.
+This flag is used to tell the recipient that the sent message is
+digitally signed by the sender, and that the receipient should verify
+the signature to verify the true authenticity of the received message.
+All message payloads in SILC provides message authentication code (MAC)
+which can be used to verify that the sender produced and sent the message.
+Even so, signing messages digitally can be used to verify the authenticity
+of the message when recipient trusts the sender.
+
+This flag defines a payload which is used to deliver the actual message,
+sender's public key and the digital signature.  The payload for
+SILC_MESSAGE_FLAG_SIGNED is as follows:
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                       Message Payload                         ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                      Public Key Payload                       ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|     Signature Data Length     |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                        Signature Data                         ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 1:  SILC_MESSAGE_FLAG_SIGNED Payload
+
+
+.in 6
+o Message Payload (variable length) - This is a message payload
+  consisting of the encrypted message.  When this flag is used
+  with channel messages it include Channel Message Payload, and
+  when used with private messages it include Private Message
+  Payload [SILC2].
+
+o Public Key Payload (variable length) - This includes the
+  Public Key Payload which can be used to deliver the sender's
+  public key (or certificate).  It also indicates the type of the
+  public key (or certificate) which the recipient use to identify
+  how the signature must be verified.  This payload must always
+  be present but it is not required to include the public key
+  data.  The Public Key Type field in the Public Key Payload
+  MUST be set to the correct type of the key, even if the
+  actual public key data is not included.
+
+o Signature Data Length (2 bytes) - Indicates the length of
+  the Signature Data field not including any other field.
+
+o Signature Data (variable lenght) - Includes the actual
+  signature data.  The signature computation and encoding
+  is key type specific.  See [SILC3] for all key types, and
+  their respective references of how to compute and encode
+  the signature.
+.in 3
+
+How the data is processed before it is signed is key type specific.
+The actual data that to be signed MUST be the plaintext message
+payload before encryption.  For Channel Message Payload the data to
+be signed is concatenation of Message Flags, Message Length, Message
+Data, Padding Length, Padding, Initial Vector fields and the Public
+Key Payload.  Any other field is not included for signature data.
+For Private Message Payload the data to be signed is concatenation
+of Message Flags, Message Data Length, Message Data, Padding fields and
+the Public Key Payload fields.  Any other field is not included for
+signature data.  Before signing, the data is always processed, usually
+hashed.  The hash function to be used is defined in the key type
+specific definitions.  See the key type specific references in
+[SILC3].
+
+If the public key of the sender is included in the payload the
+recipient SHOULD verify before accepting the public key.  Recipient
+SHOULD verify the signature before accepting a public key.  With
+certificates the certificate verification may be done before
+verifying the signature.  If the signature verification fails the
+message should still be displayed.  The end user should also be
+notified about the result of the signature verification.
+
+To make the packet size smaller implementations may not want to
+include the actual public key in all signed messages.  Sending the
+public key in the first message is usually sufficient.  Subsequent
+messages may include empty Public Key Payload with an indication of
+the public key type.
+
+Implementations that do not support this flag can still process the
+message payload in normal manner.  These implementations merely ignore
+rest of the data after the message payload.
+
+This flag MAY be masked with any other Message Flag including those that
+define additional payloads.  As long as the defined payload resides in
+the data area of the message payload this flag may be masked with the
+other flags.
 
 
 .ti 0
@@ -236,10 +335,12 @@ MIME fragmentation is defined for gateway usage, but in case of SILC the
 sender may also start sending fragmented MIME objects.
 
 This flag SHOULD NOT be masked with some other Message Flag that defines 
-payloads.  Generally this sort of setting would be impossible for the 
-receiver to interpret.  However, flags that does not define any specific 
-payloads MAY be masked with this flag as well.  For example, this flag
-could be masked also with SILC_MESSAGE_FLAG_REQUEST flag.
+payloads for message data.  Generally this sort of setting would be
+impossible for the receiver to interpret.  However, flags that does not
+define any specific payloads MAY be masked with this flag as well.  For
+example, this flag could be masked also with SILC_MESSAGE_FLAG_REQUEST flag.
+It also can be masked with SILC_MESSAGE_FLAG_SIGNED flag since it does not
+define data specific payload.
 
 
 .ti 0
@@ -266,6 +367,9 @@ support S/MIME may be desired in some implementations.
 [SILC2]      Riikonen, P., "SILC Packet Protocol", Internet Draft,
              May 2002.
 
+[SILC3]      Riikonen, P., "SILC Key Exchange and Authentication 
+             Protocols", Internet Draft, May 2002.
+
 [RFC2045]    Freed, N., et al., "Multipurpose Internet Mail Extensions 
              (MIME) Part One: Format of Internet Message Bodies",
              Standards Track, RFC 2045, November 1996.
@@ -301,4 +405,4 @@ Finland
 
 EMail: priikone@iki.fi
 
-This Internet-Draft expires 15 November 2002
+This Internet-Draft expires 20 April 2003
index 6c511ffad81f82110f511e0f57de75a65500682d..24e7690ead21ecdc78b16bf65c32583b33281e9d 100644 (file)
@@ -231,11 +231,9 @@ packet.  The packet data is the packet payloads defined in this
 protocol.  The data payload area is always encrypted.
 
 The last part of SILC packet is the packet MAC that assures the
-integrity of the packet.  The MAC is always computed from the packet
-before the encryption is applied to the packet.  If compression is used
-in the packet the MAC is computed after the compression has been
-applied.  The compression, on the other hand, is always applied before
-encryption.  See more details in the section 2.6 Packet MAC Generation.
+integrity of the packet.  See the section 2.6 Packet MAC Generation
+for more information.  If compsession is used the compsession is
+always applied before encryption.
 
 All fields in all packet payloads are always in MSB (most significant
 byte first) order.
@@ -1009,7 +1007,7 @@ The following diagram represents the Public Key Payload.
 |       Public Key Length       |        Public Key Type        |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
-~            Public Key of the party (or certificate)           ~
+~                  Public Key (or certificate)                  ~
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 .in 3
@@ -1214,8 +1212,8 @@ The following list of currently defined notify types.  The format for
 notify arguments is same as in SILC commands described in [SILC4]. 
 Note that all ID's sent in arguments are sent inside ID Payload.  Also
 note that all passphrases that may be sent inside arguments MUST be
-UTF-8 [RFC2279] encoded.
-
+UTF-8 [RFC2279] encoded.  Also note that all public keys or certificates
+sent in arguments are actually Public Key Payloads.
 
 
 .in 6
@@ -1870,11 +1868,16 @@ Private Message Payload is used to send private message between
 two clients (or users for that matter).  The messages are sent only
 to the specified user and no other user inside SILC network is
 able to see the message.  The message is protected by the session 
-key established by the SILC Key Exchange Protocol.  However,
-it is also possible to agree to use a private key to protect
-just the private messages.  See section 2.3.11 Private Message
-Key Payload for detailed description of how to agree to use
-specific key.
+key established by the SILC Key Exchange Protocol.
+
+However, it is also possible to agree to use a private key to
+protect just the private messages.  It is for example possible to
+perform Key Agreement between two clients.  See section 2.3.20
+Key Agreement Payload how to perform key agreement.  See also
+section 2.3.12 Private Message Key Payload for another way of
+using private keys with private messages.  See [SILC1] section
+4.6 for detailed description for private message key generation
+procedure.
 
 If normal session key is used to protect the message, every server
 between the sender client and the receiving client MUST decrypt the
@@ -1903,7 +1906,11 @@ diagram represents the Private Message Payload.
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
-~                             Padding                           ~
+~                            Padding                            ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                              MAC                              ~
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 .in 3
@@ -1921,11 +1928,10 @@ o Message Flags (2 bytes) - This field includes the Message
   same purpose.
 
 o Message Data Length (2 bytes) - Indicates the length of the
-  Message Data field, not includes any other field.
+  Message Data field, not including any other field.
 
 o Message Data (variable length) - The actual message to
-  the client.  Rest of the packet is reserved for the message
-  data.
+  the client.
 
 o Padding (variable length) - This field is present only
   when the private message payload is encrypted with private
@@ -1933,6 +1939,16 @@ o Padding (variable length) - This field is present only
   the payload 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.
+
+o MAC (variable length) - This field is present only when
+  the private message payload is encrypted with private
+  message key. The MAC is computed from the Message Flags,
+  Message Data Length, Message Data and Padding fields in
+  that order.  The MAC protects the integrity of the channel
+  message.  The MAC is computed after encryption from the
+  ciphertext.  Note that, this field is not encrypted and
+  thus not included in the padding calculation.  When encrypted
+  with normal session keys, this field MUST NOT be included.
 .in 3
 
 
@@ -1950,7 +1966,7 @@ whether user wants to receive private message key.  Note that there
 are other, more secure ways of exchanging private message keys in
 the SILC network.  Instead of sending this payload it is possible to
 negotiate the private message key with SKE protocol using the Key
-Agreement payload directly peer to peer.
+Agreement payload directly peer to peer, see section 2.3.20.
 
 This payload may only be sent by client to another client.  Server
 MUST NOT send this payload at any time.  After sending this payload
@@ -1979,6 +1995,12 @@ diagram represents the Private Message Key Payload.
 ~                          Cipher Name                          ~
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       HMAC Name Length        |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                           HMAC Name                           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 .in 3
 
 .ce
@@ -2003,8 +2025,16 @@ o Cipher Name (variable length) - Name of the cipher to use
   in the private message encryption.  If this field does not
   exist then the default cipher of the SILC protocol is used.
   See the [SILC1] for defined ciphers.
-.in 3
 
+o HMAC Name Length (2 bytes) - Indicates the length of the
+  HMAC Name field in the payload, not including any other
+  field.
+
+o HMAC Name (variable length) - Name of the HMAC to use
+  in the private message MAC computation.  If this field does
+  not exist then the default HMAC of the SILC protocol is used.
+  See the [SILC1] for defined HMACs.
+.in 3
 
 
 .ti 0
@@ -2380,9 +2410,9 @@ After the key material has been received from the SKE protocol it is
 processed as the [SILC3] describes.  If the key material is used as
 channel private key then the Sending Encryption Key, as defined in
 [SILC3] is used as the channel private key.  Other key material must
-be discarded.  The [SILC1] defines the way to use the key material if
-it is intended to be used as private message keys.  Any other use for
-the key material is undefined.
+be discarded.  The [SILC1] in section 4.6 defines the way to use the
+key material if it is intended to be used as private message keys.
+Any other use for the key material is undefined.
 
 
 .ti 0
@@ -2719,7 +2749,7 @@ However, rekey MUST be performed before the sequence number wraps
 and repeats from zero.  Note that the sequence number is incremented only
 when MAC is computed for a packet.  If packet is not encrypted and MAC is
 not computed then the sequence number is not incremented.  Hence, the
-sequence number is zero for first encrypted packet.
+sequence number is zero for the very first encrypted packet.
 
 See [SILC1] for defined and allowed MAC algorithms.
 
@@ -2736,16 +2766,20 @@ and between the Data Payload area.  The padding for normal packets
 may be calculated as follows:
 
 .in 6
-padding length = 16 - (packet_length mod block_size)
+padding_length = 16 - (packet_length mod block_size)
+if (padding_length < 8)
+  padding_length += block_size
 .in 3
 
 The `block_size' is the block size of the cipher.  The maximum padding
-length is 128 bytes, and minimum is 1 byte.  The above algorithm calculates
-the padding to the next block size, and always returns the padding
-length between 1 - 16 bytes.  However, implementations may add padding
-up to 128 bytes.  For example packets that include a passphrase or a
-password for authentication purposes SHOULD pad the packet up to the
-maximum padding length.
+length is 128 bytes, and minimum is 8 bytes.  For example, packets that
+include a passphrase or a password for authentication purposes SHOULD
+pad the packet up to the maximum padding length.  The maximum padding
+is calculated as follows:
+
+.in 6
+padding_length = 128 - (packet_length mod block_size)
+.in 3
 
 For special packets the padding calculation is different as special
 packets may be encrypted differently.  In these cases the encrypted
index 7c5cf2502f921f70b4f421e52cea641a911f2ce3..0cf5c3adc1b61894b963ab053fa5b5f50ce93050 100644 (file)
@@ -1457,7 +1457,7 @@ software version = <major>[.<minor>[.<build or vendor string>]]
 
 Protocol version MAY provide both major and minor version.  Currently
 implementations MUST set the protocol version and accept at least the 
-protocol version as SILC-1.1-<software version>.  If new protocol version 
+protocol version as SILC-1.2-<software version>.  If new protocol version 
 causes incompatibilities with older version the <minor> version number 
 MUST be incremented.  The <major> is incremented if new protocol version 
 is fully incompatible.
@@ -1472,8 +1472,8 @@ Thus, the version strings could be, for example:
 .in 6
 SILC-1.1-2.0.2
 SILC-1.0-1.2
-SILC-1.1-1.0.VendorXYZ
-SILC-1.1-2.4.5 Vendor Limited
+SILC-1.2-1.0.VendorXYZ
+SILC-1.2-2.4.5 Vendor Limited
 .in 3
 
 
@@ -1987,7 +1987,7 @@ the MACs of the channel messages.  The processing is as follows:
 
 The raw key data is the key data received in the Channel Key Payload.
 The hash() function is the hash function used in the HMAC of the channel.
-Note that the server MUST also save the channel key.
+Note that the server also MUST save the channel key.
 
 
 .ti 0
@@ -2038,12 +2038,13 @@ generated key, and the SILC_PACKET_KEY_AGREEMENT was not used, then
 the key material SHOULD be processed as defined in the [SILC3].  In
 the processing, however, the HASH, as defined in [SILC3] MUST be 
 ignored.  After processing the key material it is employed as defined
-in [SILC3], however, the HMAC key material MUST be discarded.
+in [SILC3].
 
 If the key is pre-shared-key or randomly generated the implementations
-SHOULD use the SILC protocol's mandatory cipher as the cipher.  If the
-SKE was used to negotiate key material the cipher was negotiated as well,
-and may be different from default cipher.
+SHOULD use the SILC protocol's mandatory cipher as the cipher, and the
+mandatory HMAC as the HMAC.  If the SKE was used to negotiate key material
+the cipher was negotiated as well, and may be different from default
+cipher and default HMAC.
 
 
 .ti 0
index 60a382384e7eaef93fd0643478b3592e080e4a19..16bbf4d25889359661cd63c8c18f3da242840bb9 100644 (file)
@@ -221,6 +221,11 @@ extern "C" {
 #include "silcmp.h"
 #include "silcmath.h"
 
+/* SILC util library includes */
+#include "silcmemory.h"
+#include "silcbuffer.h"
+#include "silcbuffmt.h"
+
 /* Crypto library includes */
 #include "silccipher.h"
 #include "silchash.h"
@@ -228,17 +233,14 @@ extern "C" {
 #include "silcrng.h"
 #include "silcpkcs.h"
 
-/* SILC util library includes */
+/* More SILC util library includes */
 #include "silcmutex.h"
 #include "silcthread.h"
 #include "silcschedule.h"
 #include "silchashtable.h"
 #include "silclog.h"
-#include "silcmemory.h"
 #include "silclist.h"
 #include "silcdlist.h"
-#include "silcbuffer.h"
-#include "silcbuffmt.h"
 #include "silcnet.h"
 #include "silcfileutil.h"
 #include "silcstrutil.h"
index 9d1841651f5b51c751b345d28e5b77a36f054c62..e8959c134b85121f67d2c43ffcfdeb973fbe2c8b 100644 (file)
@@ -27,7 +27,7 @@ extern "C" {
 #include "version_internal.h"
 
 /* SILC Protocol version number */
-#define SILC_PROTOCOL_VERSION_CURRENT 11
+#define SILC_PROTOCOL_VERSION_CURRENT 12
 
 /* SILC version string */
 #define silc_version SILC_VERSION_STRING
index 62dba28ceeeada8d0339efe853e77fd1c556556a..631862a88d46e6012171c75d9f5da6f559ee4072 100644 (file)
@@ -26,7 +26,6 @@
 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
-SILC_TASK_CALLBACK(silc_client_rekey_callback);
 SILC_TASK_CALLBACK(silc_client_rekey_final);
 
 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
@@ -100,7 +99,7 @@ void silc_client_free(SilcClient client)
    the client ready to be run. One must call silc_client_run to run the
    client. Returns FALSE if error occured, TRUE otherwise. */
 
-int silc_client_init(SilcClient client)
+bool silc_client_init(SilcClient client)
 {
   SILC_LOG_DEBUG(("Initializing client"));
 
@@ -427,7 +426,7 @@ silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
    case then this function is not used at all. When the connecting is
    done the `connect' client operation is called. */
 
-int silc_client_connect_to_server(SilcClient client,
+bool silc_client_connect_to_server(SilcClient client,
                                   SilcClientConnectionParams *params,
                                   int port, char *host, void *context)
 {
@@ -890,7 +889,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
    is used directly only in special cases. Normal cases should use
    silc_server_packet_send. Returns < 0 on error. */
 
-int silc_client_packet_send_real(SilcClient client,
+bool silc_client_packet_send_real(SilcClient client,
                                 SilcSocketConnection sock,
                                 bool force_send)
 {
@@ -1402,6 +1401,12 @@ void silc_client_packet_send(SilcClient client,
 
     if (hmac)
       sequence = ((SilcClientConnection)sock->user_data)->internal->psn_send++;
+
+    /* Check for mandatory rekey */
+    if (sequence == SILC_CLIENT_REKEY_THRESHOLD)
+      silc_schedule_task_add(client->schedule, sock->sock,
+                            silc_client_rekey_callback, sock, 0, 1,
+                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
   }
 
   block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
@@ -1434,7 +1439,10 @@ void silc_client_packet_send(SilcClient client,
                                            packetdata.dst_id_len));
   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
     packetdata.src_id_len + packetdata.dst_id_len;
-  packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
+  if (type == SILC_PACKET_CONNECTION_AUTH)
+    SILC_PACKET_PADLEN_MAX(packetdata.truelen, block_len, packetdata.padlen);
+  else
+    SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
 
   /* Create the outgoing packet */
   if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock, 
@@ -1832,7 +1840,7 @@ void silc_client_process_failure(SilcClient client,
 /* A timeout callback for the re-key. We will be the initiator of the
    re-key protocol. */
 
-SILC_TASK_CALLBACK(silc_client_rekey_callback)
+SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback)
 {
   SilcSocketConnection sock = (SilcSocketConnection)context;
   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
index d4aac686b25dbfe4f0309d034e053fc5787fbd9d..0eb263c1f4e4b08dd985d89e7c265060fb484739 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  client_channel.c
+  client_channel.c 
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2002 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.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -40,7 +39,7 @@ void silc_client_send_channel_message(SilcClient client,
                                      SilcMessageFlags flags,
                                      unsigned char *data, 
                                      SilcUInt32 data_len, 
-                                     int force_send)
+                                     bool force_send)
 {
   int i;
   SilcSocketConnection sock;
@@ -146,9 +145,9 @@ void silc_client_send_channel_message(SilcClient client,
                                 packetdata.dst_id_len);
   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
     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), block_len);
+  SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
+                     packetdata.src_id_len +
+                     packetdata.dst_id_len), block_len, packetdata.padlen);
 
   /* Create the outgoing packet */
   if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
@@ -170,6 +169,12 @@ void silc_client_send_channel_message(SilcClient client,
   /* Now actually send the packet */
   silc_client_packet_send_real(client, sock, force_send);
 
+  /* Check for mandatory rekey */
+  if (conn->internal->psn_send == SILC_CLIENT_REKEY_THRESHOLD)
+    silc_schedule_task_add(client->schedule, sock->sock,
+                          silc_client_rekey_callback, sock, 0, 1,
+                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+
  out:
   silc_buffer_free(payload);
   silc_free(id_string);
@@ -484,7 +489,7 @@ void silc_client_receive_channel_key(SilcClient client,
    currently it is not expected that the SKE key material would be used
    as channel private key. However, this API allows it. */
 
-int silc_client_add_channel_private_key(SilcClient client,
+bool silc_client_add_channel_private_key(SilcClient client,
                                        SilcClientConnection conn,
                                        SilcChannelEntry channel,
                                        const char *name,
@@ -571,7 +576,7 @@ int silc_client_add_channel_private_key(SilcClient client,
    after calling this to protect the channel messages. Returns FALSE on
    on error, TRUE otherwise. */
 
-int silc_client_del_channel_private_keys(SilcClient client,
+bool silc_client_del_channel_private_keys(SilcClient client,
                                         SilcClientConnection conn,
                                         SilcChannelEntry channel)
 {
@@ -607,7 +612,7 @@ int silc_client_del_channel_private_keys(SilcClient client,
    old channel key is used hereafter to protect the channel messages. This
    returns FALSE on error, TRUE otherwise. */
 
-int silc_client_del_channel_private_key(SilcClient client,
+bool silc_client_del_channel_private_key(SilcClient client,
                                        SilcClientConnection conn,
                                        SilcChannelEntry channel,
                                        SilcChannelPrivateKey key)
index 195f5cdf0ec2c47249903c4d9fb03ff96a59d10d..098054804d5fc71d000d9155af996b02606cb7f5 100644 (file)
@@ -155,6 +155,9 @@ typedef void (*SilcClientResumeSessionCallback)(SilcClient client,
                                                bool success,
                                                void *context);
 
+/* Rekey must be performed at the lastest when this many packets is sent */
+#define SILC_CLIENT_REKEY_THRESHOLD 0xfffffe00
+
 /* Macros */
 
 /* Registers generic task for file descriptor for reading from network and
@@ -218,7 +221,7 @@ void silc_client_packet_send(SilcClient client,
                              unsigned char *data,
                              SilcUInt32 data_len,
                              bool force_send);
-int silc_client_packet_send_real(SilcClient client,
+bool silc_client_packet_send_real(SilcClient client,
                                 SilcSocketConnection sock,
                                 bool force_send);
 void silc_client_ftp_free_sessions(SilcClient client,
@@ -286,5 +289,6 @@ void silc_client_resume_session(SilcClient client,
 SilcBuffer silc_client_attributes_process(SilcClient client,
                                          SilcSocketConnection sock,
                                          SilcDList attrs);
+SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback);
 
 #endif
index dc7b14d467760966b4bdc2220005d4869970ec13..d447e0af24f2abd8c51888a549fd721b884c27df 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  client_prvmsg.c
+  client_prvmsg.c 
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2002 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.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -39,7 +38,7 @@ void silc_client_send_private_message(SilcClient client,
                                      SilcMessageFlags flags,
                                      unsigned char *data, 
                                      SilcUInt32 data_len, 
-                                     int force_send)
+                                     bool force_send)
 {
   SilcSocketConnection sock;
   SilcBuffer buffer;
@@ -57,6 +56,7 @@ void silc_client_send_private_message(SilcClient client,
   buffer = silc_private_message_payload_encode(flags,
                                               data_len, data,
                                               client_entry->send_key,
+                                              client_entry->hmac_send,
                                               client->rng);
 
   /* If we don't have private message specific key then private messages
@@ -93,9 +93,9 @@ void silc_client_send_private_message(SilcClient client,
                                 packetdata.dst_id_len);
   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
     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), block_len);
+  SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
+                     packetdata.src_id_len +
+                     packetdata.dst_id_len), block_len, packetdata.padlen);
 
   /* Create the outgoing packet */
   if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock, 
@@ -106,7 +106,7 @@ void silc_client_send_private_message(SilcClient client,
 
   /* Encrypt the header and padding of the packet. */
   silc_packet_encrypt(cipher, hmac, conn->internal->psn_send++,
-                     (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN + 
+                     (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN +
                      packetdata.src_id_len + packetdata.dst_id_len +
                      packetdata.padlen);
 
@@ -115,6 +115,13 @@ void silc_client_send_private_message(SilcClient client,
 
   /* Now actually send the packet */
   silc_client_packet_send_real(client, sock, force_send);
+
+  /* Check for mandatory rekey */
+  if (conn->internal->psn_send == SILC_CLIENT_REKEY_THRESHOLD)
+    silc_schedule_task_add(client->schedule, sock->sock,
+                          silc_client_rekey_callback, sock, 0, 1,
+                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+
   silc_free(packetdata.dst_id);
 
  out:
@@ -153,6 +160,7 @@ void silc_client_private_message(SilcClient client,
   unsigned char *message;
   SilcUInt32 message_len;
   SilcCipher cipher = NULL;
+  SilcHmac hmac = NULL;
 
   if (packet->src_id_type != SILC_ID_CLIENT)
     goto out;
@@ -182,14 +190,16 @@ void silc_client_private_message(SilcClient client,
   }
 
   cipher = remote_client->receive_key;
-  if (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY && !cipher) {
+  hmac = remote_client->hmac_receive;
+  if (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY && !cipher && !hmac) {
     silc_free(remote_id);
     return;
   }
 
   /* Parse the payload and decrypt it also if private message key is set */
   payload = silc_private_message_payload_parse(packet->buffer->data,
-                                              packet->buffer->len, cipher);
+                                              packet->buffer->len,
+                                              cipher, hmac);
   if (!payload) {
     silc_free(remote_id);
     return;
@@ -235,7 +245,7 @@ static void silc_client_private_message_key_cb(SilcClient client,
   SilcPacketContext *packet = (SilcPacketContext *)context;
   unsigned char *key;
   SilcUInt16 key_len;
-  unsigned char *cipher;
+  unsigned char *cipher = NULL, *hmac = NULL;
   int ret;
 
   if (!clients)
@@ -244,7 +254,8 @@ static void silc_client_private_message_key_cb(SilcClient client,
   /* Parse the private message key payload */
   ret = silc_buffer_unformat(packet->buffer,
                             SILC_STR_UI16_NSTRING(&key, &key_len),
-                            SILC_STR_UI16_STRING(&cipher),
+                            SILC_STR_UI16_STRING_ALLOC(&cipher),
+                            SILC_STR_UI16_STRING_ALLOC(&hmac),
                             SILC_STR_END);
   if (!ret)
     goto out;
@@ -254,7 +265,8 @@ 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, TRUE))
+                                          cipher, hmac, key, key_len,
+                                          FALSE, TRUE))
     goto out;
 
   /* Print some info for application */
@@ -269,6 +281,8 @@ static void silc_client_private_message_key_cb(SilcClient client,
                     clients[0]->username ? ")" : "");
 
  out:
+  silc_free(cipher);
+  silc_free(hmac);
   silc_packet_context_free(packet);
 }
 
@@ -301,9 +315,9 @@ void silc_client_private_message_key(SilcClient client,
    indicated by the `client_entry'. If the `key' is NULL and the boolean
    value `generate_key' is TRUE the library will generate random key.
    The `key' maybe for example pre-shared-key, passphrase or similar.
-   The `cipher' MAY be provided but SHOULD be NULL to assure that the
-   requirements of the SILC protocol are met. The API, however, allows
-   to allocate any cipher.
+   The `cipher' and `hmac' MAY be provided but SHOULD be NULL to assure
+   that the requirements of the SILC protocol are met. The API, however,
+   allows to allocate any cipher and HMAC.
 
    If `responder' is TRUE then the sending and receiving keys will be
    set according the client being the receiver of the private key.  If
@@ -317,14 +331,15 @@ void silc_client_private_message_key(SilcClient client,
    Returns FALSE if the key is already set for the `client_entry', TRUE
    otherwise. */
 
-int silc_client_add_private_message_key(SilcClient client,
-                                       SilcClientConnection conn,
-                                       SilcClientEntry client_entry,
-                                       char *cipher,
-                                       unsigned char *key,
-                                       SilcUInt32 key_len,
-                                       bool generate_key,
-                                       bool responder)
+bool silc_client_add_private_message_key(SilcClient client,
+                                        SilcClientConnection conn,
+                                        SilcClientEntry client_entry,
+                                        const char *cipher,
+                                        const char *hmac,
+                                        unsigned char *key,
+                                        SilcUInt32 key_len,
+                                        bool generate_key,
+                                        bool responder)
 {
   unsigned char private_key[32];
   SilcUInt32 len;
@@ -339,15 +354,20 @@ int silc_client_add_private_message_key(SilcClient client,
 
   if (!cipher)
     cipher = SILC_DEFAULT_CIPHER;
+  if (!hmac)
+    hmac = SILC_DEFAULT_HMAC;
 
-  /* Check the requested cipher */
+  /* Check the requested cipher and HMAC */
   if (!silc_cipher_is_supported(cipher))
     return FALSE;
+  if (!silc_hmac_is_supported(hmac))
+    return FALSE;
 
   /* Generate key if not provided */
   if (generate_key == TRUE) {
     len = 32;
-    for (i = 0; i < len; i++) private_key[i] = silc_rng_get_byte(client->rng);
+    for (i = 0; i < len; i++)
+      private_key[i] = silc_rng_get_byte_fast(client->rng);
     key = private_key;
     key_len = len;
     client_entry->generated = TRUE;
@@ -364,9 +384,11 @@ int silc_client_add_private_message_key(SilcClient client,
       != SILC_SKE_STATUS_OK)
     return FALSE;
 
-  /* Allocate the ciphers */
+  /* Allocate the cipher and HMAC */
   silc_cipher_alloc(cipher, &client_entry->send_key);
   silc_cipher_alloc(cipher, &client_entry->receive_key);
+  silc_hmac_alloc(hmac, NULL, &client_entry->hmac_send);
+  silc_hmac_alloc(hmac, NULL, &client_entry->hmac_receive);
 
   /* Set the keys */
   if (responder == TRUE) {
@@ -376,6 +398,10 @@ int silc_client_add_private_message_key(SilcClient client,
     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);
+    silc_hmac_set_key(client_entry->hmac_send, keymat->receive_hmac_key,
+                     keymat->hmac_key_len);
+    silc_hmac_set_key(client_entry->hmac_receive, keymat->send_hmac_key,
+                     keymat->hmac_key_len);
   } else {
     silc_cipher_set_key(client_entry->send_key, keymat->send_enc_key,
                        keymat->enc_key_len);
@@ -383,6 +409,10 @@ int silc_client_add_private_message_key(SilcClient client,
     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);
+    silc_hmac_set_key(client_entry->hmac_send, keymat->send_hmac_key,
+                     keymat->hmac_key_len);
+    silc_hmac_set_key(client_entry->hmac_receive, keymat->receive_hmac_key,
+                     keymat->hmac_key_len);
   }
 
   /* Free the key material */
@@ -394,15 +424,16 @@ int silc_client_add_private_message_key(SilcClient client,
 /* 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. */
-
-int silc_client_add_private_message_key_ske(SilcClient client,
-                                           SilcClientConnection conn,
-                                           SilcClientEntry client_entry,
-                                           char *cipher,
-                                           SilcSKEKeyMaterial *key,
-                                           bool responder)
+   `cipher' and `hmac' SHOULD be provided as it is negotiated also in
+   the SKE protocol. */
+
+bool silc_client_add_private_message_key_ske(SilcClient client,
+                                            SilcClientConnection conn,
+                                            SilcClientEntry client_entry,
+                                            const char *cipher,
+                                            const char *hmac,
+                                            SilcSKEKeyMaterial *key,
+                                            bool responder)
 {
   assert(client && client_entry);
 
@@ -412,14 +443,20 @@ int silc_client_add_private_message_key_ske(SilcClient client,
 
   if (!cipher)
     cipher = SILC_DEFAULT_CIPHER;
+  if (!hmac)
+    hmac = SILC_DEFAULT_HMAC;
 
-  /* Check the requested cipher */
+  /* Check the requested cipher and HMAC */
   if (!silc_cipher_is_supported(cipher))
     return FALSE;
+  if (!silc_hmac_is_supported(hmac))
+    return FALSE;
 
-  /* Allocate the ciphers */
+  /* Allocate the cipher and HMAC */
   silc_cipher_alloc(cipher, &client_entry->send_key);
   silc_cipher_alloc(cipher, &client_entry->receive_key);
+  silc_hmac_alloc(hmac, NULL, &client_entry->hmac_send);
+  silc_hmac_alloc(hmac, NULL, &client_entry->hmac_receive);
 
   /* Set the keys */
   if (responder == TRUE) {
@@ -429,6 +466,10 @@ int silc_client_add_private_message_key_ske(SilcClient client,
     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);
+    silc_hmac_set_key(client_entry->hmac_send, key->receive_hmac_key,
+                     key->hmac_key_len);
+    silc_hmac_set_key(client_entry->hmac_receive, key->send_hmac_key,
+                     key->hmac_key_len);
   } else {
     silc_cipher_set_key(client_entry->send_key, key->send_enc_key,
                        key->enc_key_len);
@@ -436,6 +477,10 @@ int silc_client_add_private_message_key_ske(SilcClient client,
     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);
+    silc_hmac_set_key(client_entry->hmac_send, key->send_hmac_key,
+                     key->hmac_key_len);
+    silc_hmac_set_key(client_entry->hmac_receive, key->receive_hmac_key,
+                     key->hmac_key_len);
   }
 
   return TRUE;
@@ -451,15 +496,15 @@ int silc_client_add_private_message_key_ske(SilcClient client,
    through the SILC network. The packet is protected using normal session
    keys. */
 
-int silc_client_send_private_message_key(SilcClient client,
+bool silc_client_send_private_message_key(SilcClient client,
                                         SilcClientConnection conn,
                                         SilcClientEntry client_entry,
-                                        int force_send)
+                                        bool force_send)
 {
   SilcSocketConnection sock;
   SilcBuffer buffer;
-  int cipher_len;
-  const char *cipher;
+  int cipher_len, hmac_len;
+  const char *cipher, *hmac;
 
   assert(client && conn && client_entry);
 
@@ -471,6 +516,8 @@ int silc_client_send_private_message_key(SilcClient client,
 
   cipher = silc_cipher_get_name(client_entry->send_key);
   cipher_len = strlen(cipher);
+  hmac = silc_hmac_get_name(client_entry->hmac_send);
+  hmac_len = strlen(hmac);
 
   /* Create private message key payload */
   buffer = silc_buffer_alloc(2 + client_entry->key_len);
@@ -482,6 +529,9 @@ int silc_client_send_private_message_key(SilcClient client,
                     SILC_STR_UI_SHORT(cipher_len),
                     SILC_STR_UI_XNSTRING(cipher,
                                          cipher_len),
+                    SILC_STR_UI_SHORT(hmac_len),
+                    SILC_STR_UI_XNSTRING(hmac,
+                                         hmac_len),
                     SILC_STR_END);
 
   /* Send the packet */
@@ -497,7 +547,7 @@ int silc_client_send_private_message_key(SilcClient client,
    after this to protect the private messages with the remote `client_entry'
    client. Returns FALSE on error, TRUE otherwise. */
 
-int silc_client_del_private_message_key(SilcClient client,
+bool silc_client_del_private_message_key(SilcClient client,
                                        SilcClientConnection conn,
                                        SilcClientEntry client_entry)
 {
index 66e51786d1fce744d30d5e97cb74cb58d01046a3..f765408cdf946fb38d26cb1b9ec41ae116af91c1 100644 (file)
@@ -845,9 +845,9 @@ SILC_CLIENT_CMD_FUNC(kill)
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClient client = cmd->client;
   SilcClientConnection conn = cmd->conn;
-  SilcBuffer buffer, idp;
+  SilcBuffer buffer, idp, auth = NULL;
   SilcClientEntry target;
-  char *nickname = NULL;
+  char *nickname = NULL, *comment = NULL;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -857,7 +857,7 @@ SILC_CLIENT_CMD_FUNC(kill)
 
   if (cmd->argc < 2) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, 
-       "Usage: /KILL <nickname> [<comment>]");
+       "Usage: /KILL <nickname> [<comment>] [-pubkey]");
     COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
     goto out;
   }
@@ -887,22 +887,35 @@ SILC_CLIENT_CMD_FUNC(kill)
     goto out;
   }
 
+  if (cmd->argc >= 3) {
+    if (strcasecmp(cmd->argv[2], "-pubkey"))
+      comment = cmd->argv[2];
+
+    if (!strcasecmp(cmd->argv[2], "-pubkey") ||
+       (cmd->argc >= 4 && !strcasecmp(cmd->argv[3], "-pubkey"))) {
+      /* Encode the public key authentication payload */
+      auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
+                                               cmd->client->private_key,
+                                               cmd->client->rng,
+                                               client->sha1hash,
+                                               target->id, SILC_ID_CLIENT);
+    }
+  }
+
   /* Send the KILL command to the server */
   idp = silc_id_payload_encode(target->id, SILC_ID_CLIENT);
-  if (cmd->argc == 2)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 
-                                           ++conn->cmd_ident, 1, 
-                                           1, idp->data, idp->len);
-  else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 
-                                           ++conn->cmd_ident, 2, 
-                                           1, idp->data, idp->len,
-                                           2, cmd->argv[2], 
-                                           strlen(cmd->argv[2]));
+  buffer =
+    silc_command_payload_encode_va(SILC_COMMAND_KILL, 
+                                  ++conn->cmd_ident, 3, 
+                                  1, idp->data, idp->len,
+                                  2, comment, comment ? strlen(comment) : 0,
+                                  3, auth ? auth->data : NULL,
+                                  auth ? auth->len : 0);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
   silc_buffer_free(buffer);
   silc_buffer_free(idp);
+  silc_buffer_free(auth);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -996,7 +1009,7 @@ SILC_CLIENT_CMD_FUNC(ping)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
-  SilcBuffer buffer;
+  SilcBuffer buffer, idp;
   void *id;
   int i;
 
@@ -1006,14 +1019,15 @@ SILC_CLIENT_CMD_FUNC(ping)
     goto out;
   }
 
+  idp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER); 
+
   /* Send the command */
   buffer = silc_command_payload_encode_va(SILC_COMMAND_PING, 0, 1, 
-                                         1, conn->remote_id_data, 
-                                         silc_id_get_len(conn->remote_id,
-                                                         SILC_ID_SERVER));
+                                         1, idp->data, idp->len);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, 
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
   silc_buffer_free(buffer);
+  silc_buffer_free(idp);
 
   id = silc_id_str2id(conn->remote_id_data, conn->remote_id_data_len,
                      SILC_ID_SERVER);
@@ -2548,7 +2562,7 @@ void silc_client_commands_register(SilcClient client)
   SILC_CLIENT_CMD(topic, TOPIC, "TOPIC", 3);
   SILC_CLIENT_CMD(invite, INVITE, "INVITE", 3);
   SILC_CLIENT_CMD(quit, QUIT, "QUIT", 2);
-  SILC_CLIENT_CMD(kill, KILL, "KILL", 3);
+  SILC_CLIENT_CMD(kill, KILL, "KILL", 4);
   SILC_CLIENT_CMD(info, INFO, "INFO", 2);
   SILC_CLIENT_CMD(stats, STATS, "STATS", 0);
   SILC_CLIENT_CMD(ping, PING, "PING", 2);
index e1c03f38870fb3c4032c763fb2e32308f81295b2..67d8f666790a46fb943df753ca549dd93547fe04 100644 (file)
@@ -1770,10 +1770,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
   SilcClientEntry client_entry;
   SilcServerID *server_id = NULL;
   SilcServerEntry server_entry;
-  SilcSKEPKType type;
-  unsigned char *tmp, *pk;
+  unsigned char *tmp;
   SilcUInt32 len;
-  SilcUInt16 pk_len;
   SilcIdType id_type;
   SilcPublicKey public_key = NULL;
 
@@ -1800,15 +1798,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
   /* Get the public key payload */
   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
   if (tmp) {
-    /* Decode the public key */
-    SILC_GET16_MSB(pk_len, tmp);
-    SILC_GET16_MSB(type, tmp + 2);
-    pk = tmp + 4;
-    
-    if (type == SILC_SKE_PK_TYPE_SILC)
-      if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
-       public_key = NULL;
-  } 
+    if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
+      public_key = NULL;
+  }
    
   id_type = silc_id_payload_get_type(idp);
   if (id_type == SILC_ID_CLIENT) {
index 156cdf1dc8698be8e5e3a3376db8d95d07476cfd..62a788a3d1df13dbc2bd609ceff46ad8b98278d2 100644 (file)
@@ -215,7 +215,9 @@ struct SilcClientEntryStruct {
   /* Private message keys */
   SilcCipher send_key;         /* Private message key for sending */
   SilcCipher receive_key;      /* Private message key for receiving */
-  unsigned char *key;          /* Set only if appliation provided the
+  SilcHmac hmac_send;          /* Private mesage key HMAC for sending */
+  SilcHmac hmac_receive;       /* Private mesage key HMAC for receiving */
+  unsigned char *key;          /* Set only if application provided the
                                   key material. NULL if the library 
                                   generated the key. */
   SilcUInt32 key_len;          /* Key length */
@@ -853,7 +855,7 @@ void silc_client_free(SilcClient client);
  *
  * SYNOPSIS
  *
- *    int silc_client_init(SilcClient client);
+ *    bool silc_client_init(SilcClient client);
  *
  * DESCRIPTION
  *
@@ -862,7 +864,7 @@ void silc_client_free(SilcClient client);
  *    client. Returns FALSE if error occurred, TRUE otherwise.
  *
  ***/
-int silc_client_init(SilcClient client);
+bool silc_client_init(SilcClient client);
 
 /****f* silcclient/SilcClientAPI/silc_client_run
  *
@@ -952,7 +954,7 @@ typedef struct {
  *
  * SYNOPSIS
  *
- *    int silc_client_connect_to_server(SilcClient client, 
+ *    bool silc_client_connect_to_server(SilcClient client, 
  *                                      SilcClientConnectionParams *params,
  *                                      int port, char *host, void *context);
  *
@@ -969,9 +971,9 @@ typedef struct {
  *    If the `params' is provided they are used by the routine.
  *
  ***/
-int silc_client_connect_to_server(SilcClient client, 
-                                 SilcClientConnectionParams *params,
-                                 int port, char *host, void *context);
+bool silc_client_connect_to_server(SilcClient client, 
+                                  SilcClientConnectionParams *params,
+                                  int port, char *host, void *context);
 
 /****f* silcclient/SilcClientAPI/silc_client_add_connection
  *
@@ -1107,7 +1109,7 @@ void silc_client_close_connection(SilcClient client,
  *                                          SilcMessageFlags flags,
  *                                          unsigned char *data, 
  *                                          SilcUInt32 data_len, 
- *                                          int force_send);
+ *                                          bool_force_send);
  *
  * DESCRIPTION
  *
@@ -1132,7 +1134,7 @@ void silc_client_send_channel_message(SilcClient client,
                                      SilcMessageFlags flags,
                                      unsigned char *data, 
                                      SilcUInt32 data_len, 
-                                     int force_send);
+                                     bool force_send);
 
 /****f* silcclient/SilcClientAPI/silc_client_send_private_message
  *
@@ -1144,7 +1146,7 @@ void silc_client_send_channel_message(SilcClient client,
  *                                          SilcMessageFlags flags,
  *                                          unsigned char *data, 
  *                                          SilcUInt32 data_len, 
- *                                          int force_send);
+ *                                          bool force_send);
  *
  * DESCRIPTION
  *
@@ -1163,7 +1165,7 @@ void silc_client_send_private_message(SilcClient client,
                                      SilcMessageFlags flags,
                                      unsigned char *data, 
                                      SilcUInt32 data_len, 
-                                     int force_send);
+                                     bool force_send);
 
 
 /* Client and Channel entry retrieval (idlist.c) */
@@ -1533,7 +1535,7 @@ SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
  *
  * SYNOPSIS
  *
- *    void silc_client_command_call(SilcClient client,
+ *    bool silc_client_command_call(SilcClient client,
  *                                  SilcClientConnection conn,
  *                                  const char *command_line, ...);
  *
@@ -1664,14 +1666,15 @@ void silc_client_command_pending(SilcClientConnection conn,
  *
  * SYNOPSIS
  *
- *    int silc_client_add_private_message_key(SilcClient client,
- *                                            SilcClientConnection conn,
- *                                            SilcClientEntry client_entry,
- *                                            char *cipher,
- *                                            unsigned char *key,
- *                                            SilcUInt32 key_len,
- *                                            bool generate_key,
- *                                            bool responder);
+ *    bool silc_client_add_private_message_key(SilcClient client,
+ *                                             SilcClientConnection conn,
+ *                                             SilcClientEntry client_entry,
+ *                                             const char *cipher,
+ *                                             const char *hmac,
+ *                                             unsigned char *key,
+ *                                             SilcUInt32 key_len,
+ *                                             bool generate_key,
+ *                                             bool responder);
  *
  * DESCRIPTION
  *
@@ -1680,9 +1683,9 @@ void silc_client_command_pending(SilcClientConnection conn,
  *    indicated by the `client_entry'. If the `key' is NULL and the boolean
  *    value `generate_key' is TRUE the library will generate random key.
  *    The `key' maybe for example pre-shared-key, passphrase or similar.
- *    The `cipher' MAY be provided but SHOULD be NULL to assure that the
- *    requirements of the SILC protocol are met. The API, however, allows
- *    to allocate any cipher.
+ *    The `cipher' and `hmac' MAY be provided but SHOULD be NULL to assure
+ *    that the requirements of the SILC protocol are met. The API, however,
+ *    allows to allocate any cipher and HMAC.
  *
  *    If `responder' is TRUE then the sending and receiving keys will be
  *    set according the client being the receiver of the private key.  If
@@ -1697,48 +1700,52 @@ void silc_client_command_pending(SilcClientConnection conn,
  *    otherwise. 
  *
  ***/
-int silc_client_add_private_message_key(SilcClient client,
-                                       SilcClientConnection conn,
-                                       SilcClientEntry client_entry,
-                                       char *cipher,
-                                       unsigned char *key,
-                                       SilcUInt32 key_len,
-                                       bool generate_key,
-                                       bool responder);
+bool silc_client_add_private_message_key(SilcClient client,
+                                        SilcClientConnection conn,
+                                        SilcClientEntry client_entry,
+                                        const char *cipher,
+                                        const char *hmac,
+                                        unsigned char *key,
+                                        SilcUInt32 key_len,
+                                        bool generate_key,
+                                        bool responder);
 
 /****f* silcclient/SilcClientAPI/silc_client_add_private_message_key_ske
  *
  * SYNOPSIS
  *
- *    int silc_client_add_private_message_key_ske(SilcClient client,
- *                                                SilcClientConnection conn,
- *                                                SilcClientEntry client_entry,
- *                                                char *cipher,
- *                                                SilcSKEKeyMaterial *key);
+ *    bool
+ *    silc_client_add_private_message_key_ske(SilcClient client,
+ *                                            SilcClientConnection conn,
+ *                                            SilcClientEntry client_entry,
+ *                                            const char *cipher,
+ *                                            const char *hmac,
+ *                                            SilcSKEKeyMaterial *key);
  *
  * DESCRIPTION
  *
  *    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. 
+ *    the key material. The `cipher' and `hmac' 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,
-                                           bool responder);
+bool silc_client_add_private_message_key_ske(SilcClient client,
+                                            SilcClientConnection conn,
+                                            SilcClientEntry client_entry,
+                                            const char *cipher,
+                                            const char *hmac,
+                                            SilcSKEKeyMaterial *key,
+                                            bool responder);
 
 /****f* silcclient/SilcClientAPI/silc_client_del_private_message_key
  *
  * SYNOPSIS
  *
- *    int silc_client_del_private_message_key(SilcClient client,
- *                                            SilcClientConnection conn,
- *                                            SilcClientEntry client_entry);
+ *    bool silc_client_del_private_message_key(SilcClient client,
+ *                                             SilcClientConnection conn,
+ *                                             SilcClientEntry client_entry);
  *
  * DESCRIPTION
  *
@@ -1747,9 +1754,9 @@ int silc_client_add_private_message_key_ske(SilcClient client,
  *    client. Returns FALSE on error, TRUE otherwise. 
  *
  ***/
-int silc_client_del_private_message_key(SilcClient client,
-                                       SilcClientConnection conn,
-                                       SilcClientEntry client_entry);
+bool silc_client_del_private_message_key(SilcClient client,
+                                        SilcClientConnection conn,
+                                        SilcClientEntry client_entry);
 
 /****f* silcclient/SilcClientAPI/silc_client_list_private_message_keys
  *
@@ -1800,14 +1807,14 @@ void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
  *
  * SYNOPSIS
  *
- *    int silc_client_add_channel_private_key(SilcClient client,
- *                                            SilcClientConnection conn,
- *                                            SilcChannelEntry channel,
- *                                            const char *name,
- *                                            char *cipher,
- *                                            char *hmac,
- *                                            unsigned char *key,
- *                                            SilcUInt32 key_len);
+ *    bool silc_client_add_channel_private_key(SilcClient client,
+ *                                             SilcClientConnection conn,
+ *                                             SilcChannelEntry channel,
+ *                                             const char *name,
+ *                                             char *cipher,
+ *                                             char *hmac,
+ *                                             unsigned char *key,
+ *                                             SilcUInt32 key_len);
  * 
  * DESCRIPTION
  *
@@ -1841,22 +1848,22 @@ void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
  *    as channel private key. However, this API allows it. 
  *
  ***/
-int silc_client_add_channel_private_key(SilcClient client,
-                                       SilcClientConnection conn,
-                                       SilcChannelEntry channel,
-                                       const char *name,
-                                       char *cipher,
-                                       char *hmac,
-                                       unsigned char *key,
-                                       SilcUInt32 key_len);
+bool silc_client_add_channel_private_key(SilcClient client,
+                                        SilcClientConnection conn,
+                                        SilcChannelEntry channel,
+                                        const char *name,
+                                        char *cipher,
+                                        char *hmac,
+                                        unsigned char *key,
+                                        SilcUInt32 key_len);
 
 /****f* silcclient/SilcClientAPI/silc_client_del_channel_private_keys
  *
  * SYNOPSIS
  *
- *    int silc_client_del_channel_private_keys(SilcClient client,
- *                                             SilcClientConnection conn,
- *                                             SilcChannelEntry channel);
+ *    bool silc_client_del_channel_private_keys(SilcClient client,
+ *                                              SilcClientConnection conn,
+ *                                              SilcChannelEntry channel);
  * 
  * DESCRIPTION
  *
@@ -1865,15 +1872,15 @@ int silc_client_add_channel_private_key(SilcClient client,
  *    on error, TRUE otherwise. 
  *
  ***/
-int silc_client_del_channel_private_keys(SilcClient client,
-                                        SilcClientConnection conn,
-                                        SilcChannelEntry channel);
+bool silc_client_del_channel_private_keys(SilcClient client,
+                                         SilcClientConnection conn,
+                                         SilcChannelEntry channel);
 
 /****f* silcclient/SilcClientAPI/silc_client_del_channel_private_key
  *
  * SYNOPSIS
  *
- *    int silc_client_del_channel_private_key(SilcClient client,
+ *    bool silc_client_del_channel_private_key(SilcClient client,
  *                                            SilcClientConnection conn,
  *                                            SilcChannelEntry channel,
  *                                            SilcChannelPrivateKey key);
@@ -1888,10 +1895,10 @@ int silc_client_del_channel_private_keys(SilcClient client,
  *    on error, TRUE otherwise. 
  *
  ***/
-int silc_client_del_channel_private_key(SilcClient client,
-                                       SilcClientConnection conn,
-                                       SilcChannelEntry channel,
-                                       SilcChannelPrivateKey key);
+bool silc_client_del_channel_private_key(SilcClient client,
+                                        SilcClientConnection conn,
+                                        SilcChannelEntry channel,
+                                        SilcChannelPrivateKey key);
 
 /****f* silcclient/SilcClientAPI/silc_client_list_channel_private_keys
  *
index 2b69f80b3ad5b295a9189b64d9b9c45bf3965b51..58ddbed9be2bb01c42da45073145edfe8adff7bb 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2002 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
index bb38c75fd29a1431354262e43cce51ae2508d2c2..305b690287291a5f8fb654a3c9ae482cbeea6840 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2002 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
index 067d8c6724923a59bd6c622128255d3bc4f822bd..fee2c3959b0d19c82565ebdf023ba625bc485265 100644 (file)
@@ -70,18 +70,23 @@ silc_attribute_payload_encode_int(SilcAttribute attribute,
     case SILC_ATTRIBUTE_SERVICE:
       {
        SilcAttributeObjService *service = object;
+       int len2;
        if (object_size != sizeof(*service))
          return NULL;
        len = strlen(service->address);
-       str = silc_malloc(7 + len);
-       if (!str)
-         return NULL;
-       SILC_PUT32_MSB(service->port, str);
-       SILC_PUT16_MSB(len, str + 4);
-       memcpy(str + 6, service->address, len);
-       str[6 + len] = service->status;
-       object = str;
-       object_size = 7 + len;
+       len2 = strlen(service->signon);
+       tmpbuf = silc_buffer_alloc_size(13 + len + len2);
+       silc_buffer_format(tmpbuf,
+                          SILC_STR_UI_INT(service->port),
+                          SILC_STR_UI_SHORT(len),
+                          SILC_STR_UI_XNSTRING(service->address, len),
+                          SILC_STR_UI_CHAR(service->status),
+                          SILC_STR_UI_SHORT(len2),
+                          SILC_STR_UI_XNSTRING(service->signon, len2),
+                          SILC_STR_UI_INT(service->idle),
+                          SILC_STR_END);
+       object = tmpbuf->data;
+       object_size = tmpbuf->len;
       }
       break;
 
@@ -481,18 +486,32 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
   case SILC_ATTRIBUTE_SERVICE:
     {
       SilcAttributeObjService *service = object;
+      SilcBufferStruct buf;
+      SilcUInt16 addr_len, signon_len;
+      char *addr, *signon;
+      int res;
       if (object_size != sizeof(*service))
        break;
-      if (payload->data_len < 7)
+      if (payload->data_len < 13)
        break;
-      SILC_GET32_MSB(service->port, payload->data);
-      SILC_GET16_MSB(len, payload->data + 4);
-      if (payload->data_len < 7 + len)
+      silc_buffer_set(&buf, payload->data, payload->data_len);
+      res = silc_buffer_unformat(&buf,
+                                SILC_STR_UI_INT(&service->port),
+                                SILC_STR_UI16_NSTRING(&addr, &addr_len),
+                                SILC_STR_UI_CHAR(&service->status),
+                                SILC_STR_UI16_NSTRING(&signon, &signon_len),
+                                SILC_STR_UI_INT(&service->idle),
+                                SILC_STR_END);
+      if (res == -1)
        break;
-      memcpy(service->address, payload->data + 6,
-            (len < sizeof(service->address) - 1 ? len :
+      memset(service->address, 0, sizeof(service->address));
+      memset(service->signon, 0, sizeof(service->signon));
+      memcpy(service->address, addr,
+            (addr_len < sizeof(service->address) - 1 ? addr_len :
              sizeof(service->address) - 1));
-      service->status = payload->data[6 + len] ? TRUE : FALSE;
+      memcpy(service->signon, signon,
+            (signon_len < sizeof(service->signon) - 1 ? signon_len :
+             sizeof(service->signon) - 1));
       ret = TRUE;
     }
     break;
index b9097bc6b273832107d09ae531e2f934c2f14a98..afcc019405b55bd3dac9492718a921c380ad1ed4 100644 (file)
@@ -390,6 +390,8 @@ unsigned char *silc_attribute_get_verify_data(SilcDList attrs,
  */
 typedef struct {
   SilcUInt32 port;             /* IANA specified service port */
+  SilcUInt32 idle;             /* Idle time in the service */
+  char signon[64];             /* Signon date and time (UTC) */
   char address[256];           /* service address */
   bool status;                 /* online status (TRUE present in service) */
 } SilcAttributeObjService;
index aea21a993f34f62a777a06815a3f78e2e1d4ad1b..c93f02df1e2b0213a4dce16c2b90a79441cfc373 100644 (file)
@@ -1,6 +1,6 @@
 /*
 
-  silcauth.c
+  silcauth.c 
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
@@ -8,8 +8,7 @@
 
   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.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,6 +20,8 @@
 
 #include "silcincludes.h"
 #include "silcauth.h"
+#include "silcchannel_i.h"
+#include "silcprivate_i.h"
 
 /******************************************************************************
 
@@ -224,6 +225,7 @@ silc_auth_public_key_encode_data(SilcPublicKey public_key,
   if (ret_len)
     *ret_len = buf->len;
 
+  silc_buffer_clear(buf);
   silc_buffer_free(buf);
   silc_free(id_data);
   silc_free(pk);
@@ -265,7 +267,7 @@ SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key,
     return NULL;
 
   /* Allocate PKCS object */
-  if (!silc_pkcs_alloc(public_key->name, &pkcs)) {
+  if (!silc_pkcs_alloc(private_key->name, &pkcs)) {
     memset(tmp, 0, tmp_len);
     silc_free(tmp);
     return NULL;
@@ -538,3 +540,319 @@ SilcUInt32 silc_key_agreement_get_port(SilcKeyAgreementPayload payload)
 {
   return payload->port;
 }
+
+/******************************************************************************
+
+                     SILC_MESSAGE_FLAG_SIGNED Payload
+
+******************************************************************************/
+
+/* The SILC_MESSAGE_FLAG_SIGNED Payload */
+struct SilcSignedPayloadStruct {
+  SilcUInt16 pk_len;
+  SilcUInt16 pk_type;
+  SilcUInt16 sign_len;
+  unsigned char *pk_data;
+  unsigned char *sign_data;
+};
+
+/* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
+
+static SilcBuffer
+silc_signed_payload_encode_data(const unsigned char *message_payload,
+                               SilcUInt32 message_payload_len,
+                               unsigned char *pk,
+                               SilcUInt32 pk_len, SilcUInt32 pk_type)
+{
+  SilcBuffer sign;
+
+  sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
+  if (!sign)
+    return NULL;
+
+  silc_buffer_format(sign,
+                    SILC_STR_UI_XNSTRING(message_payload,
+                                         message_payload_len),
+                    SILC_STR_UI_SHORT(pk_len),
+                    SILC_STR_UI_SHORT(pk_type),
+                    SILC_STR_END);
+
+  if (pk && pk_len) {
+    silc_buffer_pull(sign, message_payload_len + 4);
+    silc_buffer_format(sign,
+                      SILC_STR_UI_XNSTRING(pk, pk_len),
+                      SILC_STR_END);
+    silc_buffer_push(sign, message_payload_len + 4);
+  }
+
+  return sign;
+}
+
+/* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
+
+SilcSignedPayload silc_signed_payload_parse(const unsigned char *data,
+                                           SilcUInt32 data_len)
+{
+  SilcSignedPayload sig;
+  SilcBufferStruct buffer;
+  int ret;
+
+  SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
+
+  silc_buffer_set(&buffer, (unsigned char *)data, data_len);
+  sig = silc_calloc(1, sizeof(*sig));
+  if (!sig)
+    return NULL;
+
+  /* Parse the payload */
+  ret = silc_buffer_unformat(&buffer,
+                            SILC_STR_UI_SHORT(&sig->pk_len),
+                            SILC_STR_UI_SHORT(&sig->pk_type),
+                            SILC_STR_END);
+  if (ret == -1 || sig->pk_len > data_len - 4) {
+    silc_signed_payload_free(sig);
+    return NULL;
+  }
+
+  silc_buffer_pull(&buffer, 4);
+  ret = silc_buffer_unformat(&buffer,
+                            SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
+                                                       sig->pk_len),
+                            SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
+                                                        &sig->sign_len),
+                            SILC_STR_END);
+  if (ret == -1) {
+    silc_signed_payload_free(sig);
+    return NULL;
+  }
+  silc_buffer_push(&buffer, 4);
+
+  /* Signature must be provided */
+  if (sig->sign_len < 1)  {
+    silc_signed_payload_free(sig);
+    return NULL;
+  }
+
+  return sig;
+}
+
+/* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
+   signature. */
+
+SilcBuffer silc_signed_payload_encode(const unsigned char *message_payload,
+                                     SilcUInt32 message_payload_len,
+                                     SilcPublicKey public_key,
+                                     SilcPrivateKey private_key,
+                                     SilcHash hash,
+                                     bool include_public_key)
+{
+  SilcBuffer buffer, sign;
+  SilcPKCS pkcs;
+  unsigned char auth_data[2048];
+  SilcUInt32 auth_len;
+  unsigned char *pk = NULL;
+  SilcUInt32 pk_len = 0;
+  SilcUInt16 pk_type;
+
+  if (!message_payload || !message_payload_len || !private_key || !hash)
+    return NULL;
+  if (include_public_key && !public_key)
+    return NULL;
+
+  if (include_public_key)
+    pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+
+  /* Now we support only SILC style public key */
+  pk_type = SILC_SKE_PK_TYPE_SILC;
+
+  /* Encode the data to be signed */
+  sign = silc_signed_payload_encode_data(message_payload,
+                                        message_payload_len,
+                                        pk, pk_len, pk_type);
+  if (!sign) {
+    silc_free(pk);
+    return NULL;
+  }
+
+  /* Sign the buffer */
+
+  /* Allocate PKCS object */
+  if (!silc_pkcs_alloc(private_key->name, &pkcs)) {
+    silc_buffer_clear(sign);
+    silc_buffer_free(sign);
+    silc_free(pk);
+    return NULL;
+  }
+  silc_pkcs_private_key_set(pkcs, private_key);
+
+  /* Compute the hash and the signature. */
+  if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
+      !silc_pkcs_sign_with_hash(pkcs, hash, sign->data, sign->len, auth_data,
+                               &auth_len)) {
+    silc_buffer_clear(sign);
+    silc_buffer_free(sign);
+    silc_pkcs_free(pkcs);
+    silc_free(pk);
+    return NULL;
+  }
+
+  /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
+
+  buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
+  if (!buffer) {
+    silc_buffer_clear(sign);
+    silc_buffer_free(sign);
+    silc_pkcs_free(pkcs);
+    memset(auth_data, 0, sizeof(auth_data));
+    silc_free(pk);
+    return NULL;
+  }
+
+  silc_buffer_format(sign,
+                    SILC_STR_UI_SHORT(pk_len),
+                    SILC_STR_UI_SHORT(pk_type),
+                    SILC_STR_END);
+
+  if (pk_len && pk) {
+    silc_buffer_pull(sign, 4);
+    silc_buffer_format(sign,
+                      SILC_STR_UI_XNSTRING(pk, pk_len),
+                      SILC_STR_END);
+    silc_buffer_push(sign, 4);
+  }
+
+  silc_buffer_pull(sign, 4 + pk_len);
+  silc_buffer_format(sign,
+                    SILC_STR_UI_SHORT(auth_len),
+                    SILC_STR_UI_XNSTRING(auth_data, auth_len),
+                    SILC_STR_END);
+  silc_buffer_push(sign, 4 + pk_len);
+
+  memset(auth_data, 0, sizeof(auth_data));
+  silc_pkcs_free(pkcs);
+  silc_buffer_clear(sign);
+  silc_buffer_free(sign);
+  silc_free(pk);
+
+  return buffer;
+}
+
+/* Free the payload */
+
+void silc_signed_payload_free(SilcSignedPayload sig)
+{
+  if (sig) {
+    memset(sig->sign_data, 0, sig->sign_len);
+    silc_free(sig->sign_data);
+    silc_free(sig->pk_data);
+    silc_free(sig);
+  }
+}
+
+/* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
+
+int silc_signed_payload_verify(SilcSignedPayload sig,
+                              bool channel_message,
+                              void *message_payload,
+                              SilcPublicKey remote_public_key,
+                              SilcHash hash)
+{
+  int ret = SILC_AUTH_FAILED;
+#if 0
+  SilcBuffer sign;
+  SilcPKCS pkcs;
+  
+  if (!sig || !remote_public_key || !hash)
+    return ret;
+
+  /* Generate the signature verification data */
+  if (channel_message) {
+    SilcChannelMessagePayload chm =
+      (SilcChannelMessagePayload)message_payload;
+    SilcBuffer tmp;
+
+    /* Encode Channel Message Payload */
+    tmp = silc_buffer_alloc_size(6 + chm->data_len + chm->pad_len +
+                                chm->iv_len);
+    silc_buffer_format(tmp,
+                      SILC_STR_UI_SHORT(chm->flags),
+                      SILC_STR_UI_SHORT(chm->data_len),
+                      SILC_STR_UI_XNSTRING(chm->data, chm->data_len),
+                      SILC_STR_UI_SHORT(chm->pad_len),
+                      SILC_STR_UI_XNSTRING(chm->pad, chm->pad_len),
+                      SILC_STR_UI_XNSTRING(chm->iv, chm->iv_len),
+                      SILC_STR_END);
+
+    sign = silc_signed_payload_encode_data(tmp->data, tmp->len,
+                                          sig->pk_data, sig->pk_len,
+                                          sig->pk_type);
+    silc_buffer_clear(tmp);
+    silc_buffer_free(tmp);
+  } else {
+    SilcPrivateMessagePayload prm =
+      (SilcPrivateMessagePayload)message_payload;
+    SilcBuffer tmp;
+
+    /* Encode Private Message Payload */
+    tmp = silc_buffer_alloc_size(4 + prm->data_len +
+                                SILC_PRIVATE_MESSAGE_PAD(4 + prm->data_len));
+    silc_buffer_format(tmp,
+                      SILC_STR_UI_SHORT(prm->flags),
+                      SILC_STR_UI_SHORT(prm->message_len),
+                      SILC_STR_UI_XNSTRING(prm->message, prm->message_len),
+                      SILC_STR_END);
+
+    sign = silc_signed_payload_encode_data(tmp->data, tmp->len,
+                                          sig->pk_data, sig->pk_len,
+                                          sig->pk_type);
+    silc_buffer_clear(tmp);
+    silc_buffer_free(tmp);
+  }
+
+  if (!sign)
+    return ret;
+  
+  /* Allocate PKCS object */
+  if (!silc_pkcs_alloc(remote_public_key->name, &pkcs)) {
+    silc_buffer_clear(sign);
+    silc_buffer_free(sign);
+    return ret;
+  }
+  silc_pkcs_public_key_set(pkcs, remote_public_key);
+
+  /* Verify the authentication data */
+  if (!silc_pkcs_verify_with_hash(pkcs, hash, payload->sign_data
+                                 payload->sign_len,
+                                 sign->data, sign->len)) {
+
+    silc_buffer_clear(sign);
+    silc_buffer_free(sign);
+    silc_pkcs_free(pkcs);
+    SILC_LOG_DEBUG(("Signature verification failed"));
+    return ret;
+  }
+
+  ret = SILC_AUTH_OK;
+
+  silc_buffer_clear(sign);
+  silc_buffer_free(sign);
+  silc_pkcs_free(pkcs);
+
+  SILC_LOG_DEBUG(("Signature verification successful"));
+
+#endif
+  return ret;
+}
+
+/* Return the public key from the payload */
+
+SilcPublicKey silc_signed_payload_get_public_key(SilcSignedPayload sig)
+{
+  SilcPublicKey pk;
+
+  if (!sig->pk_data || !silc_pkcs_public_key_decode(sig->pk_data,
+                                                   sig->pk_len, &pk))
+    return NULL;
+
+  return pk;
+}
index f66621324107bbc403b2c85a45f4b05b270b920c..be30c1a6a03ab2a3426e7290c363992dcb19cde2 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  silcauth.h
+  silcauth.h 
+
   Author: Pekka Riikonen <priikone@silcnet.org>
-  Copyright (C) 2001 Pekka Riikonen
+
+  Copyright (C) 2001 - 2002 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.
+  the Free Software Foundation; version 2 of the License.
+
   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
  * used by client to agree on key material usually with another client
  * in the network.
  *
+ * This interface defines also the SILC_MESSAGE_FLAG_SIGNED Payload,
+ * which defines how channel messages and private messages can be digitally
+ * signed.  This interface provides the payload parsing, encoding, 
+ * signature computing and signature verification routines.
+ *
  ***/
 
 #ifndef SILCAUTH_H
 #define SILCAUTH_H
 
-/****s* silccore/SilcAuthAPI/SilcAuthPayload
- *
- * NAME
- * 
- *    typedef struct SilcAuthPayloadStruct *SilcAuthPayload; 
- *
- *
- * DESCRIPTION
- *
- *    This context is the actual Authentication Payload and is allocated
- *    by silc_auth_payload_parse and given as argument usually to all
- *    silc_auth_payload_* functions.  It is freed by silc_auth_payload_free
- *    function.
- *
- ***/
-typedef struct SilcAuthPayloadStruct *SilcAuthPayload;
-
-/****s* silccore/SilcAuthAPI/SilcKeyAgreementPayload
- *
- * NAME
- * 
- *    typedef struct SilcKeyAgreementPayloadStruct *SilcKeyAgreementPayload;
- *
- * DESCRIPTION
- *
- *    This context is the actual Key Agreement Payload and is allocated
- *    by silc_key_agreement_payload_parse and given as argument usually to all
- *    silc_key_agreement_* functions.  It is freed by the function
- *    silc_key_agreement_payload_free.
- *
- ***/
-typedef struct SilcKeyAgreementPayloadStruct *SilcKeyAgreementPayload;
-
 /****d* silccore/SilcAuthAPI/SilcAuthMethod
  *
  * NAME
@@ -97,7 +68,22 @@ typedef SilcUInt16 SilcAuthMethod;
 #define SILC_AUTH_FAILED      1
 /***/
 
-/* Prototypes */
+/****s* silccore/SilcAuthAPI/SilcAuthPayload
+ *
+ * NAME
+ * 
+ *    typedef struct SilcAuthPayloadStruct *SilcAuthPayload; 
+ *
+ *
+ * DESCRIPTION
+ *
+ *    This context is the actual Authentication Payload and is allocated
+ *    by silc_auth_payload_parse and given as argument usually to all
+ *    silc_auth_payload_* functions.  It is freed by silc_auth_payload_free
+ *    function.
+ *
+ ***/
+typedef struct SilcAuthPayloadStruct *SilcAuthPayload;
 
 /****f* silccore/SilcAuthAPI/silc_auth_payload_parse
  *
@@ -308,6 +294,22 @@ bool silc_auth_verify_data(const unsigned char *payload,
                           SilcUInt32 auth_data_len, SilcHash hash, 
                           const void *id, SilcIdType type);
 
+/****s* silccore/SilcAuthAPI/SilcKeyAgreementPayload
+ *
+ * NAME
+ * 
+ *    typedef struct SilcKeyAgreementPayloadStruct *SilcKeyAgreementPayload;
+ *
+ * DESCRIPTION
+ *
+ *    This context is the actual Key Agreement Payload and is allocated
+ *    by silc_key_agreement_payload_parse and given as argument usually to all
+ *    silc_key_agreement_* functions.  It is freed by the function
+ *    silc_key_agreement_payload_free.
+ *
+ ***/
+typedef struct SilcKeyAgreementPayloadStruct *SilcKeyAgreementPayload;
+
 /****f* silccore/SilcAuthAPI/silc_key_agreement_payload_parse
  *
  * SYNOPSIS
@@ -383,4 +385,126 @@ char *silc_key_agreement_get_hostname(SilcKeyAgreementPayload payload);
  ***/
 SilcUInt32 silc_key_agreement_get_port(SilcKeyAgreementPayload payload);
 
+/****s* silccore/SilcAuthAPI/SilcSignedPayload
+ *
+ * NAME
+ * 
+ *    typedef struct SilcSignedPayloadStruct *SilcSignedPayload;
+ *
+ *
+ * DESCRIPTION
+ *
+ *    This context represents the SILC_MESSAGE_FLAG_SIGNED Payload which
+ *    is used with channel messages and private messages to indicate that
+ *    the message is digitally signed.  This payload may include the
+ *    message sender's public key and it includes the digital signature.
+ *    This payload MUST NOT be used in any other context except with
+ *    channel and private message sending and reception.
+ *
+ ***/
+typedef struct SilcSignedPayloadStruct *SilcSignedPayload;
+
+/****f* silccore/SilcAuthAPI/silc_signed_payload_parse
+ *
+ * SYNOPSIS
+ *
+ *    SilcSignedPayload silc_signed_payload_parse(const unsigned char *data,
+ *                                                SilcUInt32 data_len);
+ *
+ * DESCRIPTION
+ *
+ *    Parses the SILC_MESSAGE_FLAG_SIGNED Payload from the `data' of
+ *    length of `data_len' bytes.  The `data' must be payload without
+ *    the actual message payload.  Returns the parsed payload or NULL
+ *    on error.  Caller must free the returned payload.
+ *
+ ***/
+SilcSignedPayload silc_signed_payload_parse(const unsigned char *data,
+                                           SilcUInt32 data_len);
+
+/****f* silccore/SilcAuthAPI/silc_signed_payload_encode
+ *
+ * SYNOPSIS
+ *
+ *    SilcBuffer
+ *    silc_signed_payload_encode(const unsigned char *message_payload,
+ *                               SilcUInt32 message_payload_len,
+ *                               SilcPublicKey public_key,
+ *                               SilcPrivateKey private_key,
+ *                               bool include_public_key);
+ *
+ * DESCRIPTION
+ *
+ *    Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the
+ *    digital signature.  The `message_payload' is the message data that
+ *    is used in the signature computation.  The encoding of the buffer
+ *    is specified in the SILC protocol.  If `include_public_key' is
+ *    TRUE then the public key included in the payload.  The `private_key'
+ *    is used to produce the signature.  This function returns the encoded
+ *    payload with the signature or NULL on error.  Caller must free the
+ *    returned buffer.
+ *
+ ***/
+SilcBuffer silc_signed_payload_encode(const unsigned char *message_payload,
+                                     SilcUInt32 message_payload_len,
+                                     SilcPublicKey public_key,
+                                     SilcPrivateKey private_key,
+                                     SilcHash hash,
+                                     bool include_public_key);
+
+/****f* silccore/SilcAuthAPI/silc_signed_payload_free
+ *
+ * SYNOPSIS
+ *
+ *    void silc_signed_payload_free(SilcSignedPayload sig);
+ *
+ * DESCRIPTION
+ *
+ *    Frees the SILC_MESSAGE_FLAG_SIGNED Payload.
+ *
+ ***/
+void silc_signed_payload_free(SilcSignedPayload sig);
+
+/****f* silccore/SilcAuthAPI/silc_signed_payload_verify
+ *
+ * SYNOPSIS
+ *
+ *    int silc_signed_payload_verify(SilcSignedPayload sig,
+ *                                   bool channel_message,
+ *                                   void *message_payload,
+ *                                   SilcPublicKey remote_public_key,
+ *                                   SilcHash hash);
+ *
+ * DESCRIPTION
+ *
+ *    This routine can be used to verify the signature found in
+ *    SILC_MESSAGE_FLAG_SIGNED Payload.  The `remote_public_key' is the
+ *    sender's public key and is used in the verification.  If the
+ *    `channel_message' is TRUE then `message_payload' must include the
+ *    SilcChannelMessagePayload.  If it is FALSE then it must include
+ *    SilcPrivateMessagePayload.  This returns SILC_AUTH_OK if the
+ *    signature verification was successful.
+ *
+ ***/
+int silc_signed_payload_verify(SilcSignedPayload sig,
+                              bool channel_message,
+                              void *message_payload,
+                              SilcPublicKey remote_public_key,
+                              SilcHash hash);
+
+/****f* silccore/SilcAuthAPI/silc_signed_payload_get_public_key
+ *
+ * SYNOPSIS
+ *
+ *    SilcPublicKey silc_signed_payload_get_public_key(SilcSignedPayload sig);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the public key from the SILC_MESSAGE_FLAG_SIGNED Payload
+ *    or NULL if it does not include public key.  The caller must free
+ *    the returned public key.
+ *
+ ***/
+SilcPublicKey silc_signed_payload_get_public_key(SilcSignedPayload sig);
+
 #endif
index e87cf934bababcdba933cf29746291e35c578e4b..adc857ee88c34449c406e164e43503811ebbbc8b 100644 (file)
 
 #include "silcincludes.h"
 #include "silcchannel.h"
-
-/******************************************************************************
-
-                              Channel Payload
-
-******************************************************************************/
-
-/* Channel Message Payload structure. Contents of this structure is parsed
-   from SILC packets. */
-struct SilcChannelPayloadStruct {
-  SilcUInt16 name_len;
-  unsigned char *channel_name;
-  SilcUInt16 id_len;
-  unsigned char *channel_id;
-  SilcUInt32 mode;
-};
+#include "silcchannel_i.h"
 
 /* Parses channel payload returning new channel payload structure. */
 
@@ -231,32 +216,6 @@ SilcUInt32 silc_channel_get_mode(SilcChannelPayload payload)
 
 ******************************************************************************/
 
-/* Calculates padding length for message payload */
-#define SILC_CHANNEL_MESSAGE_PAD(__payloadlen) (16 - ((__payloadlen) % 16))
-
-/* Header length plus maximum padding length */
-#define SILC_CHANNEL_MESSAGE_HLEN 6 + 16
-
-/* Returns the data length that fits to the packet.  If data length is too
-   big it will be truncated to fit to the payload. */
-#define SILC_CHANNEL_MESSAGE_DATALEN(data_len, header_len)             \
-  ((data_len + SILC_CHANNEL_MESSAGE_HLEN + header_len) >               \
-   SILC_PACKET_MAX_LEN ?                                               \
-   data_len - ((data_len + SILC_CHANNEL_MESSAGE_HLEN + header_len) -   \
-              SILC_PACKET_MAX_LEN) : data_len)
-
-/* Channel Message Payload structure. Contents of this structure is parsed
-   from SILC packets. */
-struct SilcChannelMessagePayloadStruct {
-  SilcMessageFlags flags;
-  SilcUInt16 data_len;
-  unsigned char *data;
-  SilcUInt16 pad_len;
-  unsigned char *pad;
-  unsigned char *mac;
-  unsigned char *iv;
-};
-
 /* Decrypts the channel message payload. First push the IV out of the
    packet. The IV is used in the decryption process. Then decrypt the
    message. After decyprtion, take the MAC from the decrypted packet, 
@@ -305,18 +264,9 @@ bool silc_channel_message_payload_decrypt(unsigned char *data,
     silc_hmac_update(hmac, data + (data_len - iv_len), iv_len);
     silc_hmac_final(hmac, mac2, &mac_len);
     if (memcmp(mac, mac2, mac_len)) {
-#if 1
-      /* Backwards support for old mac checking, remove in 1.0 */
-      silc_hmac_make(hmac, dst, (data_len - iv_len - mac_len), mac2, &mac_len);
-      if (memcmp(mac, mac2, mac_len)) {
-#endif
-
       SILC_LOG_DEBUG(("Channel message MACs does not match"));
       silc_free(dst);
       return FALSE;
-#if 1
-      }
-#endif
     }
     SILC_LOG_DEBUG(("MAC is Ok"));
 
@@ -381,6 +331,8 @@ silc_channel_message_payload_parse(unsigned char *payload,
     goto err;
   }
 
+  newp->iv_len = iv_len;
+
   return newp;
 
  err:
@@ -434,7 +386,7 @@ bool silc_channel_message_payload_encrypt(unsigned char *data,
    encrypted separately from other parts of the packet padding must
    be applied to the payload. */
 
-SilcBuffer silc_channel_message_payload_encode(SilcUInt16 flags,
+SilcBuffer silc_channel_message_payload_encode(SilcMessageFlags flags,
                                               SilcUInt16 data_len,
                                               const unsigned char *data,
                                               SilcUInt16 iv_len,
@@ -544,17 +496,6 @@ unsigned char *silc_channel_message_get_iv(SilcChannelMessagePayload payload)
 
 ******************************************************************************/
 
-/* Channel Key Payload structrue. Channel keys are parsed from SILC
-   packets into this structure. */
-struct SilcChannelKeyPayloadStruct {
-  SilcUInt16 id_len;
-  unsigned char *id;
-  SilcUInt16 cipher_len;
-  unsigned char *cipher;
-  SilcUInt16 key_len;
-  unsigned char *key;
-};
-
 /* Parses channel key payload returning new channel key payload structure */
 
 SilcChannelKeyPayload 
index fa471a4263e41986c73e3fa0e6ba9e63afcb46bf..23dfccf1db2b87714e385557ba012feb8d384c1e 100644 (file)
@@ -357,7 +357,7 @@ bool silc_channel_message_payload_encrypt(unsigned char *data,
  *
  * SYNOPSIS
  *
- *    SilcBuffer silc_channel_message_payload_encode(SilcUInt16 flags,
+ *    SilcBuffer silc_channel_message_payload_encode(SilcMessageFlags flags,
  *                                                   SilcUInt16 data_len,
  *                                                   const unsigned char *data,
  *                                                   SilcUInt16 iv_len,
@@ -378,7 +378,7 @@ bool silc_channel_message_payload_encrypt(unsigned char *data,
  *    the `rng' is used.
  *
  ***/
-SilcBuffer silc_channel_message_payload_encode(SilcUInt16 flags,
+SilcBuffer silc_channel_message_payload_encode(SilcMessageFlags flags,
                                               SilcUInt16 data_len,
                                               const unsigned char *data,
                                               SilcUInt16 iv_len,
diff --git a/lib/silccore/silcchannel_i.h b/lib/silccore/silcchannel_i.h
new file mode 100644 (file)
index 0000000..372094d
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+
+  silcchannel_i.h 
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 1997 - 2002 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; version 2 of the License.
+
+  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 SILCCHANNEL_I_H
+#define SILCCHANNEL_I_H
+
+#ifndef SILCCHANNEL_H
+#error "Do not include internal header file directly"
+#endif
+
+/******************************************************************************
+
+                              Channel Payload
+
+******************************************************************************/
+
+/* Channel Message Payload structure. Contents of this structure is parsed
+   from SILC packets. */
+struct SilcChannelPayloadStruct {
+  unsigned char *channel_name;
+  unsigned char *channel_id;
+  SilcUInt32 mode;
+  SilcUInt16 name_len;
+  SilcUInt16 id_len;
+};
+
+
+/******************************************************************************
+
+                          Channel Message Payload
+
+******************************************************************************/
+
+/* Calculates padding length for message payload */
+#define SILC_CHANNEL_MESSAGE_PAD(__payloadlen) (16 - ((__payloadlen) % 16))
+
+/* Header length plus maximum padding length */
+#define SILC_CHANNEL_MESSAGE_HLEN 6 + 16
+
+/* Returns the data length that fits to the packet.  If data length is too
+   big it will be truncated to fit to the payload. */
+#define SILC_CHANNEL_MESSAGE_DATALEN(data_len, header_len)             \
+  ((data_len + SILC_CHANNEL_MESSAGE_HLEN + header_len) >               \
+   SILC_PACKET_MAX_LEN ?                                               \
+   data_len - ((data_len + SILC_CHANNEL_MESSAGE_HLEN + header_len) -   \
+              SILC_PACKET_MAX_LEN) : data_len)
+
+/* Channel Message Payload structure. Contents of this structure is parsed
+   from SILC packets. */
+struct SilcChannelMessagePayloadStruct {
+  unsigned char *data;
+  unsigned char *pad;
+  unsigned char *mac;
+  unsigned char *iv;
+  SilcMessageFlags flags;
+  SilcUInt16 data_len;
+  SilcUInt16 pad_len;
+  SilcUInt16 iv_len;
+};
+
+
+/******************************************************************************
+
+                             Channel Key Payload
+
+******************************************************************************/
+
+/* Channel Key Payload structrue. Channel keys are parsed from SILC
+   packets into this structure. */
+struct SilcChannelKeyPayloadStruct {
+  unsigned char *id;
+  unsigned char *cipher;
+  unsigned char *key;
+  SilcUInt16 id_len;
+  SilcUInt16 cipher_len;
+  SilcUInt16 key_len;
+};
+
+#endif /* SILCCHANNEL_I_H */
index c6cba515af1b558f8ad96060113a9c574fd56b5b..fe76866208d8dc32890bca3bee5092cc69c94e71 100644 (file)
@@ -141,9 +141,10 @@ bool silc_packet_assemble(SilcPacketContext *packet, SilcRng rng,
   /* Calculate the length of the padding. The padding is calculated from
      the data that will be encrypted. */
   if (!packet->padlen) {
-    packet->padlen = (packet->long_pad ?
-                     SILC_PACKET_PADLEN_MAX(packet->truelen) :
-                     SILC_PACKET_PADLEN(packet->truelen, block_len));
+    if (packet->long_pad)
+      SILC_PACKET_PADLEN_MAX(packet->truelen, block_len, packet->padlen);
+    else
+      SILC_PACKET_PADLEN(packet->truelen, block_len, packet->padlen);
   }
 
   /* Now prepare the outgoing data buffer for packet sending and start
index 3583e473927e5a952819b8422e0aa2ebad5bde23..7d62a3b4210b754cada5dda1c3e50499ecad33ec 100644 (file)
@@ -370,14 +370,18 @@ do {                                                                      \
  *
  * DESCRIPTION
  *
- *    Returns the length of the padding in the packet. This is used
+ *    Calculates the length of the padding in the packet. This is used
  *    by various library routines to determine needed padding length.
  *
  * SOURCE
  */
-#define SILC_PACKET_PADLEN(__packetlen, __blocklen)            \
-  SILC_PACKET_DEFAULT_PADLEN - (__packetlen) %                 \
-    ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)
+#define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen)             \
+do {                                                                      \
+  __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) %                \
+             ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
+  if (__padlen < 8)                                                       \
+    __padlen = ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
+} while(0)
 /***/
 
 /****d* silccore/SilcPacketAPI/SILC_PACKET_PADLEN_MAX
@@ -389,13 +393,16 @@ do {                                                                      \
  * DESCRIPTION
  *
  *    Returns the length of the padding up to the maximum length, which
- *    is 128 butes. This is used by various library routines to determine
+ *    is 128 bytes. This is used by various library routines to determine
  *    needed padding length.
  *
  * SOURCE
  */
-#define SILC_PACKET_PADLEN_MAX(__packetlen)                            \
-  SILC_PACKET_MAX_PADLEN - (__packetlen) % SILC_PACKET_MAX_PADLEN
+#define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen)         \
+do {                                                                      \
+  __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) %                            \
+             ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
+} while(0)
 /***/
 
 /* Prototypes */
index 67cb967b078c039c477cb4af05f687d5083ed7e0..b90d01096dcdb058380b017fd0d56598f309b503 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "silcincludes.h"
 #include "silcprivate.h"
+#include "silcprivate_i.h"
 
 /******************************************************************************
 
 
 ******************************************************************************/
 
-/* Calculates padding length for message payload */
-#define SILC_PRIVATE_MESSAGE_PAD(__payloadlen) (16 - ((__payloadlen) % 16))
-
-/* Header length plus maximum padding length */
-#define SILC_PRIVATE_MESSAGE_HLEN 4 + 16
-
-/* Returns the data length that fits to the packet.  If data length is too
-   big it will be truncated to fit to the payload. */
-#define SILC_PRIVATE_MESSAGE_DATALEN(data_len)                         \
-  ((data_len + SILC_PRIVATE_MESSAGE_HLEN) > SILC_PACKET_MAX_LEN ?      \
-   data_len - ((data_len + SILC_PRIVATE_MESSAGE_HLEN) -                \
-              SILC_PACKET_MAX_LEN) : data_len)
-
-/* Private Message Payload structure. Contents of this structure is parsed
-   from SILC packets. */
-struct SilcPrivateMessagePayloadStruct {
-  SilcUInt16 flags;
-  SilcUInt16 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(unsigned char *payload,
                                   SilcUInt32 payload_len,
-                                  SilcCipher cipher)
+                                  SilcCipher cipher,
+                                  SilcHmac hmac)
 {
   SilcBufferStruct buffer;
   SilcPrivateMessagePayload newp;
-  int ret;
+  SilcUInt32 mac_len = 0, block_len, pad_len = 0;
+  unsigned char data[16], mac[32];
+  int len, totlen;
 
   SILC_LOG_DEBUG(("Parsing private message payload"));
 
   silc_buffer_set(&buffer, payload, payload_len);
 
-  /* Decrypt the payload */
-  if (cipher)
-    silc_cipher_decrypt(cipher, buffer.data, buffer.data, 
-                       buffer.len, silc_cipher_get_iv(cipher));
-
   newp = silc_calloc(1, sizeof(*newp));
   if (!newp)
     return NULL;
 
-  /* Parse the Private Message Payload. Ignore the padding. */
-  ret = silc_buffer_unformat(&buffer,
+  /* Decrypt the payload */
+  if (cipher) {
+    /* Decrypt first block. This is to get the true length of the data in
+       payload.  It is possible there is additional data after the message
+       payload with private messages. */
+    block_len = silc_cipher_get_block_len(cipher);
+    if (block_len > buffer.len)
+      goto err;
+    silc_cipher_decrypt(cipher, buffer.data, data, block_len,
+                       silc_cipher_get_iv(cipher));
+
+    /* Length of encrypted area */
+    SILC_GET16_MSB(newp->message_len, data + 2);
+    totlen = 4 + newp->message_len;
+    pad_len = SILC_PRIVATE_MESSAGE_PAD(4 + newp->message_len);
+    totlen += pad_len;
+
+    /* Sanity checks */
+    if (totlen > buffer.len || newp->message_len < 1 ||
+       newp->message_len > buffer.len - 4) {
+      SILC_LOG_DEBUG(("Incorrect private message payload in packet"));
+      goto err;
+    }
+
+    /* Compute MAC for integrity check from the cipher text */
+    if (hmac) {
+      SILC_LOG_DEBUG(("Checking private message MAC"));
+      silc_hmac_init(hmac);
+      silc_hmac_update(hmac, buffer.data, totlen);
+      silc_hmac_final(hmac, mac, &mac_len);
+      if (memcmp(mac, buffer.data + totlen, mac_len)) {
+       SILC_LOG_DEBUG(("Private message MAC does not match"));
+       goto err;
+      }
+      SILC_LOG_DEBUG(("MAC is Ok"));
+    }
+
+    /* Now decrypt rest of the data */
+    memcpy(buffer.data, data, block_len);
+    if (totlen - block_len > 0)
+      silc_cipher_decrypt(cipher, buffer.data + block_len,
+                         buffer.data + block_len, totlen - block_len,
+                         silc_cipher_get_iv(cipher));
+    memset(data, 0, sizeof(data));
+  }
+
+  /* Parse the Private Message Payload. */
+  len = silc_buffer_unformat(&buffer,
                             SILC_STR_UI_SHORT(&newp->flags),
                             SILC_STR_UI16_NSTRING_ALLOC(&newp->message, 
                                                         &newp->message_len),
                             SILC_STR_END);
-  if (ret == -1) {
-    SILC_LOG_DEBUG(("Incorrect private message payload"));
+  if (len == -1 || newp->message_len < 1 ||
+      newp->message_len > buffer.len - 4) {
+    SILC_LOG_DEBUG(("Incorrect private message payload in packet"));
     goto err;
   }
 
-  if ((newp->message_len < 1 || newp->message_len > buffer.len - 4)) {
-    SILC_LOG_DEBUG(("Incorrect private message payload in packet, "
-                   "packet dropped"));
-    goto err;
+  /* Parse also padding and MAC */
+  if (cipher) {
+    silc_buffer_pull(&buffer, 4 + newp->message_len);
+    len = silc_buffer_unformat(&buffer,
+                              SILC_STR_UI_XNSTRING_ALLOC(&newp->pad,
+                                                         pad_len),
+                              SILC_STR_UI_XNSTRING_ALLOC(&newp->mac,
+                                                         mac_len),
+                              SILC_STR_END);
+    silc_buffer_push(&buffer, 4 + newp->message_len);
   }
 
   return newp;
@@ -107,12 +138,13 @@ SilcBuffer silc_private_message_payload_encode(SilcUInt16 flags,
                                               SilcUInt16 data_len,
                                               const unsigned char *data,
                                               SilcCipher cipher,
+                                              SilcHmac hmac,
                                               SilcRng rng)
 {
   int i;
   SilcBuffer buffer;
-  SilcUInt32 len, pad_len = 0;
-  unsigned char pad[16];
+  SilcUInt32 len, pad_len = 0, mac_len = 0;
+  unsigned char pad[16], mac[32];
 
   SILC_LOG_DEBUG(("Encoding private message payload"));
 
@@ -123,9 +155,15 @@ SilcBuffer silc_private_message_payload_encode(SilcUInt16 flags,
     /* Calculate length of padding. */
     pad_len = SILC_PRIVATE_MESSAGE_PAD(len);
     len += pad_len;
+    mac_len = hmac ? silc_hmac_len(hmac) : 0;
+    len += mac_len;
 
     /* Generate padding */
-    for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte();
+    if (rng) {
+      for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
+    } else {
+      for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
+    }
   }
 
   /* Allocate private message payload buffer */
@@ -144,8 +182,17 @@ SilcBuffer silc_private_message_payload_encode(SilcUInt16 flags,
   if (cipher) {
     /* Encrypt payload of the packet. */
     silc_cipher_encrypt(cipher, buffer->data, buffer->data, 
-                       buffer->len, silc_cipher_get_iv(cipher));
+                       buffer->len - mac_len, silc_cipher_get_iv(cipher));
     memset(pad, 0, sizeof(pad));
+
+    /* Compute MAC from the ciphertext */
+    if (hmac) {
+      silc_hmac_init(hmac);
+      silc_hmac_update(hmac, buffer->data, buffer->len - mac_len);
+      silc_hmac_final(hmac, mac, &mac_len);
+      memcpy(buffer->data + (buffer->len - mac_len), mac, mac_len);
+      memset(mac, 0, sizeof(mac));
+    }
   }
 
   return buffer;
@@ -181,3 +228,11 @@ silc_private_message_get_message(SilcPrivateMessagePayload payload,
 
   return payload->message;
 }
+
+/* Return MAC.  Caller knows its length */
+
+unsigned char *
+silc_private_message_get_mac(SilcPrivateMessagePayload payload)
+{
+  return payload->mac;
+}
index bede78e2f3dd23d388175672223fa48be2c8fae7..d776bf6dceb98f54eea57a626003f4744b1697b5 100644 (file)
@@ -57,18 +57,21 @@ typedef struct SilcPrivateMessagePayloadStruct *SilcPrivateMessagePayload;
  *    SilcPrivateMessagePayload 
  *    silc_private_message_payload_parse(unsigned char *payload,
  *                                       SilcUInt32 payload_len,
- *                                       SilcCipher cipher);
+ *                                       SilcCipher cipher,
+ *                                       SilcHmac hmac);
  *
  * DESCRIPTION
  *
  *    Parses private message payload returning new private mesage payload 
  *    structure. This also decrypts the message if the `cipher' is provided.
+ *    The data integrity is checked with `hmac'.
  *
  ***/
 SilcPrivateMessagePayload 
 silc_private_message_payload_parse(unsigned char *payload,
                                   SilcUInt32 payload_len,
-                                  SilcCipher cipher);
+                                  SilcCipher cipher,
+                                  SilcHmac hmac);
 
 /****f* silccore/SilcPrivateAPI/silc_private_message_payload_encode
  *
@@ -78,20 +81,23 @@ silc_private_message_payload_parse(unsigned char *payload,
  *                                                   SilcUInt16 data_len,
  *                                                   const unsigned char *data,
  *                                                   SilcCipher cipher,
+ *                                                   SilcHmac hmac,
  *                                                   SilcRng rng);
  *
  * DESCRIPTION
  *
  *    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.  If the `rng' is NULL
- *    then global RNG is used, if non-NULL then `rng' is used.
+ *    the `cipher' is provided the packet is also encrypted here.  It is
+ *    provided if the private message private keys are used.  If the `rng'
+ *    is NULL then global RNG is used, if non-NULL then `rng' is used.
+ *    The MAC for the message is computed with `hmac'.
  *
  ***/
 SilcBuffer silc_private_message_payload_encode(SilcUInt16 flags,
                                               SilcUInt16 data_len,
                                               const unsigned char *data,
                                               SilcCipher cipher,
+                                              SilcHmac hmac,
                                               SilcRng rng);
 
 /****f* silccore/SilcPrivateAPI/silc_private_message_payload_free
@@ -142,4 +148,20 @@ unsigned char *
 silc_private_message_get_message(SilcPrivateMessagePayload payload,
                                 SilcUInt32 *message_len);
 
+/****f* silccore/SilcPrivateAPI/silc_private_message_get_mac
+ *
+ * SYNOPSIS
+ *
+ *    unsigned char *
+ *    silc_private_message_get_mac(SilcPrivateMessagePayload payload);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the MAC from the payload.  The caller knows its length.
+ *    The caller must not free it.
+ *
+ ***/
+unsigned char *
+silc_private_message_get_mac(SilcPrivateMessagePayload payload);
+
 #endif
diff --git a/lib/silccore/silcprivate_i.h b/lib/silccore/silcprivate_i.h
new file mode 100644 (file)
index 0000000..d3ad843
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+
+  silcprivate_i.h 
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 1997 - 2002 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; version 2 of the License.
+
+  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_I_H
+#define SILCPRIVATE_I_H
+
+#ifndef SILCPRIVATE_H
+#error "Do not include internal header file directly"
+#endif
+
+/******************************************************************************
+
+                           Private Message Payload
+
+******************************************************************************/
+
+/* Calculates padding length for message payload */
+#define SILC_PRIVATE_MESSAGE_PAD(__payloadlen) (16 - ((__payloadlen) % 16))
+
+/* Header length plus maximum padding length */
+#define SILC_PRIVATE_MESSAGE_HLEN 4 + 16
+
+/* Returns the data length that fits to the packet.  If data length is too
+   big it will be truncated to fit to the payload. */
+#define SILC_PRIVATE_MESSAGE_DATALEN(data_len)                         \
+  ((data_len + SILC_PRIVATE_MESSAGE_HLEN) > SILC_PACKET_MAX_LEN ?      \
+   data_len - ((data_len + SILC_PRIVATE_MESSAGE_HLEN) -                \
+              SILC_PACKET_MAX_LEN) : data_len)
+
+/* Private Message Payload structure. Contents of this structure is parsed
+   from SILC packets. */
+struct SilcPrivateMessagePayloadStruct {
+  SilcUInt16 flags;
+  SilcUInt16 message_len;
+  unsigned char *message;
+  unsigned char *pad;
+  unsigned char *mac;
+};
+
+#endif /* SILCPRIVATE_I_H */
index 8c91d7eb7893b8ccace45df7f703a1094e33f277..4564a55dffe9e7cf37347516d663811b328a77fd 100644 (file)
@@ -100,6 +100,8 @@ typedef SilcUInt8 SilcStatus;
 #define SILC_STATUS_ERR_KEY_EXCHANGE_FAILED 52
 #define SILC_STATUS_ERR_BAD_VERSION         53
 #define SILC_STATUS_ERR_TIMEDOUT            54
+#define SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY    55
+#define SILC_STATUS_ERR_OPERATION_ALLOWED   56
 /***/
 
 #define SILC_STATUS_IS_ERROR(status) (status >= SILC_STATUS_ERR_NO_SUCH_NICK)
index 290fbed134db617114a976c5a43f4144a3694f61..7b853d91092ddb46757e08ce9222dd5814aca4fd 100644 (file)
@@ -150,7 +150,8 @@ bool silc_hmac_unregister_all(void);
  *
  * SYNOPSIS
  *
- *    bool silc_hmac_alloc(char *name, SilcHash hash, SilcHmac *new_hmac);
+ *    bool silc_hmac_alloc(const char *name, SilcHash hash,
+ *                         SilcHmac *new_hmac);
  *
  * DESCRIPTION
  *
@@ -161,7 +162,7 @@ bool silc_hmac_unregister_all(void);
  *    FALSE if such HMAC does not exist.
  *
  ***/
-bool silc_hmac_alloc(char *name, SilcHash hash, SilcHmac *new_hmac);
+bool silc_hmac_alloc(const char *name, SilcHash hash, SilcHmac *new_hmac);
 
 /****f* silccrypt/SilcHMACAPI/silc_hmac_free
  *
index a8a2a3a41f0dfb00b8754f836f14379394c89d5a..08543c5b73468390916d558608eebb70b705254c 100644 (file)
@@ -620,6 +620,7 @@ SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
   public_key->name = strdup(name);
   public_key->pk_len = pk_len;
   public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
+  public_key->pk_type = SILC_SKE_PK_TYPE_SILC;
   memcpy(public_key->pk, pk, pk_len);
 
   if (!silc_utf8_valid(identifier, strlen(identifier))) {
@@ -826,6 +827,7 @@ bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
     (*public_key)->identifier = ident;
     (*public_key)->pk = key_data;
     (*public_key)->pk_len = key_len;
+    (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
   }
 
   silc_buffer_free(buf);
@@ -842,6 +844,88 @@ bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
   return FALSE;
 }
 
+/* Encodes Public Key Payload for transmitting public keys and certificates. */
+
+SilcBuffer silc_pkcs_public_key_payload_encode(SilcPublicKey public_key)
+{
+  SilcBuffer buffer;
+  unsigned char *pk;
+  SilcUInt32 pk_len;
+
+  if (!public_key)
+    return NULL;
+
+  pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+  if (!pk)
+    return NULL;
+
+  buffer = silc_buffer_alloc_size(4 + pk_len);
+  if (!buffer) {
+    silc_free(pk);
+    return NULL;
+  }
+
+  silc_buffer_format(buffer,
+                    SILC_STR_UI_SHORT(pk_len),
+                    SILC_STR_UI_SHORT(public_key->pk_type),
+                    SILC_STR_UI_XNSTRING(pk, pk_len),
+                    SILC_STR_END);
+
+  silc_free(pk);
+  return buffer;
+}
+
+/* Decode Public Key Payload and decodes the public key inside it to
+   to `payload'. */
+
+bool silc_pkcs_public_key_payload_decode(unsigned char *data,
+                                        SilcUInt32 data_len,
+                                        SilcPublicKey *public_key)
+{
+  SilcBufferStruct buf;
+  SilcUInt16 pk_len, pk_type;
+  unsigned char *pk;
+  int ret;
+
+  if (!public_key)
+    return FALSE;
+
+#if 1
+  /* XXX 1.1 version support.  Check whether the data is actually raw
+     public key and attempt to decode.  Remove this later! */
+  if (silc_pkcs_public_key_decode(data, data_len, public_key)) {
+    (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
+    return TRUE;
+  }
+#endif
+
+  silc_buffer_set(&buf, data, data_len);
+  ret = silc_buffer_unformat(&buf,
+                            SILC_STR_UI_SHORT(&pk_len),
+                            SILC_STR_UI_SHORT(&pk_type),
+                            SILC_STR_END);
+  if (ret < 0 || pk_len > data_len - 4)
+    return FALSE;
+
+  /* For now we support only SILC public keys */
+  if (pk_type != SILC_SKE_PK_TYPE_SILC)
+    return FALSE;
+
+  silc_buffer_pull(&buf, 4);
+  ret = silc_buffer_unformat(&buf,
+                            SILC_STR_UI_XNSTRING(&pk, pk_len),
+                            SILC_STR_END);
+  silc_buffer_push(&buf, 4);
+  if (ret < 0)
+    return FALSE;
+
+  if (!silc_pkcs_public_key_decode(pk, pk_len, public_key))
+    return FALSE;
+  (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
+
+  return TRUE;
+}
+
 /* Compares two public keys and returns TRUE if they are same key, and
    FALSE if they are not same. */
 
@@ -876,6 +960,7 @@ SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
                                strlen(public_key->identifier));
   key->pk = silc_memdup(public_key->pk, public_key->pk_len);
   key->pk_len = public_key->pk_len;
+  key->pk_type = public_key->pk_type;
 
   return key;
 }
index d96d9ef604721be848bac3a37ad091315433e5c3..d9497309729b4b37112b365dd55163732d74dc4c 100644 (file)
@@ -92,6 +92,7 @@ typedef struct SilcPKCSObjectStruct {
  * SOURCE
  */
 typedef struct {
+  SilcUInt16 pk_type;          /* Public key type (SilcSKEPKType) */
   SilcUInt32 len;
   char *name;
   char *identifier;
@@ -734,8 +735,9 @@ silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
  *
  * SYNOPSIS
  *
- *    bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
- *                                    SilcPublicKey *public_key);
+ *    bool silc_pkcs_public_key_decode(unsigned char *data,
+ *                                     SilcUInt32 data_len,
+ *                                     SilcPublicKey *public_key);
  *
  * DESCRIPTION
  *
@@ -746,6 +748,41 @@ silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
 bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
                                 SilcPublicKey *public_key);
 
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_decode
+ *
+ * SYNOPSIS
+ *
+ *    bool silc_pkcs_public_key_payload_encode(SilcPublicKey public_key);
+ *
+ * DESCRIPTION
+ *
+ *    Encodes the Public Key Payload from the public key indicated by
+ *    `public_key' of type of `pk_type'.  The type is SilcSKEPKType.
+ *    Returns the encoded payload buffer.
+ *
+ ***/
+SilcBuffer silc_pkcs_public_key_payload_encode(SilcPublicKey public_key);
+
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_decode
+ *
+ * SYNOPSIS
+ *
+ *    bool
+ *    silc_pkcs_public_key_payload_decode(unsigned char *data,
+ *                                        SilcUInt32 data_len,
+ *                                        SilcPublicKey *public_key);
+ *
+ * DESCRIPTION
+ *
+ *    Decodes Public Key Payload from `data' of `data_len' bytes in length
+ *    data buffer into `public_key' pointer. Returns FALSE if the payload
+ *    cannot be decoded.
+ *
+ ***/
+bool silc_pkcs_public_key_payload_decode(unsigned char *data,
+                                        SilcUInt32 data_len,
+                                        SilcPublicKey *public_key);
+
 /****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_compare
  *
  * SYNOPSIS
index 83d240ca32d5d6882dffb66826b6066c0e106407..3f0a529b575fdbe5b27d7a918e738aaff50fb210 100644 (file)
@@ -179,6 +179,8 @@ int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
 
  fail:
   SILC_LOG_DEBUG(("Error occured while formatting data"));
+  len = dst->data - start_ptr;
+  silc_buffer_push(dst, len);
   return -1;
 
  ok:
@@ -491,6 +493,8 @@ int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
 
  fail:
   SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
+  len = src->data - start_ptr;
+  silc_buffer_push(src, len);
   return -1;
 
  ok:
index 1ede14fc8c81e7f623250b50013dd6a3813c2fdf..7898a4c94f7b518f67709d45577dbf0383873339 100644 (file)
@@ -1031,6 +1031,8 @@ static const SilcStatusMessage silc_status_messages[] = {
   { STAT(KEY_EXCHANGE_FAILED), "Key exchange failed" },
   { STAT(BAD_VERSION), "Bad version" },
   { STAT(TIMEDOUT), "Service timed out" },
+  { STAT(UNSUPPORTED_PUBLIC_KEY), "Unsupported public key type" },
+  { STAT(OPERATION_ALLOWED), "Operation is not allowed" },
 
   { 0, NULL }
 };
index 5c4688682f19bab3a2c589f0d800d0b700e43d9f..bfe8ae035e34badbcb7ed1de5b74f363aba705ce 100644 (file)
@@ -21,7 +21,7 @@
 #define STACKTRACE_H
 
 #ifndef SILCMEMORY_H
-#error "Do not include this file directly"
+#error "Do not include internal header file directly"
 #endif
 
 #if defined(__GNUC__) && defined(__i386__)
diff --git a/prepare b/prepare
index a3b58a7ec54a75dd8bedbba49471075b44c3a8c0..fbdcd9b0ad00d117356c535e1e46b6906684c2c5 100755 (executable)
--- a/prepare
+++ b/prepare
@@ -140,7 +140,7 @@ file=includes/version_internal.h
 echo "/* Automatically generated by ./prepare */" >$file
 echo "#define SILC_VERSION_STRING \"$dist_version\"" >>$file
 echo "#define SILC_DIST_VERSION_STRING \"$dist_version\"" >>$file
-echo "#define SILC_PROTOCOL_VERSION_STRING \"SILC-1.1-$dist_version $distribution\"" >>$file
+echo "#define SILC_PROTOCOL_VERSION_STRING \"SILC-1.2-$dist_version $distribution\"" >>$file
 echo "#define SILC_NAME \"SILC $distribution\"" >>$file
 
 # preparing irssi