Added support for WATCH list announcing in backup protocol.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 3 Apr 2005 12:27:55 +0000 (12:27 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 3 Apr 2005 12:27:55 +0000 (12:27 +0000)
CHANGES
apps/silcd/command.c
apps/silcd/packet_receive.c
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/server_backup.c
lib/silccrypt/silccipher.c
lib/silcutil/silcutf8.c

diff --git a/CHANGES b/CHANGES
index c2d55609a23391a0c9ebec3dc61e88436031de18..a4d5f0c7a5044ee5d3cb4589fd52a702b26b0b76 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+Sun Apr  3 14:58:53 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added WATCH list announcing in backup router protocol.
+         Affected files are silcd/command.c, server.c, server_backup.c.
+
 Sat Apr  2 18:09:30 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
 
        * Splitted the SILC libraries configuration into a configure
index e33a8cef41ca846eb07806861326b3b7ad8eb8d8..1b848205d639619f74219e28687386202e813291 100644 (file)
@@ -658,7 +658,8 @@ SILC_SERVER_CMD_FUNC(nick)
   }
 
   /* Check for same nickname */
-  if (!memcmp(client->nickname, nick, nick_len)) {
+  if (strlen(client->nickname) == nick_len &&
+      !memcmp(client->nickname, nick, nick_len)) {
     nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
     silc_free(nickc);
     goto send_reply;
@@ -2088,6 +2089,7 @@ static void silc_server_command_join_channel(SilcServer server,
       passphrase = silc_memdup(tmp, tmp_len);
 
     if (!passphrase || !channel->passphrase ||
+       strlen(channel->passphrase) != strlen(passphrase) ||
         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
       chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
@@ -4097,7 +4099,6 @@ SILC_SERVER_CMD_FUNC(detach)
 SILC_SERVER_CMD_FUNC(watch)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-  SilcServerEntry server_entry;
   SilcServer server = cmd->server;
   char *add_nick, *del_nick;
   SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
@@ -4113,6 +4114,11 @@ SILC_SERVER_CMD_FUNC(watch)
       SilcBuffer tmpbuf;
       SilcUInt16 old_ident;
 
+      /* If backup receives this from primary, handle it locally */
+      if (server->server_type == SILC_BACKUP_ROUTER &&
+         cmd->sock == SILC_PRIMARY_ROUTE(server))
+       goto process_watch;
+
       SILC_LOG_DEBUG(("Forwarding WATCH to router"));
 
       old_ident = silc_command_get_ident(cmd->payload);
@@ -4131,20 +4137,28 @@ SILC_SERVER_CMD_FUNC(watch)
       cmd->pending = TRUE;
       silc_command_set_ident(cmd->payload, old_ident);
       silc_buffer_free(tmpbuf);
-    } else if (context2) {
-      /* Received reply from router, just send same data to the client. */
-      SilcServerCommandReplyContext reply = context2;
-      SilcStatus status;
-
-      SILC_LOG_DEBUG(("Received reply to WATCH from router"));
-      silc_command_get_status(reply->payload, &status, NULL);
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
-                                           0);
+      goto out;
+    } else {
+      if (!context2)
+        goto out;
+
+      /* Backup router handles the WATCH command also. */
+      if (server->server_type != SILC_BACKUP_ROUTER) {
+       /* Received reply from router, just send same data to the client. */
+       SilcServerCommandReplyContext reply = context2;
+       SilcStatus status;
+
+       SILC_LOG_DEBUG(("Received reply to WATCH from router"));
+       silc_command_get_status(reply->payload, &status, NULL);
+       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
+                                             0);
+       goto out;
+      }
     }
-    goto out;
   }
 
   /* We are router and keep the watch list for local cell */
+ process_watch:
 
   /* Get the client ID */
   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
@@ -4166,10 +4180,16 @@ SILC_SERVER_CMD_FUNC(watch)
   client = silc_idlist_find_client_by_id(server->local_list,
                                         client_id, TRUE, NULL);
   if (!client) {
-    silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
-                                        SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
-                                        2, tmp, tmp_len);
-    goto out;
+    /* Backup checks global list also */
+    if (server->server_type == SILC_BACKUP_ROUTER)
+      client = silc_idlist_find_client_by_id(server->global_list,
+                                            client_id, TRUE, NULL);
+    if (!client) {
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
+                                          SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+                                          0, 2, tmp, tmp_len);
+      goto out;
+    }
   }
 
   /* Take public key for watching by public key */
