Fixed fingerprint emptines checking. Bug #18.
[silc.git] / apps / silcd / command.c
index 5d6b3cda0a86012b518213d379e88fd35f89a01b..49904b7235c5cbf11c965c4ff572bef1facacc40 100644 (file)
@@ -234,9 +234,15 @@ void silc_server_command_process(SilcServer server,
      seconds. */
   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
     SilcClientEntry client = (SilcClientEntry)sock->user_data;
-    SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
+    SilcServerCommandTimeout timeout;
     int fast;
 
+    if (!client) {
+      SILC_LOG_DEBUG(("Client entry is invalid"));
+      silc_server_command_free(ctx);
+    }
+
+    timeout = silc_calloc(1, sizeof(*timeout));
     timeout->ctx = ctx;
     timeout->cmd = cmd;
 
@@ -366,9 +372,11 @@ void silc_server_command_pending_del(SilcServer server,
 
   silc_dlist_start(server->pending_commands);
   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
-    if (r->reply_cmd == reply_cmd && r->ident == ident) {
+    if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
+                                       r->reply_check))
+        && r->ident == ident) {
       silc_dlist_del(server->pending_commands, r);
-      break;
+      silc_free(r);
     }
   }
 }
@@ -394,6 +402,7 @@ silc_server_command_pending_check(SilcServer server,
       callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
       callbacks[i].context = r->context;
       callbacks[i].callback = r->callback;
+      r->reply_check = TRUE;
       ctx->ident = ident;
       i++;
     }
@@ -733,7 +742,7 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   char nh[256], uh[256];
   unsigned char idle[4], mode[4];
-  unsigned char *fingerprint;
+  unsigned char *fingerprint, fempty[20];
   SilcSocketConnection hsock;
 
   if (nickname) {
@@ -755,6 +764,8 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
     }
   }
 
+  memset(fempty, 0, sizeof(fempty));
+
   /* Start processing found clients. */
   status = SILC_STATUS_OK;
   if (valid_count > 1)
@@ -808,7 +819,7 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
       channels = silc_server_get_client_channel_list(server, entry, TRUE, 
                                                     TRUE, &umode_list);
 
-    if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
+    if (memcmp(entry->data.fingerprint, fempty, sizeof(fempty)))
       fingerprint = entry->data.fingerprint;
     else
       fingerprint = NULL;
@@ -1617,6 +1628,7 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
        break;
       }
 
+      silc_id_payload_free(idp);
       silc_free(id);
     }
   }
@@ -2078,7 +2090,7 @@ SILC_SERVER_CMD_FUNC(nick)
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   int nickfail = 0;
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
@@ -2374,6 +2386,9 @@ SILC_SERVER_CMD_FUNC(topic)
   SilcUInt32 argc, tmp_len;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
 
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+    goto out;
+
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
 
   argc = silc_argument_get_arg_num(cmd->args);
@@ -2532,7 +2547,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, &chl)) {
+  if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
     goto out;
@@ -2788,7 +2803,7 @@ SILC_SERVER_CMD_FUNC(kill)
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
 
-  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
   /* KILL command works only on router */
@@ -3192,6 +3207,8 @@ static void silc_server_command_join_channel(SilcServer server,
   /* Get the client entry */
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
     client = (SilcClientEntry)sock->user_data;
+    if (!client)
+      return;
   } else {
     client = silc_server_get_client_resolve(server, client_id, FALSE, 
                                            &resolve);
@@ -3554,6 +3571,13 @@ SILC_SERVER_CMD_FUNC(join)
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
+    if (!entry) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+                                           0);
+      goto out;
+    }
+
     silc_free(client_id);
     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
 
@@ -3692,7 +3716,7 @@ SILC_SERVER_CMD_FUNC(join)
        /* Save channel passphrase, if user provided it successfully */
        unsigned char *pa;
        SilcUInt32 pa_len;
-       pa = silc_argument_get_arg_type(reply->args, 3, &pa_len);
+       pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
        if (pa) {
          silc_free(channel->passphrase);
          channel->passphrase = silc_memdup(pa, pa_len);
@@ -3873,7 +3897,7 @@ SILC_SERVER_CMD_FUNC(umode)
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   bool set_mask = FALSE;
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
@@ -3958,13 +3982,18 @@ SILC_SERVER_CMD_FUNC(cmode)
   SilcBuffer packet, cidp;
   unsigned char *tmp, *tmp_id, *tmp_mask;
   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
-  SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
+  SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   bool set_mask = FALSE;
   SilcPublicKey founder_key = NULL;
   unsigned char *fkey = NULL;
   SilcUInt32 fkey_len = 0;
 
+  if (!client) {
+    silc_server_command_free(cmd);
+    return;
+  }
+
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
 
   /* Get Channel ID */
@@ -3972,20 +4001,15 @@ SILC_SERVER_CMD_FUNC(cmode)
   if (!tmp_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
-    goto out;
+    silc_server_command_free(cmd);
+    return;
   }
   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, 0);
-    goto out;
-  }
-
-  /* Get the channel mode mask */
-  tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
-  if (tmp_mask) {
-    SILC_GET32_MSB(mode_mask, tmp_mask);
-    set_mask = TRUE;
+    silc_server_command_free(cmd);
+    return;
   }
 
   /* Get channel entry */
