updates.
[silc.git] / apps / silcd / command.c
index e70478a0361675cd26a46f4fe6b9ea7eb94281ca..59509fdda36d7fca1c2d65ebdee8220ba7b8e717 100644 (file)
@@ -122,6 +122,10 @@ static int silc_server_is_registered(SilcServer server,
                                     SilcCommand command)
 {
   SilcIDListData idata = (SilcIDListData)sock->user_data;
+
+  if (!idata)
+    return FALSE;
+
   if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
     return TRUE;
 
@@ -678,6 +682,24 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
     if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
       len++;
 
+  if (len == 0 && clients_count) {
+    entry = clients[0];
+    if (entry->nickname) {
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
+                                          SILC_STATUS_ERR_NO_SUCH_NICK,
+                                          3, entry->nickname, 
+                                          strlen(entry->nickname));
+    } else {
+      SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
+                                          SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+                                          2, idp->data, idp->len);
+      silc_buffer_free(idp);
+    }
+
+    return;
+  }
+
   status = SILC_STATUS_OK;
   if (len > 1)
     status = SILC_STATUS_LIST_START;
@@ -844,7 +866,7 @@ silc_server_command_whois_process(SilcServerCommandContext cmd)
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
     check_global = TRUE;
-  else if (server->server_type == SILC_ROUTER)
+  else if (server->server_type != SILC_SERVER)
     check_global = TRUE;
 
   /* Parse the whois request */
@@ -921,12 +943,9 @@ silc_server_command_whois_process(SilcServerCommandContext cmd)
       silc_free(client_id[i]);
     silc_free(client_id);
   }
-  if (clients)
-    silc_free(clients);
-  if (nick)
-    silc_free(nick);
-  if (server_name)
-    silc_free(server_name);
+  silc_free(clients);
+  silc_free(nick);
+  silc_free(server_name);
 
   return ret;
 }
@@ -1182,7 +1201,7 @@ silc_server_command_whowas_process(SilcServerCommandContext cmd)
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
     check_global = TRUE;
-  else if (server->server_type == SILC_ROUTER)
+  else if (server->server_type != SILC_SERVER)
     check_global = TRUE;
 
   /* Parse the whowas request */
@@ -1215,8 +1234,7 @@ silc_server_command_whowas_process(SilcServerCommandContext cmd)
     goto out;
   }
 
-  if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
-      !silc_server_command_whowas_check(cmd, clients, clients_count)) {
+  if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
     ret = -1;
     goto out;
   }
@@ -1275,7 +1293,7 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
     check_global = TRUE;
-  else if (server->server_type == SILC_ROUTER)
+  else if (server->server_type != SILC_SERVER)
     check_global = TRUE;
 
   /* If ID Payload is in the command it must be used instead of names */
@@ -1323,7 +1341,7 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
       entry = silc_idlist_find_server_by_name(server->local_list,
                                              tmp, TRUE, NULL);
       if (!entry && check_global)
