+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
}
/* 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;
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,
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;
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);
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);
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 */
}
}
+ /* 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;
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);
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)
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,
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
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,
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,
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);
/* 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;
/* 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 */
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);
+}
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
/* 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 }
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. */
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. */
SilcCipherObject *entry = NULL;
SILC_LOG_DEBUG(("Allocating new cipher object"));
-
+
#ifndef SILC_EPOC
if (silc_cipher_list) {
silc_dlist_start(silc_cipher_list);
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;
}
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++;
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++;
/* 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
/* 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;
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 */