updates.
authorPekka Riikonen <priikone@silcnet.org>
Fri, 17 May 2002 09:08:07 +0000 (09:08 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Fri, 17 May 2002 09:08:07 +0000 (09:08 +0000)
CHANGES
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/packet_receive.c
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/server_util.c
doc/draft-riikonen-silc-commands-04.nroff
doc/draft-riikonen-silc-spec-06.nroff
lib/silcclient/command_reply.c

diff --git a/CHANGES b/CHANGES
index 6e12aef3668047ba984ac43a9b13bb71fa7788f3..133015d22556b88d77499867b9ae11ea6472c509 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,16 @@ Fri May 17 08:33:41 CEST 2002 Pekka Riikonen <priikone@silcnet.org>
        * Fixed watcher list checking during server signoff.  It
          crashed the server.  Affected file silcd/server_util.c.
 
+       * The JOIN command reply returns now the founder's public
+         key.  Affected file is silcd/command.c.
+
+       * Announce the channel mode, and the mode properties with
+         CMODE_CHANGE notify.  Affected file silcd/server.c.
+
+       * Mark new channels by default disabled, untill at least
+         one user joins the channel.  Affected file is
+         silcd/packet_receive.c.
+
 Thu May 16 13:05:13 CEST 2002 Pekka Riikonen <priikone@silcnet.org>
 
        * The nickname argument to watch notify can be optional.
index 28c4663405244fb4d450307feeb6bf9852e40070..4c8b900b64f9f18d30d47592a5634a62e6829fd0 100644 (file)
@@ -3174,6 +3174,8 @@ static void silc_server_command_join_channel(SilcServer server,
   char check[512], check2[512];
   bool founder = FALSE;
   bool resolve;
+  unsigned char *fkey = NULL;
+  SilcUInt32 fkey_len = 0;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -3370,9 +3372,12 @@ static void silc_server_command_join_channel(SilcServer server,
     silc_free(tmp);
   }
 
+  if (channel->founder_key)
+    fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
+
   reply = 
     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
-                                        SILC_STATUS_OK, 0, ident, 13,
+                                        SILC_STATUS_OK, 0, ident, 14,
                                         2, channel->channel_name,
                                         strlen(channel->channel_name),
                                         3, chidp->data, chidp->len,
@@ -3396,7 +3401,8 @@ static void silc_server_command_join_channel(SilcServer server,
                                         12, tmp3, 4,
                                         13, user_list->data, user_list->len,
                                         14, mode_list->data, 
-                                        mode_list->len);
+                                        mode_list->len,
+                                        15, fkey, fkey_len);
 
   /* Send command reply */
   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
@@ -3429,13 +3435,11 @@ static void silc_server_command_join_channel(SilcServer server,
        notify the mode change to the channel. */
     if (founder) {
       SILC_PUT32_MSB(chl->mode, mode);
-      tmp = silc_pkcs_public_key_encode(channel->founder_key, &tmp_len);
       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
                                         SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
                                         clidp->data, clidp->len,
                                         mode, 4, clidp->data, clidp->len,
-                                        tmp, tmp_len);
-      silc_free(tmp);
+                                        fkey, fkey_len);
       
       /* Set CUMODE notify type to network */
       if (!server->standalone)
@@ -3453,6 +3457,7 @@ static void silc_server_command_join_channel(SilcServer server,
   silc_buffer_free(keyp);
   silc_buffer_free(user_list);
   silc_buffer_free(mode_list);
+  silc_free(fkey);
 
  out:
   silc_free(passphrase);
@@ -3647,7 +3652,7 @@ SILC_SERVER_CMD_FUNC(join)
     }
 
     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
-       !silc_hash_table_count(channel->user_list))
+       !channel->disabled && !silc_hash_table_count(channel->user_list))
       created = TRUE;
   }
 
index 3696ec3accb78127416f2b8fa92c4f5eafaa4645..22fe1f1c9b78ac305d8bfde08bdf6efb5f57b80a 100644 (file)
@@ -781,6 +781,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
   char *channel_name, *tmp;
   SilcUInt32 mode, created;
   SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
+  SilcPublicKey founder_key = NULL;
 
   COMMAND_CHECK_STATUS;
 
@@ -860,6 +861,11 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
   silc_buffer_pull_tail(client_mode_list, len);
   silc_buffer_put(client_mode_list, tmp, len);
 
