From 9f0a4806bb31cd830975adce3db124b5b3c6a573 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 12 Jul 2001 09:23:15 +0000 Subject: [PATCH] updates. --- CHANGES | 15 ++++ TODO | 5 ++ apps/silcd/command.c | 4 +- apps/silcd/packet_receive.c | 2 +- apps/silcd/server.c | 142 ++++++++++++++++++++++++++++-------- 5 files changed, 136 insertions(+), 32 deletions(-) diff --git a/CHANGES b/CHANGES index fe7056cd..47158a73 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,18 @@ +Thu Jul 12 10:18:40 EEST 2001 Pekka Riikonen + + * Do not cancel the protocol in silc_server_close_connection + it might cause recursion. Now cancelled in the function + silc_server_free_sock_user_data. Affected file silcd/server.c. + + * Fixed the silc_server_remove_clients_by_server to regenerate + the channel keys correctly finally. Added also new function + silc_server_remove_clients_channels to actually do it. + Affected file silcd/server.c. + + * Fixed the silc_server_new_channel to not crash by giving + wrong router to the new channel. Affected file is + silcd/packet_receive.c. + Wed Jul 11 18:31:57 EEST 2001 Pekka Riikonen * Added SilcClientParams structure to the lib/silcclient/silcapi.h diff --git a/TODO b/TODO index 4f205059..c6fce455 100644 --- a/TODO +++ b/TODO @@ -5,6 +5,11 @@ TODO/bugs in Irssi SILC client cipher, hash, hmac and pkcs configuration to the Irssi SILC's config file. + o Add local command to switch the channel's private key when channel has + several private keys. Currently sending channel messages with many + keys is not possible because changing the key is not possible by the + user. + o Add local commands to list the current server and client public keys that the user has. And a local command to dump the contents of the public key to the screen. Something like LISTKEYS, SHOWKEY... diff --git a/apps/silcd/command.c b/apps/silcd/command.c index bdb236d3..14a6550f 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -4798,11 +4798,11 @@ SILC_SERVER_CMD_FUNC(users) return; } - /* We are router and we will check the global list as well. */ + /* Check the global list as well. */ if (id) channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL); else - channel = silc_idlist_find_channel_by_name(server->local_list, + channel = silc_idlist_find_channel_by_name(server->global_list, channel_name, NULL); if (!channel) { /* Channel really does not exist */ diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index be1ee659..83a9348f 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -1872,7 +1872,7 @@ void silc_server_new_channel(SilcServer server, sock->hostname)); silc_idlist_add_channel(server->global_list, strdup(channel_name), - 0, channel_id, server->router->connection, + 0, channel_id, sock->user_data, NULL, NULL); server->stat.channels++; diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 38f645e4..91ee0291 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -2114,14 +2114,6 @@ void silc_server_close_connection(SilcServer server, sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" : "Router"), sock->sock)); - /* If any protocol is active cancel its execution */ - if (sock->protocol) { - silc_protocol_cancel(sock->protocol, server->timeout_queue); - sock->protocol->state = SILC_PROTOCOL_STATE_ERROR; - silc_protocol_execute_final(sock->protocol, server->timeout_queue); - sock->protocol = NULL; - } - /* We won't listen for this connection anymore */ silc_schedule_unset_listen_fd(server->schedule, sock->sock); @@ -2300,9 +2292,118 @@ void silc_server_free_sock_user_data(SilcServer server, } } + /* If any protocol is active cancel its execution */ + if (sock->protocol) { + silc_protocol_cancel(sock->protocol, server->timeout_queue); + sock->protocol->state = SILC_PROTOCOL_STATE_ERROR; + silc_protocol_execute_final(sock->protocol, server->timeout_queue); + sock->protocol = NULL; + } + sock->user_data = NULL; } +/* Removes the client from channels and possibly removes the channels + as well. After removing those channels that exist, their channel + keys are regnerated. This is called only by the function + silc_server_remove_clients_by_server. */ + +static void silc_server_remove_clients_channels(SilcServer server, + SilcSocketConnection sock, + SilcClientEntry client, + SilcHashTable channels) +{ + SilcChannelEntry channel; + SilcChannelClientEntry chl; + SilcHashTableList htl; + SilcBuffer clidp; + + SILC_LOG_DEBUG(("Start")); + + if (!client || !client->id) + return; + + clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT); + + /* Remove the client from all channels. The client is removed from + the channels' user list. */ + silc_hash_table_list(client->channels, &htl); + 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 */ + 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_task_unregister_by_context(server->timeout_queue, channel->rekey); + + if (!silc_idlist_del_channel(server->local_list, channel)) + silc_idlist_del_channel(server->global_list, channel); + server->stat.my_channels--; + continue; + } + + /* Remove client from channel's client list */ + silc_hash_table_del(channel->user_list, chl->client); + silc_free(chl); + server->stat.my_chanclients--; + + /* If there is no global users on the channel anymore mark the 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 + need the channel entry anymore, we can remove it safely. */ + if (server->server_type == SILC_SERVER && + !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_task_unregister_by_context(server->timeout_queue, channel->rekey); + + if (channel->founder_key) { + /* The founder auth data exists, do not remove the channel entry */ + SilcChannelClientEntry chl2; + SilcHashTableList htl2; + + channel->id = NULL; + + 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); + silc_free(chl2); + } + continue; + } + + /* Remove the channel entry */ + if (!silc_idlist_del_channel(server->local_list, channel)) + silc_idlist_del_channel(server->global_list, channel); + server->stat.my_channels--; + continue; + } + + /* Add the channel to the the channels list to regenerate the + channel key */ + if (!silc_hash_table_find(channels, channel, NULL, NULL)) + silc_hash_table_add(channels, channel, channel); + } + + silc_buffer_free(clidp); +} + /* This function is used to remove all client entries by the server `entry'. This is called when the connection is lost to the server. In this case we must invalidate all the client entries owned by the server `entry'. @@ -2321,10 +2422,9 @@ 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 channels; - SilcChannelClientEntry chl; - SilcChannelEntry channel; SilcHashTableList htl; + SilcChannelEntry channel; + SilcHashTable channels; int i; SILC_LOG_DEBUG(("Start")); @@ -2389,16 +2489,8 @@ 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)) { - if (silc_hash_table_find(channels, chl->channel, NULL, NULL)) - continue; - silc_hash_table_add(channels, chl->channel, chl->channel); - } - /* Remove the client entry */ - silc_server_remove_from_channels(server, NULL, client, FALSE, - NULL, FALSE); + silc_server_remove_clients_channels(server, NULL, client, channels); silc_idlist_del_client(server->local_list, client); if (!silc_idcache_list_next(list, &id_cache)) @@ -2449,16 +2541,8 @@ 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)) { - if (silc_hash_table_find(channels, chl->channel, NULL, NULL)) - continue; - silc_hash_table_add(channels, chl->channel, chl->channel); - } - /* Remove the client entry */ - silc_server_remove_from_channels(server, NULL, client, FALSE, - NULL, FALSE); + silc_server_remove_clients_channels(server, NULL, client, channels); silc_idlist_del_client(server->global_list, client); if (!silc_idcache_list_next(list, &id_cache)) -- 2.24.0