updates.
authorPekka Riikonen <priikone@silcnet.org>
Sat, 15 Sep 2001 12:09:55 +0000 (12:09 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sat, 15 Sep 2001 12:09:55 +0000 (12:09 +0000)
CHANGES
apps/irssi/src/fe-common/silc/module-formats.c
apps/irssi/src/fe-common/silc/module-formats.h
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/clientconfig.c
apps/irssi/src/silc/core/silc-servers.c
apps/silcd/command_reply.c
lib/silcclient/command.c
lib/silcclient/command_reply.c

diff --git a/CHANGES b/CHANGES
index d168ed8587ee15a0809e2ce7c53e6f879e23fb94..6101c8a8b5d90ce63c99ca2cf0d4303d1c503f94 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,32 @@
+Sat Sep 15 13:29:17 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
+
+       * Check that the public key exists in the GETKEY command before
+         trying to encode it.  Affected file silcd/command.c.
+
+       * Print some notifications on received public keys with GETKEY
+         command in the Irssi SILC Client.  Affected files are
+         irssi/src/fe-common/silc/module-formats.[ch],
+         irssi/src/silc/core/client_ops.c.
+
+       * Use IDENTIFY command to resolve the server information in the
+         GETKEY command instead of INFO command.  Affected file
+         lib/silcclient/command.c.
+
+       * All command reply functions in the client library now calls
+         the pending command reply callbacks even if an error has
+         occurred.  The server has done this a long time and now it was
+         time to move the client library to this as well.  Now all
+         errors can be delivered back to the pending command reply
+         callbacks if necessary.  Affected files are
+         lib/silcclient/command[_reply].[ch].
+
+       * Change the nickname on disconnection back to the username
+         because in reconnect the server will enforce it to it anyway.
+         Affected file irssi/src/silc/core/silc-servers.c.
+
+       * Fixed a config file parsing bug in the Irssi SILC client.
+         Affected file irssi/src/silc/core/clientconfig.c.
+
 Thu Sep 13 23:11:18 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
 
        * When printing the channel mode on JOIN, verify that the
index 8f70760ddd3430dfa16149f84a94952ed2c73be2..aef9af93f2dbbceb6b267daa40f73597468261aa 100644 (file)
@@ -90,6 +90,8 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "pubkey_maybe_expired", "It is possible that the key has expired or changed", 0 },
        { "pubkey_mitm_attach", "It is also possible that someone is performing man-in-the-middle attack", 0 },
        { "getkey_notkey", "Server did not return any public key", 0 },
+       { "getkey_verified", "Verified successfully $0 {hilight $1}'s cached public key", 2, { 0, 0 } },
+       { "getkey_discard", "Could not verify $0 {hilight $1}'s public key", 2, { 0, 0 } },
 
        /* Misc messages */
        { NULL, "Misc", 0 },
index 60cd99a781f2504a9dfcbb04ce10f27b9c10063d..9ec9b8efcd9166f6a55923244768e22fd75d256f 100644 (file)
@@ -85,6 +85,8 @@ enum {
   SILCTXT_PUBKEY_MAYBE_EXPIRED,
   SILCTXT_PUBKEY_MITM_ATTACK,
   SILCTXT_GETKEY_NOKEY,
+  SILCTXT_GETKEY_VERIFIED,
+  SILCTXT_GETKEY_DISCARD,
 
   SILCTXT_FILL_4,
 
index 4f6758145a562fc6c686479dfee3380bd29eb8ae..8bb18afd62a6464ebf2919673c95250b016a8ade 100644 (file)
@@ -307,6 +307,34 @@ static void silc_client_join_get_users(SilcClient client,
   }
 }
 