@@ -3998,9 +4022,19 @@ SILC_SERVER_CMD_FUNC(cmode)
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL,
                                            0);
-      goto out;
+      silc_free(channel_id);
+      silc_server_command_free(cmd);
+      return;
     }
   }
+  old_mask = channel->mode;
+
+  /* Get the channel mode mask */
+  tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+  if (tmp_mask) {
+    SILC_GET32_MSB(mode_mask, tmp_mask);
+    set_mask = TRUE;
+  }
 
   /* Check whether this client is on the channel */
   if (!silc_server_client_on_channel(client, channel, &chl)) {
@@ -4284,6 +4318,8 @@ SILC_SERVER_CMD_FUNC(cmode)
          silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                                SILC_STATUS_ERR_AUTH_FAILED,
                                                0);
+         silc_pkcs_public_key_free(channel->founder_key);
+         channel->founder_key = NULL;
          goto out;
         }
       }
@@ -4299,7 +4335,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   }
 
   /* Finally, set the mode */
-  channel->mode = mode_mask;
+  old_mask = channel->mode = mode_mask;
 
   /* Send CMODE_CHANGE notify. */
   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
@@ -4331,6 +4367,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   silc_buffer_free(cidp);
 
  out:
+  channel->mode = old_mask;
   silc_free(fkey);
   silc_free(channel_id);
   silc_server_command_free(cmd);
@@ -4358,6 +4395,9 @@ SILC_SERVER_CMD_FUNC(cumode)
   unsigned char *fkey = NULL;
   SilcUInt32 fkey_len = 0;
 
+  if (!client)
+    goto out;
+
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
 
   /* Get Channel ID */
@@ -4712,6 +4752,9 @@ SILC_SERVER_CMD_FUNC(kick)
   SilcUInt32 tmp_len, target_idp_len;
   unsigned char *tmp, *comment, *target_idp;
 
+  if (!client)
+    goto out;
+
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
 
   /* Get Channel ID */
@@ -4858,11 +4901,11 @@ SILC_SERVER_CMD_FUNC(oper)
   bool result = FALSE;
   SilcPublicKey cached_key;
 
-  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
-
-  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
+  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
+
   /* Get the username */
   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
   if (!username) {
@@ -4921,7 +4964,7 @@ SILC_SERVER_CMD_FUNC(oper)
   client->mode |= SILC_UMODE_SERVER_OPERATOR;
 
   /* Update statistics */
-  if (client->connection)
+  if (SILC_IS_LOCAL(client))
     server->stat.my_server_ops++;
   if (server->server_type == SILC_ROUTER)
     server->stat.server_ops++;
@@ -5005,15 +5048,15 @@ SILC_SERVER_CMD_FUNC(detach)
     goto out;
   }
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
 
   /* Remove operator privileges, since the client may resume in some
      other server which to it does not have operator privileges. */
-  client->mode &= ~(SILC_UMODE_SERVER_OPERATOR |
-                   SILC_UMODE_ROUTER_OPERATOR);
+  SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
+  SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
 
   /* Send the user mode notify to notify that client is detached */
   client->mode |= SILC_UMODE_DETACHED;
@@ -5245,11 +5288,11 @@ SILC_SERVER_CMD_FUNC(silcoper)
   bool result = FALSE;
   SilcPublicKey cached_key;
 
-  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
-
-  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
+  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
+
   if (server->server_type != SILC_ROUTER) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
                                          SILC_STATUS_ERR_AUTH_FAILED, 0);
@@ -5312,7 +5355,7 @@ SILC_SERVER_CMD_FUNC(silcoper)
   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
 
   /* Update statistics */
-  if (client->connection)
+  if (SILC_IS_LOCAL(client))
     server->stat.my_router_ops++;
   if (server->server_type == SILC_ROUTER)
     server->stat.router_ops++;
@@ -5351,7 +5394,7 @@ SILC_SERVER_CMD_FUNC(ban)
   SilcUInt32 id_len, tmp_len;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
@@ -5471,6 +5514,9 @@ SILC_SERVER_CMD_FUNC(leave)
   SilcUInt32 len;
   unsigned char *tmp;
 
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
+    goto out;
+
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
 
   /* Get Channel ID */
@@ -5636,7 +5682,8 @@ SILC_SERVER_CMD_FUNC(users)
        && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
                                          NULL)) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
-                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
+                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL,
+                                           0);
       goto out;
     }
   }
@@ -5893,11 +5940,11 @@ SILC_SERVER_CMD_FUNC(connect)
   SilcUInt32 tmp_len;
   SilcUInt32 port = SILC_PORT;
 
-  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
-
-  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
+  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
+
   /* Check whether client has the permissions. */
   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
@@ -5952,11 +5999,11 @@ SILC_SERVER_CMD_FUNC(close)
   unsigned char *name;
   SilcUInt32 port = SILC_PORT;
 
-  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
-
-  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
+  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
+
   /* Check whether client has the permissions. */
   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
@@ -6022,11 +6069,11 @@ SILC_SERVER_CMD_FUNC(shutdown)
   SilcServer server = cmd->server;
   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
 
-  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
-
-  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
+  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
+
   /* Check whether client has the permission. */
   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {