updates.
authorPekka Riikonen <priikone@silcnet.org>
Mon, 6 May 2002 20:11:02 +0000 (20:11 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 6 May 2002 20:11:02 +0000 (20:11 +0000)
20 files changed:
CHANGES
TODO
apps/irssi/docs/help/in/cmode.in
apps/irssi/docs/help/in/cumode.in
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/packet_send.h
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/server_util.c
apps/silcd/server_util.h
lib/silcclient/client.c
lib/silcclient/client_notify.c
lib/silcclient/command.c
lib/silccrypt/silcpkcs.c
lib/silccrypt/silcpkcs.h

diff --git a/CHANGES b/CHANGES
index 8388cc15d6c41062cbebaa34623870409bb502cb..688fb222cc03348e37795fea82f8591e826f3e91 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,32 @@
+Mon May  6 19:46:12 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
+
+       * Added silc_pkcs_public_key_copy function into the
+         lib/silccrypt/silcpkcs.[ch].
+
+       * Remove the `iv' from the SilcChannelEntry since we can
+         live without it.  Affected files are silcd/idlist.h and
+         silcd/packet_receive.c.
+
+       * Added support for sending the founder's public key in
+         the CMODE_CHANGE notify packet in the server.  Affected
+         files are silcd/packet_send.[ch], silcd/packet_receive.c,
+         silcd/command.c and silcd/server.c.
+
+       * Changed the FOUNDER_AUTH authentication to use only
+         public key authentication as defined by new protocol
+         specs.  Passphrase authentication with that mode cannot
+         be used anymore.  It is now possible to reclaim founder
+         mode from any server in the network.  Affected files are
+         silcd/command.c, silcd/idlist.h and silcd/command_reply.c.
+
+       * Added permanent channels support by making the channel
+         permanent when FOUNDER_AUTH mode is set on the channel.
+         The channel will not be destroyed even if channel is empty
+         when that mode is set.  Protocol TODO #17.  Affected
+         files are silcd/server.[ch], server_util.[ch],
+         silcd/command.c, silcd/packet_receive.c and
+         lib/silcclient/command.c. 
+
 Fri May  3 18:36:51 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
 
        * Added reference counter to the command reply context in
diff --git a/TODO b/TODO
index 77cf72b478c80c3679adba146127de0705a4fdfd..752dc8ec67ececfe5f4c352e81470e8e02cfd610 100644 (file)
--- a/TODO
+++ b/TODO
@@ -24,12 +24,6 @@ TODO/bugs In SILC Server
          for single IP address, key exchange frequency, key exchange
          frequency for single IP. Add also frequency base.
 
- o If server send CUMODE_CHANGE notify (like setting founder) to router
-   and router does not have founder on channel (founder is left or there's
-   no founder on channel at all), the router will accept the server's
-   founder mode change, even though it perhaps should not do that (Fix 
-   this to 0.9).
-
  o Implement the SILC_CUMODE_QUIET user mode (Do this to 0.9.x).
 
  o Implement the <Requested Attributes> and the Attribute Payload to
@@ -90,10 +84,3 @@ Manual (Do these to 0.9 and 1.0).
  o Write "Platform Implementations" document to describe what platforms
    Toolkit support, what has been implemented, what has not been, what
    works differently etc.
-
-
-TODO in SILC Protocol
-=====================
-
- 17. Cell wide channel founder support, and permanent channels when
-     founder mode set.
index b9e49b81ec652fe01370e8a0ffc00bf8dd2411de..6f4f25db9920fb2d29c5d3fa88f55bfa7a383ff3 100644 (file)
@@ -24,18 +24,16 @@ option(s).  The following modes are available:
                     be provided when joining to the channel.
     c <cipher>      Set/unset channel's cipher
     h <hmac>        Set/unset channel's hmac
-    f <-pubkey|<password>
-                    Set/unset channel founder authentication.
+    f               Set/unset channel founder authentication.
                     Channel founder may set this mode so that
                     if the client leaves the channel it can
                     claim the founder rights when it returns
-                    to the channel.  If -pubkey is set then
-                    the authentication will be done using the
-                    client's public key.  You can claim the
-                    founder rights using the CUMODE command.
+                    to the channel, and to set the channel to
+                    be permanent channel.  You can claim the
+                    founder rights using CUMODE or JOIN commands.
 
 Multiple modes can be set/unset at once if the modes does not
 require any arguments.  If mode requires an argument then only
 one mode can be set at once.
 
-See also: CUMODE, UMODE
+See also: CUMODE, UMODE, JOIN
index 84d0e2083c57863eb64e655345321c2ac0adbe91..ba88119050580a21fd0df4ffad8605c540dd7c97 100644 (file)
@@ -14,17 +14,14 @@ are available:
         both founder and operator rights, can be used
         only to remove both modes at once).
 
-    f <nickname>[@<server>] [-pubkey|<password>]
+    f <nickname>[@<server>] [-pubkey]
 
         Set/Unset channel founder.  If the -pubkey
         option or <password> is provided then the
         client is claiming the founder rights by
-        providing the channel founder authentication
-        data.  If the -pubkey is provided then the
-        authentication is performed using the
-        client's public key.  If you are channel
-        founder you can set the channel founder
-        authentication using CMODE command.
+        providing your public key as argument.  If
+        you are channel founder you can set the channel
+        founder authentication using CMODEc command.
 
     o <nickname>[@<server>]
 
index cedebbd4bf80cdd66012e7f2e4b3d299658dc1d8..653996dccfbee45aaca632af43710daf34a1d027 100644 (file)
@@ -3221,16 +3221,9 @@ static void silc_server_command_join_channel(SilcServer server,
     if (channel->founder_key && idata->public_key &&
        silc_pkcs_public_key_compare(channel->founder_key, 
                                     idata->public_key)) {
-      void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
-                        (void *)channel->founder_passwd : 
-                        (void *)channel->founder_key);
-      SilcUInt32 auth_data_len = 
-       (channel->founder_method == SILC_AUTH_PASSWORD ?
-        channel->founder_passwd_len : 0);
-
       /* Check whether the client is to become founder */
-      if (silc_auth_verify_data(auth, auth_len, channel->founder_method, 
-                               auth_data, auth_data_len,
+      if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
+                               channel->founder_key, 0,
                                idata->hash, client->id, SILC_ID_CLIENT)) {
        umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
        founder = TRUE;
@@ -3350,6 +3343,7 @@ static void silc_server_command_join_channel(SilcServer server,
   silc_hash_table_add(channel->user_list, client, chl);
   silc_hash_table_add(client->channels, channel, chl);
   channel->user_count++;
+  channel->disabled = FALSE;
 
   /* Get users on the channel */
   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
@@ -3526,7 +3520,8 @@ SILC_SERVER_CMD_FUNC(join)
     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
 
-    if (!channel || channel->disabled) {
+    if (!channel || 
+       (channel->disabled && server->server_type != SILC_ROUTER)) {
       /* Channel not found */
 
       /* If we are standalone server we don't have a router, we just create 
@@ -3655,7 +3650,8 @@ SILC_SERVER_CMD_FUNC(join)
 
   /* 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))
+  if (!channel->disabled &&
+      !channel->global_users && !silc_hash_table_count(channel->user_list))
     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
 
   /* Join to the channel */
@@ -3898,6 +3894,9 @@ SILC_SERVER_CMD_FUNC(cmode)
   SilcUInt32 mode_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;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
 
@@ -4184,46 +4183,28 @@ SILC_SERVER_CMD_FUNC(cmode)
     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
        /* Set the founder authentication */
-       SilcAuthPayload auth;
-       
        tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
        if (!tmp) {
-         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
+         silc_server_command_send_status_reply(
+                                    cmd, SILC_COMMAND_CMODE,
                                     SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
          goto out;
        }
 
-       auth = silc_auth_payload_parse(tmp, tmp_len);
-       if (!auth) {
+       /* Verify the payload before setting the mode */
+       if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY, 
+                                  idata->public_key, 0, idata->hash,
+                                  client->id, SILC_ID_CLIENT)) {
          silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
-                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
+                                               SILC_STATUS_ERR_AUTH_FAILED,
+                                               0);
          goto out;
        }
 
        /* Save the public key */
-       tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
-       silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
-       silc_free(tmp);
-       
-       channel->founder_method = silc_auth_get_method(auth);
-
-       if (channel->founder_method == SILC_AUTH_PASSWORD) {
-         tmp = silc_auth_get_data(auth, &tmp_len);
-         channel->founder_passwd = silc_memdup(tmp, tmp_len);
-         channel->founder_passwd_len = tmp_len;
-       } else {
-         /* Verify the payload before setting the mode */
-         if (!silc_auth_verify(auth, channel->founder_method, 
-                               channel->founder_key, 0, idata->hash,
-                               client->id, SILC_ID_CLIENT)) {
-           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
-                                                 SILC_STATUS_ERR_AUTH_FAILED,
-                                                 0);
-           goto out;
-         }
-       }
-
-       silc_auth_payload_free(auth);
+       channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
+       founder_key = channel->founder_key;
+       fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
       }
     }
   } else {
@@ -4231,10 +4212,7 @@ SILC_SERVER_CMD_FUNC(cmode)
       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
        if (channel->founder_key)
          silc_pkcs_public_key_free(channel->founder_key);
-       if (channel->founder_passwd) {
-         silc_free(channel->founder_passwd);
-         channel->founder_passwd = NULL;
-       }
+       channel->founder_key = NULL;
       }
     }
   }
@@ -4245,13 +4223,14 @@ SILC_SERVER_CMD_FUNC(cmode)
   /* Send CMODE_CHANGE notify. */
   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
-                                    SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
+                                    SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
                                     cidp->data, cidp->len, 
                                     tmp_mask, 4,
                                     cipher, cipher ? strlen(cipher) : 0,
                                     hmac, hmac ? strlen(hmac) : 0,
                                     passphrase, passphrase ? 
-                                    strlen(passphrase) : 0);
+                                    strlen(passphrase) : 0,
+                                    fkey, fkey_len);
 
   /* Set CMODE notify type to network */
   if (!server->standalone)
@@ -4259,7 +4238,7 @@ SILC_SERVER_CMD_FUNC(cmode)
                                  server->server_type == SILC_ROUTER ? 
                                  TRUE : FALSE, channel,
                                  mode_mask, client->id, SILC_ID_CLIENT,
-                                 cipher, hmac, passphrase);
+                                 cipher, hmac, passphrase, founder_key);
 
   /* Send command reply to sender */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
@@ -4273,6 +4252,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   silc_buffer_free(cidp);
 
  out:
+  silc_free(fkey);
   silc_free(channel_id);
   silc_server_command_free(cmd);
 }
@@ -4406,38 +4386,33 @@ SILC_SERVER_CMD_FUNC(cumode)
     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
       /* The client tries to claim the founder rights. */
       unsigned char *tmp_auth;
-      SilcUInt32 tmp_auth_len, auth_len;
-      void *auth;
-      
+      SilcUInt32 tmp_auth_len;
+
       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
          !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, 0);
+                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
        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, 0);
+                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
        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)) {
+      /* Verify the authentication payload */
+      if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
+                                channel->founder_key, 0, idata->hash,
+                                client->id, SILC_ID_CLIENT)) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                              SILC_STATUS_ERR_AUTH_FAILED, 0);
        goto out;
       }
-      
+
       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
       notify = TRUE;
     }
index 9b344cda9a157b17729b19fe2a7bce772b7dc4c7..3696ec3accb78127416f2b8fa92c4f5eafaa4645 100644 (file)
@@ -899,8 +899,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
        them in the entry */
     if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
       silc_pkcs_public_key_free(entry->founder_key);
-      silc_free(entry->founder_passwd);
-      entry->founder_passwd = NULL;
+      entry->founder_key = NULL;
     }
   }
 
index 211d59eb0bae2a81d999fd65e19258b6d74e2a07..9503742f82e7c66fb08d48536047bf608d2ca01e 100644 (file)
@@ -663,6 +663,8 @@ int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
       silc_hmac_free(entry->hmac);
     silc_free(entry->hmac_name);
     silc_free(entry->rekey);
+    if (entry->founder_key)
+      silc_pkcs_public_key_free(entry->founder_key);
 
     memset(entry, 'F', sizeof(*entry));
     silc_free(entry);
index c9fa2fa76bb095cd1d515c7f595cdc0e5913dfa3..e2acc32919dd88a8b0a52dde01055c67848ab1d4 100644 (file)
@@ -415,14 +415,10 @@ struct SilcClientEntryStruct {
        the cipher to be used. This can be set at SILC_COMMAND_JOIN.
 
    SilcPublicKey founder_key
-   SilcAuthMethod founder_method
-   unsigned char *founder_passwd
-   SilcUInt32 founder_passwd_len
 
-       If the SILC_CMODE_FOUNDER_AUTH has been set then these will include
-       the founder's public key, authentication method and the password
-       if the method is SILC_AUTH_PASSWORD.  If it is SILC_AUTH_PUBLIC_KEY
-       then the `founder_passwd' is NULL.
+       If the SILC_CMODE_FOUNDER_AUTH has been set then this will include
+       the founder's public key.  When the mode and this key is set the
+       channel is also permanent channel and cannot be destroyed.
 
    SilcHashTable user_list
 
@@ -463,15 +459,10 @@ struct SilcChannelEntryStruct {
   char *channel_name;
   SilcUInt32 mode;
   SilcChannelID *id;
-  bool global_users;
   char *topic;
   char *cipher;
   char *hmac_name;
-
   SilcPublicKey founder_key;
-  SilcAuthMethod founder_method;
-  unsigned char *founder_passwd;
-  SilcUInt32 founder_passwd_len;
 
   SilcUInt32 user_limit;
   unsigned char *passphrase;
@@ -489,14 +480,15 @@ struct SilcChannelEntryStruct {
   SilcCipher channel_key;
   unsigned char *key;
   SilcUInt32 key_len;
-  unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
   SilcHmac hmac;
 
   SilcServerChannelRekey rekey;
-
   unsigned long created;
-  bool disabled;
-  bool users_resolved;
+
+  /* Flags */
+  unsigned int global_users : 1;
+  unsigned int disabled : 1;
+  unsigned int users_resolved : 1;
 };
 
 /* 
index 20dd6210af285df4be1fdf46d33a2bbc79ad3c34..03fcde91e8430f7cb9e16d2072bb163e618e7920 100644 (file)
@@ -575,9 +575,6 @@ void silc_server_notify(SilcServer server,
                                   FALSE : !server->standalone);
     }
 
-    /* Change mode */
-    channel->mode = mode;
-
     /* Get the hmac */
     tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
     if (tmp) {
@@ -604,6 +601,48 @@ void silc_server_notify(SilcServer server,
       channel->passphrase = silc_memdup(tmp, tmp_len);
     }
 
+    /* Get founder public key */
+    tmp = silc_argument_get_arg_type(args, 6, &tmp_len);
+    if (tmp && mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
+      if (channel->founder_key)
+       silc_pkcs_public_key_free(channel->founder_key);
+      channel->founder_key = NULL;
+      silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
+
+      if (!channel->founder_key || 
+         (client && client->data.public_key && 
+          server->server_type == SILC_ROUTER &&
+          !silc_pkcs_public_key_compare(channel->founder_key,
+                                        client->data.public_key))) {
+       /* A really buggy server isn't checking public keys correctly.
+          It's not possible that the mode setter and founder wouldn't
+          have same public key. */
+       SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
+
+       mode &= ~SILC_CHANNEL_MODE_FOUNDER_AUTH;
+       silc_server_send_notify_cmode(server, sock, FALSE, channel,
+                                     mode, server->id, SILC_ID_SERVER,
+                                     channel->cipher, 
+                                     channel->hmac_name,
+                                     channel->passphrase, NULL);
+       if (channel->founder_key)
+         silc_pkcs_public_key_free(channel->founder_key);
+       channel->founder_key = NULL;
+      } else if (!client->data.public_key) {
+       client->data.public_key = 
+         silc_pkcs_public_key_copy(channel->founder_key);
+      }
+    }
+
+    /* Change mode */
+    channel->mode = mode;
+
+    if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) &&
+       channel->founder_key) {
+      silc_pkcs_public_key_free(channel->founder_key);
+      channel->founder_key = NULL;
+    }
+
     break;
 
   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
@@ -713,66 +752,53 @@ void silc_server_notify(SilcServer server,
        }
       }
 
-      /* Get entry to the channel user list */
-      silc_hash_table_list(channel->user_list, &htl);
-      while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
-       /* If the mode is channel founder and we already find a client 
-          to have that mode on the channel we will enforce the sender
-          to change the channel founder mode away. There can be only one
-          channel founder on the channel. */
-       if (server->server_type == SILC_ROUTER &&
-           mode & SILC_CHANNEL_UMODE_CHANFO &&
-           chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
-         SilcBuffer idp;
-         unsigned char cumode[4];
-
-         if (chl->client == client && chl->mode == mode) {
-           notify_sent = TRUE;
-           break;
-         }
-
+      if (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. */
+
+       /* 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)) {
+         /* Force the mode to not have founder mode */
          mode &= ~SILC_CHANNEL_UMODE_CHANFO;
-         silc_server_send_notify_cumode(server, sock, FALSE, channel, mode,
-                                        client2->id, SILC_ID_CLIENT,
-                                        client2->id);
-         
-         idp = silc_id_payload_encode(client2->id, SILC_ID_CLIENT);
-         SILC_PUT32_MSB(mode, cumode);
-         silc_server_send_notify_to_channel(server, sock, channel, FALSE, 
-                                            SILC_NOTIFY_TYPE_CUMODE_CHANGE,
-                                            3, idp->data, idp->len,
-                                            cumode, 4,
-                                            idp->data, idp->len);
-         silc_buffer_free(idp);
+         silc_server_force_cumode_change(server, sock, channel, chl, mode);
          notify_sent = TRUE;
-
-         /* Force the mode change if we alredy set the mode */
-         if (chl2) {
-           chl2->mode = mode;
-           silc_free(channel_id);
-           silc_hash_table_list_reset(&htl);
-           goto out;
-         }
+         break;
        }
-       
-       if (chl->client == client2) {
-         if (chl->mode == mode) {
+
+       /* 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;
+
+       /* XXX Founder not found of the channel.  Since the founder auth mode
+          is set on the channel now check whether this is the client that
+          originally set the mode. If we don't have the public key it
+          is resolved first.
+       if (!silc_pkcs_public_key_compare(channel->founder_key,
+                                         client->data.public_key))
+       */
+      }
 
-         SILC_LOG_DEBUG(("Changing the channel user mode"));
+      SILC_LOG_DEBUG(("Changing the channel user mode"));
+
+      /* Change the mode */
+      chl->mode = mode;
 
-         /* Change the mode */
-         chl->mode = mode;
-         if (!(mode & SILC_CHANNEL_UMODE_CHANFO))
-           break;
-         
-         chl2 = chl;
-       }
-      }
-      silc_hash_table_list_reset(&htl);
-      
       /* Send the same notify to the channel */
       if (!notify_sent)
        silc_server_packet_send_to_channel(server, sock, channel, 
@@ -2627,14 +2653,14 @@ void silc_server_new_channel(SilcServer server,
        SILC_LOG_DEBUG(("Forcing the server to change channel mode"));
        silc_server_send_notify_cmode(server, sock, FALSE, channel,
                                      channel->mode, server->id,
-                                     SILC_ID_SERVER,
-                                     channel->cipher, channel->hmac_name,
-                                     channel->passphrase);
+                                     SILC_ID_SERVER, channel->cipher,
+                                     channel->hmac_name,
+                                     channel->passphrase,
+                                     channel->founder_key);
       }
 
       /* Create new key for the channel and send it to the server and
         everybody else possibly on the channel. */
