updates.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 24 Mar 2002 14:18:42 +0000 (14:18 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 24 Mar 2002 14:18:42 +0000 (14:18 +0000)
32 files changed:
CHANGES
TODO
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/clientutil.c
apps/irssi/src/silc/core/clientutil.h
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/packet_send.h
apps/silcd/server.c
apps/silcd/server_internal.h
apps/silcd/server_util.c
apps/silcd/server_util.h
apps/silcd/silcd.c
configure.in.pre
doc/draft-riikonen-silc-pp-05.nroff
includes/silcincludes.h
lib/silcclient/client_notify.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/command_reply.h
lib/silcclient/idlist.c
lib/silcclient/idlist.h
lib/silccore/silcchannel.c
lib/silccore/silcchannel.h
lib/silccore/silccommand.c
lib/silccore/silccommand.h
lib/silccore/silcid.c
lib/silccore/silcid.h
lib/silcutil/silcutil.c
lib/silcutil/silcutil.h

diff --git a/CHANGES b/CHANGES
index 9560b47a42fbab71c37392fbcee5a4cfa390ff76..757cb6490f764b6068c40968d031a85b9a472358 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,66 @@
+Sun Mar 24 11:21:04 EET 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added `type' argument to silc_id_payload_parse_id function which
+         now returns the type of the ID to the sent pointer.  Affected
+         file is lib/silccore/silcid.[ch].
+
+       * Added check for CMODE_CHANGE notify type that mode change is
+         allowed by the sender.  Affected file silcd/packet_receive.c.
+
+       * Added check for CUMODE_CHANGE notify type that mode change is
+         allowed by the sender.  Affected file silcd/packet_receive.c.
+         Added the ID type as CUMODE_CHANGE notify type as argument
+         to the `notify' client operation.  Affected files are
+         lib/silcclient/client_notify.c, irssi/src/silc/core/client_ops.c.
+
+       * Added function silc_client_add_server to the client library.
+         Added support for resolving also channel and server info when
+         received unknown entity in notify packet.  Affected files are
+         lib/silcclient/idlist.[ch], lib/silcclient/client_notify.c.
+
+       * Added function silc_command_get_status to return the command
+         status from the command reply's argument payload.  Affected files
+         are lib/silccore/silccommand.[ch].
+
+       * Added check for KICKED notify type that the kicking is
+         allowed by the client.  Affected file silcd/packet_receive.c.
+
+       * Created function silc_get_input which can be used to get input
+         (echo on or off) from user on command line.  Affected files are
+         lib/silcutil/silcutil.[ch].
+
+Sat Mar 23 09:51:26 EET 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * Optimized silc_server_packet_relay_to_channel function.
+         Added new function silc_channel_message_payload_encrypt which
+         can be called directly if channel message payload needs to
+         be encrypted and is already encoded (no need to call _encode
+         function).  Packet relaying is now done by router without any
+         extra memory allocations.  Affected files are
+         lib/silccore/silcchanel.[ch], silcd/packet_receive.c and
+         silcd/packet_send.c.
+
+       * Fixed the INVITE notify handling.  It took wrong arguments
+         as invite list and invite delete.  Affected file is
+         silcd/packet_receive.c.
+
+       * Added check for TOPIC_SET notify type that the topic change is
+         allowed by the client.  Affected file silcd/packet_receive.c.
+
+       * Added check for INVITE notify type that inviting is allowed by
+         the client.  Affected file silcd/packet_receive.c.
+
+       * Changed the silc_server_client_on_channel to return the
+         SilcChannelClientEntry as well.  Moved the function
+         silc_server_check_cmode_rights to server_util.[ch].
+         Affected files are silcd/server_util.[ch], silcd/command.c.
+
+       * Added function silc_server_check_umode_rights to check whether
+         changing client's user mode is allowed.  Added check for
+         UMODE_CHANGE notify type that the umode change is allowed
+         by the client.  Affected files are silcd/server_util.[ch],
+         silcd/packet_receive.c and silcd/command.c.
+
 Fri Mar 22 12:25:58 CET 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed the SILC_PACKET_MAX_ID_LEN to actually be the max
diff --git a/TODO b/TODO
index 980ff9d4417ccdca139ebe682efd13a074da4c84..622624f7023d8b090b2376683c24dfa5d158b4ae 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,7 +1,8 @@
 TODO/bugs in Irssi SILC client
 ==============================
 
- o /cumode for unknown nick does not give any error message.
+ o /cumode for unknown nick does not give any error message (Fix this to
+   1.0).
 
 
 TODO/bugs In SILC Client Library
@@ -10,7 +11,8 @@ TODO/bugs In SILC Client Library
  o The PRIVATE_MESSAGE_KEY packet is not handled (it is implemented 
    though).  This should be added and perhaps new client operation
    should be added to notify application that it was received and
-   set the key only if application wishes to set (accept the key) it.
+   set the key only if application wishes to set (accept the key) it
+   (Do this to 1.0).
 
  o Additions to do after protocol version 1.1:
 
@@ -25,36 +27,38 @@ TODO/bugs In SILC Client Library
 TODO/bugs In SILC Server
 ========================
 
- o Configuration file additions:
+ o Configuration file additions (Do this to 0.8.x):
 
        o Add incoming connection frequency, incoming connection frequency
          for single IP address, key exchange frequency, key exchange
          frequency for single IP. Add also frequency base.
 
-       o Add hashed passwords to config file.
-
        o Add rehashing support.
 
  o If server send CUMODE_CHANGE notify (like setting founder) to router
    and router does not have founder on channel (founder is left or there's
    no founder on channel at all), the router will accept the server's
-   founder mode change, even though it perhaps should not do that.
+   founder mode change, even though it perhaps should not do that (Fix 
+   this to 0.9).
 
  o The router should check for validity of received notify packets from
-   servers (after all buggy servers may send notify that is actually
-   something that should have not been sent).
+   routers (fix this to 0.9).  Following NOTIFYs needs to be verified:
+
+       o JOIN (check that joining is allowed)
+       o SIGNOFF (maybe should check that notifier owns the client)
+       o KILLED (check that killling is allowed (Protocol TODO #13))
+
+ o Backup router related issues (Fix this to 1.0):
+
+       o Channel user mode changes are notified unnecessarely when
+         switching to backup router on router crash.
 
  o Add a timeout to handling incoming JOIN commands.  It should be 
    enforced that JOIN command is executed only once in a second or two
    seconds.  Now it is possible to accept n incoming JOIN commands
    and process them without any timeouts.  THis must be employed because
    each JOIN command will create and distribute the new channel key
-   to everybody on the channel.
-
- o Backup router related issues
-
-       o Channel user mode changes are notified unnecessarely when
-         switching to backup router on router crash.
+   to everybody on the channel (Fix this to 1.0).
 
  o Lots of statistics updating is missing around the server.
 
index 065c980e3264a094aca347d7aadfaffab196bb71..16415900889e9d758e0eb05ad89f1f77f0ee7bfd 100644 (file)
@@ -158,7 +158,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
   SILC_CHANNEL_REC *chanrec;
   SILC_NICK_REC *nickrec;
   SilcClientEntry client_entry, client_entry2;
-  SilcChannelEntry channel;
+  SilcChannelEntry channel, channel2;
   SilcServerEntry server_entry;
   SilcIdType idtype;
   void *entry;
@@ -383,6 +383,12 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
                         MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
                         channel->channel_name, tmp ? tmp : "removed all",
                         server_entry->server_name);
+    } else {
+      channel2 = (SilcChannelEntry)entry;
+      printformat_module("fe-common/silc", server, channel->channel_name,
+                        MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
+                        channel->channel_name, tmp ? tmp : "removed all",
+                        channel2->channel_name);
     }
 
     silc_free(tmp);
@@ -395,7 +401,8 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
 
     SILC_LOG_DEBUG(("Notify: CUMODE_CHANGE"));
 
-    client_entry = va_arg(va, SilcClientEntry);
+    idtype = va_arg(va, int);
+    entry = va_arg(va, void *);
     mode = va_arg(va, SilcUInt32);
     client_entry2 = va_arg(va, SilcClientEntry);
     channel = va_arg(va, SilcChannelEntry);
@@ -416,11 +423,28 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
       }
     }
 
-    printformat_module("fe-common/silc", server, channel->channel_name,
-                      MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
-                      channel->channel_name, client_entry2->nickname, 
-                      tmp ? tmp : "removed all",
-                      client_entry->nickname);
+    if (idtype == SILC_ID_CLIENT) {
+      client_entry = (SilcClientEntry)entry;
+      printformat_module("fe-common/silc", server, channel->channel_name,
+                        MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
+                        channel->channel_name, client_entry2->nickname, 
+                        tmp ? tmp : "removed all",
+                        client_entry->nickname);
+    } else if (idtype == SILC_ID_SERVER) {
+      server_entry = (SilcServerEntry)entry;
+      printformat_module("fe-common/silc", server, channel->channel_name,
+                        MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
+                        channel->channel_name, client_entry2->nickname, 
+                        tmp ? tmp : "removed all",
+                        server_entry->server_name);
+    } else {
+      channel2 = (SilcChannelEntry)entry;
+      printformat_module("fe-common/silc", server, channel->channel_name,
+                        MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
+                        channel->channel_name, client_entry2->nickname, 
+                        tmp ? tmp : "removed all",
+                        channel2->channel_name);
+    }
 
     if (mode & SILC_CHANNEL_UMODE_CHANFO)
       printformat_module("fe-common/silc", 
@@ -786,7 +810,8 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
          silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
                                     2, &tmp_len);
        if (tmp) {
-         SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+         SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, 
+                                                            NULL);
          if (client_id) {
            client_entry = silc_client_get_client_by_id(client, conn,
                                                        client_id);
@@ -902,7 +927,8 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
          silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
                                     2, &tmp_len);
        if (tmp) {
-         SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+         SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len,
+                                                            NULL);
          if (client_id) {
            client_entry = silc_client_get_client_by_id(client, conn,
                                                        client_id);
index cf0604d818cf188e992a348808c48936a002c0da..a98b971426ce54329ddd78482b2d39d986f80bf9 100644 (file)
@@ -80,38 +80,6 @@ void silc_client_list_pkcs()
   silc_free(pkcs);
 }
 
-/* Displays input prompt on command line and takes input data from user */
-
-char *silc_client_get_input(const char *prompt)
-{
-  char input[2048];
-  int fd;
-
-  fd = open("/dev/tty", O_RDONLY);
-  if (fd < 0) {
-    fprintf(stderr, "silc: %s\n", strerror(errno));
-    return NULL;
-  }
-
-  memset(input, 0, sizeof(input));
-
-  printf("%s", prompt);
-  fflush(stdout);
-
-  if ((read(fd, input, sizeof(input))) < 0) {
-    fprintf(stderr, "silc: %s\n", strerror(errno));
-    return NULL;
-  }
-
-  if (strlen(input) <= 1)
-    return NULL;
-
-  if (strchr(input, '\n'))
-    *strchr(input, '\n') = '\0';
-
-  return strdup(input);
-}
-
 /* Returns identifier string for public key generation. */
 
 char *silc_client_create_identifier()
@@ -171,8 +139,7 @@ New pair of keys will be created.  Please, answer to following questions.\n\
 
   if (!pkcs_name) {
   again_name:
-    pkcs_name = 
-      silc_client_get_input("PKCS name (l to list names) [rsa]: ");
+    pkcs_name = silc_get_input("PKCS name (l to list names) [rsa]: ", FALSE);
     if (!pkcs_name)
       pkcs_name = strdup("rsa");
 
@@ -190,8 +157,7 @@ New pair of keys will be created.  Please, answer to following questions.\n\
 
   if (!bits) {
     char *length = NULL;
-    length = 
-      silc_client_get_input("Key length in bits [1024]: ");
+    length = silc_get_input("Key length in bits [1024]: ", FALSE);
     if (!length)
       bits = 1024;
     else
@@ -210,7 +176,7 @@ New pair of keys will be created.  Please, answer to following questions.\n\
               "RN=Jon Johnson, E=jon@dummy.com): ");
 
     while (!identifier) {
-      identifier = silc_client_get_input(line);
+      identifier = silc_get_input(line, FALSE);
       if (!identifier && def)
        identifier = strdup(def);
     }
@@ -227,7 +193,7 @@ New pair of keys will be created.  Please, answer to following questions.\n\
     memset(line, 0, sizeof(line));
     snprintf(line, sizeof(line), "Public key filename [%s] ", 
             SILC_CLIENT_PUBLIC_KEY_NAME);
-    pkfile = silc_client_get_input(line);
+    pkfile = silc_get_input(line, FALSE);
     if (!pkfile)
       pkfile = SILC_CLIENT_PUBLIC_KEY_NAME;
   } else {
@@ -238,7 +204,7 @@ New pair of keys will be created.  Please, answer to following questions.\n\
     memset(line, 0, sizeof(line));
     snprintf(line, sizeof(line), "Public key filename [%s] ", 
             SILC_CLIENT_PRIVATE_KEY_NAME);
-    prvfile = silc_client_get_input(line);
+    prvfile = silc_get_input(line, FALSE);
     if (!prvfile)
       prvfile = SILC_CLIENT_PRIVATE_KEY_NAME;
   } else {
index efd69da009aeb114480966b3c8bb7450cb6cd2bd..3f4a604633f1a655026f2fe8a3b80a186088ae67 100644 (file)
@@ -24,7 +24,6 @@
 #include "signals.h"
 
 /* Prototypes */
-char *silc_client_get_input(const char *prompt);
 void silc_client_list_ciphers();
 void silc_client_list_hash_funcs();
 void silc_client_list_hmacs();
index baddfb1896bb9c82aed0ac3168d8c6aa2829787d..8c93bdded56c2a36314d44bc14143d3ec474ee6a 100644 (file)
@@ -500,7 +500,7 @@ silc_server_command_whois_parse(SilcServerCommandContext cmd,
        has more than one ID set - take them all. */
 
     *client_id = silc_calloc(1, sizeof(**client_id));
-    (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
+    (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
     if ((*client_id)[0] == NULL) {
       silc_free(*client_id);
       silc_server_command_send_status_reply(cmd, command,
@@ -516,7 +516,7 @@ silc_server_command_whois_parse(SilcServerCommandContext cmd,
        if (tmp) {
          *client_id = silc_realloc(*client_id, sizeof(**client_id) *
                                    (*client_id_count + 1));
-         (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
+         (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
          if ((*client_id)[k] == NULL) {
            /* Cleanup all and fail */
            for (i = 0; i < *client_id_count; i++)
@@ -2230,7 +2230,7 @@ SILC_SERVER_CMD_FUNC(list)
   /* Get Channel ID */
   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
   if (tmp) {
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!channel_id) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
                                            SILC_STATUS_ERR_NO_CHANNEL_ID);
@@ -2284,7 +2284,7 @@ SILC_SERVER_CMD_FUNC(topic)
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
     goto out;
   }
-  channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+  channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
   if (!channel_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
@@ -2320,19 +2320,17 @@ SILC_SERVER_CMD_FUNC(topic)
     }
 
     /* See whether the client is on channel and has rights to change topic */
-    if (!silc_hash_table_find(channel->user_list, client, NULL, 
-                             (void *)&chl)) {
+    if (!silc_server_client_on_channel(client, channel, &chl)) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
                                            SILC_STATUS_ERR_NOT_ON_CHANNEL);
       goto out;
     }
 
-    if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
-      if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
-       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
-                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
-       goto out;
-      }
+    if (chl->mode == SILC_CHANNEL_UMODE_NONE && 
+       channel->mode & SILC_CHANNEL_MODE_TOPIC) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
+                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
+      goto out;
     }
 
     /* Set the topic for channel */
@@ -2404,7 +2402,7 @@ SILC_SERVER_CMD_FUNC(invite)
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
     goto out;
   }
-  channel_id = silc_id_payload_parse_id(tmp, len);
+  channel_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!channel_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
@@ -2426,7 +2424,7 @@ SILC_SERVER_CMD_FUNC(invite)
 
   /* Check whether the sender of this command is on the channel. */
   sender = (SilcClientEntry)sock->user_data;
-  if (!silc_server_client_on_channel(sender, channel)) {
+  if (!silc_server_client_on_channel(sender, channel, &chl)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
                                          SILC_STATUS_ERR_NOT_ON_CHANNEL);
     goto out;
@@ -2434,13 +2432,11 @@ SILC_SERVER_CMD_FUNC(invite)
 
   /* Check whether the channel is invite-only channel. If yes then the
      sender of this command must be at least channel operator. */
-  if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
-    silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
-    if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+  if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
+      channel->mode & SILC_CHANNEL_MODE_INVITE) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
                                            SILC_STATUS_ERR_NO_CHANNEL_PRIV);
-      goto out;
-    }
+    goto out;
   }
 
   /* Get destination client ID */
@@ -2449,7 +2445,7 @@ SILC_SERVER_CMD_FUNC(invite)
     char invite[512];
     bool resolve;
 
-    dest_id = silc_id_payload_parse_id(tmp, len);
+    dest_id = silc_id_payload_parse_id(tmp, len, NULL);
     if (!dest_id) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
                                            SILC_STATUS_ERR_NO_CLIENT_ID);
@@ -2479,7 +2475,7 @@ SILC_SERVER_CMD_FUNC(invite)
     }
 
     /* Check whether the requested client is already on the channel. */