@@ -4350,6 +4370,10 @@ SILC_SERVER_CMD_FUNC(watch)
     }
   }
 
+  /* Send reply */
+  silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
+                                       SILC_STATUS_OK, 0);
+
   /* Distribute the watch list to backup routers too */
   if (server->backup) {
     SilcBuffer tmpbuf;
@@ -4361,9 +4385,6 @@ SILC_SERVER_CMD_FUNC(watch)
     silc_buffer_free(tmpbuf);
   }
 
-  silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
-                                       SILC_STATUS_OK, 0);
-
  out:
   silc_free(client_id);
   silc_server_command_free(cmd);
index 7d0ae31462cb24d0072dc7a3f41fbfb9d4e9792d..33657ebc53d642c244502409146241540ca4c2ac 100644 (file)
@@ -1636,8 +1636,9 @@ void silc_server_notify(SilcServer server,
                                       FALSE, TRUE);
 
       /* Check if anyone is watching this nickname */
-      silc_server_check_watcher_list(server, client, NULL,
-                                    SILC_NOTIFY_TYPE_KILLED);
+      if (server->server_type == SILC_ROUTER)
+       silc_server_check_watcher_list(server, client, NULL,
+                                      SILC_NOTIFY_TYPE_KILLED);
 
       /* Remove from public key hash table. */
       if (client->data.public_key)
index e685db935301e1c2b3fe56eaec71a04028ac9706..cadbdab1ec69cb252114ec30e22a7a9a309d9ace 100644 (file)
@@ -5055,6 +5055,51 @@ void silc_server_announce_channels(SilcServer server,
   silc_free(channel_ids);
 }
 