-
       if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
        if (!silc_server_create_channel_key(server, channel, 0))
          return;
index 85e7695d70f267c814bd9f6852f1104e49cdc33e..3836144f068571fcbc0c6316d4188e0f3acbdc22 100644 (file)
@@ -683,15 +683,16 @@ silc_server_packet_relay_to_channel_encrypt(SilcServer server,
       channel->channel_key) {
     SilcUInt32 mac_len = silc_hmac_len(channel->hmac);
     SilcUInt32 iv_len = silc_cipher_get_block_len(channel->channel_key);
+    unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
 
     if (data_len <= mac_len + iv_len) {
       SILC_LOG_WARNING(("Corrupted channel message, cannot relay it"));
       return FALSE;
     }
 
-    memcpy(channel->iv, data + (data_len - iv_len), iv_len);
+    memcpy(iv, data + (data_len - iv_len), iv_len);
     silc_channel_message_payload_encrypt(data, data_len - iv_len - mac_len,
-                                        data_len, channel->iv, iv_len,
+                                        data_len, iv, iv_len,
                                         channel->channel_key, channel->hmac);
   }
 
@@ -1174,14 +1175,18 @@ void silc_server_send_notify_cmode(SilcServer server,
                                   SilcChannelEntry channel,
                                   SilcUInt32 mode_mask,
                                   void *id, SilcIdType id_type,
-                                  char *cipher, char *hmac,
-                                  char *passphrase)
+                                  const char *cipher, const char *hmac,
+                                  const char *passphrase,
+                                  SilcPublicKey founder_key)
 {
   SilcBuffer idp;
-  unsigned char mode[4];
+  unsigned char mode[4], *key = NULL;
+  SilcUInt32 key_len = 0;
 
   idp = silc_id_payload_encode((void *)id, id_type);
   SILC_PUT32_MSB(mode_mask, mode);
+  if (founder_key)
+    key = silc_pkcs_public_key_encode(founder_key, &key_len);
 
   silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
                               SILC_ID_CHANNEL, SILC_NOTIFY_TYPE_CMODE_CHANGE,
@@ -1190,11 +1195,13 @@ void silc_server_send_notify_cmode(SilcServer server,
                               cipher, cipher ? strlen(cipher) : 0,
                               hmac, hmac ? strlen(hmac) : 0,
                               passphrase, passphrase ? 
-                              strlen(passphrase) : 0);
+                              strlen(passphrase) : 0,
+                              key, key_len);
+  silc_free(key);
   silc_buffer_free(idp);
 }
 