-       entry = silc_idlist_find_server_by_name(server->local_list,
+       entry = silc_idlist_find_server_by_name(server->global_list,
                                                tmp, TRUE, NULL);
       if (entry) {
        *servers = silc_realloc(*servers, sizeof(**servers) * 
@@ -1345,7 +1363,7 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
       entry = silc_idlist_find_channel_by_name(server->local_list,
                                               tmp, NULL);
       if (!entry && check_global)
-       entry = silc_idlist_find_channel_by_name(server->local_list,
+       entry = silc_idlist_find_channel_by_name(server->global_list,
                                                 tmp, NULL);
       if (entry) {
        *channels = silc_realloc(*channels, sizeof(**channels) * 
@@ -1629,6 +1647,24 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
       if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
        len++;
 
+    if (len == 0 && clients_count) {
+      entry = clients[0];
+      if (entry->nickname) {
+       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
+                                            SILC_STATUS_ERR_NO_SUCH_NICK,
+                                            3, entry->nickname, 
+                                            strlen(entry->nickname));
+      } else {
+       SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
+       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
+                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+                                            2, idp->data, idp->len);
+       silc_buffer_free(idp);
+      }
+      
+      return;
+    }
+
     if (len > 1)
       status = SILC_STATUS_LIST_START;
 
@@ -1639,7 +1675,7 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
        if (clients_count == 1) {
          SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
          silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
-                                       SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+                                        SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
                                               2, idp->data, idp->len);
          silc_buffer_free(idp);
        }
@@ -1896,14 +1932,20 @@ SILC_SERVER_CMD_FUNC(identify)
 
 static int silc_server_command_bad_chars(char *nick)
 {
-  if (strchr(nick, '\\')) return TRUE;
-  if (strchr(nick, '\"')) return TRUE;
-  if (strchr(nick, 'ยด')) return TRUE;
-  if (strchr(nick, '`')) return TRUE;
-  if (strchr(nick, '\'')) return TRUE;
-  if (strchr(nick, '*')) return TRUE;
-  if (strchr(nick, '/')) return TRUE;
-  if (strchr(nick, '@')) return TRUE;
+  int i;
+
+  for (i = 0; i < strlen(nick); i++) {
+    if (!isascii(nick[i]))
+      return TRUE;
+    if (nick[i] <= 32) return TRUE;
+    if (nick[i] == ' ') return TRUE;
+    if (nick[i] == '\\') return TRUE;
+    if (nick[i] == '\"') return TRUE;
+    if (nick[i] == '*') return TRUE;
+    if (nick[i] == '?') return TRUE;
+    if (nick[i] == ',') return TRUE;
+    if (nick[i] == '@') return TRUE;
+  }
 
   return FALSE;
 }
@@ -2161,7 +2203,7 @@ SILC_SERVER_CMD_FUNC(list)
                                       &lch_count);
   
   /* Get the channels from global list if we are router */
-  if (server->server_type == SILC_ROUTER) 
+  if (server->server_type != SILC_SERVER) 
     gchannels = silc_idlist_get_channels(server->global_list, channel_id,
                                         &gch_count);
 
@@ -2252,8 +2294,7 @@ SILC_SERVER_CMD_FUNC(topic)
     }
 
     /* Set the topic for channel */
-    if (channel->topic)
-      silc_free(channel->topic);
+    silc_free(channel->topic);
     channel->topic = strdup(tmp);
 
     /* Send TOPIC_SET notify type to the network */
@@ -2378,7 +2419,7 @@ SILC_SERVER_CMD_FUNC(invite)
     /* Get the client entry */
     dest = silc_server_get_client_resolve(server, dest_id);
     if (!dest) {
-      if (server->server_type == SILC_ROUTER) {
+      if (server->server_type != SILC_SERVER) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
                                     SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
        goto out;
@@ -2516,10 +2557,8 @@ SILC_SERVER_CMD_FUNC(invite)
   silc_buffer_free(packet);
 
  out:
-  if (dest_id)
-    silc_free(dest_id);
-  if (channel_id)
-    silc_free(channel_id);
+  silc_free(dest_id);
+  silc_free(channel_id);
   silc_server_command_free(cmd);
 }
 
@@ -2737,7 +2776,7 @@ SILC_SERVER_CMD_FUNC(info)
     if (!entry) {
       entry = silc_idlist_find_server_by_id(server->global_list,
                                            server_id, TRUE, NULL);
-      if (!entry && server->server_type == SILC_ROUTER) {
+      if (!entry && server->server_type != SILC_SERVER) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
                                              SILC_STATUS_ERR_NO_SUCH_SERVER);
        goto out;
@@ -2746,7 +2785,7 @@ SILC_SERVER_CMD_FUNC(info)
   }
 
   /* Some buggy servers has sent request to router about themselves. */
-  if (server->server_type == SILC_ROUTER && cmd->sock->user_data == entry)
+  if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
     goto out;
 
   if ((!dest_server && !server_id && !entry) || (entry && 
@@ -2778,7 +2817,7 @@ SILC_SERVER_CMD_FUNC(info)
     }
 
     if (!cmd->pending &&
-       server->server_type == SILC_ROUTER && entry && !entry->server_info) {
+       server->server_type != SILC_SERVER && entry && !entry->server_info) {
       /* Send to the server */
       SilcBuffer tmpbuf;
       uint16 old_ident;
@@ -2829,8 +2868,7 @@ SILC_SERVER_CMD_FUNC(info)
     }
   }
 
-  if (server_id)
-    silc_free(server_id);
+  silc_free(server_id);
 
   if (!entry) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
@@ -2915,7 +2953,8 @@ static void silc_server_command_join_channel(SilcServer server,
                                             SilcServerCommandContext cmd,
                                             SilcChannelEntry channel,
                                             SilcClientID *client_id,
-                                            int created,
+                                            bool created,
+                                            bool create_key,
                                             uint32 umode)
 {
   SilcSocketConnection sock = cmd->sock;
@@ -3043,17 +3082,17 @@ static void silc_server_command_join_channel(SilcServer server,
   }
 
   /* Generate new channel key as protocol dictates */
-  if ((!created && silc_hash_table_count(channel->user_list) > 0) || 
-      !channel->channel_key)
+  if (create_key) {
     if (!silc_server_create_channel_key(server, channel, 0))
       goto out;
 
-  /* Send the channel key. This is broadcasted to the channel but is not
-     sent to the client who is joining to the channel. */
-  if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
-    silc_server_send_channel_key(server, NULL, channel, 
-                                server->server_type == SILC_ROUTER ? 
-                                FALSE : !server->standalone);
+    /* Send the channel key. This is broadcasted to the channel but is not
+       sent to the client who is joining to the channel. */
+    if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
+      silc_server_send_channel_key(server, NULL, channel, 
+                                  server->server_type == SILC_ROUTER ? 
+                                  FALSE : !server->standalone);
+  }
 
   /* Join the client to the channel by adding it to channel's user list.
      Add also the channel to client entry's channels list for fast cross-
@@ -3108,8 +3147,9 @@ static void silc_server_command_join_channel(SilcServer server,
                                         10, channel->topic,
                                         channel->topic ?
                                         strlen(channel->topic) : 0,
-                                        11, channel->hmac->hmac->name,
-                                        strlen(channel->hmac->hmac->name),
+                                        11, silc_hmac_get_name(channel->hmac),
+                                        strlen(silc_hmac_get_name(channel->
+                                                                  hmac)),
                                         12, tmp3, 4,
                                         13, user_list->data, user_list->len,
                                         14, mode_list->data, 
@@ -3119,18 +3159,28 @@ static void silc_server_command_join_channel(SilcServer server,
   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
                          reply->data, reply->len, FALSE);
 
-  if (!cmd->pending) {
-    /* Send JOIN notify to locally connected clients on the channel */
-    silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
-                                      SILC_NOTIFY_TYPE_JOIN, 2,
-                                      clidp->data, clidp->len,
-                                      chidp->data, chidp->len);
+  /* Send JOIN notify to locally connected clients on the channel. If
+     we are normal server then router will send or have sent JOIN notify
+     already. However since we've added the client already to our channel
+     we'll ignore it (in packet_receive.c) so we must send it here. If
+     we are router then this will send it to local clients and local
+     servers. */
+  silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
+                                    SILC_NOTIFY_TYPE_JOIN, 2,
+                                    clidp->data, clidp->len,
+                                    chidp->data, chidp->len);
 
+  if (!cmd->pending) {
     /* Send JOIN notify packet to our primary router */
     if (!server->standalone)
       silc_server_send_notify_join(server, server->router->connection,
                                   server->server_type == SILC_ROUTER ?
                                   TRUE : FALSE, channel, client->id);
+
+    if (keyp)
+      /* Distribute the channel key to all backup routers. */
+      silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
+                             keyp->data, keyp->len, FALSE, TRUE);
   }
 
   silc_buffer_free(reply);