+/* Announces WATCH list. */
+
+void silc_server_announce_watches(SilcServer server,
+                                 SilcSocketConnection remote)
+{
+  SilcHashTableList htl;
+  SilcBuffer buffer, idp, args, pkp;
+  SilcClientEntry client;
+  void *key;
+
+  SILC_LOG_DEBUG(("Announcing watch list"));
+
+  /* XXX because way we save the nicks (hash) we cannot announce them. */
+
+  /* XXX we should send all public keys in one command if client is
+     watching more than one key */
+  silc_hash_table_list(server->watcher_list_pk, &htl);
+  while (silc_hash_table_get(&htl, &key, (void *)&client)) {
+    if (!client || !client->id)
+      continue;
+
+    idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+    args = silc_buffer_alloc_size(2);
+    silc_buffer_format(args,
+                      SILC_STR_UI_SHORT(1),
+                      SILC_STR_END);
+    pkp = silc_pkcs_public_key_payload_encode(key);
+    args = silc_argument_payload_encode_one(args, pkp->data, pkp->len, 0x00);
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_WATCH,
+                                           ++server->cmd_ident, 2,
+                                           1, idp->data, idp->len,
+                                           4, args->data, args->len);
+
+    /* Send command */
+    silc_server_packet_send(server, remote, SILC_PACKET_COMMAND, 0,
+                           buffer->data, buffer->len, TRUE);
+
+    silc_buffer_free(pkp);
+    silc_buffer_free(args);
+    silc_buffer_free(idp);
+    silc_buffer_free(buffer);
+  }
+  silc_hash_table_list_reset(&htl);
+}
+
 /* Assembles user list and users mode list from the `channel'. */
 
 bool silc_server_get_users_on_channel(SilcServer server,
index 8cdf3b0352f35603cc4f4520f8a4d7f5b80628d4..55e5f1fc0f0e6e708d08b1c97f4a3faaaf9b7c78 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -222,6 +221,8 @@ void silc_server_announce_clients(SilcServer server,
 void silc_server_announce_channels(SilcServer server,
                                   unsigned long creation_time,
                                   SilcSocketConnection remote);
+void silc_server_announce_watches(SilcServer server,
+                                 SilcSocketConnection remote);
 bool silc_server_get_users_on_channel(SilcServer server,
                                      SilcChannelEntry channel,
                                      SilcBuffer *user_list,
index 7c5a3693fb2a533ad4f6bbe8d447a4ced3343d3b..160997b5f0384e41077a4cd734953f68f04ea920 100644 (file)
@@ -23,6 +23,7 @@
 
 SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router);
+SILC_TASK_CALLBACK(silc_server_backup_announce_watches);
 
 static void silc_server_backup_connect_primary(SilcServer server,
                                               SilcServerEntry server_entry,
@@ -1305,6 +1306,12 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
       SILC_LOG_INFO(("We are now the primary router of our cell again"));
       server->wait_backup = FALSE;
 
+      /* Announce WATCH list a little later */
+      silc_schedule_task_add(server->schedule, 0,
+                            silc_server_backup_announce_watches,
+                            silc_socket_dup(ctx->sock), 4, 0,
+                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+
       /* For us this is the end of this protocol. */
       if (protocol->final_callback)
        silc_protocol_execute_final(protocol, server->schedule);
@@ -1497,6 +1504,13 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
            /* Announce our clients and channels to the router */
            silc_server_announce_clients(server, 0, sock);
            silc_server_announce_channels(server, 0, sock);
+
+           /* Announce WATCH list a little later */
+           silc_schedule_task_add(server->schedule, 0,
+                                  silc_server_backup_announce_watches,
+                                  silc_socket_dup(sock), 5, 0,
+                                  SILC_TASK_TIMEOUT,
+                                  SILC_TASK_PRI_NORMAL);
          }
 
          continue;
@@ -1519,6 +1533,12 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
       /* Announce our clients and channels to the router */
       silc_server_announce_clients(server, 0, server->router->connection);
       silc_server_announce_channels(server, 0, server->router->connection);
+
+      /* Announce WATCH list a little later */
+      silc_schedule_task_add(server->schedule, 0,
+                            silc_server_backup_announce_watches,
+                            silc_socket_dup(server->router->connection), 4, 0,
+                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
     }
   } else {
     /* Error */
@@ -1560,3 +1580,12 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
   silc_free(ctx->sessions);
   silc_free(ctx);
 }
+
+SILC_TASK_CALLBACK(silc_server_backup_announce_watches)
+{
+  SilcSocketConnection sock = context;
+  SilcServer server = app_context;
+  if (sock->users > 1)
+    silc_server_announce_watches(server, sock);
+  silc_socket_free(sock);
+}
index ddaeee010e43539c0a16eb9bf3021bce4b5141ee..378bd73cc1d93d677dd0ec4e737c00903ff4d685 100644 (file)
@@ -2,15 +2,14 @@
 
   silccipher.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@@ -37,38 +36,38 @@ SilcDList silc_cipher_list = NULL;
 /* Static list of ciphers for silc_cipher_register_default(). */
 const SilcCipherObject silc_default_ciphers[] =
 {
-  { "aes-256-cbc", 16, 256, silc_aes_set_key, 
+  { "aes-256-cbc", 16, 256, silc_aes_set_key,
     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
     silc_aes_decrypt_cbc, silc_aes_context_len },
-  { "aes-192-cbc", 16, 192, silc_aes_set_key, 
+  { "aes-192-cbc", 16, 192, silc_aes_set_key,
     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
     silc_aes_decrypt_cbc, silc_aes_context_len },
-  { "aes-128-cbc", 16, 128, silc_aes_set_key, 
+  { "aes-128-cbc", 16, 128, silc_aes_set_key,
     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
     silc_aes_decrypt_cbc, silc_aes_context_len },
-  { "twofish-256-cbc", 16, 256, silc_twofish_set_key, 
+  { "twofish-256-cbc", 16, 256, silc_twofish_set_key,
     silc_twofish_set_key_with_string,
-    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
+    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
     silc_twofish_context_len },
-  { "twofish-192-cbc", 16, 192, silc_twofish_set_key, 
+  { "twofish-192-cbc", 16, 192, silc_twofish_set_key,
     silc_twofish_set_key_with_string,
-    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
+    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
     silc_twofish_context_len },
-  { "twofish-128-cbc", 16, 128, silc_twofish_set_key, 
+  { "twofish-128-cbc", 16, 128, silc_twofish_set_key,
     silc_twofish_set_key_with_string,
-    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
+    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
     silc_twofish_context_len },
   { "cast-256-cbc", 16, 256, silc_cast_set_key, silc_cast_set_key_with_string,
-    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
+    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
     silc_cast_context_len },
   { "cast-192-cbc", 16, 192, silc_cast_set_key, silc_cast_set_key_with_string,
-    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
+    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
     silc_cast_context_len },
   { "cast-128-cbc", 16, 128, silc_cast_set_key, silc_cast_set_key_with_string,
-    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
+    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
     silc_cast_context_len },
   { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
-    silc_none_encrypt_cbc, silc_none_decrypt_cbc, 
+    silc_none_encrypt_cbc, silc_none_decrypt_cbc,
     silc_none_context_len },
 
   { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
@@ -147,7 +146,7 @@ bool silc_cipher_unregister(SilcCipherObject *cipher)
   return FALSE;
 }
 
-/* Function that registers all the default ciphers (all builtin ciphers). 
+/* Function that registers all the default ciphers (all builtin ciphers).
    The application may use this to register the default ciphers if specific
    ciphers in any specific order is not wanted. */
 
@@ -181,7 +180,7 @@ bool silc_cipher_unregister_all(void)
   return TRUE;
 }
 
-/* Allocates a new SILC cipher object. Function returns 1 on succes and 0 
+/* Allocates a new SILC cipher object. Function returns 1 on succes and 0
    on error. The allocated cipher is returned in new_cipher argument. The
    caller must set the key to the cipher after this function has returned
    by calling the ciphers set_key function. */
@@ -191,7 +190,7 @@ bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
   SilcCipherObject *entry = NULL;
 
   SILC_LOG_DEBUG(("Allocating new cipher object"));
-  
+
 #ifndef SILC_EPOC
   if (silc_cipher_list) {
     silc_dlist_start(silc_cipher_list);
@@ -215,7 +214,7 @@ bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
 
   if (entry) {
     *new_cipher = silc_calloc(1, sizeof(**new_cipher));
-    (*new_cipher)->cipher = entry; 
+    (*new_cipher)->cipher = entry;
     (*new_cipher)->context = silc_calloc(1, entry->context_len());
     return TRUE;
   }
@@ -272,8 +271,8 @@ char *silc_cipher_get_supported(void)
     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
       len += strlen(entry->name);
       list = silc_realloc(list, len + 1);
-      
-      memcpy(list + (len - strlen(entry->name)), 
+
+      memcpy(list + (len - strlen(entry->name)),
             entry->name, strlen(entry->name));
       memcpy(list + len, ",", 1);
       len++;
@@ -286,8 +285,8 @@ char *silc_cipher_get_supported(void)
       entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
       len += strlen(entry->name);
       list = silc_realloc(list, len + 1);
-      
-      memcpy(list + (len - strlen(entry->name)), 
+
+      memcpy(list + (len - strlen(entry->name)),
             entry->name, strlen(entry->name));
       memcpy(list + len, ",", 1);
       len++;
@@ -303,7 +302,7 @@ char *silc_cipher_get_supported(void)
 /* Encrypts */
 
 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
-                        unsigned char *dst, SilcUInt32 len, 
+                        unsigned char *dst, SilcUInt32 len,
                         unsigned char *iv)
 {
 #ifdef SILC_DEBUG
@@ -318,11 +317,11 @@ bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
 /* Decrypts */
 
 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
-                        unsigned char *dst, SilcUInt32 len, 
+                        unsigned char *dst, SilcUInt32 len,
                         unsigned char *iv)
 {
 #ifdef SILC_DEBUG
-  assert((len & (cipher->cipher->block_len - 1)) == 0);
+  /*  assert((len & (cipher->cipher->block_len - 1)) == 0); */
 #endif
   if (len & (cipher->cipher->block_len - 1))
     return FALSE;
index 8fea7b394e75c4ca45b87ede74099c5fe23d1ca1..af6cac3e502d33fe9cbc9e69411a873612f70d38 100644 (file)
@@ -545,16 +545,12 @@ bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len)
 
 bool silc_utf8_strcasecmp(const char *s1, const char *s2)
 {
-  SilcUInt32 n;
-
   if (s1 == s2)
     return TRUE;
+  if (strlen(s1) != strlen(s2))
+    return FALSE;
 
-  n = strlen(s2);
-  if (strlen(s1) > n)
-    n = strlen(s1);
-
-  return silc_utf8_strncasecmp(s1, s2, n);
+  return silc_utf8_strncasecmp(s1, s2, strlen(s1));
 }
 
 /* Pretty close strcasecmp */