+typedef struct {
+  SilcClient client;
+  SilcClientConnection conn;
+  void *entry;
+  SilcIdType id_type;
+  char *fingerprint;
+} *GetkeyContext;
+
+void silc_getkey_cb(bool success, void *context)
+{
+  GetkeyContext getkey = (GetkeyContext)context;
+  char *entity = (getkey->id_type == SILC_ID_CLIENT ? "user" : "server");
+  char *name = (getkey->id_type == SILC_ID_CLIENT ? 
+               ((SilcClientEntry)getkey->entry)->nickname :
+               ((SilcServerEntry)getkey->entry)->server_name);
+
+  if (success) {
+    printformat_module("fe-common/silc", NULL, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_GETKEY_VERIFIED, entity, name);
+  } else {
+    printformat_module("fe-common/silc", NULL, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_GETKEY_DISCARD, entity, name);
+  }
+
+  silc_free(getkey->fingerprint);
+  silc_free(getkey);
+}
+
 /* Command reply handler. This function is called always in the command reply
    function. If error occurs it will be called as well. Normal scenario
    is that it will be called after the received command data has been parsed
@@ -684,6 +712,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       SilcPublicKey public_key;
       unsigned char *pk;
       uint32 pk_len;
+      GetkeyContext getkey;
       
       if (!success)
        return;
@@ -694,13 +723,20 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
 
       if (public_key) {
        pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+
+       getkey = silc_calloc(1, sizeof(*getkey));
+       getkey->entry = entry;
+       getkey->id_type = id_type;
+       getkey->client = client;
+       getkey->conn = conn;
+       getkey->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
        
        silc_verify_public_key_internal(client, conn, 
                                        (id_type == SILC_ID_CLIENT ?
                                         SILC_SOCKET_TYPE_CLIENT :
                                         SILC_SOCKET_TYPE_SERVER),
                                        pk, pk_len, SILC_SKE_PK_TYPE_SILC,
-                                       NULL, NULL);
+                                       silc_getkey_cb, getkey);
        silc_free(pk);
       } else {
        printformat_module("fe-common/silc", server, NULL,
index 5626f2a0cfa254e283e4215af8063d0fb76f1f1d..450020a3e6cf963e9866fd33edc39d52c227c616 100644 (file)
@@ -180,6 +180,12 @@ int silc_client_config_parse(SilcClientConfig config, SilcBuffer buffer,
        * Start of a configuration line
        */
 
+      if (!cptr) {
+       fprintf(stderr, "%s:%d: Unknown start of a section `%s'\n", 
+                       config->filename, linenum, cp);
+       return FALSE;
+      }        
+
       /* Handle config section */
       if (cptr->type != SILC_CLIENT_CONFIG_SECTION_TYPE_NONE) {
        
index cd15aed98e638dff3f18ddec7f4737bdeaf59228..9bc50bd4baba8ce1f12e32ac5e99791cb7bc7e9d 100644 (file)
@@ -37,6 +37,7 @@
 #include "silc-servers.h"
 #include "silc-channels.h"
 #include "silc-queries.h"
+#include "silc-nicklist.h"
 #include "window-item-def.h"
 
 #include "fe-common/core/printtext.h"
@@ -208,6 +209,12 @@ static void sig_disconnected(SILC_SERVER_REC *server)
     return;
   
   if (server->conn->sock != NULL) {
+    nicklist_rename_unique(SERVER(server),
+                          server->conn->local_entry, server->nick,
+                          server->conn->local_entry, 
+                          silc_client->username);
+    signal_emit("message own_nick", 4, server, server->nick, server->nick, "");
+
     silc_client_close_connection(silc_client, NULL, server->conn);
     
     /* SILC closes the handle */
index cb124b426389e937c302554f6e68862c2e407f7c..8945bb4191bfba1d34f506380a964354b95e6ffc 100644 (file)
@@ -883,8 +883,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
   SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
-  if (client_id)
-    silc_free(client_id);
+  silc_free(client_id);
   silc_server_command_reply_free(cmd);
 
   if (client_id_list)
index b449b1150ed9da09d1d1eccd113d1f948bf63754..0388f29a082476385b276d1ab4312beeba3b174c 100644 (file)
@@ -2053,6 +2053,23 @@ SILC_CLIENT_CMD_FUNC(getkey)
     goto out;
   }
 
+  if (cmd->pending) {
+    SilcClientCommandReplyContext reply = 
+      (SilcClientCommandReplyContext)context2;
+    SilcCommandStatus status;
+    unsigned char *tmp = silc_argument_get_arg_type(reply->args, 1, NULL);
+    SILC_GET16_MSB(status, tmp);
+    
+    if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
+       status == SILC_STATUS_ERR_NO_SUCH_SERVER) {
+      cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                           "%s", 
+                           silc_client_command_status_message(status));
+      COMMAND_ERROR;
+      goto out;
+    }
+  }
+
   /* Parse the typed nickname. */
   if (client->params->nickname_parse)
     client->params->nickname_parse(cmd->argv[1], &nickname);
@@ -2066,7 +2083,7 @@ SILC_CLIENT_CMD_FUNC(getkey)
     /* Check whether user requested server actually */
     server_entry = silc_client_get_server(client, conn, cmd->argv[1]);
 
