Improved UTF-8 encoding and decoding, improved toolkit doc,
[silc.git] / apps / silcd / packet_receive.c
index bd9545f8f1361b3f6b8af4be008eff578da4c5f1..f91d0aa119c5eeac0ddb370147e982e9188299a5 100644 (file)
@@ -368,22 +368,24 @@ 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, NULL);
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
     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, 
+    if (id_type == SILC_ID_CLIENT) {
+      client = silc_idlist_find_client_by_id(server->global_list, 
                                             client_id, TRUE, &cache);
       if (!client) {
-       silc_free(client_id);
-       goto out;
+       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);
     }
-    silc_free(client_id);
 
     /* Get the topic */
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
@@ -414,14 +416,16 @@ void silc_server_notify(SilcServer server,
     if (channel->topic && !strcmp(channel->topic, tmp))
       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 (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
-       !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
-       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
-      SILC_LOG_DEBUG(("Topic change is not allowed"));
-      goto out;
+    if (client) {
+      /* Get user's channel entry and check that topic set is allowed. */
+      if (!silc_server_client_on_channel(client, channel, &chl))
+       goto out;
+      if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
+         !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
+         !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
+       SILC_LOG_DEBUG(("Topic change is not allowed"));
+       goto out;
+      }
     }
 
     /* Change the topic */
@@ -786,40 +790,21 @@ void silc_server_notify(SilcServer server,
        }
       }
 
-      /* Get target channel entry */
+      /* Get target channel user entry */
       if (!silc_server_client_on_channel(client2, channel, &chl))
        goto out;
 
       if (mode & SILC_CHANNEL_UMODE_CHANFO &&
-         !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && !client &&
-         server->server_type == SILC_ROUTER) {
-       /* Get the founder of the channel and if found then this client
-          cannot be the founder since there already is one. */
-       silc_hash_table_list(channel->user_list, &htl);
-       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
-         if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
-           mode &= ~SILC_CHANNEL_UMODE_CHANFO;
-           silc_server_force_cumode_change(server, sock, channel, chl, mode);
-           notify_sent = TRUE;
-           break;
-         }
-       silc_hash_table_list_reset(&htl);
-       if (!(mode & SILC_CHANNEL_UMODE_CHANFO))
-         break;
-      }
-
-      if (client && mode & SILC_CHANNEL_UMODE_CHANFO &&
-         !(chl->mode & SILC_CHANNEL_UMODE_CHANFO) && 
-         server->server_type == SILC_ROUTER) {
-       /* Check whether this client is allowed to be channel founder on
-          this channel. */
+         !(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
+         server->server_type == SILC_ROUTER &&
+         sock->user_data != server->router) {
        SilcPublicKey founder_key = NULL;
 
        /* If channel doesn't have founder auth mode then it's impossible
           that someone would be getting founder rights with CUMODE command.
           In that case there already either is founder or there isn't
           founder at all on the channel. */
-       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
+       if (client && !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
          /* Force the mode to not have founder mode */
          mode &= ~SILC_CHANNEL_UMODE_CHANFO;
          silc_server_force_cumode_change(server, sock, channel, chl, mode);
@@ -833,7 +818,8 @@ void silc_server_notify(SilcServer server,
        while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
          if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
            mode &= ~SILC_CHANNEL_UMODE_CHANFO;
-           silc_server_force_cumode_change(server, sock, channel, chl, mode);
+           silc_server_force_cumode_change(server, sock, channel,
+                                           chl, mode);
            notify_sent = TRUE;
            break;
          }
@@ -855,28 +841,47 @@ void silc_server_notify(SilcServer server,
          break;
        }
 
-       /* Now match the public key we have cached and public key sent.
-          They must match. */
-       if (client->data.public_key && 
-           !silc_pkcs_public_key_compare(channel->founder_key,
-                                         client->data.public_key)) {
-         mode &= ~SILC_CHANNEL_UMODE_CHANFO;
-         silc_server_force_cumode_change(server, sock, channel, chl, mode);
-         notify_sent = TRUE;
-         break;
-       }
-       if (!silc_pkcs_public_key_compare(channel->founder_key,
-                                         founder_key)) {
-         mode &= ~SILC_CHANNEL_UMODE_CHANFO;
-         silc_server_force_cumode_change(server, sock, channel, chl, mode);
-         notify_sent = TRUE;
-         break;
+       if (channel->founder_key) {
+         /* Now match the public key we have cached and public key sent.
+            They must match. */
+         if (client && client->data.public_key && 
+             !silc_pkcs_public_key_compare(channel->founder_key,
+                                           client->data.public_key)) {
+           mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           silc_server_force_cumode_change(server, sock, channel, chl, mode);
+           notify_sent = TRUE;
+           break;
+         }
+         if (!silc_pkcs_public_key_compare(channel->founder_key,
+                                           founder_key)) {
+           mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           silc_server_force_cumode_change(server, sock, channel, chl, mode);
+           notify_sent = TRUE;
+           break;
+         }
        }
 
+       /* There cannot be anyone else as founder on the channel now.  This
+          client is definitely the founder due to this authentication */
+       silc_hash_table_list(channel->user_list, &htl);
+       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
+         if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
+           chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           silc_server_force_cumode_change(server, NULL, channel, chl2,
+                                           chl2->mode);
+           break;
+         }
+       silc_hash_table_list_reset(&htl);
+
        if (founder_key)
          silc_pkcs_public_key_free(founder_key);
       }
 
+      if (server->server_type == SILC_ROUTER && chl->mode == mode) {
+       SILC_LOG_DEBUG(("Mode is changed already"));
+       break;
+      }
+
       SILC_LOG_DEBUG(("Changing the channel user mode"));
 
       /* Change the mode */
@@ -1097,7 +1102,7 @@ void silc_server_notify(SilcServer server,
        silc_server_send_notify_topic_set(server, sock,
                                          server->server_type == SILC_ROUTER ?
                                          TRUE : FALSE, channel, 
-                                         channel->id, SILC_ID_CHANNEL,
+                                         server->id, SILC_ID_SERVER,
                                          channel->topic);
       }
     }
@@ -2676,7 +2681,6 @@ void silc_server_new_channel(SilcServer server,
   SilcUInt32 name_len;
   unsigned char *id;
   SilcUInt32 id_len;
-  SilcUInt32 mode;
   SilcServerEntry server_entry;
   SilcChannelEntry channel;
 
@@ -2805,8 +2809,14 @@ void silc_server_new_channel(SilcServer server,
        SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
        silc_server_send_notify_channel_change(server, sock, FALSE, 
                                               channel_id, channel->id);
+
+       /* Wait that server re-announces this channel */
+       return;
       }
 
+#if 0 /* Lets expect that server send CMODE_CHANGE notify anyway to
+        (attempt) force mode change, and may very well get it. */
+
       /* If the mode is different from what we have then enforce the
         mode change. */
       mode = silc_channel_get_mode(payload);
@@ -2819,6 +2829,7 @@ void silc_server_new_channel(SilcServer server,
                                      channel->passphrase,
                                      channel->founder_key);
       }
+#endif
 
       /* Create new key for the channel and send it to the server and
         everybody else possibly on the channel. */
@@ -2880,6 +2891,13 @@ void silc_server_new_channel(SilcServer server,
                                     users_modes->len, FALSE);
        silc_buffer_free(users_modes);
       }