@@ -3141,8 +3191,7 @@ static void silc_server_command_join_channel(SilcServer server,
   silc_buffer_free(mode_list);
 
  out:
-  if (passphrase)
-    silc_free(passphrase);
+  silc_free(passphrase);
 }
 
 /* Server side of command JOIN. Joins client into requested channel. If 
@@ -3156,7 +3205,7 @@ SILC_SERVER_CMD_FUNC(join)
   char *tmp, *channel_name = NULL, *cipher, *hmac;
   SilcChannelEntry channel;
   uint32 umode = 0;
-  int created = FALSE;
+  bool created = FALSE, create_key = TRUE;
   SilcClientID *client_id;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
@@ -3213,7 +3262,7 @@ SILC_SERVER_CMD_FUNC(join)
       }
     }
 
-    if (!channel || !channel->id) {
+    if (!channel || channel->disabled) {
       /* Channel not found */
 
       /* If we are standalone server we don't have a router, we just create 
@@ -3223,20 +3272,21 @@ SILC_SERVER_CMD_FUNC(join)
                                                 hmac, channel_name, TRUE);
        if (!channel) {
          silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
-                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
+                                       SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
          goto out;
        }
-
+       
        umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
        created = TRUE;
-
+       create_key = FALSE;
+       
       } else {
 
        /* The channel does not exist on our server. If we are normal server 
           we will send JOIN command to our router which will handle the
           joining procedure (either creates the channel if it doesn't exist 
           or joins the client to it). */