-    if (!server_entry) {
+    if (!server_entry && !cmd->pending) {
       /* No. what ever user wants we don't have it, so resolve it. We
         will try to resolve both client and server, one of them is
         bound to be wrong. */
@@ -2079,13 +2096,12 @@ SILC_CLIENT_CMD_FUNC(getkey)
                                  silc_client_command_getkey, 
                                  silc_client_command_dup(cmd));
 
-      /* This sends the INFO command to resolve the server. */
-      silc_client_send_command(client, conn, SILC_COMMAND_INFO,
+      /* This sends the IDENTIFY command to resolve the server. */
+      silc_client_send_command(client, conn, SILC_COMMAND_IDENTIFY,
                               ++conn->cmd_ident, 1, 
-                              1, cmd->argv[1], cmd->argv_lens[1]);
+                              2, cmd->argv[1], cmd->argv_lens[1]);
       silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 
-                                 conn->cmd_ident,  
-                                 silc_client_command_destructor,
+                                 conn->cmd_ident, NULL,
                                  silc_client_command_getkey, 
                                  silc_client_command_dup(cmd));
 
index 2fc508ac4bc0cd13d84a0ba9dca7a6056e4b1a23..0396ae9ca5388a2bd49d96e6cdbc352a60536ce2 100644 (file)
@@ -122,6 +122,32 @@ const SilcCommandStatusMessage silc_command_status_messages[] = {
   cmd->sock->user_data, cmd->payload, FALSE, \
   silc_command_get(cmd->payload), status)
 
+/* 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;                                                            \
+  }                                                                      \
+} 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;                                                            \
+  }                                                                      \
+} while(0)
+
 /* Process received command reply. */
 
 void silc_client_command_reply_process(SilcClient client,
@@ -283,29 +309,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcCommandStatus status;
-  unsigned char *tmp;
 
-  SILC_LOG_DEBUG(("Start"));
-
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  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;
-  }
+  COMMAND_CHECK_STATUS_LIST;
 
-  /* Display one whois reply */
-  if (status == SILC_STATUS_OK)
-    silc_client_command_reply_whois_save(cmd, status);
-
-  /* List */
-  if (status == SILC_STATUS_LIST_START ||
-      status == SILC_STATUS_LIST_ITEM ||
-      status == SILC_STATUS_LIST_END)
-    silc_client_command_reply_whois_save(cmd, status);
+  /* Save WHOIS info */
+  silc_client_command_reply_whois_save(cmd, status);
 
   /* Pending callbacks are not executed if this was an list entry */
   if (status != SILC_STATUS_OK &&
@@ -314,10 +322,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois)
     return;
   }
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
   silc_client_command_reply_free(cmd);
 }
@@ -333,32 +339,22 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas)
   SilcIDCacheEntry id_cache = NULL;
   SilcClientEntry client_entry = NULL;
   uint32 len;
-  unsigned char *id_data, *tmp;
+  unsigned char *id_data;
   char *nickname, *username;
   char *realname = NULL;
 
-  SILC_LOG_DEBUG(("Start"));
+  COMMAND_CHECK_STATUS_LIST;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  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;
-  }
-  
   id_data = silc_argument_get_arg_type(cmd->args, 2, &len);
   if (!id_data) {
     COMMAND_REPLY_ERROR;
-    return;
+    goto out;
   }
   
   client_id = silc_id_payload_parse_id(id_data, len);
   if (!client_id) {
     COMMAND_REPLY_ERROR;
-    return;
+    goto out;
   }
 
   /* Get the client entry, if exists */
@@ -374,8 +370,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas)
   realname = silc_argument_get_arg_type(cmd->args, 5, &len);
   if (!nickname || !username) {
     COMMAND_REPLY_ERROR;
-    return;
+    goto out;
   }
+
   /* Notify application. We don't save any history information to any
      cache. Just pass the data to the application for displaying on 
      the screen. */
@@ -388,10 +385,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas)
     return;
   }
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
   silc_client_command_reply_free(cmd);
 }
@@ -525,29 +520,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcCommandStatus status;
-  unsigned char *tmp;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  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;
-  }
 
-  /* Save one IDENTIFY entry */
-  if (status == SILC_STATUS_OK)
-    silc_client_command_reply_identify_save(cmd, status);
+  COMMAND_CHECK_STATUS_LIST;
 
-  /* List */
-  if (status == SILC_STATUS_LIST_START ||
-      status == SILC_STATUS_LIST_ITEM ||
-      status == SILC_STATUS_LIST_END)
-    silc_client_command_reply_identify_save(cmd, status);
+  /* Save IDENTIFY info */
+  silc_client_command_reply_identify_save(cmd, status);
 
   /* Pending callbacks are not executed if this was an list entry */
   if (status != SILC_STATUS_OK &&
@@ -556,10 +533,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify)
     return;
   }
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
   silc_client_command_reply_free(cmd);
 }
