From: Pekka Riikonen Date: Sun, 3 Apr 2005 12:27:55 +0000 (+0000) Subject: Added support for WATCH list announcing in backup protocol. X-Git-Tag: silc.server.0.9.19~11 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=7b170abd6ceab7fb346a62ba285a9957a4347c49 Added support for WATCH list announcing in backup protocol. --- diff --git a/CHANGES b/CHANGES index c2d55609..a4d5f0c7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +Sun Apr 3 14:58:53 EEST 2005 Pekka Riikonen + + * 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 * Splitted the SILC libraries configuration into a configure diff --git a/apps/silcd/command.c b/apps/silcd/command.c index e33a8cef..1b848205 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -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); diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 7d0ae314..33657ebc 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -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) diff --git a/apps/silcd/server.c b/apps/silcd/server.c index e685db93..cadbdab1 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -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, diff --git a/apps/silcd/server.h b/apps/silcd/server.h index 8cdf3b03..55e5f1fc 100644 --- a/apps/silcd/server.h +++ b/apps/silcd/server.h @@ -4,12 +4,11 @@ Author: Pekka Riikonen - 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, diff --git a/apps/silcd/server_backup.c b/apps/silcd/server_backup.c index 7c5a3693..160997b5 100644 --- a/apps/silcd/server_backup.c +++ b/apps/silcd/server_backup.c @@ -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); +} diff --git a/lib/silccrypt/silccipher.c b/lib/silccrypt/silccipher.c index ddaeee01..378bd73c 100644 --- a/lib/silccrypt/silccipher.c +++ b/lib/silccrypt/silccipher.c @@ -2,15 +2,14 @@ silccipher.c - Author: Pekka Riikonen + Author: Pekka Riikonen - 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; diff --git a/lib/silcutil/silcutf8.c b/lib/silcutil/silcutf8.c index 8fea7b39..af6cac3e 100644 --- a/lib/silcutil/silcutf8.c +++ b/lib/silcutil/silcutf8.c @@ -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 */