-       if (server->server_type == SILC_SERVER) {
+       if (server->server_type != SILC_ROUTER) {
          SilcBuffer tmpbuf;
          uint16 old_ident;
 
@@ -3282,6 +3332,7 @@ SILC_SERVER_CMD_FUNC(join)
 
          umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
          created = TRUE;
+         create_key = FALSE;
        }
       }
     }
@@ -3289,11 +3340,11 @@ SILC_SERVER_CMD_FUNC(join)
     if (!channel) {
       /* Channel not found */
 
-      /* If the command came from router and/or we are normal server then
+      /* If the command came from router and we are normal server then
         something went wrong with the joining as the channel was not found.
         We can't do anything else but ignore this. */
       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
-         server->server_type == SILC_SERVER)
+         server->server_type != SILC_ROUTER)
        goto out;
       
       /* We are router and the channel does not seem exist so we will check
@@ -3312,21 +3363,30 @@ SILC_SERVER_CMD_FUNC(join)
 
        umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
        created = TRUE;
+       create_key = FALSE;
       }
     }
   }
 
-  /* If the channel does not have global users and is also empty it means the
-     channel was created globally (by our router) and the client will be the
-     channel founder and operator. */
-  if (!channel->global_users && !silc_hash_table_count(channel->user_list)) {
-    umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
-    created = TRUE;            /* Created globally by our router */
+  /* Check whether the channel was created by our router */
+  if (cmd->pending && context2) {
+    SilcServerCommandReplyContext reply = 
+      (SilcServerCommandReplyContext)context2;
+    if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
+      tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
+      SILC_GET32_MSB(created, tmp);
+      create_key = FALSE;      /* Router returned the key already */
+    }
   }
 
+  /* If the channel does not have global users and is also empty the client
+     will be the channel founder and operator. */
+  if (!channel->global_users && !silc_hash_table_count(channel->user_list))
+    umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
+
   /* Join to the channel */
   silc_server_command_join_channel(server, cmd, channel, client_id,
-                                  created, umode);
+                                  created, create_key, umode);
 
   silc_free(client_id);
 
@@ -3364,7 +3424,7 @@ SILC_SERVER_CMD_FUNC(motd)
     if (server->config && server->config->motd && 
        server->config->motd->motd_file) {
       /* Send motd */
-      motd = silc_file_read(server->config->motd->motd_file, &motd_len);
+      motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
       if (!motd)
        goto out;
       
@@ -3396,7 +3456,7 @@ SILC_SERVER_CMD_FUNC(motd)
                                              dest_server, TRUE, NULL);
     }
 
-    if (server->server_type == SILC_ROUTER && !cmd->pending && 
+    if (server->server_type != SILC_SERVER && !cmd->pending && 
        entry && !entry->motd) {
       /* Send to the server */
       SilcBuffer tmpbuf;
@@ -3582,8 +3642,9 @@ int silc_server_check_cmode_rights(SilcChannelEntry channel,
      modes are available automatically for channel operator. */
 
   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
-    if (is_op && !is_fo)
-      return FALSE;
+    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)
@@ -3592,8 +3653,9 @@ int silc_server_check_cmode_rights(SilcChannelEntry channel,
   }
   
   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
-    if (is_op && !is_fo)
-      return FALSE;
+    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)
@@ -3602,8 +3664,9 @@ int silc_server_check_cmode_rights(SilcChannelEntry channel,
   }
 
   if (mode & SILC_CHANNEL_MODE_CIPHER) {
-    if (is_op && !is_fo)
-      return FALSE;
+    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)
@@ -3612,8 +3675,9 @@ int silc_server_check_cmode_rights(SilcChannelEntry channel,
   }
   
   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
-    if (is_op && !is_fo)
-      return FALSE;
+    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)
@@ -3722,7 +3786,7 @@ SILC_SERVER_CMD_FUNC(cmode)
                                   FALSE : !server->standalone);
 
       cipher = channel->channel_key->cipher->name;
-      hmac = channel->hmac->hmac->name;
+      hmac = (char *)silc_hmac_get_name(channel->hmac);
     }
   }
   