@@ -582,7 +557,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick)
   if (status != SILC_STATUS_OK) {
     cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
                          "Cannot set nickname: %s", 
-            silc_client_command_status_message(status));
+                         silc_client_command_status_message(status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -607,10 +582,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick)
   /* Notify application */
   COMMAND_REPLY((ARGS, conn->local_entry));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_NICK);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_NICK);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_NICK);
   silc_client_command_reply_free(cmd);
 }
@@ -624,15 +597,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(list)
   unsigned char *tmp, *name, *topic;
   uint32 usercount = 0;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  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;
-  }
+  COMMAND_CHECK_STATUS_LIST;
 
   name = silc_argument_get_arg_type(cmd->args, 3, NULL);
   topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
@@ -650,10 +615,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(list)
     return;
   }
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_LIST);
   silc_client_command_reply_free(cmd);
 }
@@ -677,9 +640,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic)
     cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
             "%s", silc_client_command_status_message(status));
     COMMAND_REPLY_ERROR;
-    SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_TOPIC);
-    silc_client_command_reply_free(cmd);
-    return;
+    goto out;
   }
 
   argc = silc_argument_get_arg_num(cmd->args);
@@ -715,10 +676,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic)
   /* Notify application */
   COMMAND_REPLY((ARGS, channel, topic));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_TOPIC);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_TOPIC);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_TOPIC);
   silc_client_command_reply_free(cmd);
 }
@@ -742,9 +701,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite)
     cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
             "%s", silc_client_command_status_message(status));
     COMMAND_REPLY_ERROR;
-    SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INVITE);
-    silc_client_command_reply_free(cmd);
-    return;
+    goto out;
   }
 
   /* Take Channel ID */
@@ -772,10 +729,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite)
   /* Notify application */
   COMMAND_REPLY((ARGS, channel, tmp));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INVITE);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INVITE);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INVITE);
   silc_client_command_reply_free(cmd);
 }
@@ -801,10 +756,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(kill)
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_KILL);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_KILL);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_KILL);
   silc_client_command_reply_free(cmd);
 }
@@ -830,9 +783,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info)
     cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
             "%s", silc_client_command_status_message(status));
     COMMAND_REPLY_ERROR;
-    SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
-    silc_client_command_reply_free(cmd);
-    return;
+    goto out;
   }
 
   /* Get server ID */
@@ -874,13 +825,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(info)
   /* Notify application */
   COMMAND_REPLY((ARGS, server, server->server_name, server->server_info));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
-
  out:
-  if (server_id)
-    silc_free(server_id);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
+  silc_free(server_id);
   silc_client_command_reply_free(cmd);
 }
 
@@ -933,10 +881,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(ping)
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PING);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PING);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_PING);
   silc_client_command_reply_free(cmd);
 }
@@ -954,7 +900,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
   SilcChannelUser chu;
   uint32 argc, mode, len, list_count;
   char *topic, *tmp, *channel_name = NULL, *hmac;
-  SilcBuffer keyp = NULL, client_id_list, client_mode_list;
+  SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
   int i;
 
   SILC_LOG_DEBUG(("Start"));
@@ -1123,17 +1069,17 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
                 NULL, topic, hmac, list_count, client_id_list, 
                 client_mode_list));
 
-  /* Execute any pending command callbacks */
+ out:
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
+  silc_client_command_reply_free(cmd);
 
   if (keyp)
     silc_buffer_free(keyp);
-  silc_buffer_free(client_id_list);
-  silc_buffer_free(client_mode_list);
-
- out:
-  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
-  silc_client_command_reply_free(cmd);
+  if (client_id_list)
+    silc_buffer_free(client_id_list);
+  if (client_mode_list)
+    silc_buffer_free(client_mode_list);
 }
 
 /* Received reply for MOTD command */
@@ -1193,10 +1139,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd)
   /* Notify application */
   COMMAND_REPLY((ARGS, motd));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_MOTD);
   silc_client_command_reply_free(cmd);
 }
@@ -1232,10 +1176,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(umode)
   /* Notify application */
   COMMAND_REPLY((ARGS, mode));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_UMODE);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_UMODE);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_UMODE);
   silc_client_command_reply_free(cmd);
 }
@@ -1294,12 +1236,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode)
 
   /* Notify application */
   COMMAND_REPLY((ARGS, channel, mode));
-  silc_free(channel_id);
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CMODE);
+  silc_free(channel_id);
 
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CMODE);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CMODE);
   silc_client_command_reply_free(cmd);
 }
