updates.
[silc.git] / apps / silcd / command.c
index d60bf2c65553fe572b17e0007257b260b9f075b1..5c42734f73d5a067aa15904e77bc56d2a08be6c5 100644 (file)
@@ -1341,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) * 
@@ -1363,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) * 
@@ -1937,6 +1937,7 @@ static int silc_server_command_bad_chars(char *nick)
   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;
@@ -2952,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;
@@ -3033,7 +3035,8 @@ static void silc_server_command_join_channel(SilcServer server,
      username and/or hostname is in the ban list the access to the
      channel is denied. */
   if (channel->ban_list) {
-    if (silc_string_match(channel->ban_list, check) ||
+    if (!channel->ban_list ||
+        silc_string_match(channel->ban_list, check) ||
        silc_string_match(channel->ban_list, check2)) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                              SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
@@ -3050,8 +3053,9 @@ static void silc_server_command_join_channel(SilcServer server,
   
   /* Check the channel passphrase if set. */
   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
-    if (!passphrase || memcmp(channel->passphrase, passphrase,
-                             strlen(channel->passphrase))) {
+    if (!passphrase || !channel->passphrase ||
+        memcmp(channel->passphrase, passphrase,
+               strlen(channel->passphrase))) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                            SILC_STATUS_ERR_BAD_PASSWORD);
       goto out;
@@ -3080,17 +3084,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-
@@ -3145,8 +3149,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, 
@@ -3202,7 +3207,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);
@@ -3259,7 +3264,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 
@@ -3269,13 +3274,14 @@ 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 
@@ -3328,6 +3334,7 @@ SILC_SERVER_CMD_FUNC(join)
 
          umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
          created = TRUE;
+         create_key = FALSE;
        }
       }
     }
@@ -3358,21 +3365,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);
 
@@ -3410,7 +3426,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;
       
@@ -3628,8 +3644,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)
@@ -3638,8 +3655,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)
@@ -3648,8 +3666,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)
@@ -3658,8 +3677,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)
@@ -3768,7 +3788,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);
     }
   }
   
@@ -3899,10 +3919,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 {
@@ -3923,10 +3944,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));
     }
   }
@@ -4164,7 +4186,9 @@ SILC_SERVER_CMD_FUNC(cumode)
       }
 
       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
-         !channel->founder_key) {
+         !channel->founder_key || !idata->public_key ||
+         !silc_pkcs_public_key_compare(channel->founder_key, 
+                                       idata->public_key)) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                              SILC_STATUS_ERR_NOT_YOU);
        goto out;
@@ -4176,7 +4200,7 @@ SILC_SERVER_CMD_FUNC(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 ?
@@ -4799,6 +4823,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);
@@ -4991,7 +5018,7 @@ SILC_SERVER_CMD_FUNC(users)
     channel = silc_idlist_find_channel_by_name(server->local_list, 
                                               channel_name, NULL);
 
-  if (!channel) {
+  if (!channel || channel->disabled) {
     if (server->server_type != SILC_ROUTER && !server->standalone &&
        !cmd->pending) {
       SilcBuffer tmpbuf;