@@ -3811,7 +3875,7 @@ SILC_SERVER_CMD_FUNC(cmode)
 
       /* Delete old cipher and allocate default one */
       silc_cipher_free(channel->channel_key);
-      if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc"
+      if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER
                             &channel->channel_key)) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                   SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
@@ -3853,10 +3917,11 @@ SILC_SERVER_CMD_FUNC(cmode)
 
       /* Set the HMAC key out of current channel key. The client must do
         this locally. */
-      silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8, 
+      silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
+                    channel->key_len / 8, 
                     hash);
       silc_hmac_set_key(channel->hmac, hash, 
-                       silc_hash_len(channel->hmac->hash));
+                       silc_hash_len(silc_hmac_get_hash(channel->hmac)));
       memset(hash, 0, sizeof(hash));
     }
   } else {
@@ -3868,7 +3933,7 @@ SILC_SERVER_CMD_FUNC(cmode)
 
       /* Delete old hmac and allocate default one */
       silc_hmac_free(channel->hmac);
-      if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL, 
+      if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, 
                           &channel->hmac)) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                       SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
@@ -3877,10 +3942,11 @@ SILC_SERVER_CMD_FUNC(cmode)
 
       /* Set the HMAC key out of current channel key. The client must do
         this locally. */
-      silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8, 
+      silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
+                    channel->key_len / 8, 
                     hash);
       silc_hmac_set_key(channel->hmac, hash, 
-                       silc_hash_len(channel->hmac->hash));
+                       silc_hash_len(silc_hmac_get_hash(channel->hmac)));
       memset(hash, 0, sizeof(hash));
     }
   }
@@ -4105,46 +4171,48 @@ SILC_SERVER_CMD_FUNC(cumode)
   }
 
   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
-    /* The client tries to claim the founder rights. */
-    unsigned char *tmp_auth;
-    uint32 tmp_auth_len, auth_len;
-    void *auth;
-    
-    if (target_client != client) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
-                                           SILC_STATUS_ERR_NOT_YOU);
-      goto out;
-    }
-
-    if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
-       !channel->founder_key) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
-                                           SILC_STATUS_ERR_NOT_YOU);
-      goto out;
-    }
+    if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
+      /* The client tries to claim the founder rights. */
+      unsigned char *tmp_auth;
+      uint32 tmp_auth_len, auth_len;
+      void *auth;
+      
+      if (target_client != client) {
+       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
+                                             SILC_STATUS_ERR_NOT_YOU);
+       goto out;
+      }
 
-    tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
-    if (!tmp_auth) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
-                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
-      goto out;
-    }
+      if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
+         !channel->founder_key) {
+       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
+                                             SILC_STATUS_ERR_NOT_YOU);
+       goto out;
+      }
 
-    auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
-           (void *)channel->founder_passwd : (void *)channel->founder_key);
-    auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
-               channel->founder_passwd_len : 0);
-    
-    if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
-                              channel->founder_method, auth, auth_len,
-                              idata->hash, client->id, SILC_ID_CLIENT)) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
-                                           SILC_STATUS_ERR_AUTH_FAILED);
-      goto out;
+      tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
+      if (!tmp_auth) {
+       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
+                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+       goto out;
+      }
+      
+      auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
+             (void *)channel->founder_passwd : (void *)channel->founder_key);
+      auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
+                 channel->founder_passwd_len : 0);
+      
+      if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
+                                channel->founder_method, auth, auth_len,
+                                idata->hash, client->id, SILC_ID_CLIENT)) {
+       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
+                                             SILC_STATUS_ERR_AUTH_FAILED);
+       goto out;
+      }
+      
+      sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
+      notify = TRUE;
     }
-
-    sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
-    notify = TRUE;
   } else {
     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
       if (target_client == client) {
@@ -4463,7 +4531,7 @@ SILC_SERVER_CMD_FUNC(silcoper)
   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
     goto out;
 
-  if (server->server_type == SILC_SERVER) {
+  if (server->server_type != SILC_ROUTER) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
                                          SILC_STATUS_ERR_AUTH_FAILED);
     goto out;
@@ -4706,8 +4774,7 @@ SILC_SERVER_CMD_FUNC(ban)
   silc_buffer_free(packet);
 
  out:
-  if (channel_id)
-    silc_free(channel_id);
+  silc_free(channel_id);
   silc_server_command_free(cmd);
 }
 
@@ -4752,6 +4819,9 @@ SILC_SERVER_CMD_FUNC(close)
 
   server_entry = silc_idlist_find_server_by_conn(server->local_list,
                                                 name, port, FALSE, NULL);
+  if (!server_entry)
+    server_entry = silc_idlist_find_server_by_conn(server->global_list,
+                                                  name, port, FALSE, NULL);
   if (!server_entry) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
                                          SILC_STATUS_ERR_NO_SERVER_ID);
