+Sat Sep 1 00:29:33 EEST 2001 Pekka Riikonen <priikone@silcnet.org>
+
+ * Changed the silc_id_create_client_id to be collision
+ resistant. It is now assured that there cannot be created
+ two same client ID's. I suspect that some weird bugs in
+ the server were actually caused by duplicate Client IDs.
+ Affected file silcd/serverid.[ch]. A router receiving
+ new ID now also assures and informs the sending server
+ if the ID caused collision.
+
+ * Changed the silc_id_create_channel_id to also assure that
+ there are no collisions.
+
Wed Aug 29 17:55:01 EEST 2001 Pekka Riikonen <priikone@silcnet.org>
* Statement about ignoring the Mutual Authentication flag when
SilcClientID *new_id;
char *nick;
uint16 ident = silc_command_get_ident(cmd->payload);
+ int nickfail = 0;
if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
goto out;
}
if (strlen(nick) > 128)
- nick[127] = '\0';
+ nick[128] = '\0';
/* Create new Client ID */
- silc_id_create_client_id(cmd->server->id, cmd->server->rng,
- cmd->server->md5hash, nick,
- &new_id);
+ while (!silc_id_create_client_id(cmd->server, cmd->server->id,
+ cmd->server->rng,
+ cmd->server->md5hash, nick,
+ &new_id)) {
+ nickfail++;
+ snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
+ }
/* Send notify about nickname change to our router. We send the new
ID and ask to replace it with the old one. If we are router the
uint32 id_len;
int ret;
char *hostname, *nickname;
+ int nickfail = 0;
SILC_LOG_DEBUG(("Creating new client"));
}
/* Create Client ID */
- silc_id_create_client_id(server->id, server->rng, server->md5hash,
- nickname, &client_id);
+ while (!silc_id_create_client_id(server, server->id, server->rng,
+ server->md5hash, nickname, &client_id)) {
+ nickfail++;
+ snprintf(&nickname[strlen(nickname) - 1], 1, "%d", nickfail);
+ }
/* Update client entry */
idata->registered = TRUE;
id, router, NULL);
if (!entry) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
+
+ /* Inform the sender that the ID is not usable */
+ silc_server_send_notify_signoff(server, sock, FALSE, id, NULL);
goto out;
}
entry->nickname = NULL;
channel_name = strdup(channel_name);
/* Create the channel */
- silc_id_create_channel_id(router_id, server->rng, &channel_id);
+ if (!silc_id_create_channel_id(server, router_id, server->rng,
+ &channel_id)) {
+ silc_free(channel_name);
+ silc_cipher_free(key);
+ silc_hmac_free(newhmac);
+ return NULL;
+ }
entry = silc_idlist_add_channel(server->local_list, channel_name,
SILC_CHANNEL_MODE_NONE, channel_id,
NULL, key, newhmac);
/* $Id$ */
#include "serverincludes.h"
+#include "server_internal.h"
/* Creates a Server ID. Newly created Server ID is returned to the
new_id argument. */
SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_SERVER)));
}
-/* Creates Client ID */
+/* Creates Client ID. This assures that there are no collisions in the
+ created Client IDs. If the collision would occur (meaning that there
+ are 2^8 occurences of the `nickname' this will return FALSE, and the
+ caller must recall the function with different nickname. If this returns
+ TRUE the new ID was created successfully. */
-void silc_id_create_client_id(SilcServerID *server_id, SilcRng rng,
+bool silc_id_create_client_id(SilcServer server,
+ SilcServerID *server_id, SilcRng rng,
SilcHash md5hash, char *nickname,
SilcClientID **new_id)
{
unsigned char hash[16];
+ bool finding = FALSE;
SILC_LOG_DEBUG(("Creating new Client ID"));
(*new_id)->rnd = silc_rng_get_byte(rng);
memcpy((*new_id)->hash, hash, CLIENTID_HASH_LEN);
+ /* Assure that the ID does not exist already */
+ while (1) {
+ if (!silc_idlist_find_client_by_id(server->local_list,
+ *new_id, FALSE, NULL))
+ if (!silc_idlist_find_client_by_id(server->global_list,
+ *new_id, FALSE, NULL))
+ break;
+
+ /* The ID exists, start increasing the rnd from 0 until we find a
+ ID that does not exist. If we wrap and it still exists then we
+ will return FALSE and the caller must send some other nickname
+ since this cannot be used anymore. */
+ (*new_id)->rnd++;
+
+ if (finding && (*new_id)->rnd == 0)
+ return FALSE;
+
+ if (!finding) {
+ (*new_id)->rnd = 0;
+ finding = TRUE;
+ }
+ }
+
SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_CLIENT)));
+
+ return TRUE;
}
/* Creates Channel ID */
-void silc_id_create_channel_id(SilcServerID *router_id, SilcRng rng,
+bool silc_id_create_channel_id(SilcServer server,
+ SilcServerID *router_id, SilcRng rng,
SilcChannelID **new_id)
{
+ bool finding = TRUE;
+
SILC_LOG_DEBUG(("Creating new Channel ID"));
*new_id = silc_calloc(1, sizeof(**new_id));
(*new_id)->port = router_id->port;
(*new_id)->rnd = silc_rng_get_rn16(rng);
+ /* Assure that the ID does not exist already */
+ while (1) {
+ if (!silc_idlist_find_channel_by_id(server->local_list,
+ *new_id, NULL))
+ if (!silc_idlist_find_channel_by_id(server->global_list,
+ *new_id, NULL))
+ break;
+
+ (*new_id)->rnd++;
+
+ if (finding && (*new_id)->rnd == 0)
+ return FALSE;
+
+ if (!finding) {
+ (*new_id)->rnd = 0;
+ finding = TRUE;
+ }
+ }
+
SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_CHANNEL)));
+
+ return TRUE;
}
/* Prototypes */
void silc_id_create_server_id(int sock, SilcRng rng, SilcServerID **new_id);
-void silc_id_create_client_id(SilcServerID *server_id, SilcRng rng,
+bool silc_id_create_client_id(SilcServer server,
+ SilcServerID *server_id, SilcRng rng,
SilcHash md5hash, char *nickname,
SilcClientID **new_id);
-void silc_id_create_channel_id(SilcServerID *router_id, SilcRng rng,
+bool silc_id_create_channel_id(SilcServer server,
+ SilcServerID *router_id, SilcRng rng,
SilcChannelID **new_id);
#endif
/* SILC Server includes */
#include "idlist.h"
-#include "serverid.h"
#include "serverconfig.h"
#include "server.h"
+#include "serverid.h"
#include "packet_send.h"
#include "packet_receive.h"
#include "route.h"