-    if (silc_server_client_on_channel(dest, channel)) {
+    if (silc_server_client_on_channel(dest, channel, NULL)) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
                                            SILC_STATUS_ERR_USER_ON_CHANNEL);
       goto out;
@@ -2703,7 +2699,7 @@ SILC_SERVER_CMD_FUNC(kill)
                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
     goto out;
   }
-  client_id = silc_id_payload_parse_id(tmp, tmp_len);
+  client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
   if (!client_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
                                          SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
@@ -2812,7 +2808,7 @@ SILC_SERVER_CMD_FUNC(info)
   /* Get Server ID */
   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
   if (tmp) {
-    server_id = silc_id_payload_parse_id(tmp, tmp_len);
+    server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!server_id) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
                                            SILC_STATUS_ERR_NO_SERVER_ID);
@@ -3062,8 +3058,9 @@ static void silc_server_command_join_channel(SilcServer server,
       void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
                         (void *)channel->founder_passwd : 
                         (void *)channel->founder_key);
-      SilcUInt32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
-                             channel->founder_passwd_len : 0);
+      SilcUInt32 auth_data_len = 
+       (channel->founder_method == SILC_AUTH_PASSWORD ?
+        channel->founder_passwd_len : 0);
 
       /* Check whether the client is to become founder */
       if (silc_auth_verify_data(auth, auth_len, channel->founder_method, 
@@ -3157,7 +3154,7 @@ static void silc_server_command_join_channel(SilcServer server,
    */
 
   /* Check whether the client already is on the channel */
-  if (silc_server_client_on_channel(client, channel)) {
+  if (silc_server_client_on_channel(client, channel, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                          SILC_STATUS_ERR_USER_ON_CHANNEL);
     goto out;
@@ -3337,7 +3334,7 @@ SILC_SERVER_CMD_FUNC(join)
                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
     goto out;
   }
-  client_id = silc_id_payload_parse_id(tmp, tmp_len);
+  client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
   if (!client_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
@@ -3659,53 +3656,15 @@ SILC_SERVER_CMD_FUNC(umode)
   }
   SILC_GET32_MSB(mask, tmp_mask);
 
-  /* 
-   * Change the mode 
-   */
-
-  if (mask & SILC_UMODE_SERVER_OPERATOR) {
-    if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
-      /* Cannot operator mode */
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
-                                           SILC_STATUS_ERR_PERM_DENIED);
-      goto out;
-    }
-  } else {
-    /* Remove the server operator rights */
-    if (client->mode & SILC_UMODE_SERVER_OPERATOR) {
-      client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
-      if (client->connection)
-       server->stat.my_server_ops--;
-      if (server->server_type == SILC_ROUTER)
-       server->stat.server_ops--;
-    }
-  }
-
-  if (mask & SILC_UMODE_ROUTER_OPERATOR) {
-    if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
-      /* Cannot operator mode */
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
-                                           SILC_STATUS_ERR_PERM_DENIED);
-      goto out;
-    }
-  } else {
-    /* Remove the router operator rights */
-    if (client->mode & SILC_UMODE_ROUTER_OPERATOR) {
-      client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
-      if (client->connection)
-       server->stat.my_router_ops--;
-      if (server->server_type == SILC_ROUTER)
-       server->stat.router_ops--;
-    }
+  /* Check that mode changing is allowed. */
+  if (!silc_server_check_umode_rights(server, client, mask)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
+                                         SILC_STATUS_ERR_PERM_DENIED);
+    goto out;
   }
 
-  if (mask & SILC_UMODE_GONE) {
-    client->mode |= SILC_UMODE_GONE;
-  } else {
-    if (client->mode & SILC_UMODE_GONE)
-      /* Remove the gone status */
-      client->mode &= ~SILC_UMODE_GONE;
-  }
+  /* Change the mode */
+  client->mode = mask;
 
   /* Send UMODE change to primary router */
   if (!server->standalone)
@@ -3724,75 +3683,6 @@ SILC_SERVER_CMD_FUNC(umode)
   silc_server_command_free(cmd);
 }
 
-/* Checks that client has rights to add or remove channel modes. If any
-   of the checks fails FALSE is returned. */
-
-int silc_server_check_cmode_rights(SilcChannelEntry channel,
-                                  SilcChannelClientEntry client,
-                                  SilcUInt32 mode)
-{
-  int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
-  int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
-
-  /* Check whether has rights to change anything */
-  if (!is_op && !is_fo)
-    return FALSE;
-
-  /* Check whether has rights to change everything */
-  if (is_op && is_fo)
-    return TRUE;
-
-  /* We know that client is channel operator, check that they are not
-     changing anything that requires channel founder rights. Rest of the
-     modes are available automatically for channel operator. */
-
-  if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
-    if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
-      if (is_op && !is_fo)
-       return FALSE;
-  } else {
-    if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
-      if (is_op && !is_fo)
-       return FALSE;
-    }
-  }
-  
-  if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
-    if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
-      if (is_op && !is_fo)
-       return FALSE;
-  } else {
-    if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
-      if (is_op && !is_fo)
-       return FALSE;
-    }
-  }
-
-  if (mode & SILC_CHANNEL_MODE_CIPHER) {
-    if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
-      if (is_op && !is_fo)
-       return FALSE;
-  } else {
-    if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
-      if (is_op && !is_fo)
-       return FALSE;
-    }
-  }
-  
-  if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
-    if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
-      if (is_op && !is_fo)
-       return FALSE;
-  } else {
-    if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
-      if (is_op && !is_fo)
-       return FALSE;
-    }
-  }
-  
-  return TRUE;
-}
-
 /* Server side command of CMODE. Changes channel mode */
 
 SILC_SERVER_CMD_FUNC(cmode)
@@ -3819,7 +3709,7 @@ SILC_SERVER_CMD_FUNC(cmode)
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
     goto out;
   }
-  channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
+  channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
   if (!channel_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
@@ -3849,17 +3739,14 @@ SILC_SERVER_CMD_FUNC(cmode)
   }
 
   /* Check whether this client is on the channel */
-  if (!silc_server_client_on_channel(client, channel)) {
+  if (!silc_server_client_on_channel(client, channel, &chl)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                          SILC_STATUS_ERR_NOT_ON_CHANNEL);
     goto out;
   }
 
-  /* Get entry to the channel user list */
-  silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
-
   /* Check that client has rights to change any requested channel modes */
-  if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
+  if (!silc_server_check_cmode_rights(server, channel, chl, mode_mask)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV);
     goto out;
@@ -4202,7 +4089,7 @@ SILC_SERVER_CMD_FUNC(cumode)
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
     goto out;
   }
-  channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
+  channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
   if (!channel_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
@@ -4223,14 +4110,11 @@ SILC_SERVER_CMD_FUNC(cumode)
   }
 
   /* Check whether sender is on the channel */
-  if (!silc_server_client_on_channel(client, channel)) {
+  if (!silc_server_client_on_channel(client, channel, &chl)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                          SILC_STATUS_ERR_NOT_ON_CHANNEL);
     goto out;
   }
-
-  /* Check that client has rights to change other's rights */
-  silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
   sender_mask = chl->mode;
   
   /* Get the target client's channel mode mask */
@@ -4249,7 +4133,7 @@ SILC_SERVER_CMD_FUNC(cumode)
                                          SILC_STATUS_ERR_NO_CLIENT_ID);
     goto out;
   }
-  client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
+  client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
   if (!client_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                          SILC_STATUS_ERR_NO_CLIENT_ID);
@@ -4274,15 +4158,11 @@ SILC_SERVER_CMD_FUNC(cumode)
 
   /* Check whether target client is on the channel */
   if (target_client != client) {
-    if (!silc_server_client_on_channel(target_client, channel)) {
+    if (!silc_server_client_on_channel(target_client, channel, &chl)) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
       goto out;
     }
-
-    /* Get entry to the channel user list */
-    silc_hash_table_find(channel->user_list, target_client, NULL, 
-                        (void *)&chl);
   }
 
   /* 
@@ -4448,7 +4328,7 @@ SILC_SERVER_CMD_FUNC(kick)
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
     goto out;
   }
-  channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+  channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
   if (!channel_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
@@ -4469,14 +4349,13 @@ SILC_SERVER_CMD_FUNC(kick)
   }
 
   /* Check whether sender is on the channel */
-  if (!silc_server_client_on_channel(client, channel)) {
+  if (!silc_server_client_on_channel(client, channel, &chl)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
                                          SILC_STATUS_ERR_NOT_ON_CHANNEL);
     goto out;
   }
 
   /* Check that the kicker is channel operator or channel founder */
-  silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV);
@@ -4490,7 +4369,7 @@ SILC_SERVER_CMD_FUNC(kick)
                                          SILC_STATUS_ERR_NO_CLIENT_ID);
     goto out;
   }
-  client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
+  client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
   if (!client_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
                                          SILC_STATUS_ERR_NO_CLIENT_ID);
@@ -4505,22 +4384,21 @@ SILC_SERVER_CMD_FUNC(kick)
                                                  client_id, TRUE, NULL);
   }
 
+  /* Check whether target client is on the channel */
+  if (!silc_server_client_on_channel(target_client, channel, &chl)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
+                                         SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
+    goto out;
+  }
+
   /* Check that the target client is not channel founder. Channel founder
      cannot be kicked from the channel. */
-  silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
                                          SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
     goto out;
   }
   
-  /* Check whether target client is on the channel */
-  if (!silc_server_client_on_channel(target_client, channel)) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
-                                         SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
-    goto out;
-  }
-
   /* Get comment */
   tmp_len = 0;
   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
@@ -4839,7 +4717,7 @@ SILC_SERVER_CMD_FUNC(ban)
   /* Get Channel ID */
   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
   if (id) {
-    channel_id = silc_id_payload_parse_id(id, id_len);
+    channel_id = silc_id_payload_parse_id(id, id_len, NULL);
     if (!channel_id) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
                                            SILC_STATUS_ERR_NO_CHANNEL_ID);
@@ -4862,14 +4740,7 @@ SILC_SERVER_CMD_FUNC(ban)
   }
 
   /* Check whether this client is on the channel */
-  if (!silc_server_client_on_channel(client, channel)) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
-                                         SILC_STATUS_ERR_NOT_ON_CHANNEL);
-    goto out;
-  }
-
-  /* Get entry to the channel user list */
-  if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
+  if (!silc_server_client_on_channel(client, channel, &chl)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
                                          SILC_STATUS_ERR_NOT_ON_CHANNEL);
     goto out;
@@ -5072,7 +4943,7 @@ SILC_SERVER_CMD_FUNC(leave)
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
     goto out;
   }
-  id = silc_id_payload_parse_id(tmp, len);
+  id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
@@ -5091,7 +4962,7 @@ SILC_SERVER_CMD_FUNC(leave)
   }
 
   /* Check whether this client is on the channel */
-  if (!silc_server_client_on_channel(id_entry, channel)) {
+  if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
                                          SILC_STATUS_ERR_NOT_ON_CHANNEL);
     goto out;
@@ -5164,7 +5035,7 @@ SILC_SERVER_CMD_FUNC(users)
   }
 
   if (channel_id) {
-    id = silc_id_payload_parse_id(channel_id, channel_id_len);
+    id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
     if (!id) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
                                            SILC_STATUS_ERR_NO_CHANNEL_ID);
@@ -5224,7 +5095,8 @@ SILC_SERVER_CMD_FUNC(users)
      user requesting this command is on the channel. */
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
-       && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
+       && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
+                                         NULL)) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL);
       goto out;
index 3c4f490e4c46e4d9c6ead1999520079160318649..c87c2c5727d3ac342c155ad112e4e9ef20bd901f 100644 (file)
@@ -158,7 +158,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
   if (tmp)
     SILC_GET32_MSB(mode, tmp);
 
-  client_id = silc_id_payload_parse_id(id_data, id_len);
+  client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
   if (!client_id)
     return FALSE;
 
@@ -278,7 +278,7 @@ SILC_SERVER_CMD_REPLY_FUNC(whois)
     SilcUInt32 tmp_len;
     unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
     if (tmp) {
-      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
       if (client_id) {
        SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
                        "the entry from cache"));
@@ -321,7 +321,7 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
 
   realname = silc_argument_get_arg_type(cmd->args, 5, &len);
 
-  client_id = silc_id_payload_parse_id(id_data, id_len);
+  client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
   if (!client_id)
     return FALSE;
 
@@ -639,7 +639,7 @@ SILC_SERVER_CMD_REPLY_FUNC(identify)
     SilcUInt32 tmp_len;
     unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
     if (tmp) {
-      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
       if (client_id) {
        SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
                        "the entry from cache"));
@@ -677,7 +677,7 @@ SILC_SERVER_CMD_REPLY_FUNC(info)
   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
   if (!tmp)
     goto out;
-  server_id = silc_id_payload_parse_id(tmp, tmp_len);
+  server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
   if (!server_id)
     goto out;
 
@@ -734,7 +734,7 @@ SILC_SERVER_CMD_REPLY_FUNC(motd)
   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
   if (!tmp)
     goto out;
-  server_id = silc_id_payload_parse_id(tmp, tmp_len);
+  server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
   if (!server_id)
     goto out;
 
@@ -798,7 +798,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
   tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
   if (!tmp)
     goto out;
-  client_id = silc_id_payload_parse_id(tmp, len);
+  client_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!client_id)
     goto out;
 
@@ -825,7 +825,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
   }
 
   /* Parse the Channel ID */
-  id = silc_id_payload_parse_id(id_string, id_len);
+  id = silc_id_payload_parse_id(id_string, id_len, NULL);
   if (!id)
     goto out;
 
@@ -991,7 +991,7 @@ SILC_SERVER_CMD_REPLY_FUNC(users)
   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
   if (!tmp)
     goto out;
-  channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+  channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
   if (!channel_id)
     goto out;
 
@@ -1162,7 +1162,7 @@ SILC_SERVER_CMD_REPLY_FUNC(list)
   COMMAND_CHECK_STATUS_LIST;
 
   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
-  channel_id = silc_id_payload_parse_id(tmp, len);
+  channel_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!channel_id)
     goto out;
 