@@ -1394,10 +1335,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode)
   silc_free(client_id);
   silc_free(channel_id);
   
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CUMODE);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CUMODE);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CUMODE);
   silc_client_command_reply_free(cmd);
 }
@@ -1421,10 +1360,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(kick)
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_KICK);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_KICK);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_KICK);
   silc_client_command_reply_free(cmd);
 }
@@ -1448,10 +1385,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(silcoper)
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_SILCOPER);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_SILCOPER);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_SILCOPER);
   silc_client_command_reply_free(cmd);
 }
@@ -1475,10 +1410,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(oper)
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_OPER);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_OPER);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_OPER);
   silc_client_command_reply_free(cmd);
 }
@@ -1502,10 +1435,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(connect)
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CONNECT);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CONNECT);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CONNECT);
   silc_client_command_reply_free(cmd);
 }
@@ -1555,10 +1486,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban)
   /* Notify application */
   COMMAND_REPLY((ARGS, channel, tmp));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_BAN);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_BAN);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_BAN);
   silc_client_command_reply_free(cmd);
 }
@@ -1582,10 +1511,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(close)
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CLOSE);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CLOSE);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CLOSE);
   silc_client_command_reply_free(cmd);
 }
@@ -1609,10 +1536,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(shutdown)
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_SHUTDOWN);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_SHUTDOWN);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_SHUTDOWN);
   silc_client_command_reply_free(cmd);
 }
@@ -1638,10 +1563,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(leave)
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LEAVE);
-
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LEAVE);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_LEAVE);
   silc_client_command_reply_free(cmd);
 }
@@ -1658,8 +1581,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
   SilcChannelEntry channel;
   SilcChannelUser chu;
   SilcChannelID *channel_id = NULL;
-  SilcBuffer client_id_list;
-  SilcBuffer client_mode_list;
+  SilcBuffer client_id_list = NULL;
+  SilcBuffer client_mode_list = NULL;
   unsigned char *tmp;
   uint32 tmp_len, list_count;
   int i;
@@ -1830,17 +1753,15 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
   /* Notify application */
   COMMAND_REPLY((ARGS, channel, list_count, client_id_list, client_mode_list));
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
-
-  silc_buffer_free(client_id_list);
-  silc_buffer_free(client_mode_list);
-
  out:
-  if (channel_id)
-    silc_free(channel_id);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
   silc_client_command_reply_free(cmd);
+  silc_free(channel_id);
+  if (client_id_list)
+    silc_buffer_free(client_id_list);
+  if (client_mode_list)
+    silc_buffer_free(client_mode_list);
 }
 
 /* Received command reply to GETKEY command. WE've received the remote
@@ -1870,17 +1791,21 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
   SILC_GET16_MSB(status, tmp);
   if (status != SILC_STATUS_OK) {
     cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-            "%s", silc_client_command_status_message(status));
+                         "%s", silc_client_command_status_message(status));
     COMMAND_REPLY_ERROR;
     goto out;
   }
 
   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
-  if (!tmp)
+  if (!tmp) {
+    COMMAND_REPLY_ERROR;
     goto out;
+  }
   idp = silc_id_payload_parse_data(tmp, len);
-  if (!idp)
+  if (!idp) {
+    COMMAND_REPLY_ERROR;
     goto out;
+  }
 
   /* Get the public key payload */
   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
@@ -1890,11 +1815,15 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
     SILC_GET16_MSB(type, tmp + 2);
     pk = tmp + 4;
     
-    if (type != SILC_SKE_PK_TYPE_SILC)
+    if (type != SILC_SKE_PK_TYPE_SILC) {
+      COMMAND_REPLY_ERROR;
       goto out;
+    }
     
-    if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
+    if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key)) {
+      COMMAND_REPLY_ERROR;
       goto out;
+    }
   } 
    
   id_type = silc_id_payload_get_type(idp);
@@ -1905,8 +1834,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
                                         (void *)client_id, 
                                         NULL, NULL, 
                                         silc_hash_client_id_compare, NULL,
-                                        &id_cache))
+                                        &id_cache)) {
+      COMMAND_REPLY_ERROR;
       goto out;
+    }
 
     client_entry = (SilcClientEntry)id_cache->context;
 
@@ -1916,8 +1847,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
     /* 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))
+                                    &id_cache)) {
+      COMMAND_REPLY_ERROR;
       goto out;
+    }
 
     server_entry = (SilcServerEntry)id_cache->context;
 
@@ -1926,6 +1859,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
   }
 
  out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_GETKEY);
   if (idp)
     silc_id_payload_free(idp);