From 5d5f6c15653598af5ca0392441654bb0561e3f99 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 5 Jul 2001 19:34:42 +0000 Subject: [PATCH] updates. --- CHANGES | 20 +++++++++++++++ TODO | 5 ---- apps/silcd/idlist.c | 2 +- apps/silcd/protocol.c | 2 +- apps/silcd/server.c | 47 ++++++++++++++++++++++++++++++------ lib/silcutil/silchashtable.h | 4 +-- 6 files changed, 64 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index feb120c5..e3e718fc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,23 @@ +Thu Jul 5 21:22:32 EEST 2001 Pekka Riikonen + + * Fixed a possible crash in silc_server_remove_clients_by_server + in silcd/server.c. Fixed there also some memory leaks. + + * Fixed the silc_idlist_replace_client_id. It could replace + wrong key in the hash table. Affected file silcd/idlist.c. + + * Do not check whether there are global users on the channel + if the channel->global_users is FALSE. Affected functions + silc_server_remove_from_one_channel and + silc_server_remove_from_channels in silcd/server.c. Also, + do not check if the removed client is local as we can be + sure that global client was not removed from the channel + and checking for global users is not needed. + + * The silc_server_remove_clients_by_server now re-generates + the channel keys correctly for those channels that had + clients removed from them. Affected file silcd/server.c. + Tue Jul 3 11:39:20 EEST 2001 Pekka Riikonen * Found the reason of random crashes in the server. We weren't diff --git a/TODO b/TODO index 29bda114..623f541a 100644 --- a/TODO +++ b/TODO @@ -56,11 +56,6 @@ TODO/bugs In SILC Client Library TODO/bugs In SILC Server ======================== - o When server quits and all clients of that server are removed from all - channels the channel keys are re-generated for all clients. This is - a bug and should be done only once per channel after all clients of - the server has been removed. - o Incomplete IPv6 support: o silc_server_get_users_on_channel does not support IPv6 based diff --git a/apps/silcd/idlist.c b/apps/silcd/idlist.c index e973a1d6..abcfb9f1 100644 --- a/apps/silcd/idlist.c +++ b/apps/silcd/idlist.c @@ -502,7 +502,7 @@ silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id, /* Remove the old entry and add a new one */ - silc_idcache_del_by_id(id_list->clients, (void *)client->id); + silc_idcache_del_by_context(id_list->clients, client); silc_free(client->id); client->id = new_id; diff --git a/apps/silcd/protocol.c b/apps/silcd/protocol.c index 76b45942..0a720081 100644 --- a/apps/silcd/protocol.c +++ b/apps/silcd/protocol.c @@ -335,7 +335,7 @@ SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version, if (maj != maj2) status = SILC_SKE_STATUS_BAD_VERSION; - if (min < min2) + if (min > min2) status = SILC_SKE_STATUS_BAD_VERSION; return status; diff --git a/apps/silcd/server.c b/apps/silcd/server.c index d1d0003c..8947435e 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -2304,16 +2304,27 @@ int silc_server_remove_clients_by_server(SilcServer server, uint32 clients_c = 0; unsigned char **argv = NULL; uint32 *argv_lens = NULL, *argv_types = NULL, argc = 0; + SilcHashTable servers; + SilcChannelClientEntry chl; + SilcChannelEntry channel; + SilcHashTableList htl; int i; SILC_LOG_DEBUG(("Start")); + /* Allocate the hash table that holds the channels that require + channel key re-generation after we've removed this servers clients + from the channels. */ + servers = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL, + NULL, NULL, TRUE); + if (server_signoff) { idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER); argv = silc_realloc(argv, sizeof(*argv) * (argc + 1)); argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1)); argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1)); - argv[argc] = idp->data; + argv[argc] = silc_calloc(idp->len, sizeof(*argv[0])); + memcpy(argv[argc], idp->data, idp->len); argv_lens[argc] = idp->len; argv_types[argc] = argc + 1; argc++; @@ -2361,6 +2372,10 @@ int silc_server_remove_clients_by_server(SilcServer server, silc_buffer_free(idp); } + silc_hash_table_list(client->channels, &htl); + while (silc_hash_table_get(&htl, NULL, (void *)&chl)) + silc_hash_table_replace(servers, chl->channel, chl->channel); + /* Remove the client entry */ silc_server_remove_from_channels(server, NULL, client, FALSE, NULL, FALSE); @@ -2414,6 +2429,10 @@ int silc_server_remove_clients_by_server(SilcServer server, silc_buffer_free(idp); } + silc_hash_table_list(client->channels, &htl); + while (silc_hash_table_get(&htl, NULL, (void *)&chl)) + silc_hash_table_replace(servers, chl->channel, chl->channel); + /* Remove the client entry */ silc_server_remove_from_channels(server, NULL, client, FALSE, NULL, FALSE); @@ -2455,11 +2474,25 @@ int silc_server_remove_clients_by_server(SilcServer server, silc_free(clients); silc_buffer_free(args); + for (i = 0; i < argc; i++) + silc_free(argv[i]); silc_free(argv); silc_free(argv_lens); silc_free(argv_types); } + /* We must now re-generate the channel key for all channels that had + this server's client(s) on the channel. As they left the channel we + must re-generate the channel key. */ + silc_hash_table_list(servers, &htl); + while (silc_hash_table_get(&htl, NULL, (void *)&channel)) { + silc_server_create_channel_key(server, channel, 0); + silc_server_send_channel_key(server, NULL, channel, + server->server_type == SILC_ROUTER ? + FALSE : !server->standalone); + } + silc_hash_table_free(servers); + return TRUE; } @@ -2546,9 +2579,9 @@ void silc_server_remove_from_channels(SilcServer server, server->stat.my_chanclients--; /* If there is no global users on the channel anymore mark the channel - as local channel. */ - if (server->server_type == SILC_SERVER && - !silc_server_channel_has_global(channel)) + as local channel. Do not check if the removed client is local client. */ + if (server->server_type == SILC_SERVER && channel->global_users && + chl->client->router && !silc_server_channel_has_global(channel)) channel->global_users = FALSE; /* If there is not at least one local user on the channel then we don't @@ -2663,9 +2696,9 @@ int silc_server_remove_from_one_channel(SilcServer server, server->stat.my_chanclients--; /* If there is no global users on the channel anymore mark the channel - as local channel. */ - if (server->server_type == SILC_SERVER && - !silc_server_channel_has_global(channel)) + as local channel. Do not check if the client is local client. */ + if (server->server_type == SILC_SERVER && channel->global_users && + chl->client->router && !silc_server_channel_has_global(channel)) channel->global_users = FALSE; /* If there is not at least one local user on the channel then we don't diff --git a/lib/silcutil/silchashtable.h b/lib/silcutil/silchashtable.h index 9578965b..fd73e7d0 100644 --- a/lib/silcutil/silchashtable.h +++ b/lib/silcutil/silchashtable.h @@ -264,7 +264,7 @@ void silc_hash_table_add(SilcHashTable ht, void *key, void *context); * DESCRIPTION * * Same as silc_hash_table_add but if the `key' already exists in the - * hash table the old key and the old context will be replace with the + * hash table the old key and the old context will be replaced with the * `key' and the `context. The destructor function will be called for the * replaced key and context. * @@ -442,7 +442,7 @@ void silc_hash_table_add_ext(SilcHashTable ht, void *key, void *context, * DESCRIPTION * * Same as silc_hash_table_add_ext but if the `key' already exists in the - * hash table the old key and the old context will be replace with the + * hash table the old key and the old context will be replaced with the * `key' and the `context. The destructor function will be called for the * replaced key and context. * -- 2.43.0