+      if (channel->topic) {
+       silc_server_send_notify_topic_set(server, sock,
+                                         server->server_type == SILC_ROUTER ?
+                                         TRUE : FALSE, channel, 
+                                         server->id, SILC_ID_SERVER,
+                                         channel->topic);
+      }
     }
   }
 
@@ -3014,10 +3032,10 @@ void silc_server_connection_auth_request(SilcServer server,
   int ret;
   SilcAuthMethod auth_meth = SILC_AUTH_NONE;
 
-  SILC_LOG_DEBUG(("Start"));
-
-  if (packet->src_id_type && packet->src_id_type != SILC_ID_CLIENT)
+  if (packet->src_id_type && packet->src_id_type != SILC_ID_CLIENT) {
+    SILC_LOG_DEBUG(("Request not from client"));
     return;
+  }
 
   /* Parse the payload */
   ret = silc_buffer_unformat(packet->buffer,
@@ -3045,6 +3063,11 @@ void silc_server_connection_auth_request(SilcServer server,
       auth_meth = SILC_AUTH_PUBLIC_KEY;
   }
 
+  SILC_LOG_DEBUG(("Authentication method is [%s]",
+                 (auth_meth == SILC_AUTH_NONE ? "None" :
+                  auth_meth == SILC_AUTH_PASSWORD ? "Passphrase" :
+                  "Digital signatures")));
+
   /* Send it back to the client */
   silc_server_send_connection_auth_request(server, sock, conn_type, auth_meth);
 }