index 61b3e4faf1d8eda17a9a9d6534352150bf636c0a..87f8b70f082d61ad3b50a025a15e510c5b72c108 100644 (file)
@@ -40,9 +40,10 @@ void silc_server_notify(SilcServer server,
   SilcChannelID *channel_id = NULL, *channel_id2;
   SilcClientID *client_id, *client_id2;
   SilcServerID *server_id;
-  SilcChannelEntry channel;
-  SilcClientEntry client;
-  SilcServerEntry server_entry;
+  SilcIdType id_type;
+  SilcChannelEntry channel = NULL;
+  SilcClientEntry client = NULL, client2 = NULL;
+  SilcServerEntry server_entry = NULL;
   SilcChannelClientEntry chl;
   SilcIDCacheEntry cache;
   SilcHashTableList htl;
@@ -138,7 +139,7 @@ void silc_server_notify(SilcServer server,
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
     if (!tmp)
       goto out;
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!channel_id)
       goto out;
 
@@ -159,7 +160,7 @@ void silc_server_notify(SilcServer server,
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
@@ -197,7 +198,7 @@ void silc_server_notify(SilcServer server,
       break;
 
     /* Do not add client to channel if it is there already */
-    if (silc_server_client_on_channel(client, channel)) {
+    if (silc_server_client_on_channel(client, channel, NULL)) {
       SILC_LOG_DEBUG(("Client already on channel"));
       break;
     }
@@ -263,7 +264,7 @@ void silc_server_notify(SilcServer server,
       silc_free(channel_id);
       goto out;
     }
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id) {
       silc_free(channel_id);
       goto out;
@@ -284,7 +285,7 @@ void silc_server_notify(SilcServer server,
     silc_free(client_id);
 
     /* Check if on channel */
-    if (!silc_server_client_on_channel(client, channel))
+    if (!silc_server_client_on_channel(client, channel, NULL))
       break;
 
     /* Send the leave notify to channel */
@@ -306,7 +307,7 @@ void silc_server_notify(SilcServer server,
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
@@ -349,6 +350,27 @@ void silc_server_notify(SilcServer server,
 
     SILC_LOG_DEBUG(("TOPIC SET notify"));
 
+    /* Get client ID */
+    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+    if (!tmp)
+      goto out;
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+    if (!client_id)
+      goto out;
+
+    /* Get client entry */
+    client = silc_idlist_find_client_by_id(server->global_list, 
+                                          client_id, TRUE, &cache);
+    if (!client) {
+      client = silc_idlist_find_client_by_id(server->local_list, 
+                                            client_id, TRUE, &cache);
+      if (!client) {
+       silc_free(client_id);
+       goto out;
+      }
+    }
+    silc_free(client_id);
+
     if (!channel_id) {
       channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
                                  packet->dst_id_type);
@@ -375,6 +397,14 @@ void silc_server_notify(SilcServer server,
       goto out;
     }
 
+    /* Get user's channel entry and check that topic set is allowed. */
+    if (!silc_server_client_on_channel(client, channel, &chl))
+      goto out;
+    if (chl->mode == SILC_CHANNEL_UMODE_NONE && 
+       channel->mode & SILC_CHANNEL_MODE_TOPIC)
+      goto out;
+
+    /* Set the topic for channel */    
     silc_free(channel->topic);
     channel->topic = strdup(tmp);
 
@@ -398,7 +428,7 @@ void silc_server_notify(SilcServer server,
       id = silc_argument_get_arg_type(args, 1, &tmp_len);
       if (!id)
        goto out;
-      client_id = silc_id_payload_parse_id(id, tmp_len);
+      client_id = silc_id_payload_parse_id(id, tmp_len, NULL);
       if (!client_id)
        goto out;
       
@@ -406,7 +436,7 @@ void silc_server_notify(SilcServer server,
       id2 = silc_argument_get_arg_type(args, 2, &tmp_len);
       if (!id2)
        goto out;
-      client_id2 = silc_id_payload_parse_id(id2, tmp_len);
+      client_id2 = silc_id_payload_parse_id(id2, tmp_len, NULL);
       if (!client_id2)
        goto out;
       
@@ -450,6 +480,29 @@ void silc_server_notify(SilcServer server,
     
     SILC_LOG_DEBUG(("CMODE CHANGE notify"));
       
+    /* Get client ID */
+    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+    if (!tmp)
+      goto out;
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
+    if (!client_id)
+      goto out;
+
+    /* Get client entry */
+    if (id_type == SILC_ID_CLIENT) {
+      client = silc_idlist_find_client_by_id(server->global_list, 
+                                            client_id, TRUE, &cache);
+      if (!client) {
+       client = silc_idlist_find_client_by_id(server->local_list, 
+                                              client_id, TRUE, &cache);
+       if (!client) {
+         silc_free(client_id);
+         goto out;
+       }
+      }
+      silc_free(client_id);
+    }
+
     if (!channel_id) {
       channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
                                  packet->dst_id_type);
@@ -468,20 +521,26 @@ void silc_server_notify(SilcServer server,
        goto out;
       }
     }
+    silc_free(channel_id);
 
     /* Get the mode */
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
-    if (!tmp) {
-      silc_free(channel_id);
+    if (!tmp)
       goto out;
-    }
-
     SILC_GET32_MSB(mode, tmp);
 
     /* Check if mode changed */
     if (channel->mode == mode)
       break;
 
+    /* Get user's channel entry and check that mode change is allowed */
+    if (client) {
+      if (!silc_server_client_on_channel(client, channel, &chl))
+       goto out;
+      if (!silc_server_check_cmode_rights(server, channel, chl, mode))
+       goto out;
+    }
+
     /* Send the same notify to the channel */
     silc_server_packet_send_to_channel(server, sock, channel, packet->type, 
                                       FALSE, packet->buffer->data, 
@@ -504,7 +563,6 @@ void silc_server_notify(SilcServer server,
 
     /* Change mode */
     channel->mode = mode;
-    silc_free(channel_id);
 
     /* Get the hmac */
     tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
@@ -545,6 +603,29 @@ void silc_server_notify(SilcServer server,
       
       SILC_LOG_DEBUG(("CUMODE CHANGE notify"));
       
+      /* Get client ID */
+      tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+      if (!tmp)
+       goto out;
+      client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
+      if (!client_id)
+       goto out;
+
+      /* Get client entry */
+      if (id_type == SILC_ID_CLIENT) {
+       client = silc_idlist_find_client_by_id(server->global_list, 
+                                              client_id, TRUE, &cache);
+       if (!client) {
+         client = silc_idlist_find_client_by_id(server->local_list, 
+                                                client_id, TRUE, &cache);
+         if (!client) {
+           silc_free(client_id);
+           goto out;
+         }
+       }
+       silc_free(client_id);
+      }
+
       if (!channel_id) {
        channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
                                    packet->dst_id_type);
@@ -577,23 +658,43 @@ void silc_server_notify(SilcServer server,
       tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
       if (!tmp)
        goto out;
-      client_id = silc_id_payload_parse_id(tmp, tmp_len);
+      client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
       if (!client_id)
        goto out;
       
       /* Get client entry */
-      client = silc_idlist_find_client_by_id(server->global_list, 
-                                            client_id, TRUE, NULL);
-      if (!client) {
-       client = silc_idlist_find_client_by_id(server->local_list, 
-                                              client_id, TRUE, NULL);
-       if (!client) {
+      client2 = silc_idlist_find_client_by_id(server->global_list, 
+                                             client_id, TRUE, NULL);
+      if (!client2) {
+       client2 = silc_idlist_find_client_by_id(server->local_list, 
+                                               client_id, TRUE, NULL);
+       if (!client2) {
          silc_free(client_id);
          goto out;
        }
       }
       silc_free(client_id);
 
+      if (client) {
+       /* Check that sender is on channel */
+       if (!silc_server_client_on_channel(client, channel, &chl))
+         goto out;
+       
+       if (client != client2) {
+         /* Sender must be operator */
+         if (chl->mode == SILC_CHANNEL_UMODE_NONE)
+           goto out;
+
+         /* Check that target is on channel */
+         if (!silc_server_client_on_channel(client2, channel, &chl))
+           goto out;
+
+         /* If target is founder mode change is not allowed. */
+         if (chl->mode & SILC_CHANNEL_UMODE_CHANFO)
+           goto out;
+       }
+      }
+
       /* Get entry to the channel user list */
       silc_hash_table_list(channel->user_list, &htl);
       while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
@@ -614,10 +715,10 @@ void silc_server_notify(SilcServer server,
 
          mode &= ~SILC_CHANNEL_UMODE_CHANFO;
          silc_server_send_notify_cumode(server, sock, FALSE, channel, mode,
-                                        client->id, SILC_ID_CLIENT,
-                                        client->id);
+                                        client2->id, SILC_ID_CLIENT,
+                                        client2->id);
          
-         idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+         idp = silc_id_payload_encode(client2->id, SILC_ID_CLIENT);
          SILC_PUT32_MSB(mode, cumode);
          silc_server_send_notify_to_channel(server, sock, channel, FALSE, 
                                             SILC_NOTIFY_TYPE_CUMODE_CHANGE,
@@ -636,7 +737,7 @@ void silc_server_notify(SilcServer server,
          }
        }
        
-       if (chl->client == client) {
+       if (chl->client == client2) {
          if (chl->mode == mode) {
            notify_sent = TRUE;
            break;
@@ -676,7 +777,7 @@ void silc_server_notify(SilcServer server,
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!channel_id)
       goto out;
 
@@ -693,8 +794,36 @@ void silc_server_notify(SilcServer server,
     }
     silc_free(channel_id);
 
-    /* Get the added invite */
+    /* Get client ID */
     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+    if (!tmp)
+      goto out;
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+    if (!client_id)
+      goto out;
+
+    /* Get client entry */
+    client = silc_idlist_find_client_by_id(server->global_list, 
+                                          client_id, TRUE, &cache);
+    if (!client) {
+      client = silc_idlist_find_client_by_id(server->local_list, 
+                                            client_id, TRUE, &cache);
+      if (!client) {
+       silc_free(client_id);
+       goto out;
+      }
+    }
+    silc_free(client_id);
+
+    /* Get user's channel entry and check that inviting is allowed. */
+    if (!silc_server_client_on_channel(client, channel, &chl))
+      goto out;
+    if (chl->mode == SILC_CHANNEL_UMODE_NONE && 
+       channel->mode & SILC_CHANNEL_MODE_INVITE)
+      goto out;
+
+    /* Get the added invite */
+    tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
     if (tmp) {
       if (!channel->invite_list)
        channel->invite_list = silc_calloc(tmp_len + 2, 
@@ -713,7 +842,7 @@ void silc_server_notify(SilcServer server,
     }
 
     /* Get the deleted invite */
-    tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
+    tmp = silc_argument_get_arg_type(args, 5, &tmp_len);
     if (tmp && channel->invite_list) {
       char *start, *end, *n;
       
@@ -752,7 +881,7 @@ void silc_server_notify(SilcServer server,
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!channel_id)
       goto out;
 
@@ -777,7 +906,7 @@ void silc_server_notify(SilcServer server,
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
     if (!tmp)
       goto out;
-    channel_id2 = silc_id_payload_parse_id(tmp, tmp_len);
+    channel_id2 = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!channel_id2)
       goto out;
 
@@ -850,7 +979,7 @@ void silc_server_notify(SilcServer server,
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-    server_id = silc_id_payload_parse_id(tmp, tmp_len);
+    server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!server_id)
       goto out;
 
@@ -876,7 +1005,7 @@ void silc_server_notify(SilcServer server,
            tmp = silc_argument_get_arg_type(args, i + 1, &tmp_len);
            if (!tmp)
              continue;
-           client_id = silc_id_payload_parse_id(tmp, tmp_len);
+           client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
            if (!client_id)
              continue;
 
@@ -961,7 +1090,7 @@ void silc_server_notify(SilcServer server,
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
@@ -976,6 +1105,41 @@ void silc_server_notify(SilcServer server,
        goto out;
       }
     }
+    silc_free(client_id);
+
+    /* If target is founder they cannot be kicked */
+    if (!silc_server_client_on_channel(client, channel, &chl))
+      goto out;
+    if (chl->mode & SILC_CHANNEL_UMODE_CHANFO)
+      goto out;
+    
+    /* Get kicker. In protocol version 1.0 this is not mandatory argument
+       so we check it only if it is provided. */
+    tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+    if (tmp) {
+      client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+      if (!client_id)
+       goto out;
+
+      /* If the the client is not in local list we check global list */
+      client2 = silc_idlist_find_client_by_id(server->global_list, 
+                                             client_id, TRUE, NULL);
+      if (!client2) {
+       client = silc_idlist_find_client_by_id(server->local_list, 
+                                              client_id, TRUE, NULL);
+       if (!client2) {
+         silc_free(client_id);
+         goto out;
+       }
+      }
+      silc_free(client_id);
+
+      /* Kicker must be operator on channel */
+      if (!silc_server_client_on_channel(client2, channel, &chl))
+       goto out;
+      if (chl->mode == SILC_CHANNEL_UMODE_NONE)
+       goto out;
+    }
 
     /* Send to channel */
     silc_server_packet_send_to_channel(server, sock, channel, packet->type, 
@@ -1001,7 +1165,7 @@ void silc_server_notify(SilcServer server,
       id = silc_argument_get_arg_type(args, 1, &id_len);
       if (!id)
        goto out;
-      client_id = silc_id_payload_parse_id(id, id_len);
+      client_id = silc_id_payload_parse_id(id, id_len, NULL);
       if (!client_id)
        goto out;
 
@@ -1058,7 +1222,7 @@ void silc_server_notify(SilcServer server,
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
@@ -1081,30 +1245,11 @@ void silc_server_notify(SilcServer server,
       goto out;
     SILC_GET32_MSB(mode, tmp);
 
-#define SILC_UMODE_STATS_UPDATE(oper, mod)     \
-do {                                           \
-    if (client->mode & (mod)) {                        \
-      if (!(mode & (mod))) {                   \
-       if (client->connection)                 \
-         server->stat.my_ ## oper ## _ops--;   \
-        if (server->server_type == SILC_ROUTER)        \
-         server->stat. oper ## _ops--;         \
-      }                                                \
-    } else {                                   \
-      if (mode & (mod)) {                      \
-       if (client->connection)                 \
-         server->stat.my_ ## oper ## _ops++;   \
-        if (server->server_type == SILC_ROUTER)        \
-         server->stat. oper ## _ops++;         \
-      }                                                \
-    }                                          \
-} while(0)
-
-    /* Update statistics */
-    SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
-    SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
+    /* Check that mode changing is allowed. */
+    if (!silc_server_check_umode_rights(server, client, mode))
+      goto out;
 
-    /* Save the mode */
+    /* Change the mode */
     client->mode = mode;
 
     break;
@@ -1120,7 +1265,7 @@ do {                                              \
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!channel_id)
       goto out;
     
@@ -1413,8 +1558,8 @@ void silc_server_channel_message(SilcServer server,
 {
   SilcChannelEntry channel = NULL;
   SilcChannelID *id = NULL;
-  void *sender = NULL;
-  void *sender_entry = NULL;
+  void *sender_id = NULL;
+  SilcClientEntry sender_entry = NULL;
   bool local = TRUE;
 
   SILC_LOG_DEBUG(("Processing channel message"));
@@ -1440,27 +1585,28 @@ void silc_server_channel_message(SilcServer server,
 
   /* See that this client is on the channel. If the original sender is
      not client (as it can be server as well) we don't do the check. */
-  sender = silc_id_str2id(packet->src_id, packet->src_id_len, 
-                         packet->src_id_type);
-  if (!sender)
+  sender_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
+                            packet->src_id_type);
+  if (!sender_id)
     goto out;
   if (packet->src_id_type == SILC_ID_CLIENT) {
     sender_entry = silc_idlist_find_client_by_id(server->local_list, 
-                                                sender, TRUE, NULL);
+                                                sender_id, TRUE, NULL);
     if (!sender_entry) {
       local = FALSE;
       sender_entry = silc_idlist_find_client_by_id(server->global_list, 
-                                                  sender, TRUE, NULL);
+                                                  sender_id, TRUE, NULL);
     }
     if (!sender_entry || !silc_server_client_on_channel(sender_entry, 
-                                                       channel)) {
+                                                       channel, NULL)) {
       SILC_LOG_DEBUG(("Client not on channel"));
       goto out;
     }
 
-    /* If the packet is coming from router, but the client entry is
-       local entry to us then some router is rerouting this to us and it is
-       not allowed. */
+    /* If the packet is coming from router, but the client entry is local 
+       entry to us then some router is rerouting this to us and it is not 
+       allowed. When the client is local to us it means that we've routed
+       this packet to network, and now someone is routing it back to us. */
     if (server->server_type == SILC_ROUTER &&
        sock->type == SILC_SOCKET_TYPE_ROUTER && local) {
       SILC_LOG_DEBUG(("Channel message rerouted to the sender, drop it"));
@@ -1470,16 +1616,14 @@ void silc_server_channel_message(SilcServer server,
 
   /* Distribute the packet to our local clients. This will send the
      packet for further routing as well, if needed. */
-  silc_server_packet_relay_to_channel(server, sock, channel, sender,
+  silc_server_packet_relay_to_channel(server, sock, channel, sender_id,
                                      packet->src_id_type, sender_entry,
                                      packet->buffer->data,
                                      packet->buffer->len, FALSE);
 
  out:
-  if (sender)
-    silc_free(sender);
-  if (id)
-    silc_free(id);
+  silc_free(sender_id);
+  silc_free(id);
 }
 
 /* Received channel key packet. We distribute the key to all of our locally
index a6191b799191098310069d7284be31b42ce18d73..da4379ea9827db611dd8896f26d33ddc926c764a 100644 (file)
@@ -610,7 +610,8 @@ void silc_server_packet_send_to_channel(SilcServer server,
       if (sender && sock == sender)
        continue;
 
-      /* Route only once to router */
+      /* Route only once to router. Protocol prohibits sending channel
+        messages to more than one router. */
       if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
        if (gone)
          continue;
@@ -677,32 +678,18 @@ silc_server_packet_relay_to_channel_encrypt(SilcServer server,
       sock->type == SILC_SOCKET_TYPE_ROUTER &&
       !(channel->mode & SILC_CHANNEL_MODE_PRIVKEY) &&
       channel->channel_key) {
-    SilcBuffer chp;
-    SilcUInt32 iv_len, i;
-    SilcUInt16 dlen, flags;
-
-    iv_len = silc_cipher_get_block_len(channel->channel_key);
-    if (channel->iv[0] == '\0')
-      for (i = 0; i < iv_len; i++) channel->iv[i] = 
-                                    silc_rng_get_byte(server->rng);
-    else
-      silc_hash_make(server->md5hash, channel->iv, iv_len, channel->iv);
-    
-    /* Encode new payload. This encrypts it also. */
-    SILC_GET16_MSB(flags, data);
-    SILC_GET16_MSB(dlen, data + 2);
+    SilcUInt32 mac_len = silc_hmac_len(channel->hmac);
+    SilcUInt32 iv_len = silc_cipher_get_block_len(channel->channel_key);
 
-    if (dlen > data_len) {
+    if (data_len <= mac_len + iv_len) {
       SILC_LOG_WARNING(("Corrupted channel message, cannot relay it"));
       return FALSE;
     }
 
-    chp = silc_channel_message_payload_encode(flags, dlen, data + 4,
-                                             iv_len, channel->iv,
-                                             channel->channel_key,
-                                             channel->hmac, NULL);
-    memcpy(data, chp->data, chp->len);
-    silc_buffer_free(chp);
+    memcpy(channel->iv, data + (data_len - iv_len), iv_len);
+    silc_channel_message_payload_encrypt(data, data_len - iv_len - mac_len,
+                                        data_len, channel->iv, iv_len,
+                                        channel->channel_key, channel->hmac);
   }
 
   return TRUE;
@@ -720,14 +707,13 @@ silc_server_packet_relay_to_channel_encrypt(SilcServer server,
 void silc_server_packet_relay_to_channel(SilcServer server,
                                         SilcSocketConnection sender_sock,
                                         SilcChannelEntry channel,
-                                        void *sender
+                                        void *sender_id,
                                         SilcIdType sender_type,
-                                        void *sender_entry,
+                                        SilcClientEntry sender_entry,
                                         unsigned char *data,
                                         SilcUInt32 data_len,
                                         bool force_send)
 {
-  bool found = FALSE;
   SilcSocketConnection sock = NULL;
   SilcPacketContext packetdata;
   SilcClientEntry client = NULL;
@@ -753,8 +739,8 @@ void silc_server_packet_relay_to_channel(SilcServer server,
   /* Set the packet context pointers. */
   packetdata.flags = 0;
   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
-  packetdata.src_id = silc_id_id2str(sender, sender_type);
-  packetdata.src_id_len = silc_id_get_len(sender, sender_type);
+  packetdata.src_id = silc_id_id2str(sender_id, sender_type);
+  packetdata.src_id_len = silc_id_get_len(sender_id, sender_type);
   packetdata.src_id_type = sender_type;
   packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
   packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
@@ -787,59 +773,34 @@ void silc_server_packet_relay_to_channel(SilcServer server,
   routed = silc_calloc(silc_hash_table_count(channel->user_list), 
                       sizeof(*routed));
 
-  /* Mark that to the route the original sender if from is not routed */
-  if (sender_type == SILC_ID_CLIENT) {
-    client = (SilcClientEntry)sender_entry;
-    if (client->router) {
-      routed[routed_count++] = client->router;
-      SILC_LOG_DEBUG(("************* router %s", 
-                     silc_id_render(client->router->id, SILC_ID_SERVER)));
-    }
-  }
+  /* Assure we won't route the message back to the sender's way. */
+  if (sender_entry->router)
+    routed[routed_count++] = sender_entry->router;
 
   /* Send the message to clients on the channel's client list. */
   silc_hash_table_list(channel->user_list, &htl);
   while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     client = chl->client;
-    if (!client)
+    if (!client || client == sender_entry)
       continue;
 
-    /* Do not send to the sender */
-    if (!found && client == sender_entry) {
-      found = TRUE;
-      continue;
-    }
-
     /* If the client has set router it means that it is not locally
        connected client and we will route the packet further. */
     if (server->server_type == SILC_ROUTER && client->router) {
 
-      /* Sender maybe server as well so we want to make sure that
-        we won't send the message to the server it came from. */
-      if (!found && SILC_ID_SERVER_COMPARE(client->router->id, sender)) {
-       found = TRUE;
-       routed[routed_count++] = client->router;
-       continue;
-      }
-
       /* Check if we have sent the packet to this route already */
       for (k = 0; k < routed_count; k++)
        if (routed[k] == client->router)
          break;
       if (k < routed_count)
        continue;
-       
+
       /* Get data used in packet header encryption, keys and stuff. */
       sock = (SilcSocketConnection)client->router->connection;
       idata = (SilcIDListData)client->router;
 
-      /* Do not send to the sender. Check first whether the true
-        sender's router is same as this client's router. Also check
-        if the sender socket is the same as this client's router
+      /* Check if the sender socket is the same as this client's router
         socket. */
-      if (sender_entry &&
-         ((SilcClientEntry)sender_entry)->router == client->router)
-       continue;
       if (sender_sock && sock == sender_sock)
        continue;
 
@@ -850,63 +811,60 @@ void silc_server_packet_relay_to_channel(SilcServer server,
       /* Mark this route routed already. */
       routed[routed_count++] = client->router;
        
-      /* If the remote connection is router then we'll decrypt the
-        channel message and re-encrypt it with the session key shared
-        between us and the remote router. This is done because the
-        channel keys are cell specific and we have different channel
-        key than the remote router has. */
       if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+       /* The remote connection is router then we'll decrypt the
+          channel message and re-encrypt it with the session key shared
+          between us and the remote router. This is done because the
+          channel keys are cell specific and we have different channel
+          key than the remote router has. */
+
+       /* Route only once to router. Protocol prohibits sending channel
+          messages to more than one router. */
        if (gone)
          continue;
+       gone = TRUE;
 
        SILC_LOG_DEBUG(("Remote is router, encrypt with session key"));
-       gone = TRUE;
 
        /* If private key mode is not set then decrypt the packet
           and re-encrypt it */
-       if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
-         unsigned char *tmp = silc_memdup(data, data_len);
+       if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY) && 
+           channel->channel_key) {
+         unsigned char tmp[SILC_PACKET_MAX_LEN];
+
+         if (data_len > SILC_PACKET_MAX_LEN)
+           data_len = SILC_PACKET_MAX_LEN;
+         memcpy(tmp, data, data_len);
 
          /* Decrypt the channel message (we don't check the MAC) */
-         if (channel->channel_key &&
-             !silc_channel_message_payload_decrypt(tmp, data_len, 
-                                                   channel->channel_key,
-                                                   NULL)) {
-           memset(tmp, 0, data_len);
-           silc_free(tmp);
-           continue;
-         }
+         silc_channel_message_payload_decrypt(tmp, data_len,
+                                              channel->channel_key, NULL);
 
          /* Now re-encrypt and send it to the router */
-         silc_server_packet_send_srcdest(server, sock, 
+         silc_server_packet_send_srcdest(server, sock,
                                          SILC_PACKET_CHANNEL_MESSAGE, 0,
-                                         sender, sender_type,
+                                         sender_id, sender_type,
                                          channel->id, SILC_ID_CHANNEL,
                                          tmp, data_len, force_send);
-
-         /* Free the copy of the channel message */
-         memset(tmp, 0, data_len);
-         silc_free(tmp);
        } else {
          /* Private key mode is set, we don't have the channel key, so
             just re-encrypt the entire packet and send it to the router. */
-         silc_server_packet_send_srcdest(server, sock, 
+         silc_server_packet_send_srcdest(server, sock,
                                          SILC_PACKET_CHANNEL_MESSAGE, 0,
-                                         sender, sender_type,
+                                         sender_id, sender_type,
                                          channel->id, SILC_ID_CHANNEL,
                                          data, data_len, force_send);
        }
-       continue;
+      } else {
+       /* Send the packet to normal server */
+       silc_server_packet_send_to_channel_real(server, sock, &packetdata,
+                                               idata->send_key,
+                                               idata->hmac_send,
+                                               idata->psn_send++,
+                                               data, data_len, TRUE,
+                                               force_send);
       }
 
-      /* Send the packet (to normal server) */
-      silc_server_packet_send_to_channel_real(server, sock, &packetdata,
-                                             idata->send_key, 
-                                             idata->hmac_send, 
-                                             idata->psn_send++, 
-                                             data, data_len, TRUE, 
-                                             force_send);
-
       continue;
     }
 
index 703eaeafae9392acdd11a35bb8fa95e2e70c5baa..e6abf48e062eb4b16fdf7f16239532fc78710072 100644 (file)
@@ -79,9 +79,9 @@ void silc_server_packet_send_to_channel(SilcServer server,
 void silc_server_packet_relay_to_channel(SilcServer server,
                                         SilcSocketConnection sender_sock,
                                         SilcChannelEntry channel,
-                                        void *sender, 
+                                        void *sender_id
                                         SilcIdType sender_type,
-                                        void *sender_entry,
+                                        SilcClientEntry sender_entry,
                                         unsigned char *data,
                                         SilcUInt32 data_len,
                                         bool force_send);
index cc43d3ba596fbdc7becd9668e18a9a196a17bc33..609b02df49ca39131d1c1bd73c4e2e634e71743f 100644 (file)
@@ -3800,7 +3800,7 @@ void silc_server_save_users_on_channel(SilcServer server,
     /* Client ID */
     SILC_GET16_MSB(idp_len, user_list->data + 2);
     idp_len += 4;
-    client_id = silc_id_payload_parse_id(user_list->data, idp_len);
+    client_id = silc_id_payload_parse_id(user_list->data, idp_len, NULL);
     silc_buffer_pull(user_list, idp_len);
     if (!client_id)
       continue;
@@ -3855,7 +3855,7 @@ void silc_server_save_users_on_channel(SilcServer server,
 
     silc_free(client_id);
 
-    if (!silc_server_client_on_channel(client, channel)) {
+    if (!silc_server_client_on_channel(client, channel, NULL)) {
       /* Client was not on the channel, add it. */
       SilcChannelClientEntry chl = silc_calloc(1, sizeof(*chl));
       chl->client = client;
index b0d38cb1473604d776f351462d8de85d0c6f00c1..d0062e11ca3b174eb69c520283d22d509e3903bc 100644 (file)
@@ -175,6 +175,25 @@ do {                                               \
   }                                            \
 } while(0)
 
+#define SILC_UMODE_STATS_UPDATE(oper, mod)     \
+do {                                           \
+    if (client->mode & (mod)) {                        \
+      if (!(mode & (mod))) {                   \
+       if (client->connection)                 \
+         server->stat.my_ ## oper ## _ops--;   \
+        if (server->server_type == SILC_ROUTER)        \
+         server->stat. oper ## _ops--;         \
+      }                                                \
+    } else {                                   \
+      if (mode & (mod)) {                      \
+       if (client->connection)                 \
+         server->stat.my_ ## oper ## _ops++;   \
+        if (server->server_type == SILC_ROUTER)        \
+         server->stat. oper ## _ops++;         \
+      }                                                \
+    }                                          \
+} while(0)
+
 #define SILC_GET_SKE_FLAGS(x, p)                       \
   if ((x)) {                                           \
     if ((x)->param && (x)->param->key_exchange_pfs)    \
index 529b75de5fdcca6999210533542f7fa7350b9944..cad3223a67a16a8e91cf01c2d28ca448066ead8c 100644 (file)
@@ -743,12 +743,14 @@ bool silc_server_channel_has_local(SilcChannelEntry channel)
    `client' which is faster than checking the user list from `channel'. */
 
 bool silc_server_client_on_channel(SilcClientEntry client,
-                                  SilcChannelEntry channel)
+                                  SilcChannelEntry channel,
+                                  SilcChannelClientEntry *chl)
 {
   if (!client || !channel)
     return FALSE;
 
-  return silc_hash_table_find(client->channels, channel, NULL, NULL);
+  return silc_hash_table_find(client->channels, channel, NULL, 
+                             (void **)chl);
 }
 
 /* Checks string for bad characters and returns TRUE if they are found. */
@@ -957,3 +959,110 @@ bool silc_server_connection_allowed(SilcServer server,
 
   return TRUE;
 }
+
+/* Checks that client has rights to add or remove channel modes. If any
+   of the checks fails FALSE is returned. */
+
+bool silc_server_check_cmode_rights(SilcServer server,
+                                   SilcChannelEntry channel,
+                                   SilcChannelClientEntry client,
+                                   SilcUInt32 mode)
+{
+  bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
+  bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
+
+  /* Check whether has rights to change anything */
+  if (!is_op && !is_fo)
+    return FALSE;
+
+  /* Check whether has rights to change everything */
+  if (is_op && is_fo)
+    return TRUE;
+
+  /* We know that client is channel operator, check that they are not
+     changing anything that requires channel founder rights. Rest of the
+     modes are available automatically for channel operator. */
+
+  if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
+    if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
+      if (is_op && !is_fo)
+       return FALSE;
+  } else {
+    if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
+      if (is_op && !is_fo)
+       return FALSE;
+    }
+  }
+  
+  if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
+    if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
+      if (is_op && !is_fo)
+       return FALSE;
+  } else {
+    if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
+      if (is_op && !is_fo)
+       return FALSE;
+    }
+  }
+
+  if (mode & SILC_CHANNEL_MODE_CIPHER) {
+    if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
+      if (is_op && !is_fo)
+       return FALSE;
+  } else {
+    if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
+      if (is_op && !is_fo)
+       return FALSE;
+    }
+  }
+  
+  if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
+    if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
+      if (is_op && !is_fo)
+       return FALSE;
+  } else {
+    if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
+      if (is_op && !is_fo)
+       return FALSE;
+    }
+  }
+  
+  return TRUE;
+}
+
+/* Check that the client has rights to change its user mode.  Returns
+   FALSE if setting some mode is not allowed. */
+
+bool silc_server_check_umode_rights(SilcServer server,
+                                   SilcClientEntry client,
+                                   SilcUInt32 mode)
+{
+  bool server_op = FALSE, router_op = FALSE;
+
+  if (mode & SILC_UMODE_SERVER_OPERATOR) {
+    /* Cannot set server operator mode (must use OPER command) */
+    if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
+      return FALSE;
+  } else {
+    /* Remove the server operator rights */
+    if (client->mode & SILC_UMODE_SERVER_OPERATOR)
+      server_op = TRUE;
+  }
+
+  if (mode & SILC_UMODE_ROUTER_OPERATOR) {
+    /* Cannot set router operator mode (must use SILCOPER command) */
+    if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
+      return FALSE;
+  } else {
+    /* Remove the router operator rights */
+    if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
+      router_op = TRUE;
+  }
+
+  if (server_op)
+    SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
+  if (router_op)
+    SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
+
+  return TRUE;
+}
index 4feb4ee545bd8f6d977b9cb2ce50a9519f20a1b3..8300a4b57b997fab3b248610d8517f302291fd46 100644 (file)
@@ -72,7 +72,8 @@ bool silc_server_channel_has_local(SilcChannelEntry channel);
    always in up to date thus we can only check the channel list from 
    `client' which is faster than checking the user list from `channel'. */
 bool silc_server_client_on_channel(SilcClientEntry client,
-                                  SilcChannelEntry channel);
+                                  SilcChannelEntry channel,
+                                  SilcChannelClientEntry *chl);
 
 /* Checks string for bad characters and returns TRUE if they are found. */
 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len);
@@ -111,4 +112,17 @@ bool silc_server_connection_allowed(SilcServer server,
                                    SilcServerConfigConnParams *params,
                                    SilcSKE ske);
 
+/* Checks that client has rights to add or remove channel modes. If any
+   of the checks fails FALSE is returned. */
+bool silc_server_check_cmode_rights(SilcServer server,
+                                   SilcChannelEntry channel,
+                                   SilcChannelClientEntry client,
+                                   SilcUInt32 mode);
+
+/* Check that the client has rights to change its user mode.  Returns
+   FALSE if setting some mode is not allowed. */
+bool silc_server_check_umode_rights(SilcServer server,
+                                   SilcClientEntry client,
+                                   SilcUInt32 mode);
+
 #endif /* SERVER_UTIL_H */
index e5f45e3b850be4a7dc235729e55f287ee620409d..2e65293e23900cee13f59635329a853457241e57 100644 (file)
 /* For now, we'll have this one server context global for this module. */
 static SilcServer silcd;
 
-static void silc_usage();
-static char *silc_server_create_identifier();
+static void silc_usage(void);
+static char *silc_server_create_identifier(void);
 static int
 silc_server_create_key_pair(char *pkcs_name, int bits, char *path,
                            char *identifier,
                            SilcPublicKey *ret_pub_key,
                            SilcPrivateKey *ret_prv_key);
+static void silc_server_create_passphrase(void);
 
 /* Long command line options */
 static struct option long_opts[] =
 {
   { "config-file", 1, NULL, 'f' },
+  { "passphrase", 1, NULL, 'p' },
   { "debug", 1, NULL, 'd' },
   { "help", 0, NULL, 'h' },
   { "foreground", 0, NULL, 'F' },
@@ -67,7 +69,7 @@ static int opt_bits = 1024;
 
 /* Prints out the usage of silc client */
 
-static void silc_usage()
+static void silc_usage(void)
 {
   printf("\
 Usage: silcd [options]\n\
@@ -119,7 +121,8 @@ static void silc_server_checkpid(SilcServer silcd)
       return;
     kill(oldpid, SIGCHLD); /* this signal does nothing, check if alive */
     if (errno != ESRCH) {
-      fprintf(stderr, "\nI detected another daemon running with the same pid file.\n");
+      fprintf(stderr, "\nI detected another daemon running with the "
+             "same pid file.\n");
       fprintf(stderr, "Please change the config file, or erase the %s\n",
        silcd->config->server_info->pid_file);
       exit(1);
@@ -156,7 +159,7 @@ int main(int argc, char **argv)
 
   /* Parse command line arguments */
   if (argc > 1) {
-    while ((opt = getopt_long(argc, argv, "cf:d:hFVC:",
+    while ((opt = getopt_long(argc, argv, "f:d:hFVC:",
                              long_opts, &option_index)) != EOF) {
       switch(opt)
        {
@@ -298,7 +301,7 @@ int main(int argc, char **argv)
 
 /* Returns identifier string for public key generation. */
 
-static char *silc_server_create_identifier()
+static char *silc_server_create_identifier(void)
 {
   char *username = NULL, *realname = NULL;
   char hostname[256], email[256];
index fa3957bc28b10558eb629bf31434a91d6ee245e0..2c86bf9abac99c4dcd9e3261477329b71a1da7c1 100644 (file)
@@ -71,7 +71,7 @@ AC_CHECK_HEADERS(sys/types.h sys/stat.h sys/time.h stddef.h)
 AC_CHECK_HEADERS(netinet/in.h netinet/tcp.h xti.h netdb.h)
 AC_CHECK_HEADERS(pwd.h grp.h termcap.h paths.h)
 AC_CHECK_HEADERS(ncurses.h signal.h ctype.h regex.h)
-AC_CHECK_HEADERS(arpa/inet.h sys/mman.h limits.h)
+AC_CHECK_HEADERS(arpa/inet.h sys/mman.h limits.h termios.h)
 
 # Data type checking
 AC_TYPE_SIGNAL
index d31a2e2f51d38fad0b4038164865ddb250375492..a8ed3e67d619561c90b101441c552472c7502b48 100644 (file)
@@ -2688,8 +2688,8 @@ directly connected to the server.
 Routers form a ring in the SILC network.  However, routers may have other
 direct connections to other routers in the network too.  This can cause
 interesting routing problems in the network.  Since the network is a ring,
-the packets usually should be routed into counter clock-wise direction,
-or if it cannot be used then always clock-wise (primary route) direction.
+the packets usually should be routed into clock-wise direction, or if it 
+cannot be used then always counter clock-wise (primary route) direction.
 Problems may arise when a faster direct route exists and router is routing
 a channel message.  Currently channel messages must be routed either
 in upstream or downstream, they cannot be routed to other direct routes.
index cf63d7bab2b3234bad283d2b995972cb7955b9f1..67a8b6c1c14dabe6519d088fa55eb8f14793db82 100644 (file)
@@ -193,6 +193,10 @@ extern "C" {
 #include <stddef.h>
 #endif
 
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
 #endif                         /* !SILC_WIN32 */
 
 #ifndef HAVE_GETOPT_LONG
index 28982fa277fc6ebb66d0d9b78eed4067746636b0..89073dd98e99c0ee7aef19b992de8fefea537e31 100644 (file)
@@ -44,9 +44,7 @@ static void silc_client_notify_by_server_pending(void *context, void *context2)
   SILC_LOG_DEBUG(("Start"));
 
   if (reply) {
-    SilcCommandStatus status;
-    unsigned char *tmp = silc_argument_get_arg_type(reply->args, 1, NULL);
-    SILC_GET16_MSB(status, tmp);
+    SilcCommandStatus status = silc_command_get_status(reply->payload);
     if (status != SILC_STATUS_OK)
       goto out;
   }
@@ -59,27 +57,39 @@ static void silc_client_notify_by_server_pending(void *context, void *context2)
   silc_free(res);
 }
 
-/* Resolve client information from server by Client ID. */
+/* Resolve client, channel or server information. */
 
 static void silc_client_notify_by_server_resolve(SilcClient client,
                                                 SilcClientConnection conn,
                                                 SilcPacketContext *packet,
-                                                SilcClientID *client_id)
+                                                SilcIdType id_type,
+                                                void *id)
 {
   SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
-  SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
+  SilcBuffer idp = silc_id_payload_encode(id, id_type);
 
   res->packet = silc_packet_context_dup(packet);
   res->context = client;
   res->sock = silc_socket_dup(conn->sock);
 
-  silc_client_command_register(client, SILC_COMMAND_WHOIS, NULL, NULL,
-                              silc_client_command_reply_whois_i, 0,
-                              ++conn->cmd_ident);
-  silc_client_command_send(client, conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
-                          1, 3, idp->data, idp->len);
-  silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
-                             silc_client_notify_by_server_pending, res);
+  /* For client resolving use WHOIS, and oterhwise use IDENTIFY */
+  if (id_type == SILC_ID_CLIENT) {
+    silc_client_command_register(client, SILC_COMMAND_WHOIS, NULL, NULL,
+                                silc_client_command_reply_whois_i, 0,
+                                ++conn->cmd_ident);
+    silc_client_command_send(client, conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
+                            1, 3, idp->data, idp->len);
+    silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
+                               silc_client_notify_by_server_pending, res);
+  } else {
+    silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
+                                silc_client_command_reply_identify_i, 0,
+                                ++conn->cmd_ident);
+    silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY, 
+                            conn->cmd_ident, 1, 5, idp->data, idp->len);
+    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident,
+                               silc_client_notify_by_server_pending, res);
+  }
   silc_buffer_free(idp);
 }
 
@@ -95,7 +105,8 @@ void silc_client_notify_by_server(SilcClient client,
   SilcNotifyType type;
   SilcArgumentPayload args;
 
-  SilcIDPayload idp;
+  void *id;
+  SilcIdType id_type;
   SilcClientID *client_id = NULL;
   SilcChannelID *channel_id = NULL;
   SilcServerID *server_id = NULL;
@@ -138,7 +149,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!tmp)
       goto out;
 
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!channel_id)
       goto out;
 
@@ -150,14 +161,15 @@ void silc_client_notify_by_server(SilcClient client,
     if (!tmp)
       goto out;
 
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
     /* Find Client entry and if not found query it */
     client_entry = silc_client_get_client_by_id(client, conn, client_id);
     if (!client_entry) {
-      silc_client_notify_by_server_resolve(client, conn, packet, client_id);
+      silc_client_notify_by_server_resolve(client, conn, packet, 
+                                          SILC_ID_CLIENT, client_id);
       goto out;
     }
 
@@ -184,14 +196,15 @@ void silc_client_notify_by_server(SilcClient client,
     if (!tmp)
       goto out;
 
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
     /* Find Client entry and if not found query it */
     client_entry = silc_client_get_client_by_id(client, conn, client_id);
     if (!client_entry) {
-      silc_client_notify_by_server_resolve(client, conn, packet, client_id);
+      silc_client_notify_by_server_resolve(client, conn, packet, 
+                                          SILC_ID_CLIENT, client_id);
       goto out;
     }
 
@@ -202,7 +215,8 @@ void silc_client_notify_by_server(SilcClient client,
        goto out;
       }
       client_entry->status |= SILC_CLIENT_STATUS_RESOLVING;
-      silc_client_notify_by_server_resolve(client, conn, packet, client_id);
+      silc_client_notify_by_server_resolve(client, conn, packet, 
+                                          SILC_ID_CLIENT, client_id);
       goto out;
     } else {
       if (client_entry != conn->local_entry)
@@ -214,7 +228,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!tmp)
       goto out;
 
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!channel_id)
       goto out;
 
@@ -251,7 +265,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!tmp)
       goto out;
 
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
@@ -296,7 +310,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!tmp)
       goto out;
 
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
@@ -331,62 +345,50 @@ void silc_client_notify_by_server(SilcClient client,
 
     SILC_LOG_DEBUG(("Notify: TOPIC_SET"));
 
-    /* Get Client ID */
+    /* Get ID */
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-
-    idp = silc_id_payload_parse(tmp, tmp_len);
-    if (!idp)
+    id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
+    if (!id)
       goto out;
 
     /* Find Client entry */
-    if (silc_id_payload_get_type(idp) == SILC_ID_CLIENT) {
-      client_id = silc_id_payload_parse_id(tmp, tmp_len);
-      if (!client_id) {
-       silc_id_payload_free(idp);
-       goto out;
-      }
-
+    if (id_type == SILC_ID_CLIENT) {
       /* Find Client entry */
-      client_entry = 
-       silc_client_get_client_by_id(client, conn, client_id);
-      if (!client_entry)
-       goto out;
-    } else if (silc_id_payload_get_type(idp) == SILC_ID_SERVER) {
-      server_id = silc_id_payload_parse_id(tmp, tmp_len);
-      if (!server_id) {
-       silc_id_payload_free(idp);
+      client_id = id;
+      client_entry = silc_client_get_client_by_id(client, conn, client_id);
+      if (!client_entry) {
+       silc_client_notify_by_server_resolve(client, conn, packet, 
+                                            SILC_ID_CLIENT, client_id);
        goto out;
       }
-      
+    } else if (id_type == SILC_ID_SERVER) {
+      /* Find Server entry */
+      server_id = id;
       server = silc_client_get_server_by_id(client, conn, server_id);
       if (!server) {
-       silc_id_payload_free(idp);
-       silc_free(server_id);
+       silc_client_notify_by_server_resolve(client, conn, packet, 
+                                            SILC_ID_SERVER, server_id);
        goto out;
       }
       
       /* Save the pointer to the client_entry pointer */
       client_entry = (SilcClientEntry)server;
-      silc_free(server_id);
     } else {
-      channel_id = silc_id_payload_parse_id(tmp, tmp_len);
-      if (!channel_id) {
-       silc_id_payload_free(idp);
-       goto out;
-      }
-      
+      /* Find Channel entry */
+      channel_id = id;
       channel = silc_client_get_channel_by_id(client, conn, channel_id);
       if (!channel) {
-       silc_id_payload_free(idp);
-       silc_free(channel_id);
+       silc_client_notify_by_server_resolve(client, conn, packet, 
+                                            SILC_ID_CHANNEL, channel_id);
        goto out;
       }
       
       /* Save the pointer to the client_entry pointer */
       client_entry = (SilcClientEntry)channel;
       silc_free(channel_id);
+      channel_id = NULL;
     }
 
     /* Get topic */
@@ -406,11 +408,9 @@ void silc_client_notify_by_server(SilcClient client,
     /* Notify application. The channel entry is sent last as this notify
        is for channel but application don't know it from the arguments
        sent by server. */
-    client->internal->ops->notify(client, conn, type, 
-                                 silc_id_payload_get_type(idp),
+    client->internal->ops->notify(client, conn, type, id_type,
                                  client_entry, tmp, channel);
 
-    silc_id_payload_free(idp);
     break;
 
   case SILC_NOTIFY_TYPE_NICK_CHANGE:
@@ -428,7 +428,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!tmp)
       goto out;
 
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
@@ -449,7 +449,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!tmp)
       goto out;
 
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
@@ -457,7 +457,8 @@ void silc_client_notify_by_server(SilcClient client,
     client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
     if (!client_entry2) {
       /* Resolve the entry information */
-      silc_client_notify_by_server_resolve(client, conn, packet, client_id);
+      silc_client_notify_by_server_resolve(client, conn, packet, 
+                                          SILC_ID_CLIENT, client_id);
 
       /* Add the new entry even though we resolved it. This is because we
         want to replace the old entry with the new entry here right now. */
@@ -496,68 +497,67 @@ void silc_client_notify_by_server(SilcClient client,
 
     SILC_LOG_DEBUG(("Notify: CMODE_CHANGE"));
 
-    /* Get Client ID */
+    /* Get ID */
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-
-    idp = silc_id_payload_parse(tmp, tmp_len);
-    if (!idp)
+    id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
+    if (!id)
       goto out;
 
     /* Find Client entry */
-    if (silc_id_payload_get_type(idp) == SILC_ID_CLIENT) {
-      client_id = silc_id_payload_parse_id(tmp, tmp_len);
-      if (!client_id) {
-       silc_id_payload_free(idp);
-       goto out;
-      }
-
+    if (id_type == SILC_ID_CLIENT) {
+      /* Find Client entry */
+      client_id = id;
       client_entry = silc_client_get_client_by_id(client, conn, client_id);
       if (!client_entry) {
-       silc_id_payload_free(idp);
-       goto out;
-      }
-    } else {
-      server_id = silc_id_payload_parse_id(tmp, tmp_len);
-      if (!server_id) {
-       silc_id_payload_free(idp);
+       silc_client_notify_by_server_resolve(client, conn, packet, 
+                                            SILC_ID_CLIENT, client_id);
        goto out;
       }
-      
+    } else if (id_type == SILC_ID_SERVER) {
+      /* Find Server entry */
+      server_id = id;
       server = silc_client_get_server_by_id(client, conn, server_id);
       if (!server) {
-       silc_id_payload_free(idp);
-       silc_free(server_id);
+       silc_client_notify_by_server_resolve(client, conn, packet, 
+                                            SILC_ID_SERVER, server_id);
        goto out;
       }
-      
+
       /* Save the pointer to the client_entry pointer */
       client_entry = (SilcClientEntry)server;
-      silc_free(server_id);
+    } else {
+      /* Find Channel entry */
+      channel_id = id;
+      channel = silc_client_get_channel_by_id(client, conn, channel_id);
+      if (!channel) {
+       silc_client_notify_by_server_resolve(client, conn, packet, 
+                                            SILC_ID_CHANNEL, channel_id);
+       goto out;
+      }
+      
+      /* Save the pointer to the client_entry pointer */
+      client_entry = (SilcClientEntry)channel;
+      silc_free(channel_id);
+      channel_id = NULL;
     }
 
     /* Get the mode */
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
-    if (!tmp) {
-      silc_id_payload_free(idp);
+    if (!tmp)
       goto out;
-    }
 
     SILC_GET32_MSB(mode, tmp);
 
     /* Get channel entry */
     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
                                SILC_ID_CHANNEL);
-    if (!channel_id) {
-      silc_id_payload_free(idp);
+    if (!channel_id)
       goto out;
-    }
     channel = silc_client_get_channel_by_id(client, conn, channel_id);
-    if (!channel) {
-      silc_id_payload_free(idp);
+    if (!channel)
       goto out;
-    }
 
     /* Save the new mode */
     channel->mode = mode;
@@ -583,11 +583,8 @@ void silc_client_notify_by_server(SilcClient client,
     /* Notify application. The channel entry is sent last as this notify
        is for channel but application don't know it from the arguments
        sent by server. */
-    client->internal->ops->notify(client, conn, type, 
-                                 silc_id_payload_get_type(idp), 
+    client->internal->ops->notify(client, conn, type, id_type,
                                  client_entry, mode, NULL, tmp, channel);
-
-    silc_id_payload_free(idp);
     break;
 
   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
@@ -597,20 +594,50 @@ void silc_client_notify_by_server(SilcClient client,
 
     SILC_LOG_DEBUG(("Notify: CUMODE_CHANGE"));
 
-    /* Get Client ID */
+    /* Get ID */
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
-    if (!client_id)
+    id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
+    if (!id)
       goto out;
 
     /* Find Client entry */
-    client_entry = silc_client_get_client_by_id(client, conn, client_id);
-    if (!client_entry) {
-      silc_client_notify_by_server_resolve(client, conn, packet, client_id);
-      goto out;
+    if (id_type == SILC_ID_CLIENT) {
+      /* Find Client entry */
+      client_id = id;
+      client_entry = silc_client_get_client_by_id(client, conn, client_id);
+      if (!client_entry) {
+       silc_client_notify_by_server_resolve(client, conn, packet, 
+                                            SILC_ID_CLIENT, client_id);
+       goto out;
+      }
+    } else if (id_type == SILC_ID_SERVER) {
+      /* Find Server entry */
+      server_id = id;
+      server = silc_client_get_server_by_id(client, conn, server_id);
+      if (!server) {
+       silc_client_notify_by_server_resolve(client, conn, packet, 
+                                            SILC_ID_SERVER, server_id);
+       goto out;
+      }
+
+      /* Save the pointer to the client_entry pointer */
+      client_entry = (SilcClientEntry)server;
+    } else {
+      /* Find Channel entry */
+      channel_id = id;
+      channel = silc_client_get_channel_by_id(client, conn, channel_id);
+      if (!channel) {
+       silc_client_notify_by_server_resolve(client, conn, packet, 
+                                            SILC_ID_CHANNEL, channel_id);
+       goto out;
+      }
+      
+      /* Save the pointer to the client_entry pointer */
+      client_entry = (SilcClientEntry)channel;
+      silc_free(channel_id);
+      channel_id = NULL;
     }
 
     /* Get the mode */
@@ -626,7 +653,7 @@ void silc_client_notify_by_server(SilcClient client,
       goto out;
 
     silc_free(client_id);
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
@@ -653,8 +680,8 @@ void silc_client_notify_by_server(SilcClient client,
     /* Notify application. The channel entry is sent last as this notify
        is for channel but application don't know it from the arguments
        sent by server. */
-    client->internal->ops->notify(client, conn, type, 
-                                 client_entry, mode, 
+    client->internal->ops->notify(client, conn, type,
+                                 id_type, client_entry, mode, 
                                  client_entry2, channel);
     break;
 
@@ -686,7 +713,7 @@ void silc_client_notify_by_server(SilcClient client,
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
       goto out;
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!channel_id)
       goto out;
 
@@ -701,7 +728,7 @@ void silc_client_notify_by_server(SilcClient client,
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
     if (!tmp)
       goto out;
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!channel_id)
       goto out;
 
@@ -724,7 +751,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!tmp)
       goto out;
 
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
@@ -745,14 +772,15 @@ void silc_client_notify_by_server(SilcClient client,
     /* Get the kicker */
     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
     if (tmp) {
-      client_id = silc_id_payload_parse_id(tmp, tmp_len);
+      client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
       if (!client_id)
        goto out;
 
       /* Find kicker's client entry and if not found resolve it */
       client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
       if (!client_entry2) {
-       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
+       silc_client_notify_by_server_resolve(client, conn, packet, 
+                                            SILC_ID_CLIENT, client_id);
        goto out;
       } else {
        if (client_entry2 != conn->local_entry)
@@ -794,7 +822,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!tmp)
       goto out;
 
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
     if (!client_id)
       goto out;
 
@@ -831,7 +859,7 @@ void silc_client_notify_by_server(SilcClient client,
        /* Get Client ID */
        tmp = silc_argument_get_arg_type(args, i + 1, &tmp_len);
        if (tmp) {
-         client_id = silc_id_payload_parse_id(tmp, tmp_len);
+         client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
          if (!client_id)
            goto out;
          
@@ -876,4 +904,5 @@ void silc_client_notify_by_server(SilcClient client,
   silc_notify_payload_free(payload);
   silc_free(client_id);
   silc_free(channel_id);
+  silc_free(server_id);
 }
index 48a0fa56231cd50841b5b8f375d6fd1d5731c718..c0c058d00aa865054db8f0cd17ff918ed946c2ea 100644 (file)
@@ -322,9 +322,8 @@ SILC_CLIENT_CMD_FUNC(nick_change)
   SilcClientConnection conn = cmd->conn;
   SilcClientCommandReplyContext reply = 
     (SilcClientCommandReplyContext)context2;
-  SilcCommandStatus status;
+  SilcCommandStatus status = silc_command_get_status(reply->payload);
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(reply->args, 1, NULL));
   if (status == SILC_STATUS_OK) {
     /* Set the nickname */
     silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
@@ -749,9 +748,8 @@ SILC_CLIENT_CMD_FUNC(kill_remove)
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientCommandReplyContext reply = 
     (SilcClientCommandReplyContext)context2;
-  SilcCommandStatus status;
+  SilcCommandStatus status = silc_command_get_status(reply->payload);
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(reply->args, 1, NULL));
   if (status == SILC_STATUS_OK) {
     /* Remove with timeout */
     silc_schedule_task_add(cmd->client->schedule, cmd->conn->sock->sock,
@@ -2167,9 +2165,7 @@ SILC_CLIENT_CMD_FUNC(getkey)
       } else {
        SilcClientCommandReplyContext reply = 
          (SilcClientCommandReplyContext)context2;
-       SilcCommandStatus status;
-       unsigned char *tmp = silc_argument_get_arg_type(reply->args, 1, NULL);
-       SILC_GET16_MSB(status, tmp);
+       SilcCommandStatus status = silc_command_get_status(reply->payload);
        
        /* If nickname was not found, then resolve the server. */
        if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
index 279489a05ebbe553609957fef6046143119652f3..9246831c0788ec5c9665738c01a172e72076f73b 100644 (file)
@@ -83,39 +83,37 @@ const SilcCommandStatusMessage silc_command_status_messages[] = {
    Usage: COMMAND_REPLY((ARGS, argument1, argument2, etc...)), */
 #define COMMAND_REPLY(args) cmd->client->internal->ops->command_reply args
 #define ARGS cmd->client, cmd->sock->user_data,                                \
-             cmd->payload, TRUE, silc_command_get(cmd->payload), status
+             cmd->payload, TRUE, silc_command_get(cmd->payload), cmd->status
 
 /* Error reply to application. Usage: COMMAND_REPLY_ERROR; */
 #define COMMAND_REPLY_ERROR cmd->client->internal->ops->               \
   command_reply(cmd->client, cmd->sock->user_data, cmd->payload,       \
-  FALSE, silc_command_get(cmd->payload), status)
+  FALSE, silc_command_get(cmd->payload), cmd->status)
 
 #define SAY cmd->client->internal->ops->say
 
 /* All functions that call the COMMAND_CHECK_STATUS or the
    COMMAND_CHECK_STATUS_LIST macros must have out: goto label. */
 
-#define COMMAND_CHECK_STATUS                                             \
-do {                                                                     \
-  SILC_LOG_DEBUG(("Start"));                                             \
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
-  if (status != SILC_STATUS_OK)  {                                       \
-    COMMAND_REPLY_ERROR;                                                 \
-    goto out;                                                            \
-  }                                                                      \
+#define COMMAND_CHECK_STATUS                   \
+do {                                           \
+  SILC_LOG_DEBUG(("Start"));                   \
+  if (cmd->status != SILC_STATUS_OK)  {                \
+    COMMAND_REPLY_ERROR;                       \
+    goto out;                                  \
+  }                                            \
 } while(0)
 
-#define COMMAND_CHECK_STATUS_LIST                                        \
-do {                                                                     \
-  SILC_LOG_DEBUG(("Start"));                                             \
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
-  if (status != SILC_STATUS_OK &&                                        \
-      status != SILC_STATUS_LIST_START &&                                \
-      status != SILC_STATUS_LIST_ITEM &&                                 \
-      status != SILC_STATUS_LIST_END) {                                          \
-    COMMAND_REPLY_ERROR;                                                 \
-    goto out;                                                            \
-  }                                                                      \
+#define COMMAND_CHECK_STATUS_LIST              \
+do {                                           \
+  SILC_LOG_DEBUG(("Start"));                   \
+  if (cmd->status != SILC_STATUS_OK &&         \
+      cmd->status != SILC_STATUS_LIST_START && \
+      cmd->status != SILC_STATUS_LIST_ITEM &&  \
+      cmd->status != SILC_STATUS_LIST_END) {   \
+    COMMAND_REPLY_ERROR;                       \
+    goto out;                                  \
+  }                                            \
 } while(0)
 
 /* Process received command reply. */
@@ -145,6 +143,7 @@ void silc_client_command_reply_process(SilcClient client,
   ctx->client = client;
   ctx->sock = sock;
   ctx->payload = payload;
+  ctx->status = silc_command_get_status(ctx->payload);
   ctx->args = silc_command_get_args(ctx->payload);
   ctx->packet = packet;
   ctx->ident = silc_command_get_ident(ctx->payload);
@@ -232,7 +231,7 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
     return;
   }
   
-  client_id = silc_id_payload_parse_id(id_data, len);
+  client_id = silc_id_payload_parse_id(id_data, len, NULL);
   if (!client_id) {
     if (notify)
       COMMAND_REPLY_ERROR;
@@ -302,16 +301,15 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
 
   COMMAND_CHECK_STATUS_LIST;
 
   /* Save WHOIS info */
-  silc_client_command_reply_whois_save(cmd, status, TRUE);
+  silc_client_command_reply_whois_save(cmd, cmd->status, TRUE);
 
   /* Pending callbacks are not executed if this was an list entry */
-  if (status != SILC_STATUS_OK &&
-      status != SILC_STATUS_LIST_END) {
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_END) {
     silc_client_command_reply_free(cmd);
     return;
   }
@@ -321,14 +319,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois)
 
   /* If we received notify for invalid ID we'll remove the ID if we
      have it cached. */
-  if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
+  if (cmd->status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
     SilcClientEntry client_entry;
     SilcUInt32 tmp_len;
     unsigned char *tmp =
       silc_argument_get_arg_type(silc_command_get_args(cmd->payload),
                                 2, &tmp_len);
     if (tmp) {
-      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
       if (client_id) {
        client_entry = silc_client_get_client_by_id(cmd->client, conn,
                                                    client_id);
@@ -348,7 +346,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   SilcClientID *client_id;
   SilcClientEntry client_entry = NULL;
   SilcUInt32 len;
@@ -364,7 +361,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas)
     goto out;
   }
   
-  client_id = silc_id_payload_parse_id(id_data, len);
+  client_id = silc_id_payload_parse_id(id_data, len, NULL);
   if (!client_id) {
     COMMAND_REPLY_ERROR;
     goto out;
@@ -388,8 +385,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas)
   COMMAND_REPLY((ARGS, client_entry, nickname, username, realname));
 
   /* Pending callbacks are not executed if this was an list entry */
-  if (status != SILC_STATUS_OK &&
-      status != SILC_STATUS_LIST_END) {
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_END) {
     silc_client_command_reply_free(cmd);
     return;
   }
@@ -409,7 +406,6 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd,
   SilcClientID *client_id = NULL;
   SilcServerID *server_id = NULL;
   SilcChannelID *channel_id = NULL;
-  SilcIDCacheEntry id_cache = NULL;
   SilcClientEntry client_entry;
   SilcServerEntry server_entry;
   SilcChannelEntry channel_entry;
@@ -472,23 +468,16 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd,
     SILC_LOG_DEBUG(("Received server information"));
 
     /* Check if we have this server cached already. */
-    if (!silc_idcache_find_by_id_one(conn->server_cache, 
-                                    (void *)server_id, &id_cache)) {
+    server_entry = silc_client_get_server_by_id(cmd->client, conn, server_id);
+    if (!server_entry) {
       SILC_LOG_DEBUG(("Adding new server entry"));
-      
-      server_entry = silc_calloc(1, sizeof(*server_entry));
-      server_entry->server_id = silc_id_dup(server_id, id_type);
-      if (name)
-       server_entry->server_name = strdup(name);
-      if (info)
-       server_entry->server_info = strdup(info);
-      
-      /* Add server to cache */
-      silc_idcache_add(conn->server_cache, server_entry->server_name,
-                      server_entry->server_id, (void *)server_entry, 
-                      0, NULL);
-    } else {
-      server_entry = (SilcServerEntry)id_cache->context;
+      server_entry = silc_client_add_server(cmd->client, conn, name, info,
+                                           silc_id_dup(server_id, id_type));
+      if (!server_entry) {
+       if (notify)
+         COMMAND_REPLY_ERROR;
+       return;
+      }
     }
 
     /* Notify application */
@@ -533,16 +522,15 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
 
   COMMAND_CHECK_STATUS_LIST;
 
   /* Save IDENTIFY info */
-  silc_client_command_reply_identify_save(cmd, status, TRUE);
+  silc_client_command_reply_identify_save(cmd, cmd->status, TRUE);
 
   /* Pending callbacks are not executed if this was an list entry */
-  if (status != SILC_STATUS_OK &&
-      status != SILC_STATUS_LIST_END) {
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_END) {
     silc_client_command_reply_free(cmd);
     return;
   }
@@ -552,14 +540,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify)
 
   /* If we received notify for invalid ID we'll remove the ID if we
      have it cached. */
-  if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
+  if (cmd->status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
     SilcClientEntry client_entry;
     SilcUInt32 tmp_len;
     unsigned char *tmp =
       silc_argument_get_arg_type(silc_command_get_args(cmd->payload),
                                 2, &tmp_len);
     if (tmp) {
-      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
       if (client_id) {
        client_entry = silc_client_get_client_by_id(cmd->client, conn,
                                                    client_id);
@@ -580,17 +568,16 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   SilcIDPayload idp;
   unsigned char *tmp;
   SilcUInt32 argc, len;
 
   SILC_LOG_DEBUG(("Start"));
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "Cannot set nickname: %s", silc_client_command_status_message(status));
+       "Cannot set nickname: %s", 
+       silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -628,7 +615,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick)
 SILC_CLIENT_CMD_REPLY_FUNC(list)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
-  SilcCommandStatus status;
   unsigned char *tmp, *name, *topic;
   SilcUInt32 usercount = 0;
 
@@ -644,8 +630,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(list)
   COMMAND_REPLY((ARGS, NULL, name, topic, usercount));
 
   /* Pending callbacks are not executed if this was an list entry */
-  if (status != SILC_STATUS_OK &&
-      status != SILC_STATUS_LIST_END) {
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_END) {
     silc_client_command_reply_free(cmd);
     return;
   }
@@ -661,17 +647,15 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   SilcChannelEntry channel;
   SilcChannelID *channel_id = NULL;
   unsigned char *tmp;
   char *topic;
   SilcUInt32 argc, len;
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -692,7 +676,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic)
   if (!topic)
     goto out;
 
-  channel_id = silc_id_payload_parse_id(tmp, len);
+  channel_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!channel_id)
     goto out;
 
@@ -718,17 +702,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   SilcChannelEntry channel;
   SilcChannelID *channel_id;
   unsigned char *tmp;
   SilcUInt32 len;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -738,7 +719,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite)
   if (!tmp)
     goto out;
 
-  channel_id = silc_id_payload_parse_id(tmp, len);
+  channel_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!channel_id)
     goto out;
 
@@ -767,12 +748,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(kill)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -792,9 +771,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   unsigned char *tmp;
-  SilcIDCacheEntry id_cache;
   SilcServerEntry server;
   SilcServerID *server_id = NULL;
   char *server_name, *server_info;
@@ -802,11 +779,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(info)
 
   SILC_LOG_DEBUG(("Start"));
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "%s", 
-       silc_client_command_status_message(status));
+       silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -816,7 +791,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info)
   if (!tmp)
     goto out;
 
-  server_id = silc_id_payload_parse_id(tmp, len);
+  server_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!server_id)
     goto out;
 
@@ -831,22 +806,16 @@ SILC_CLIENT_CMD_REPLY_FUNC(info)
     goto out;
 
   /* See whether we have this server cached. If not create it. */
-  if (!silc_idcache_find_by_id_one(conn->server_cache, (void *)server_id,
-                                  &id_cache)) {
+  server = silc_client_get_server_by_id(cmd->client, conn, server_id);
+  if (!server) {
     SILC_LOG_DEBUG(("New server entry"));
-
-    server = silc_calloc(1, sizeof(*server));
-    server->server_name = strdup(server_name);
-    server->server_info = strdup(server_info);
-    server->server_id = silc_id_dup(server_id, SILC_ID_SERVER);
-
-    /* Add it to the cache */
-    silc_idcache_add(conn->server_cache, server->server_name,
-                    server->server_id, (void *)server, 0, NULL);
-  } else {
-    server = (SilcServerEntry)id_cache->context;
+    server = silc_client_add_server(cmd->client, conn, server_name,
+                                   server_info,
+                                   silc_id_dup(server_id, SILC_ID_SERVER));
+    if (!server)
+      goto out;
   }
-  
+
   /* Notify application */
   COMMAND_REPLY((ARGS, server, server->server_name, server->server_info));
 
@@ -862,15 +831,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(ping)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   void *id;
   int i;
   time_t diff, curtime;
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -918,7 +885,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   SilcChannelEntry channel;
   SilcChannelUser chu;
   SilcChannelID *channel_id;
@@ -929,11 +895,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
 
   SILC_LOG_DEBUG(("Start"));
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
-  if (status != SILC_STATUS_OK) {
-    if (status != SILC_STATUS_ERR_USER_ON_CHANNEL)
+  if (cmd->status != SILC_STATUS_OK) {
+    if (cmd->status != SILC_STATUS_ERR_USER_ON_CHANNEL)
       SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-         "%s", silc_client_command_status_message(status));
+         "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -964,7 +929,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
     COMMAND_REPLY_ERROR;
     goto out;
   }
-  channel_id = silc_id_payload_parse_id(tmp, len);
+  channel_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!channel_id) {
     COMMAND_REPLY_ERROR;
     goto out;
@@ -1044,7 +1009,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
     /* Client ID */
     SILC_GET16_MSB(idp_len, client_id_list->data + 2);
     idp_len += 4;
-    client_id = silc_id_payload_parse_id(client_id_list->data, idp_len);
+    client_id = silc_id_payload_parse_id(client_id_list->data, idp_len, NULL);
     if (!client_id)
       continue;
 
@@ -1107,16 +1072,12 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   SilcUInt32 argc, i;
-  unsigned char *tmp;
   char *motd = NULL, *cp, line[256];
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     return;
   }
@@ -1168,15 +1129,12 @@ SILC_CLIENT_CMD_REPLY_FUNC(umode)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   unsigned char *tmp;
   SilcUInt32 mode;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1204,17 +1162,15 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   unsigned char *tmp;
   SilcUInt32 mode;
   SilcChannelID *channel_id;
   SilcChannelEntry channel;
   SilcUInt32 len;
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1223,7 +1179,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode)
   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
   if (!tmp)
     goto out;
-  channel_id = silc_id_payload_parse_id(tmp, len);
+  channel_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!channel_id)
     goto out;
 
@@ -1263,7 +1219,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   SilcClientID *client_id;
   SilcChannelID *channel_id;
   SilcClientEntry client_entry;
@@ -1272,10 +1227,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode)
   unsigned char *modev, *tmp, *id;
   SilcUInt32 len, mode;
   
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1291,7 +1245,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode)
   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
   if (!tmp)
     goto out;
-  channel_id = silc_id_payload_parse_id(tmp, len);
+  channel_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!channel_id)
     goto out;
 
@@ -1310,7 +1264,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode)
     COMMAND_REPLY_ERROR;
     goto out;
   }
-  client_id = silc_id_payload_parse_id(id, len);
+  client_id = silc_id_payload_parse_id(id, len, NULL);
   if (!client_id) {
     silc_free(channel_id);
     COMMAND_REPLY_ERROR;
@@ -1346,14 +1300,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(kick)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
-  unsigned char *tmp;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1370,14 +1320,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(silcoper)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
-  unsigned char *tmp;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1394,14 +1340,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(oper)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
-  unsigned char *tmp;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1418,14 +1360,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(connect)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
-  unsigned char *tmp;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1442,17 +1380,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   SilcChannelEntry channel;
   SilcChannelID *channel_id;
   unsigned char *tmp;
   SilcUInt32 len;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1462,7 +1397,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban)
   if (!tmp)
     goto out;
 
-  channel_id = silc_id_payload_parse_id(tmp, len);
+  channel_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!channel_id)
     goto out;
 
@@ -1489,14 +1424,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(close)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
-  unsigned char *tmp;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1513,14 +1444,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(shutdown)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
-  unsigned char *tmp;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1539,14 +1466,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(leave)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
-  unsigned char *tmp;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1590,7 +1513,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   SilcChannelEntry channel;
   SilcClientEntry client_entry;
   SilcChannelUser chu;
@@ -1605,11 +1527,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
 
   SILC_LOG_DEBUG(("Start"));
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1620,7 +1540,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
     COMMAND_REPLY_ERROR;
     goto out;
   }
-  channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+  channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
   if (!channel_id) {
     COMMAND_REPLY_ERROR;
     goto out;
@@ -1680,7 +1600,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
     /* Client ID */
     SILC_GET16_MSB(idp_len, client_id_list->data + 2);
     idp_len += 4;
-    client_id = silc_id_payload_parse_id(client_id_list->data, idp_len);
+    client_id = silc_id_payload_parse_id(client_id_list->data, idp_len, NULL);
     if (!client_id)
       continue;
 
@@ -1787,8 +1707,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
-  SilcIDCacheEntry id_cache;
   SilcIDPayload idp = NULL;
   SilcClientID *client_id = NULL;
   SilcClientEntry client_entry;
@@ -1803,11 +1721,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
 
   SILC_LOG_DEBUG(("Start"));
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
+  if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(status));
+       "%s", silc_client_command_status_message(cmd->status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1851,14 +1767,12 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
   } else if (id_type == SILC_ID_SERVER) {
     /* Received server's public key */
     server_id = silc_id_payload_get_id(idp);
-    if (!silc_idcache_find_by_id_one(conn->server_cache, (void *)server_id,
-                                    &id_cache)) {
+    server_entry = silc_client_get_server_by_id(cmd->client, conn, server_id);
+    if (!server_entry) {
       COMMAND_REPLY_ERROR;
       goto out;
     }
 
-    server_entry = (SilcServerEntry)id_cache->context;
-
     /* Notify application */
     COMMAND_REPLY((ARGS, id_type, server_entry, public_key));
   }
@@ -1890,23 +1804,21 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois_i)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
 
   SILC_LOG_DEBUG(("Start"));
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
-  if (status != SILC_STATUS_OK &&
-      status != SILC_STATUS_LIST_START &&
-      status != SILC_STATUS_LIST_ITEM &&
-      status != SILC_STATUS_LIST_END)
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_START &&
+      cmd->status != SILC_STATUS_LIST_ITEM &&
+      cmd->status != SILC_STATUS_LIST_END)
     goto out;
 
   /* Save WHOIS info */
-  silc_client_command_reply_whois_save(cmd, status, FALSE);
+  silc_client_command_reply_whois_save(cmd, cmd->status, FALSE);
 
   /* Pending callbacks are not executed if this was an list entry */
-  if (status != SILC_STATUS_OK &&
-      status != SILC_STATUS_LIST_END) {
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_END) {
     silc_client_command_reply_free(cmd);
     return;
   }
@@ -1916,14 +1828,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois_i)
 
   /* If we received notify for invalid ID we'll remove the ID if we
      have it cached. */
-  if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
+  if (cmd->status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
     SilcClientEntry client_entry;
     SilcUInt32 tmp_len;
     unsigned char *tmp =
       silc_argument_get_arg_type(silc_command_get_args(cmd->payload),
                                 2, &tmp_len);
     if (tmp) {
-      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
       if (client_id) {
        client_entry = silc_client_get_client_by_id(cmd->client, conn,
                                                    client_id);
@@ -1946,23 +1858,21 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify_i)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
 
   SILC_LOG_DEBUG(("Start"));
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
-  if (status != SILC_STATUS_OK &&
-      status != SILC_STATUS_LIST_START &&
-      status != SILC_STATUS_LIST_ITEM &&
-      status != SILC_STATUS_LIST_END)
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_START &&
+      cmd->status != SILC_STATUS_LIST_ITEM &&
+      cmd->status != SILC_STATUS_LIST_END)
     goto out;
 
   /* Save IDENTIFY info */
-  silc_client_command_reply_identify_save(cmd, status, FALSE);
+  silc_client_command_reply_identify_save(cmd, cmd->status, FALSE);
 
   /* Pending callbacks are not executed if this was an list entry */
-  if (status != SILC_STATUS_OK &&
-      status != SILC_STATUS_LIST_END) {
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_END) {
     silc_client_command_reply_free(cmd);
     return;
   }
@@ -1972,14 +1882,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify_i)
 
   /* If we received notify for invalid ID we'll remove the ID if we
      have it cached. */
-  if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
+  if (cmd->status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
     SilcClientEntry client_entry;
     SilcUInt32 tmp_len;
     unsigned char *tmp =
       silc_argument_get_arg_type(silc_command_get_args(cmd->payload),
                                 2, &tmp_len);
     if (tmp) {
-      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
       if (client_id) {
        client_entry = silc_client_get_client_by_id(cmd->client, conn,
                                                    client_id);
@@ -2002,9 +1912,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info_i)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
   unsigned char *tmp;
-  SilcIDCacheEntry id_cache;
   SilcServerEntry server;
   SilcServerID *server_id = NULL;
   char *server_name, *server_info;
@@ -2012,9 +1920,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info_i)
 
   SILC_LOG_DEBUG(("Start"));
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK)
+  if (cmd->status != SILC_STATUS_OK)
     goto out;
 
   /* Get server ID */
@@ -2022,7 +1928,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info_i)
   if (!tmp)
     goto out;
 
-  server_id = silc_id_payload_parse_id(tmp, len);
+  server_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!server_id)
     goto out;
 
@@ -2037,17 +1943,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(info_i)
     goto out;
 
   /* See whether we have this server cached. If not create it. */
-  if (!silc_idcache_find_by_id_one(conn->server_cache, (void *)server_id,
-                                  &id_cache)) {
+  server = silc_client_get_server_by_id(cmd->client, conn, server_id);
+  if (!server) {
     SILC_LOG_DEBUG(("New server entry"));
-    server = silc_calloc(1, sizeof(*server));
-    server->server_name = strdup(server_name);
-    server->server_info = strdup(server_info);
-    server->server_id = silc_id_dup(server_id, SILC_ID_SERVER);
-
-    /* Add it to the cache */
-    silc_idcache_add(conn->server_cache, server->server_name,
-                    server->server_id, (void *)server, 0, NULL);
+    silc_client_add_server(cmd->client, conn, server_name, server_info,
+                          silc_id_dup(server_id, SILC_ID_SERVER));
   }
   
  out:
index 4e5cdbee8178e133c15d7940dfd7c73306bedb3e..afc14f9a1802335f7201a1dd215108ad8072ab37 100644 (file)
@@ -31,6 +31,7 @@ struct SilcClientCommandReplyContextStruct {
   SilcClient client;
   SilcSocketConnection sock;
   SilcCommandPayload payload;
+  SilcCommandStatus status;
   SilcArgumentPayload args;
   SilcPacketContext *packet;
 
index e361a5027c39226a6357ddc12873c97abe9790b4..1bd0230943fa9ea17cb3ecd7583437ff71e34170 100644 (file)
@@ -308,7 +308,7 @@ SILC_CLIENT_CMD_FUNC(get_clients_list_callback)
     /* Get Client ID */
     SILC_GET16_MSB(idp_len, client_id_list->data + 2);
     idp_len += 4;
-    client_id = silc_id_payload_parse_id(client_id_list->data, idp_len);
+    client_id = silc_id_payload_parse_id(client_id_list->data, idp_len, NULL);
     if (!client_id) {
       silc_buffer_pull(client_id_list, idp_len);
       continue;
@@ -381,7 +381,7 @@ void silc_client_get_clients_by_list(SilcClient client,
     /* Get Client ID */
     SILC_GET16_MSB(idp_len, client_id_list->data + 2);
     idp_len += 4;
-    client_id = silc_id_payload_parse_id(client_id_list->data, idp_len);
+    client_id = silc_id_payload_parse_id(client_id_list->data, idp_len, NULL);
     if (!client_id) {
       silc_buffer_pull(client_id_list, idp_len);
       continue;
@@ -941,6 +941,39 @@ SilcServerEntry silc_client_get_server_by_id(SilcClient client,
   return entry;
 }
 
+/* Add new server entry */
+
+SilcServerEntry silc_client_add_server(SilcClient client,
+                                      SilcClientConnection conn,
+                                      const char *server_name,
+                                      const char *server_info,
+                                      SilcServerID *server_id)
+{
+  SilcServerEntry server_entry;
+
+  server_entry = silc_calloc(1, sizeof(*server_entry));
+  if (!server_entry || !server_id)
+    return NULL;
+
+  server_entry->server_id = server_id;
+  if (server_name)
+    server_entry->server_name = strdup(server_name);
+  if (server_info)
+    server_entry->server_info = strdup(server_info);
+
+  /* Add server to cache */
+  if (!silc_idcache_add(conn->server_cache, server_entry->server_name,
+                       server_entry->server_id, server_entry, 0, NULL)) {
+    silc_free(server_entry->server_id);
+    silc_free(server_entry->server_name);
+    silc_free(server_entry->server_info);
+    silc_free(server_entry);
+    return NULL;
+  }
+
+  return server_entry;
+}
+
 /* Removes server from the cache by the server entry. */
 
 bool silc_client_del_server(SilcClient client, SilcClientConnection conn,
index 7d680741f73c2f9b554784423e72c0d1a2afea2b..ffca34d40945aea947efd3b4322744b800784aa3 100644 (file)
@@ -124,6 +124,11 @@ SilcChannelEntry silc_client_add_channel(SilcClient client,
                                         const char *channel_name,
                                         SilcUInt32 mode, 
                                         SilcChannelID *channel_id);
+SilcServerEntry silc_client_add_server(SilcClient client,
+                                      SilcClientConnection conn,
+                                      const char *server_name,
+                                      const char *server_info,
+                                      SilcServerID *server_id);
 bool silc_client_replace_channel_id(SilcClient client,
                                    SilcClientConnection conn,
                                    SilcChannelEntry channel,
index d104cc182aaea154b5c2e438a10e66870ea07d32..2a853548826575e08387eabd0d4c843de3ae7320 100644 (file)
@@ -250,6 +250,8 @@ struct SilcChannelMessagePayloadStruct {
   SilcMessageFlags flags;
   SilcUInt16 data_len;
   unsigned char *data;
+  SilcUInt16 pad_len;
+  unsigned char *pad;
   unsigned char *mac;
   unsigned char *iv;
 };
@@ -346,12 +348,13 @@ silc_channel_message_payload_parse(unsigned char *payload,
   if (!newp)
     return NULL;
 
-  /* Parse the Channel Message Payload. Ignore the padding. */
+  /* Parse the Channel Message Payload. */
   ret = silc_buffer_unformat(&buffer,
                             SILC_STR_UI_SHORT(&newp->flags),
                             SILC_STR_UI16_NSTRING_ALLOC(&newp->data, 
                                                         &newp->data_len),
-                            SILC_STR_UI16_NSTRING(NULL, NULL),
+                            SILC_STR_UI16_NSTRING_ALLOC(&newp->pad, 
+                                                        &newp->pad_len),
                             SILC_STR_UI_XNSTRING(&newp->mac, mac_len),
                             SILC_STR_UI_XNSTRING(&newp->iv, iv_len),
                             SILC_STR_END);
@@ -371,6 +374,44 @@ silc_channel_message_payload_parse(unsigned char *payload,
   return NULL;
 }
 
+/* This function is used to encrypt the Channel Messsage Payload which is
+   the `data' and `data_len'.  This is used internally by the Channel Message
+   Payload encoding routines but application may call this too if needed. 
+   The `data_len' is the data lenght which is used to create MAC out of.
+   The `true_len' is the true length of `data' message payload and is used
+   assemble rest of the packet after MAC creation. The `true_len' length
+   packet will then be encrypted. */
+
+bool silc_channel_message_payload_encrypt(unsigned char *data,
+                                         SilcUInt32 data_len,
+                                         SilcUInt32 true_len,
+                                         unsigned char *iv,
+                                         SilcUInt32 iv_len,
+                                         SilcCipher cipher,
+                                         SilcHmac hmac)
+{
+  unsigned char mac[32];
+  SilcUInt32 mac_len;
+  SilcBufferStruct buf;
+
+  /* Compute the MAC of the channel message data */
+  silc_hmac_make(hmac, data, data_len, mac, &mac_len);
+
+  /* Put rest of the data to the payload */
+  silc_buffer_set(&buf, data, true_len);
+  silc_buffer_pull(&buf, data_len);
+  silc_buffer_format(&buf, 
+                    SILC_STR_UI_XNSTRING(mac, mac_len),
+                    SILC_STR_UI_XNSTRING(iv, iv_len),
+                    SILC_STR_END);
+
+  /* Encrypt payload of the packet. This is encrypted with the channel key. */
+  silc_cipher_encrypt(cipher, data, data, true_len - iv_len, iv);
+
+  memset(mac, 0, sizeof(mac));
+  return TRUE;
+}
+
 /* Encodes channel message payload into a buffer and returns it. This is used 
    to add channel message payload into a packet. As the channel payload is
    encrypted separately from other parts of the packet padding must
@@ -389,7 +430,6 @@ SilcBuffer silc_channel_message_payload_encode(SilcUInt16 flags,
   SilcBuffer buffer;
   SilcUInt32 len, pad_len, mac_len;
   unsigned char pad[16];
-  unsigned char mac[32];
 
   SILC_LOG_DEBUG(("Encoding channel message payload"));
 
@@ -408,9 +448,9 @@ SilcBuffer silc_channel_message_payload_encode(SilcUInt16 flags,
 
   /* Generate padding */
   if (rng) {
-    for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte(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();
+    for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
   }
 
   /* Encode the Channel Message Payload */
@@ -423,24 +463,16 @@ SilcBuffer silc_channel_message_payload_encode(SilcUInt16 flags,
                     SILC_STR_UI_XNSTRING(pad, pad_len),
                     SILC_STR_END);
 
-  /* Compute the MAC of the channel message data */
-  silc_hmac_make(hmac, buffer->data, buffer->len, mac, &mac_len);
-
-  /* Put rest of the data to the payload */
-  silc_buffer_pull_tail(buffer, mac_len + iv_len);
-  silc_buffer_pull(buffer, 6 + data_len + pad_len);
-  silc_buffer_format(buffer, 
-                    SILC_STR_UI_XNSTRING(mac, mac_len),
-                    SILC_STR_UI_XNSTRING(iv, iv_len),
-                    SILC_STR_END);
-  silc_buffer_push(buffer, 6 + data_len + pad_len);
+  memset(pad, 0, sizeof(pad));
 
-  /* Encrypt payload of the packet. This is encrypted with the channel key. */
-  silc_cipher_encrypt(cipher, buffer->data, buffer->data, 
-                     buffer->len - iv_len, iv);
+  if (!silc_channel_message_payload_encrypt(buffer->data, buffer->len,
+                                           buffer->truelen, iv, iv_len,
+                                           cipher, hmac)) {
+    silc_buffer_free(buffer);
+    return NULL;
+  }
 
-  memset(pad, 0, sizeof(pad));
-  memset(mac, 0, sizeof(mac));
+  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer) - buffer->len);
 
   return buffer;
 }
index 3b734fba9d79b5500a6bc13aa3fbf34f0c366505..6d97e1a251a7ae483550910a70bc928ba8ac4268 100644 (file)
@@ -316,6 +316,40 @@ silc_channel_message_payload_parse(unsigned char *payload,
                                   SilcCipher cipher,
                                   SilcHmac hmac);
 
+/****f* silccore/SilcChannelAPI/silc_channel_message_payload_encrypt
+ *
+ * SYNOPSIS
+ *
+ *    bool silc_channel_message_payload_encrypt(unsigned char *data,
+ *                                              SilcUInt32 data_len,
+ *                                              SilcUInt32 true_len,
+ *                                              unsigned char *iv,
+ *                                              SilcUInt32 iv_len,
+ *                                              SilcCipher cipher,
+ *                                              SilcHmac hmac);
+ *
+ * DESCRIPTION
+ *
+ *    This function is used to encrypt the Channel Messsage Payload which is
+ *    the `data' and `data_len'.  The `data_len' is the data length which is
+ *    used to create MAC out of.  The `true_len' is the true length of `data'
+ *    message payload and is used assemble rest of the packet after MAC
+ *    creation. The `true_len' length packet will then be encrypted.
+ *
+ *    This is usually used by the Channel Message interface itself but can
+ *    be called by the appliation if separate encryption process is required.
+ *    For example server might need to call this directly in some 
+ *    circumstances. The `cipher' is used to encrypt the payload.
+ *
+ ***/
+bool silc_channel_message_payload_encrypt(unsigned char *data,
+                                         SilcUInt32 data_len,
+                                         SilcUInt32 true_len,
+                                         unsigned char *iv,
+                                         SilcUInt32 iv_len,
+                                         SilcCipher cipher,
+                                         SilcHmac hmac);
+
 /****f* silccore/SilcChannelAPI/silc_channel_message_payload_encode
  *
  * SYNOPSIS
index aaa190c2732e1a04b30b457386553f96a1ab1161..3be0583e3a04006ffbf3573184aaea3804abc9c0 100644 (file)
@@ -386,6 +386,23 @@ SilcUInt16 silc_command_get_ident(SilcCommandPayload payload)
   return payload->ident;
 }
 
+/* Return command status */
+
+SilcCommandStatus silc_command_get_status(SilcCommandPayload payload)
+{
+  unsigned char *tmp;
+  SilcCommandStatus status;
+
+  if (!payload->args)
+    return 0;
+  tmp = silc_argument_get_arg_type(payload->args, 1, NULL);
+  if (!tmp)
+    return 0;
+
+  SILC_GET16_MSB(status, tmp);
+  return status;
+}
+
 /* Function to set identifier to already allocated Command Payload. Command
    payloads are frequentlly resent in SILC and thusly this makes it easy
    to set the identifier. */
index 46e7ddd1d96d4bd1356256a6e115faac3b16f299..a34f3d68fc87c32d975a4938b65201f9857e98fb 100644 (file)
@@ -416,11 +416,26 @@ SilcArgumentPayload silc_command_get_args(SilcCommandPayload payload);
  ***/
 SilcUInt16 silc_command_get_ident(SilcCommandPayload payload);
 
+/****f* silccore/SilcCommandAPI/silc_command_get_status
+ *
+ * SYNOPSIS
+ *
+ *    SilcCommandStatus silc_command_get_status(SilcCommandPayload payload);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the SilcCommandStatus from command reply payload's argument 
+ *    payload.  Status can be returned only from command reply payload.
+ *
+ ***/
+SilcCommandStatus silc_command_get_status(SilcCommandPayload payload);
+
 /****f* silccore/SilcCommandAPI/silc_command_set_ident
  *
  * SYNOPSIS
  *
- *    void silc_command_set_ident(SilcCommandPayload payload, SilcUInt16 ident);
+ *    void silc_command_set_ident(SilcCommandPayload payload, 
+ *                                SilcUInt16 ident);
  *
  * DESCRIPTION
  *
index a46892c1f1725be39c1f67c46371488784dd16f5..6a7fb8f2c72c38c20902cd95f137045b61b32c00 100644 (file)
@@ -64,7 +64,7 @@ SilcIDPayload silc_id_payload_parse(const unsigned char *payload,
 
   silc_buffer_pull(&buffer, 4);
 
-  if (newp->len > buffer.len)
+  if (newp->len > buffer.len || newp->len > SILC_PACKET_MAX_ID_LEN)
     goto err;
 
   ret = silc_buffer_unformat(&buffer,
@@ -84,12 +84,13 @@ SilcIDPayload silc_id_payload_parse(const unsigned char *payload,
 
 /* Return the ID directly from the raw payload data. */
 
-void *silc_id_payload_parse_id(const unsigned char *data, SilcUInt32 len)
+void *silc_id_payload_parse_id(const unsigned char *data, SilcUInt32 len,
+                              SilcIdType *ret_type)
 {
   SilcBufferStruct buffer;
   SilcIdType type;
   SilcUInt16 idlen;
-  unsigned char *id_data = NULL;
+  unsigned char *id_data;
   int ret;
   void *id;
 
@@ -99,25 +100,25 @@ void *silc_id_payload_parse_id(const unsigned char *data, SilcUInt32 len)
                             SILC_STR_UI_SHORT(&idlen),
                             SILC_STR_END);
   if (ret == -1)
-    goto err;
+    return NULL;
 
   silc_buffer_pull(&buffer, 4);
 
-  if (idlen > buffer.len)
-    goto err;
+  if (idlen > buffer.len || idlen > SILC_PACKET_MAX_ID_LEN)
+    return NULL;
 
   ret = silc_buffer_unformat(&buffer,
-                            SILC_STR_UI_XNSTRING_ALLOC(&id_data, idlen),
+                            SILC_STR_UI_XNSTRING(&id_data, idlen),
                             SILC_STR_END);
   if (ret == -1)
-    goto err;
+    return NULL;
 
   id = silc_id_str2id(id_data, idlen, type);
-  silc_free(id_data);
-  return id;
 
- err:
-  return NULL;
+  if (ret_type)
+    *ret_type = type;
+
+  return id;
 }
 
 /* Encodes ID Payload */
@@ -247,7 +248,8 @@ unsigned char *silc_id_id2str(const void *id, SilcIdType type)
 
 /* Converts string to a ID */
 
-void *silc_id_str2id(const unsigned char *id, SilcUInt32 id_len, SilcIdType type)
+void *silc_id_str2id(const unsigned char *id, SilcUInt32 id_len, 
+                    SilcIdType type)
 {
 
   switch(type) {
index 1bfbe44e5db7d30c77b0b8ded32d2377f710ba4e..82141bd9f5a765cde6de2ded3edd8382dedb9200 100644 (file)
@@ -123,7 +123,9 @@ SilcIDPayload silc_id_payload_parse(const unsigned char *payload,
  *
  * SYNOPSIS
  *
- *    void *silc_id_payload_parse_id(const unsigned char *data, SilcUInt32 len);
+ *    void *silc_id_payload_parse_id(const unsigned char *data, 
+ *                                   SilcUInt32 len,
+ *                                   SilcIdType *type);
  *
  * DESCRIPTION
  *
@@ -131,7 +133,8 @@ SilcIDPayload silc_id_payload_parse(const unsigned char *payload,
  *    caller must free the returned ID.
  *
  ***/
-void *silc_id_payload_parse_id(const unsigned char *data, SilcUInt32 len);
+void *silc_id_payload_parse_id(const unsigned char *data, SilcUInt32 len,
+                              SilcIdType *type);
 
 /****f* silccore/SilcIDAPI/silc_id_payload_encode
  *
index 82068283708b5a3b64da0bf4ce23d8ebec0f1310..199f0c37983e311aef1240fcc6ae02bcf6474a0f 100644 (file)
@@ -951,3 +951,92 @@ SilcUInt32 silc_version_to_num(const char *version)
   snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
   return (SilcUInt32)atoi(buf);
 }
+
+/* Displays input prompt on command line and takes input data from user */
+
+char *silc_get_input(const char *prompt, bool echo_off)
+{
+#ifdef SILC_UNIX
+  if (echo_off) {
+    char *ret = NULL;
+#ifdef HAVE_TERMIOS_H
+    char input[2048];
+    int fd;
+    struct termios to;
+    struct termios to_old;
+
+    fd = open("/dev/tty", O_RDONLY);
+    if (fd < 0) {
+      fprintf(stderr, "silc: %s\n", strerror(errno));
+      return NULL;
+    }
+
+    signal(SIGINT, SIG_IGN);
+
+    /* Get terminal info */
+    tcgetattr(fd, &to);
+    to_old = to;
+
+    /* Echo OFF */
+    to.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
+    tcsetattr(fd, TCSANOW, &to);
+
+    memset(input, 0, sizeof(input));
+
+    printf("%s", prompt);
+    fflush(stdout);
+
+    if ((read(fd, input, sizeof(input))) < 0) {
+      fprintf(stderr, "silc: %s\n", strerror(errno));
+      return NULL;
+    }
+
+    if (strlen(input) <= 1) {
+      tcsetattr(fd, TCSANOW, &to_old);
+      return NULL;
+    }
+
+    if (strchr(input, '\n'))
+      *strchr(input, '\n') = '\0';
+
+    /* Restore old terminfo */
+    tcsetattr(fd, TCSANOW, &to_old);
+    signal(SIGINT, SIG_DFL);
+
+    ret = silc_calloc(strlen(input), sizeof(char));
+    memcpy(ret, input, strlen(input));
+    memset(input, 0, sizeof(input));
+#endif /* HAVE_TERMIOS_H */
+    return ret;
+  } else {
+    char input[2048];
+    int fd;
+
+    fd = open("/dev/tty", O_RDONLY);
+    if (fd < 0) {
+      fprintf(stderr, "silc: %s\n", strerror(errno));
+      return NULL;
+    }
+
+    memset(input, 0, sizeof(input));
+
+    printf("%s", prompt);
+    fflush(stdout);
+
+    if ((read(fd, input, sizeof(input))) < 0) {
+      fprintf(stderr, "silc: %s\n", strerror(errno));
+      return NULL;
+    }
+
+    if (strlen(input) <= 1)
+      return NULL;
+
+    if (strchr(input, '\n'))
+      *strchr(input, '\n') = '\0';
+
+    return strdup(input);
+  }
+#else
+  return NULL;
+#endif /* SILC_UNIX */
+}
index aa4112bcface6035e36fd68d9497f4d2beeeaec7..03889e684926b2c4972f3466f9d4a163cd9f23e5 100644 (file)
@@ -69,5 +69,6 @@ bool silc_parse_version_string(const char *version,
                               char **software_version_string,
                               char **vendor_version);
 SilcUInt32 silc_version_to_num(const char *version);
+char *silc_get_input(const char *prompt, bool echo_off);
 
 #endif