@@ -4764,6 +4834,15 @@ SILC_SERVER_CMD_FUNC(close)
 
   /* Close the connection to the server */
   sock = (SilcSocketConnection)server_entry->connection;
+
+  /* If we shutdown primary router connection manually then don't trigger
+     any reconnect or backup router connections, by setting the router
+     to NULL here. */
+  if (server->router == server_entry) {
+    server->id_entry->router = NULL;
+    server->router = NULL;
+    server->standalone = TRUE;
+  }
   silc_server_free_sock_user_data(server, sock);
   silc_server_close_connection(server, sock);
   
@@ -4879,8 +4958,7 @@ SILC_SERVER_CMD_FUNC(leave)
   }
 
  out:
-  if (id)
-    silc_free(id);
+  silc_free(id);
   silc_server_command_free(cmd);
 }
 
@@ -4936,8 +5014,8 @@ SILC_SERVER_CMD_FUNC(users)
     channel = silc_idlist_find_channel_by_name(server->local_list, 
                                               channel_name, NULL);
 
-  if (!channel) {
-    if (server->server_type == SILC_SERVER && !server->standalone &&
+  if (!channel || channel->disabled) {
+    if (server->server_type != SILC_ROUTER && !server->standalone &&
        !cmd->pending) {
       SilcBuffer tmpbuf;
       
@@ -5019,8 +5097,7 @@ SILC_SERVER_CMD_FUNC(users)
   silc_buffer_free(packet);
   silc_buffer_free(client_id_list);
   silc_buffer_free(client_mode_list);
-  if (id)
-    silc_free(id);
+  silc_free(id);
 
  out:
   silc_server_command_free(cmd);
@@ -5073,10 +5150,8 @@ SILC_SERVER_CMD_FUNC(getkey)
                                             client_id, TRUE, NULL);
     
     if ((!client && !cmd->pending && !server->standalone) ||
-       (client && !client->connection && !cmd->pending && 
-        !server->standalone) ||
-       (client && !client->data.public_key && !cmd->pending &&
-        !server->standalone)) {
+       (client && !client->connection && !cmd->pending) ||
+       (client && !client->data.public_key && !cmd->pending)) {
       SilcBuffer tmpbuf;
       uint16 old_ident;
       SilcSocketConnection dest_sock;
@@ -5114,18 +5189,24 @@ SILC_SERVER_CMD_FUNC(getkey)
     }
 
     /* The client is locally connected, just get the public key and
-       send it back. */
-    tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
-    pk = silc_buffer_alloc(4 + tmp_len);
-    silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
-    silc_buffer_format(pk,
-                      SILC_STR_UI_SHORT(tmp_len),
-                      SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
-                      SILC_STR_UI_XNSTRING(tmp, tmp_len),
-                      SILC_STR_END);
-    silc_free(tmp);
-    pkdata = pk->data;
-    pklen = pk->len;
+       send it back. If they key does not exist then do not send it, 
+       send just OK reply */
+    if (!client->data.public_key) {
+      pkdata = NULL;
+      pklen = 0;
+    } else {
+      tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
+      pk = silc_buffer_alloc(4 + tmp_len);
+      silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
+      silc_buffer_format(pk,
+                        SILC_STR_UI_SHORT(tmp_len),
+                        SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
+                        SILC_STR_UI_XNSTRING(tmp, tmp_len),
+                        SILC_STR_END);
+      silc_free(tmp);
+      pkdata = pk->data;
+      pklen = pk->len;
+    }
   } else if (id_type == SILC_ID_SERVER) {
     server_id = silc_id_payload_get_id(idp);
 
@@ -5183,7 +5264,7 @@ SILC_SERVER_CMD_FUNC(getkey)
       pk = silc_buffer_alloc(4 + tmp_len);
       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
       silc_buffer_format(pk,
-                      SILC_STR_UI_SHORT(tmp_len),
+                        SILC_STR_UI_SHORT(tmp_len),
                         SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
                         SILC_STR_UI_XNSTRING(tmp, tmp_len),
                         SILC_STR_END);