From 43389514dcd9843a9b642a11cf265ec5afd3b420 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Wed, 7 Nov 2001 19:09:59 +0000 Subject: [PATCH] updates. --- CHANGES | 7 +++++++ apps/silcd/command.c | 50 +++++++++++++++++++++++++++++++------------- apps/silcd/server.c | 7 +++++-- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index 7ecfb7a1..1c229019 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,10 @@ +Wed Nov 7 20:43:03 EET 2001 Pekka Riikonen + + * Fixed CMODE command when new channel key was created. If + the creation failed the old key was removed. Next time giving + same command would crash the server since the old key was + freed already. Affected file silcd/command.c. + Wed Nov 7 17:15:07 EET 2001 Pekka Riikonen * Added silc_log_set_debug_string function to set a regex diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 5c42734f..31fe32bd 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -3842,6 +3842,7 @@ SILC_SERVER_CMD_FUNC(cmode) if (mode_mask & SILC_CHANNEL_MODE_CIPHER) { if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) { /* Cipher to use protect the traffic */ + SilcCipher newkey, oldkey; /* Get cipher */ cipher = silc_argument_get_arg_type(cmd->args, 5, NULL); @@ -3852,17 +3853,25 @@ SILC_SERVER_CMD_FUNC(cmode) } /* Delete old cipher and allocate the new one */ - silc_cipher_free(channel->channel_key); - if (!silc_cipher_alloc(cipher, &channel->channel_key)) { + if (!silc_cipher_alloc(cipher, &newkey)) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, SILC_STATUS_ERR_UNKNOWN_ALGORITHM); goto out; } + oldkey = channel->channel_key; + channel->channel_key = newkey; + /* Re-generate channel key */ - if (!silc_server_create_channel_key(server, channel, 0)) + if (!silc_server_create_channel_key(server, channel, 0)) { + /* We don't have new key, revert to old one */ + channel->channel_key = oldkey; goto out; - + } + + /* Remove old channel key for good */ + silc_cipher_free(oldkey); + /* Send the channel key. This sends it to our local clients and if we are normal server to our router as well. */ silc_server_send_channel_key(server, NULL, channel, @@ -3873,21 +3882,29 @@ SILC_SERVER_CMD_FUNC(cmode) if (channel->mode & SILC_CHANNEL_MODE_CIPHER) { /* Cipher mode is unset. Remove the cipher and revert back to default cipher */ + SilcCipher newkey, oldkey; cipher = channel->cipher; /* Delete old cipher and allocate default one */ - silc_cipher_free(channel->channel_key); - if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, - &channel->channel_key)) { + if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, SILC_STATUS_ERR_UNKNOWN_ALGORITHM); goto out; } + oldkey = channel->channel_key; + channel->channel_key = newkey; + /* Re-generate channel key */ - if (!silc_server_create_channel_key(server, channel, 0)) + if (!silc_server_create_channel_key(server, channel, 0)) { + /* We don't have new key, revert to old one */ + channel->channel_key = oldkey; goto out; + } + /* Remove old channel key for good */ + silc_cipher_free(oldkey); + /* Send the channel key. This sends it to our local clients and if we are normal server to our router as well. */ silc_server_send_channel_key(server, NULL, channel, @@ -3900,6 +3917,7 @@ SILC_SERVER_CMD_FUNC(cmode) if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) { /* HMAC to use protect the traffic */ unsigned char hash[32]; + SilcHmac newhmac; /* Get hmac */ hmac = silc_argument_get_arg_type(cmd->args, 6, NULL); @@ -3910,18 +3928,19 @@ SILC_SERVER_CMD_FUNC(cmode) } /* Delete old hmac and allocate the new one */ - silc_hmac_free(channel->hmac); - if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) { + if (!silc_hmac_alloc(hmac, NULL, &newhmac)) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, SILC_STATUS_ERR_UNKNOWN_ALGORITHM); goto out; } + silc_hmac_free(channel->hmac); + channel->hmac = newhmac; + /* Set the HMAC key out of current channel key. The client must do this locally. */ silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, - channel->key_len / 8, - hash); + channel->key_len / 8, hash); silc_hmac_set_key(channel->hmac, hash, silc_hash_len(silc_hmac_get_hash(channel->hmac))); memset(hash, 0, sizeof(hash)); @@ -3930,18 +3949,21 @@ SILC_SERVER_CMD_FUNC(cmode) if (channel->mode & SILC_CHANNEL_MODE_HMAC) { /* Hmac mode is unset. Remove the hmac and revert back to default hmac */ + SilcHmac newhmac; unsigned char hash[32]; hmac = channel->hmac_name; /* Delete old hmac and allocate default one */ silc_hmac_free(channel->hmac); - if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, - &channel->hmac)) { + if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, SILC_STATUS_ERR_UNKNOWN_ALGORITHM); goto out; } + silc_hmac_free(channel->hmac); + channel->hmac = newhmac; + /* Set the HMAC key out of current channel key. The client must do this locally. */ silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, diff --git a/apps/silcd/server.c b/apps/silcd/server.c index d7fc856c..46900b2f 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -2877,8 +2877,10 @@ bool silc_server_create_channel_key(SilcServer server, } if (!channel->channel_key) - if (!silc_cipher_alloc(SILC_DEFAULT_CIPHER, &channel->channel_key)) + if (!silc_cipher_alloc(SILC_DEFAULT_CIPHER, &channel->channel_key)) { + channel->channel_key = NULL; return FALSE; + } if (key_len) len = key_len; @@ -2999,6 +3001,7 @@ SilcChannelEntry silc_server_save_channel_key(SilcServer server, /* Create new cipher */ if (!silc_cipher_alloc(cipher, &channel->channel_key)) { + channel->channel_key = NULL; channel = NULL; goto out; } @@ -3374,7 +3377,7 @@ void silc_server_announce_get_channels(SilcServer server, (*channel_ids)[i] = NULL; silc_server_announce_get_channel_users(server, channel, channel_users, - channel_users_modes[i]); + &(*channel_users_modes)[i]); (*channel_ids)[i] = channel->id; i++; -- 2.24.0