-/* Sends CUMODE_CHANGE notify type. This tells that `client_id' changed the
+/* Sends CUMODE_CHANGE notify type. This tells that `id' changed the
    `target' client's mode on `channel'. The notify packet is always
    destined to the channel. */
 
index 2c322e200f23d55d54c8eb6106e41afecfb71e46..491fc5dba8d4c3b8d18da2731073da3f779212ef 100644 (file)
@@ -141,8 +141,9 @@ void silc_server_send_notify_cmode(SilcServer server,
                                   SilcChannelEntry channel,
                                   SilcUInt32 mode_mask,
                                   void *id, SilcIdType id_type,
-                                  char *cipher, char *hmac,
-                                  char *passphrase);
+                                  const char *cipher, const char *hmac,
+                                  const char *passphrase,
+                                  SilcPublicKey founder_key);
 void silc_server_send_notify_cumode(SilcServer server,
                                    SilcSocketConnection sock,
                                    bool broadcast,
index 6037be57522704dd83a81afe3122fa6092c13e3e..beecd96a0d522c8b1d8e9187d163e2cd97e528d7 100644 (file)
@@ -2729,9 +2729,9 @@ void silc_server_free_sock_user_data(SilcServer server,
 void silc_server_remove_from_channels(SilcServer server,
                                      SilcSocketConnection sock,
                                      SilcClientEntry client,
-                                     int notify,
-                                     char *signoff_message,
-                                     int keygen)
+                                     bool notify,
+                                     const char *signoff_message,
+                                     bool keygen)
 {
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
@@ -2744,6 +2744,8 @@ void silc_server_remove_from_channels(SilcServer server,
     return;
 
   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+  if (!clidp)
+    notify = FALSE;
 
   /* Remove the client from all channels. The client is removed from
      the channels' user list. */
@@ -2751,22 +2753,15 @@ void silc_server_remove_from_channels(SilcServer server,
   while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     channel = chl->channel;
 
-    /* Remove channel from client's channel list */
-    silc_hash_table_del(client->channels, channel);
-
-    /* Remove channel if there is no users anymore */
+    /* Remove channel if this is last client leaving the channel, unless
+       the channel is permanent. */
     if (server->server_type == SILC_ROUTER &&
        silc_hash_table_count(channel->user_list) < 2) {
-      if (channel->rekey)
-       silc_schedule_task_del_by_context(server->schedule, channel->rekey);
-      if (silc_idlist_del_channel(server->local_list, channel))
-       server->stat.my_channels--;
-      else
-        silc_idlist_del_channel(server->global_list, channel);
+      silc_server_channel_delete(server, channel);
       continue;
     }
 
-    /* Remove client from channel's client list */
+    silc_hash_table_del(client->channels, channel);
     silc_hash_table_del(channel->user_list, chl->client);
     channel->user_count--;
 
@@ -2780,7 +2775,8 @@ void silc_server_remove_from_channels(SilcServer server,
     server->stat.my_chanclients--;
 
     /* If there is not at least one local user on the channel then we don't
-       need the channel entry anymore, we can remove it safely. */
+       need the channel entry anymore, we can remove it safely, unless the
+       channel is permanent channel */
     if (server->server_type != SILC_ROUTER &&
        !silc_server_channel_has_local(channel)) {
       /* Notify about leaving client if this channel has global users. */
@@ -2792,37 +2788,13 @@ void silc_server_remove_from_channels(SilcServer server,
                                           signoff_message, signoff_message ?
                                           strlen(signoff_message) : 0);
 
-      if (channel->rekey)
-       silc_schedule_task_del_by_context(server->schedule, channel->rekey);
-
-      if (channel->founder_key) {
-       /* The founder auth data exists, do not remove the channel entry */
-       SilcChannelClientEntry chl2;
-       SilcHashTableList htl2;
-
-       channel->disabled = TRUE;
-
-       silc_hash_table_list(channel->user_list, &htl2);
-       while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
-         silc_hash_table_del(chl2->client->channels, channel);
-         silc_hash_table_del(channel->user_list, chl2->client);
-         channel->user_count--;
-         silc_free(chl2);
-       }
-       silc_hash_table_list_reset(&htl2);
-       continue;
-      }
-
-      /* Remove the channel entry */
-      if (silc_idlist_del_channel(server->local_list, channel))
-       server->stat.my_channels--;
-      else
-        silc_idlist_del_channel(server->global_list, channel);
+      silc_schedule_task_del_by_context(server->schedule, channel->rekey);
+      silc_server_channel_delete(server, channel);
+      silc_buffer_free(clidp);
       continue;
     }
 
-    /* Send notify to channel about client leaving SILC and thus
-       the entire channel. */
+    /* Send notify to channel about client leaving SILC and channel too */
     if (notify)
       silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
                                         SILC_NOTIFY_TYPE_SIGNOFF,
@@ -2831,10 +2803,10 @@ void silc_server_remove_from_channels(SilcServer server,
                                         signoff_message, signoff_message ?
                                         strlen(signoff_message) : 0);
 
+    /* Re-generate channel key if needed */
     if (keygen && !(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
-      /* Re-generate channel key */
       if (!silc_server_create_channel_key(server, channel, 0))
-       goto out;
+       continue;
 
       /* Send the channel key to the channel. The key of course is not sent
         to the client who was removed from the channel. */
@@ -2844,7 +2816,6 @@ void silc_server_remove_from_channels(SilcServer server,
     }
   }
 
- out:
   silc_hash_table_list_reset(&htl);
   silc_buffer_free(clidp);
 }
@@ -2855,44 +2826,33 @@ void silc_server_remove_from_channels(SilcServer server,
    last client leaves the channel. If `notify' is FALSE notify messages
    are not sent. */
 
-int silc_server_remove_from_one_channel(SilcServer server,
-                                       SilcSocketConnection sock,
-                                       SilcChannelEntry channel,
-                                       SilcClientEntry client,
-                                       int notify)
+bool silc_server_remove_from_one_channel(SilcServer server,
+                                        SilcSocketConnection sock,
+                                        SilcChannelEntry channel,
+                                        SilcClientEntry client,
+                                        bool notify)
 {
   SilcChannelClientEntry chl;
   SilcBuffer clidp;
 
-  SILC_LOG_DEBUG(("Start"));
+  SILC_LOG_DEBUG(("Removing %s from channel %s",
+                 silc_id_render(client->id, SILC_ID_CLIENT), 
+                 channel->channel_name));
 
   /* Get the entry to the channel, if this client is not on the channel
      then return Ok. */
   if (!silc_hash_table_find(client->channels, channel, NULL, (void *)&chl))
     return TRUE;
 
-  /* Remove the client from the channel. The client is removed from
-     the channel's user list. */
-
-  clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
-
-  /* Remove channel from client's channel list */
-  silc_hash_table_del(client->channels, chl->channel);
-
-  /* Remove channel if there is no users anymore */
+  /* Remove channel if this is last client leaving the channel, unless
+     the channel is permanent. */
   if (server->server_type == SILC_ROUTER &&
       silc_hash_table_count(channel->user_list) < 2) {
-    if (channel->rekey)
-      silc_schedule_task_del_by_context(server->schedule, channel->rekey);
-    if (silc_idlist_del_channel(server->local_list, channel))
-      server->stat.my_channels--;
-    else
-      silc_idlist_del_channel(server->global_list, channel);
-    silc_buffer_free(clidp);
+    silc_server_channel_delete(server, channel);
     return FALSE;
   }
 
-  /* Remove client from channel's client list */
+  silc_hash_table_del(client->channels, chl->channel);
   silc_hash_table_del(channel->user_list, chl->client);
   channel->user_count--;
 
@@ -2905,8 +2865,13 @@ int silc_server_remove_from_one_channel(SilcServer server,
   silc_free(chl);
   server->stat.my_chanclients--;
 
+  clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+  if (!clidp)
+    notify = FALSE;
+
   /* If there is not at least one local user on the channel then we don't
-     need the channel entry anymore, we can remove it safely. */
+     need the channel entry anymore, we can remove it safely, unless the
+     channel is permanent channel */
   if (server->server_type != SILC_ROUTER &&
       !silc_server_channel_has_local(channel)) {
     /* Notify about leaving client if this channel has global users. */
@@ -2915,34 +2880,9 @@ int silc_server_remove_from_one_channel(SilcServer server,
                                         SILC_NOTIFY_TYPE_LEAVE, 1,
                                         clidp->data, clidp->len);
 
+    silc_schedule_task_del_by_context(server->schedule, channel->rekey);
+    silc_server_channel_delete(server, channel);
     silc_buffer_free(clidp);
-
-    if (channel->rekey)
-      silc_schedule_task_del_by_context(server->schedule, channel->rekey);
-
-    if (channel->founder_key) {
-      /* The founder auth data exists, do not remove the channel entry */
-      SilcChannelClientEntry chl2;
-      SilcHashTableList htl2;
-
-      channel->disabled = TRUE;
-
-      silc_hash_table_list(channel->user_list, &htl2);
-      while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
-       silc_hash_table_del(chl2->client->channels, channel);
-       silc_hash_table_del(channel->user_list, chl2->client);
-       channel->user_count--;
-       silc_free(chl2);
-      }
-      silc_hash_table_list_reset(&htl2);
-      return FALSE;
-    }
-
-    /* Remove the channel entry */
-    if (silc_idlist_del_channel(server->local_list, channel))
-      server->stat.my_channels--;
-    else
-      silc_idlist_del_channel(server->global_list, channel);
     return FALSE;
   }
 
index c965967645ebe31eaf2564a713ed710ce3203a77..404696ce0b25daf0e725008edd79eaad996f60d0 100644 (file)
@@ -139,14 +139,14 @@ void silc_server_free_sock_user_data(SilcServer server,
 void silc_server_remove_from_channels(SilcServer server,
                                      SilcSocketConnection sock,
                                      SilcClientEntry client,
-                                     int notify,
-                                     char *signoff_message,
-                                     int keygen);
-int silc_server_remove_from_one_channel(SilcServer server,
-                                       SilcSocketConnection sock,
-                                       SilcChannelEntry channel,
-                                       SilcClientEntry client,
-                                       int notify);
+                                     bool notify,
+                                     const char *signoff_message,
+                                     bool keygen);
+bool silc_server_remove_from_one_channel(SilcServer server,
+                                        SilcSocketConnection sock,
+                                        SilcChannelEntry channel,
+                                        SilcClientEntry client,
+                                        bool notify);
 void silc_server_disconnect_remote(SilcServer server,
                                   SilcSocketConnection sock,
                                   SilcStatus status, ...);
index 38a7c49cc5817c000e2d16289c2b60b71da3df19..2a7cb7a74a36de7c7b6912b76c96000ce5df82e6 100644 (file)
@@ -51,27 +51,18 @@ static void silc_server_remove_clients_channels(SilcServer server,
   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
     channel = chl->channel;
 
-    /* Remove channel from client's channel list */
-    silc_hash_table_del(client->channels, channel);
-
-    /* Remove channel if there is no users anymore */
+    /* Remove channel if this is last client leaving the channel, unless
+       the channel is permanent. */
     if (server->server_type == SILC_ROUTER &&
        silc_hash_table_count(channel->user_list) < 2) {
-
       if (silc_hash_table_find(channels, channel, NULL, NULL))
        silc_hash_table_del(channels, channel);
-
-      if (channel->rekey)
-       silc_schedule_task_del_by_context(server->schedule, channel->rekey);
-
-      if (silc_idlist_del_channel(server->local_list, channel))
-       server->stat.my_channels--;
-      else 
-        silc_idlist_del_channel(server->global_list, channel);
+      silc_schedule_task_del_by_context(server->schedule, channel->rekey);
+      silc_server_channel_delete(server, channel);
       continue;
     }
 
-    /* Remove client from channel's client list */
+    silc_hash_table_del(client->channels, channel);
     silc_hash_table_del(channel->user_list, chl->client);
     channel->user_count--;
 
@@ -85,39 +76,14 @@ static void silc_server_remove_clients_channels(SilcServer server,
     server->stat.my_chanclients--;
 
     /* If there is not at least one local user on the channel then we don't
-       need the channel entry anymore, we can remove it safely. */
+       need the channel entry anymore, we can remove it safely, unless the
+       channel is permanent channel */
     if (server->server_type != SILC_ROUTER &&
        !silc_server_channel_has_local(channel)) {
-
       if (silc_hash_table_find(channels, channel, NULL, NULL))
        silc_hash_table_del(channels, channel);
-
-      if (channel->rekey)
-       silc_schedule_task_del_by_context(server->schedule, channel->rekey);
-
-      if (channel->founder_key) {
-       /* The founder auth data exists, do not remove the channel entry */
-       SilcChannelClientEntry chl2;
-       SilcHashTableList htl2;
-
-       channel->disabled = TRUE;
-
-       silc_hash_table_list(channel->user_list, &htl2);
-       while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
-         silc_hash_table_del(chl2->client->channels, channel);
-         silc_hash_table_del(channel->user_list, chl2->client);
-         channel->user_count--;
-         silc_free(chl2);
-       }
-       silc_hash_table_list_reset(&htl2);
-       continue;
-      }
-
-      /* Remove the channel entry */
-      if (silc_idlist_del_channel(server->local_list, channel))
-       server->stat.my_channels--;
-      else 
-        silc_idlist_del_channel(server->global_list, channel);
+      silc_schedule_task_del_by_context(server->schedule, channel->rekey);
+      silc_server_channel_delete(server, channel);
       continue;
     }
 
@@ -127,7 +93,6 @@ static void silc_server_remove_clients_channels(SilcServer server,
       silc_hash_table_add(channels, channel, channel);
   }
   silc_hash_table_list_reset(&htl);
-
   silc_buffer_free(clidp);
 }
 
@@ -742,6 +707,47 @@ bool silc_server_channel_has_local(SilcChannelEntry channel)
   return FALSE;
 }
 
+/* This function removes the channel and all users on the channel, unless
+   the channel is permanent.  In this case the channel is disabled but all
+   users are removed from the channel.  Returns TRUE if the channel is
+   destroyed totally, and FALSE if it is permanent and remains. */
+
+bool silc_server_channel_delete(SilcServer server,
+                               SilcChannelEntry channel)
+{
+  SilcChannelClientEntry chl;
+  SilcHashTableList htl;
+  bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
+
+  if (delchan) {
+    SILC_LOG_DEBUG(("Deleting %s channel", channel->channel_name));
+
+    /* Totally delete the channel and all users on the channel. The
+       users are deleted automatically in silc_idlist_del_channel. */
+    silc_schedule_task_del_by_context(server->schedule, channel->rekey);
+    if (silc_idlist_del_channel(server->local_list, channel))
+      server->stat.my_channels--;
+    else
+      silc_idlist_del_channel(server->global_list, channel);
+    return FALSE;
+  }
+
+  /* Channel is permanent, do not remove it, remove only users */
+  channel->disabled = TRUE;
+  silc_hash_table_list(channel->user_list, &htl);
+  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+    silc_hash_table_del(chl->client->channels, channel);
+    silc_hash_table_del(channel->user_list, chl->client);
+    channel->user_count--;
+    silc_free(chl);
+  }
+  silc_hash_table_list_reset(&htl);
+
+  SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
+
+  return TRUE;
+}
+
 /* Returns TRUE if the given client is on the channel.  FALSE if not. 
    This works because we assure that the user list on the channel is
    always in up to date thus we can only check the channel list from 
@@ -1371,3 +1377,31 @@ bool silc_server_del_from_watcher_list(SilcServer server,
 
   return found;
 }
+
+/* Force the client indicated by `chl' to change the channel user mode
+   on channel indicated by `channel' to `forced_mode'. */
+
+bool silc_server_force_cumode_change(SilcServer server,
+                                    SilcSocketConnection sock,
+                                    SilcChannelEntry channel,
+                                    SilcChannelClientEntry chl,
+                                    SilcUInt32 forced_mode)
+{
+  SilcBuffer idp1, idp2;
+  unsigned char cumode[4];
+
+  silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
+                                server->id, SILC_ID_SERVER,
+                                chl->client->id);
+
+  idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
+  idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
+  SILC_PUT32_MSB(forced_mode, cumode);
+  silc_server_send_notify_to_channel(server, sock, channel, FALSE,
+                                    SILC_NOTIFY_TYPE_CUMODE_CHANGE,
+                                    3, idp1->data, idp1->len,
+                                    cumode, sizeof(cumode),
+                                    idp2->data, idp2->len);
+  silc_buffer_free(idp1);
+  silc_buffer_free(idp2);
+}
index 6b421f238d0e86b3f1c8a9f477981a62b4c99eb3..84ef07838ca90d204d8187ff949487f7eb9bb533 100644 (file)
@@ -67,6 +67,13 @@ bool silc_server_channel_has_global(SilcChannelEntry channel);
    returns TRUE and FALSE if there is not one locally connected client. */
 bool silc_server_channel_has_local(SilcChannelEntry channel);
 
+/* This function removes the channel and all users on the channel, unless
+   the channel is permanent.  In this case the channel is disabled but all
+   users are removed from the channel.  Returns TRUE if the channel is
+   destroyed totally, and FALSE if it is permanent and remains. */
+bool silc_server_channel_delete(SilcServer server,
+                               SilcChannelEntry channel);
+
 /* Returns TRUE if the given client is on the channel.  FALSE if not. 
    This works because we assure that the user list on the channel is
    always in up to date thus we can only check the channel list from 
@@ -162,4 +169,12 @@ bool silc_server_check_watcher_list(SilcServer server,
 bool silc_server_del_from_watcher_list(SilcServer server,
                                       SilcClientEntry client);
 
+/* Force the client indicated by `chl' to change the channel user mode
+   on channel indicated by `channel' to `forced_mode'. */
+bool silc_server_force_cumode_change(SilcServer server,
+                                    SilcSocketConnection sock,
+                                    SilcChannelEntry channel,
+                                    SilcChannelClientEntry chl,
+                                    SilcUInt32 forced_mode);
+
 #endif /* SERVER_UTIL_H */
index b05f81b680c3a887c39a947407525b3c9829e57c..0d0aeec257e8f5a352f093f45fc837053e38df91 100644 (file)
@@ -1350,7 +1350,6 @@ void silc_client_close_connection_real(SilcClient client,
 
   /* Unregister all tasks */
   silc_schedule_task_del_by_fd(client->schedule, sock->sock);
-  silc_schedule_task_del_by_fd(client->schedule, sock->sock);
 
   /* Close the actual connection */
   silc_net_close_connection(sock->sock);
index b272e242d5e413bea56d30ed7c4d595da0365824..dea2e513510458159d5cc2358fdb97fa31c6be06 100644 (file)
@@ -312,7 +312,7 @@ void silc_client_notify_by_server(SilcClient client,
       res->context = client;
       res->sock = silc_socket_dup(conn->sock);
       res->packet = silc_id_dup(client_id, SILC_ID_CLIENT);
-      silc_schedule_task_add(client->schedule, 0,
+      silc_schedule_task_add(client->schedule, conn->sock->sock,
                             silc_client_notify_check_client, res,
                             (5 + (silc_rng_get_rn16(client->rng) % 29)),
                             0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
@@ -898,7 +898,7 @@ void silc_client_notify_by_server(SilcClient client,
        res->context = client;
        res->sock = silc_socket_dup(conn->sock);
        res->packet = silc_id_dup(client_entry->id, SILC_ID_CLIENT);
-       silc_schedule_task_add(client->schedule, 0,
+       silc_schedule_task_add(client->schedule, conn->sock->sock,
                               silc_client_notify_check_client, res,
                               (5 + (silc_rng_get_rn16(client->rng) % 529)),
                               0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
index 9373396e1ee91cc8fd04a0ca12d5cf045d959772..b62a72fe67120e49346b83320c836d527d866b62 100644 (file)
@@ -1413,26 +1413,12 @@ SILC_CLIENT_CMD_FUNC(cmode)
       if (add) {
        mode |= SILC_CHANNEL_MODE_FOUNDER_AUTH;
        type = 7;
-
-       if (cmd->argc < 4) {
-         SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, 
-             "Usage: /CMODE <channel> +|-<modes> [{ <arguments>}]");
-         COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
-         goto out;
-       }
-
-       if (!strcasecmp(cmd->argv[3], "-pubkey")) {
-         auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
-                                                   cmd->client->private_key,
-                                                   cmd->client->rng, 
-                                                   conn->hash,
-                                                   conn->local_id,
-                                                   SILC_ID_CLIENT);
-       } else {
-         auth = silc_auth_payload_encode(SILC_AUTH_PASSWORD, NULL, 0,
-                                         cmd->argv[3], cmd->argv_lens[3]);
-       }
-
+       auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
+                                                 cmd->client->private_key,
+                                                 cmd->client->rng, 
+                                                 conn->hash,
+                                                 conn->local_id,
+                                                 SILC_ID_CLIENT);
        arg = auth->data;
        arg_len = auth->len;
       } else {
index 2f2c1d16db13c2fee68848ad4a598b0eb8fe1c57..8aa9d516e8867ff986e230cad3ffe098edc5533a 100644 (file)
@@ -811,6 +811,25 @@ bool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
   return FALSE;
 }
 
+/* Copies the public key indicated by `public_key' and returns new allocated
+   public key which is indentical to the `public_key'. */
+
+SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
+{
+  SilcPublicKey key = silc_calloc(1, sizeof(*key));
+  if (!key)
+    return NULL;
+
+  key->len = public_key->len;
+  key->name = silc_memdup(public_key->name, strlen(public_key->name));
+  key->identifier = silc_memdup(public_key->identifier,
+                               strlen(public_key->identifier));
+  key->pk = silc_memdup(public_key->pk, public_key->pk_len);
+  key->pk_len = public_key->pk_len;
+
+  return key;
+}
+
 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
 
 unsigned char *
index 8e9ad2e1688a816575b6e33b422a7e30109a4d1c..86bab7336bb6da4ebc1790b7434607e4b3a94bc4 100644 (file)
@@ -227,6 +227,7 @@ silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
 int silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
                                SilcPublicKey *public_key);
 bool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2);
+SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key);
 unsigned char *
 silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len);
 unsigned char *