+  /* Get founder key */
+  tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
+  if (tmp)
+    silc_pkcs_public_key_decode(tmp, len, &founder_key);
+
   /* See whether we already have the channel. */
   entry = silc_idlist_find_channel_by_name(server->local_list, 
                                           channel_name, &cache);
@@ -903,6 +909,13 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
     }
   }
 
+  if (founder_key) {
+    if (entry->founder_key)
+      silc_pkcs_public_key_free(entry->founder_key);
+    entry->founder_key = founder_key;
+    founder_key = NULL;
+  }
+
   if (entry->hmac_name && hmac) {
     silc_free(entry->hmac_name);
     entry->hmac_name = strdup(silc_hmac_get_name(hmac));
@@ -962,6 +975,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
   silc_free(client_id);
   silc_server_command_reply_free(cmd);
 
+  silc_pkcs_public_key_free(founder_key);
   if (client_id_list)
     silc_buffer_free(client_id_list);
   if (client_mode_list)
index 91d08cd3925a399d7dbf93679d6bd83557c345aa..310a14dacce32c90267014699b709e16e03b5f0b 100644 (file)
@@ -229,6 +229,7 @@ void silc_server_notify(SilcServer server,
     silc_hash_table_add(client->channels, channel, chl);
     silc_free(client_id);
     channel->user_count++;
+    channel->disabled = FALSE;
 
     break;
 
@@ -628,7 +629,7 @@ void silc_server_notify(SilcServer server,
        if (channel->founder_key)
          silc_pkcs_public_key_free(channel->founder_key);
        channel->founder_key = NULL;
-      } else if (!client->data.public_key) {
+      } else if (client && !client->data.public_key) {
        client->data.public_key = 
          silc_pkcs_public_key_copy(channel->founder_key);
       }
@@ -768,7 +769,7 @@ void silc_server_notify(SilcServer server,
          server->server_type == SILC_ROUTER) {
        /* Check whether this client is allowed to be channel founder on
           this channel. */
-       SilcPublicKey founder_key;
+       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.
@@ -810,15 +811,26 @@ void silc_server_notify(SilcServer server,
          break;
        }
 
-       /* Now match the public key we have cached and publick key sent.
+       /* Now match the public key we have cached and public key sent.
           They must match. */
-       if (!silc_pkcs_public_key_compare(channel->founder_key,
+       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 (founder_key)
+         silc_pkcs_public_key_free(founder_key);
       }
 
       SILC_LOG_DEBUG(("Changing the channel user mode"));
@@ -999,7 +1011,7 @@ void silc_server_notify(SilcServer server,
       }
 
     if (channel_id2) {
-      SilcBuffer users = NULL, users_modes = NULL;
+      SilcBuffer modes = NULL, users = NULL, users_modes = NULL;
 
       /* Re-announce this channel which ID was changed. */
       silc_server_send_new_channel(server, sock, FALSE, channel->channel_name,
@@ -1009,8 +1021,16 @@ void silc_server_notify(SilcServer server,
                                   channel->mode);
 
       /* Re-announce our clients on the channel as the ID has changed now */
-      silc_server_announce_get_channel_users(server, channel, &users,
+      silc_server_announce_get_channel_users(server, channel, &modes, &users,
                                             &users_modes);
+      if (modes) {
+       silc_buffer_push(modes, modes->data - modes->head);
+       silc_server_packet_send_dest(server, sock,
+                                    SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+                                    channel->id, SILC_ID_CHANNEL,
+                                    modes->data, modes->len, FALSE);
+       silc_buffer_free(modes);
+      }
       if (users) {
        silc_buffer_push(users, users->data - users->head);
        silc_server_packet_send(server, sock,
@@ -2621,6 +2641,7 @@ void silc_server_new_channel(SilcServer server,
                                0, channel_id, sock->user_data, NULL, NULL, 0);
       if (!channel)
        return;
+      channel->disabled = TRUE;
 
       server->stat.channels++;
       if (server->server_type == SILC_ROUTER)
@@ -2671,9 +2692,13 @@ void silc_server_new_channel(SilcServer server,
        silc_free(channel_id);
        return;
       }
+      channel->disabled = TRUE;
 
+#if 0
+      /* CMODE change notify is expected */
       /* Get the mode and set it to the channel */
       channel->mode = silc_channel_get_mode(payload);
+#endif
 
       /* Send the new channel key to the server */
       id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
@@ -2692,7 +2717,7 @@ void silc_server_new_channel(SilcServer server,
       /* The channel exist by that name, check whether the ID's match.
         If they don't then we'll force the server to use the ID we have.
         We also create a new key for the channel. */
-      SilcBuffer users = NULL, users_modes = NULL;
+      SilcBuffer modes = NULL, users = NULL, users_modes = NULL;
 
       if (!SILC_ID_CHANNEL_COMPARE(channel_id, channel->id)) {
        /* They don't match, send CHANNEL_CHANGE notify to the server to
@@ -2745,8 +2770,16 @@ void silc_server_new_channel(SilcServer server,
       /* Since the channel is coming from server and we also know about it
         then send the JOIN notify to the server so that it see's our
         users on the channel "joining" the channel. */
-      silc_server_announce_get_channel_users(server, channel, &users,
+      silc_server_announce_get_channel_users(server, channel, &modes, &users,
                                             &users_modes);
+      if (modes) {
+       silc_buffer_push(modes, modes->data - modes->head);
+       silc_server_packet_send_dest(server, sock,
+                                    SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+                                    channel->id, SILC_ID_CHANNEL,
+                                    modes->data, modes->len, FALSE);
+       silc_buffer_free(modes);
+      }
       if (users) {
        silc_buffer_push(users, users->data - users->head);
        silc_server_packet_send(server, sock,
index 9243ad01174e487fd916e9869a89259c2031b152..e8874aeca14a87cee0bc703ea1da3eafc6cb3eae 100644 (file)
@@ -3541,6 +3541,7 @@ void silc_server_announce_get_channel_topic(SilcServer server,
 
 void silc_server_announce_get_channel_users(SilcServer server,
                                            SilcChannelEntry channel,
+                                           SilcBuffer *channel_modes,
                                            SilcBuffer *channel_users,
                                            SilcBuffer *channel_users_modes)
 {
@@ -3551,11 +3552,43 @@ void silc_server_announce_get_channel_users(SilcServer server,
   int len;
   unsigned char mode[4], *fkey = NULL;
   SilcUInt32 fkey_len = 0;
+  char *hmac;
 
   SILC_LOG_DEBUG(("Start"));
 
-  /* Now find all users on the channel */
   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
+
+  /* CMODE notify */
+  clidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
+  SILC_PUT32_MSB(channel->mode, mode);
+  hmac = channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) : NULL;
+  if (channel->founder_key)
+    fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
+  tmp = 
+    silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CMODE_CHANGE,
+                                      6, clidp->data, clidp->len,
+                                      mode, sizeof(mode),
+                                      NULL, 0,
+                                      hmac, hmac ? strlen(hmac) : 0,
+                                      channel->passphrase,
+                                      channel->passphrase ?
+                                      strlen(channel->passphrase) : 0,
+                                      fkey, fkey_len);
+  len = tmp->len;
+  *channel_modes =
+    silc_buffer_realloc(*channel_modes,
+                       (*channel_modes ?
+                        (*channel_modes)->truelen + len : len));
+  silc_buffer_pull_tail(*channel_modes,
+                       ((*channel_modes)->end -
+                        (*channel_modes)->data));
+  silc_buffer_put(*channel_modes, tmp->data, tmp->len);
+  silc_buffer_pull(*channel_modes, len);
+  silc_buffer_free(tmp);
+  silc_buffer_free(clidp);
+  silc_free(fkey);
+
+  /* Now find all users on the channel */
   silc_hash_table_list(channel->user_list, &htl);
   while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     clidp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
@@ -3612,6 +3645,7 @@ void silc_server_announce_get_channel_users(SilcServer server,
 void silc_server_announce_get_channels(SilcServer server,
                                       SilcIDList id_list,
                                       SilcBuffer *channels,
+                                      SilcBuffer **channel_modes,
                                       SilcBuffer *channel_users,
                                       SilcBuffer **channel_users_modes,
                                       SilcUInt32 *channel_users_modes_c,
@@ -3670,10 +3704,14 @@ void silc_server_announce_get_channels(SilcServer server,
                                            sizeof(**channel_users_modes) *
                                            (i + 1));
        (*channel_users_modes)[i] = NULL;
+       *channel_modes = silc_realloc(*channel_modes,
+                                     sizeof(**channel_modes) * (i + 1));
+       (*channel_modes)[i] = NULL;
        *channel_ids = silc_realloc(*channel_ids,
                                    sizeof(**channel_ids) * (i + 1));
        (*channel_ids)[i] = NULL;
        silc_server_announce_get_channel_users(server, channel,
+                                              &(*channel_modes)[i], 
                                               channel_users,
                                               &(*channel_users_modes)[i]);
        (*channel_ids)[i] = channel->id;
@@ -3708,7 +3746,7 @@ void silc_server_announce_channels(SilcServer server,
                                   unsigned long creation_time,
                                   SilcSocketConnection remote)
 {
-  SilcBuffer channels = NULL, channel_users = NULL;
+  SilcBuffer channels = NULL, *channel_modes = NULL, channel_users = NULL;
   SilcBuffer *channel_users_modes = NULL;
   SilcBuffer *channel_topics = NULL;
   SilcUInt32 channel_users_modes_c = 0;
@@ -3718,7 +3756,8 @@ void silc_server_announce_channels(SilcServer server,
 
   /* Get channels and channel users in local list */
   silc_server_announce_get_channels(server, server->local_list,
-                                   &channels, &channel_users,
+                                   &channels, &channel_modes,
+                                   &channel_users,
                                    &channel_users_modes,
                                    &channel_users_modes_c,
                                    &channel_topics,
@@ -3727,7 +3766,8 @@ void silc_server_announce_channels(SilcServer server,
   /* Get channels and channel users in global list */
   if (server->server_type != SILC_SERVER)
     silc_server_announce_get_channels(server, server->global_list,
-                                     &channels, &channel_users,
+                                     &channels, &channel_modes,
+                                     &channel_users,
                                      &channel_users_modes,
                                      &channel_users_modes_c,
                                      &channel_topics,
@@ -3746,6 +3786,28 @@ void silc_server_announce_channels(SilcServer server,
     silc_buffer_free(channels);
   }
 
+  if (channel_modes) {
+    int i;
+
+    for (i = 0; i < channel_users_modes_c; i++) {
+      if (!channel_modes[i])
+        continue;
+      silc_buffer_push(channel_modes[i],
+                      channel_modes[i]->data -
+                      channel_modes[i]->head);
+      SILC_LOG_HEXDUMP(("channel modes"), channel_modes[i]->data,
+                      channel_modes[i]->len);
+      silc_server_packet_send_dest(server, remote,
+                                  SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+                                  channel_ids[i], SILC_ID_CHANNEL,
+                                  channel_modes[i]->data,
+                                  channel_modes[i]->len,
+                                  FALSE);
+      silc_buffer_free(channel_modes[i]);
+    }
+    silc_free(channel_modes);
+  }
+
   if (channel_users) {
     silc_buffer_push(channel_users, channel_users->data - channel_users->head);
     SILC_LOG_HEXDUMP(("channel users"), channel_users->data,
index 404696ce0b25daf0e725008edd79eaad996f60d0..d4341f4dac03a7141156d9b84122c3dc500c1b19 100644 (file)
@@ -176,11 +176,13 @@ void silc_server_announce_get_channel_topic(SilcServer server,
                                            SilcBuffer *topic);
 void silc_server_announce_get_channel_users(SilcServer server,
                                            SilcChannelEntry channel,
+                                           SilcBuffer *channel_modes,
                                            SilcBuffer *channel_users,
                                            SilcBuffer *channel_users_modes);
 void silc_server_announce_get_channels(SilcServer server,
                                       SilcIDList id_list,
                                       SilcBuffer *channels,
+                                      SilcBuffer **channel_modes,
                                       SilcBuffer *channel_users,
                                       SilcBuffer **channel_users_modes,
                                       SilcUInt32 *channel_users_modes_c,
index d9d2319cf4b8451d23388d07b92ae41bc0420f59..ea53991371ac1606f17f8c5eb89362a4ae0a617d 100644 (file)
@@ -1018,6 +1018,10 @@ bool silc_server_check_cmode_rights(SilcServer server,
   if (is_op && is_fo)
     return TRUE;
 
+  /* Founder emplies operator */
+  if (is_fo)
+    is_op = TRUE;
+
   /* We know that client is channel operator, check that they are not
      changing anything that requires channel founder rights. Rest of the
      modes are available automatically for channel operator. */
index 6f776301c9f93f785a154c50b6cfef791c022ba6..9f3656e6440c4ab383ac0e9a0155b81e3914a5a8 100644 (file)
@@ -8,7 +8,7 @@
 .ds RF FORMFEED[Page %]
 .ds CF
 .ds LH Internet Draft
-.ds RH 15 May 2002
+.ds RH XXX
 .ds CH
 .na
 .hy 0
 .nf
 Network Working Group                                        P. Riikonen
 Internet-Draft
-draft-riikonen-silc-commands-03.txt                          15 May 2002
-Expires: 15 November 2002
+draft-riikonen-silc-commands-04.txt                          XXX
+Expires: XXX
 
 .in 3
 
 .ce 2
 SILC Commands
-<draft-riikonen-silc-commands-03.txt>
+<draft-riikonen-silc-commands-04.txt>
 
 .ti 0
 Status of this Memo
@@ -919,7 +919,7 @@ List of all defined commands in SILC follows.
 
         Reply messages to the command:
 
-        Max Arguments:  14
+        Max Arguments:  15
             Arguments:  (1) <Status Payload>        (2) <channel> 
                         (3) <Channel ID>            (4) <Client ID>
                         (5) <channel mode mask>     (6) <created>
@@ -927,6 +927,7 @@ List of all defined commands in SILC follows.
                         (9) [<invite list>]         (10) [<topic>]
                         (11) [<hmac>]               (12) <list count>
                         (13) <Client ID list>       (14) <client mode list>
+                        (15) [<founder pubkey>]
 
         This command replies with the channel name requested by the
         client, channel ID of the channel and topic of the channel
@@ -940,7 +941,8 @@ List of all defined commands in SILC follows.
         the clients currently on the channel and their modes on the
         channel.  The <Client ID list> is formed by adding the ID Payloads
         one after the other.  The <client mode list> is formed by adding
-        32 bit MSB first order values one after the other.
+        32 bit MSB first order values one after the other.  The <founder
+        pubkey> is the public key of the channel founder.
 
         Client receives the channel key in the reply message as well
         inside <Channel Key Payload>.
@@ -2385,7 +2387,7 @@ Finland
 
 EMail: priikone@iki.fi
 
-This Internet-Draft expires 15 November 2002
+This Internet-Draft expires XXX
 
 
 .ti 0
index e14cd82635610fa58f5a26d4b8b50b8d4156385e..45cd9476b10c6433de38385c52d1cfe9f6f3ad34 100644 (file)
@@ -8,7 +8,7 @@
 .ds RF FORMFEED[Page %]
 .ds CF
 .ds LH Internet Draft
-.ds RH 15 May 2002
+.ds RH XXX
 .ds CH
 .na
 .hy 0
 .nf
 Network Working Group                                        P. Riikonen
 Internet-Draft
-draft-riikonen-silc-spec-05.txt                              15 May 2002
-Expires: 15 November 2002
+draft-riikonen-silc-spec-06.txt                              XXX
+Expires: XXX
 
 .in 3
 
 .ce 3
 Secure Internet Live Conferencing (SILC),
 Protocol Specification
-<draft-riikonen-silc-spec-05.txt>
+<draft-riikonen-silc-spec-06.txt>
 
 .ti 0
 Status of this Memo
@@ -1837,8 +1837,10 @@ MUST be announced.
 
 All clients are announced by compiling a list of ID Payloads into the
 SILC_PACKET_NEW_ID packet.  All channels are announced by compiling a
-list of Channel Payloads into the SILC_PACKET_NEW_CHANNEL packet.  Also, 
-the channel users on the channels must be announced by compiling a
+list of Channel Payloads into the SILC_PACKET_NEW_CHANNEL packet.
+Channels' mode and founder public key and other channel mode specific
+data is announced by sending SILC_NOTIFY_TYPE_CMODE_CHANGE notify list.
+Also, the channel users on the channels must be announced by compiling a
 list of Notify Payloads with the SILC_NOTIFY_TYPE_JOIN notify type into
 the SILC_PACKET_NOTIFY packet.  The users' modes on the channel must 
 also be announced by compiling list of Notify Payloads with the 
@@ -2375,4 +2377,4 @@ Finland
 
 EMail: priikone@iki.fi
 
-This Internet-Draft expires 15 November 2002
+This Internet-Draft expires XXX
index ac40809fdbcd3619b30c1cd9b978466383122d3b..10ca6f960fa3b9f3e1d98fd7a2e543480ef5a6dd 100644 (file)
@@ -905,7 +905,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
   }
 
   argc = silc_argument_get_arg_num(cmd->args);
-  if (argc < 7 || argc > 14) {
+  if (argc < 7 || argc > 15) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
        "Cannot join channel: Bad reply packet");
     COMMAND_REPLY_ERROR;