From aa6aa20dc6bb073c88b3a55930b23357af51402d Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Wed, 30 Mar 2005 12:24:53 +0000 Subject: [PATCH] Changed identifier string handling to save the original version to context's and normalized version to cache. --- apps/silcd/command.c | 91 ++++++++++---------- apps/silcd/command_reply.c | 161 ++++++++++++++---------------------- apps/silcd/idlist.c | 127 +++++++++++++++++++--------- apps/silcd/idlist.h | 14 +++- apps/silcd/packet_receive.c | 150 +++++++++++++++++++-------------- apps/silcd/server.c | 33 ++++---- apps/silcd/server_query.c | 62 ++++++++++---- apps/silcd/server_util.c | 9 +- apps/silcd/serverid.c | 3 +- 9 files changed, 361 insertions(+), 289 deletions(-) diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 34010040..d0cf76a3 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -626,9 +626,8 @@ SILC_SERVER_CMD_FUNC(nick) SilcBuffer packet, nidp, oidp = NULL; SilcClientID *new_id; SilcUInt32 nick_len; - unsigned char *nick = NULL; + unsigned char *nick, *nickc = NULL; SilcUInt16 ident = silc_command_get_ident(cmd->payload); - int nickfail = 0; if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client) goto out; @@ -649,46 +648,31 @@ SILC_SERVER_CMD_FUNC(nick) nick_len = 128; } - /* Check for valid nickname string */ - nick = silc_identifier_check(nick, nick_len, SILC_STRING_UTF8, 128, - &nick_len); - if (!nick) { + /* Check for valid nickname string. This is cached, original is saved + in the client context. */ + nickc = silc_identifier_check(nick, nick_len, SILC_STRING_UTF8, 128, NULL); + if (!nickc) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK, SILC_STATUS_ERR_BAD_NICKNAME, 0); - silc_free(nick); goto out; } /* Check for same nickname */ if (!memcmp(client->nickname, nick, nick_len)) { nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT); - silc_free(nick); - nick = client->nickname; + silc_free(nickc); goto send_reply; } /* Create new Client ID */ - while (!silc_id_create_client_id(cmd->server, cmd->server->id, - cmd->server->rng, - cmd->server->md5hash, nick, nick_len, - &new_id)) { - nickfail++; - if (nickfail > 9) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK, - SILC_STATUS_ERR_BAD_NICKNAME, 0); - goto out; - } - if (nickfail < 2) { - nick = silc_realloc(nick, sizeof(*nick) * (nick_len + 2)); - if (!nick) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK, - SILC_STATUS_ERR_BAD_NICKNAME, 0); - goto out; - } - nick_len += 2; - nick[nick_len - 1] = '\0'; - } - snprintf(&nick[nick_len - 2], 1, "%d", nickfail); + if (!silc_id_create_client_id(cmd->server, cmd->server->id, + cmd->server->rng, + cmd->server->md5hash, + nickc, strlen(nickc), &new_id)) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK, + SILC_STATUS_ERR_BAD_NICKNAME, 0); + silc_free(nickc); + goto out; } /* Send notify about nickname change to our router. We send the new @@ -715,7 +699,7 @@ SILC_SERVER_CMD_FUNC(nick) client->nickname = nick; /* Update client cache */ - silc_idcache_add(server->local_list->clients, client->nickname, + silc_idcache_add(server->local_list->clients, nickc, client->id, (void *)client, 0, NULL); nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT); @@ -1571,7 +1555,7 @@ SILC_SERVER_CMD_FUNC(info) /* Get server name */ dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL); if (dest_server) { - /* Check server name */ + /* Check server name. */ dest_server = silc_identifier_check(dest_server, strlen(dest_server), SILC_STRING_UTF8, 256, &tmp_len); if (!dest_server) { @@ -1615,7 +1599,7 @@ SILC_SERVER_CMD_FUNC(info) if ((!dest_server && !server_id && !entry) || (entry && entry == server->id_entry) || (dest_server && !cmd->pending && - !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) { + !memcmp(dest_server, server->server_name, strlen(dest_server)))) { /* Send our reply */ char info_string[256]; @@ -1693,11 +1677,15 @@ SILC_SERVER_CMD_FUNC(info) silc_free(server_id); if (!entry) { - if (dest_server) + if (dest_server) { + silc_free(dest_server); + dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL); silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO, SILC_STATUS_ERR_NO_SUCH_SERVER, 0, 2, dest_server, strlen(dest_server)); + dest_server = NULL; + } goto out; } @@ -2342,7 +2330,7 @@ SILC_SERVER_CMD_FUNC(join) SilcServer server = cmd->server; unsigned char *auth, *cauth; SilcUInt32 tmp_len, auth_len, cauth_len; - char *tmp, *channel_name = NULL, *cipher, *hmac; + char *tmp, *channel_name, *channel_namec = NULL, *cipher, *hmac; SilcChannelEntry channel; SilcUInt32 umode = 0; bool created = FALSE, create_key = TRUE; @@ -2364,11 +2352,13 @@ SILC_SERVER_CMD_FUNC(join) tmp[256] = '\0'; tmp_len = 256; } + channel_name = tmp; - /* Check for valid channel name */ - channel_name = silc_identifier_check(tmp, tmp_len, SILC_STRING_UTF8, 256, - &tmp_len); - if (!channel_name) { + /* Check for valid channel name. This is cached, the original is saved + in the channel context. */ + channel_namec = silc_identifier_check(tmp, tmp_len, SILC_STRING_UTF8, 256, + NULL); + if (!channel_namec) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, SILC_STATUS_ERR_BAD_CHANNEL, 0); goto out; @@ -2398,7 +2388,7 @@ SILC_SERVER_CMD_FUNC(join) /* See if the channel exists */ channel = silc_idlist_find_channel_by_name(server->local_list, - channel_name, NULL); + channel_namec, NULL); if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) { SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data; @@ -2478,7 +2468,7 @@ SILC_SERVER_CMD_FUNC(join) /* We are router and the channel does not seem exist so we will check our global list as well for the channel. */ channel = silc_idlist_find_channel_by_name(server->global_list, - channel_name, NULL); + channel_namec, NULL); if (!channel) { /* Channel really does not exist, create it */ channel = silc_server_create_new_channel(server, server->id, cipher, @@ -2514,7 +2504,7 @@ SILC_SERVER_CMD_FUNC(join) /* We are router and the channel does not seem exist so we will check our global list as well for the channel. */ channel = silc_idlist_find_channel_by_name(server->global_list, - channel_name, NULL); + channel_namec, NULL); if (!channel) { /* Channel really does not exist, create it */ channel = silc_server_create_new_channel(server, server->id, cipher, @@ -2708,10 +2698,13 @@ SILC_SERVER_CMD_FUNC(motd) } if (!entry) { + silc_free(dest_server); + dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL); silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD, SILC_STATUS_ERR_NO_SUCH_SERVER, 0, 2, dest_server, strlen(dest_server)); + dest_server = NULL; goto out; } @@ -4748,7 +4741,7 @@ SILC_SERVER_CMD_FUNC(users) unsigned char lc[4]; SilcUInt32 list_count = 0; SilcUInt16 ident = silc_command_get_ident(cmd->payload); - char *channel_name = NULL; + char *channel_name, *channel_namec = NULL; SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2); @@ -4766,9 +4759,9 @@ SILC_SERVER_CMD_FUNC(users) /* Check channel name */ if (channel_name) { - channel_name = silc_identifier_check(channel_name, strlen(channel_name), - SILC_STRING_UTF8, 256, NULL); - if (!channel_name) { + channel_namec = silc_identifier_check(channel_name, strlen(channel_name), + SILC_STRING_UTF8, 256, NULL); + if (!channel_namec) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS, SILC_STATUS_ERR_BAD_CHANNEL, 0); goto out; @@ -4793,7 +4786,7 @@ SILC_SERVER_CMD_FUNC(users) channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL); else channel = silc_idlist_find_channel_by_name(server->local_list, - channel_name, NULL); + channel_namec, NULL); if (!channel || (!server->standalone && (channel->disabled || !channel->users_resolved))) { @@ -4826,7 +4819,7 @@ SILC_SERVER_CMD_FUNC(users) channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL); else channel = silc_idlist_find_channel_by_name(server->global_list, - channel_name, NULL); + channel_namec, NULL); if (!channel) { /* Channel really does not exist */ if (id) @@ -4894,7 +4887,7 @@ SILC_SERVER_CMD_FUNC(users) silc_free(id); out: - silc_free(channel_name); + silc_free(channel_namec); silc_server_command_free(cmd); } diff --git a/apps/silcd/command_reply.c b/apps/silcd/command_reply.c index 99f45955..1250eaa5 100644 --- a/apps/silcd/command_reply.c +++ b/apps/silcd/command_reply.c @@ -197,14 +197,6 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd) fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen); - /* Check for valid username */ - username = silc_identifier_check(username, strlen(username), - SILC_STRING_UTF8, 128, NULL); - if (!username) { - SILC_LOG_ERROR(("Malformed username received in WHOIS reply")); - return FALSE; - } - /* Check if we have this client cached already. */ client = silc_idlist_find_client_by_id(server->local_list, client_id, @@ -218,35 +210,21 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd) if (!client) { /* If router did not find such Client ID in its lists then this must be bogus client or some router in the net is buggy. */ - if (server->server_type != SILC_SERVER) { - silc_free(username); + if (server->server_type != SILC_SERVER) return FALSE; - } /* Take hostname out of nick string if it includes it. */ silc_parse_userfqdn(nickname, &nick, &servername); - /* Check nickname */ - nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8, - 128, NULL); - if (!nickname) { - SILC_LOG_ERROR(("Malformed nickname received in WHOIS reply")); - silc_free(username); - return FALSE; - } - silc_free(nick); - nick = nickname; - /* We don't have that client anywhere, add it. The client is added to global list since server didn't have it in the lists so it must be - global. */ + global. This will check for valid nickname and username strings. */ client = silc_idlist_add_client(server->global_list, nick, username, strdup(realname), client_id, cmd->sock->user_data, NULL, 0); if (!client) { SILC_LOG_ERROR(("Could not add new client to the ID Cache")); silc_free(nick); - silc_free(username); return FALSE; } @@ -268,11 +246,16 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd) 128, NULL); if (!nickname) { SILC_LOG_ERROR(("Malformed nickname received in WHOIS reply")); - silc_free(username); return FALSE; } - silc_free(nick); - nick = nickname; + + /* Check username */ + username = silc_identifier_check(username, strlen(username), + SILC_STRING_UTF8, 128, NULL); + if (!username) { + SILC_LOG_ERROR(("Malformed username received in WHOIS reply")); + return FALSE; + } /* Remove the old cache entry */ silc_idcache_del_by_context(global ? server->global_list->clients : @@ -293,7 +276,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd) /* Create new cache entry */ silc_idcache_add(global ? server->global_list->clients : - server->local_list->clients, nick, client->id, + server->local_list->clients, nickname, client->id, client, 0, NULL); silc_free(client_id); } @@ -397,7 +380,6 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd) } } - silc_free(username); return TRUE; } @@ -489,14 +471,6 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd) if (!client_id) return FALSE; - /* Check for valid username */ - username = silc_identifier_check(username, strlen(username), - SILC_STRING_UTF8, 128, NULL); - if (!username) { - SILC_LOG_ERROR(("Malformed username received in WHOWAS reply")); - return FALSE; - } - /* Check if we have this client cached already. */ client = silc_idlist_find_client_by_id(server->local_list, client_id, @@ -510,25 +484,12 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd) if (!client) { /* If router did not find such Client ID in its lists then this must be bogus client or some router in the net is buggy. */ - if (server->server_type != SILC_SERVER) { - silc_free(username); + if (server->server_type != SILC_SERVER) return FALSE; - } /* Take hostname out of nick string if it includes it. */ silc_parse_userfqdn(nickname, &nick, &servername); - /* Check nickname */ - nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8, - 128, NULL); - if (!nickname) { - SILC_LOG_ERROR(("Malformed nickname received in WHOWAS reply")); - silc_free(username); - return FALSE; - } - silc_free(nick); - nick = nickname; - /* We don't have that client anywhere, add it. The client is added to global list since server didn't have it in the lists so it must be global. */ @@ -540,7 +501,6 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd) if (!client) { SILC_LOG_ERROR(("Could not add new client to the ID Cache")); silc_free(nick); - silc_free(username); return FALSE; } @@ -559,11 +519,16 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd) 128, NULL); if (!nickname) { SILC_LOG_ERROR(("Malformed nickname received in WHOWAS reply")); - silc_free(username); return FALSE; } - silc_free(nick); - nick = nickname; + + /* Check username */ + username = silc_identifier_check(username, strlen(username), + SILC_STRING_UTF8, 128, NULL); + if (!username) { + SILC_LOG_ERROR(("Malformed username received in WHOWAS reply")); + return FALSE; + } silc_free(client->nickname); silc_free(client->username); @@ -579,7 +544,7 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd) silc_idcache_del_by_context(global ? server->global_list->clients : server->local_list->clients, client); silc_idcache_add(global ? server->global_list->clients : - server->local_list->clients, nick, client->id, + server->local_list->clients, nickname, client->id, client, 0, NULL); } @@ -595,7 +560,6 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd) } silc_free(client_id); - silc_free(username); return TRUE; } @@ -686,25 +650,13 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd) goto error; /* Take nickname */ - if (name) { + if (name) silc_parse_userfqdn(name, &nick, NULL); - /* Check nickname */ - name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8, - 128, NULL); - if (!name) { - SILC_LOG_ERROR(("Malformed nickname received in IDENTIFY reply")); - return FALSE; - } - silc_free(nick); - nick = name; - } - /* We don't have that client anywhere, add it. The client is added to global list since server didn't have it in the lists so it must be global. */ - client = silc_idlist_add_client(server->global_list, nick, - info ? strdup(info) : NULL, NULL, + client = silc_idlist_add_client(server->global_list, nick, info, NULL, client_id, cmd->sock->user_data, NULL, time(NULL) + 300); if (!client) { @@ -712,6 +664,7 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd) silc_free(nick); goto error; } + client->data.status |= SILC_IDLIST_STATUS_REGISTERED; client->data.status |= SILC_IDLIST_STATUS_RESOLVED; client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING; @@ -731,8 +684,6 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd) SILC_LOG_ERROR(("Malformed nickname received in IDENTIFY reply")); return FALSE; } - silc_free(nick); - nick = name; /* Remove the old cache entry */ silc_idcache_del_by_context(global ? server->global_list->clients : @@ -740,6 +691,11 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd) silc_free(client->nickname); client->nickname = nick; + + /* Add new cache entry */ + silc_idcache_add(global ? server->global_list->clients : + server->local_list->clients, name, client->id, + client, expire, NULL); } if (info) { @@ -750,13 +706,6 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd) client->data.status |= SILC_IDLIST_STATUS_RESOLVED; client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING; - if (name) { - /* Add new cache entry */ - silc_idcache_add(global ? server->global_list->clients : - server->local_list->clients, nick, client->id, - client, expire, NULL); - } - /* If client is global and is not on any channel then add that we'll expire the entry after a while. */ if (global && server->server_type == SILC_SERVER) { @@ -823,16 +772,24 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd) SILC_LOG_DEBUG(("Received channel information")); + /* Check channel name */ + info = silc_identifier_check(name, strlen(name), SILC_STRING_UTF8, + 256, NULL); + if (!info) + goto error; + channel = silc_idlist_find_channel_by_name(server->local_list, - name, NULL); + info, NULL); if (!channel) channel = silc_idlist_find_channel_by_name(server->global_list, - name, NULL); + info, NULL); if (!channel) { /* If router did not find such Channel ID in its lists then this must be bogus channel or some router in the net is buggy. */ - if (server->server_type != SILC_SERVER) + if (server->server_type != SILC_SERVER) { + silc_free(info); goto error; + } /* We don't have that channel anywhere, add it. */ channel = silc_idlist_add_channel(server->global_list, strdup(name), @@ -840,8 +797,10 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd) server->router, NULL, NULL, 0); if (!channel) { silc_free(channel_id); + silc_free(info); goto error; } + silc_free(info); channel_id = NULL; } @@ -900,7 +859,7 @@ SILC_SERVER_CMD_REPLY_FUNC(info) SilcServerEntry entry; SilcServerID *server_id; SilcUInt32 tmp_len; - unsigned char *tmp, *name = NULL; + unsigned char *tmp, *name; COMMAND_CHECK_STATUS; @@ -917,12 +876,6 @@ SILC_SERVER_CMD_REPLY_FUNC(info) if (!name) goto out; - /* Check server name */ - name = silc_identifier_check(name, tmp_len, SILC_STRING_UTF8, - 256, NULL); - if (!name) - goto out; - entry = silc_idlist_find_server_by_id(server->local_list, server_id, FALSE, NULL); if (!entry) { @@ -931,12 +884,11 @@ SILC_SERVER_CMD_REPLY_FUNC(info) if (!entry) { /* Add the server to global list */ server_id = silc_id_dup(server_id, SILC_ID_SERVER); - entry = silc_idlist_add_server(server->global_list, name, 0, + entry = silc_idlist_add_server(server->global_list, strdup(name), 0, server_id, cmd->sock->user_data, cmd->sock); if (!entry) { silc_free(server_id); - silc_free(name); goto out; } entry->data.status |= SILC_IDLIST_STATUS_REGISTERED; @@ -950,8 +902,6 @@ SILC_SERVER_CMD_REPLY_FUNC(info) entry->server_info = tmp ? strdup(tmp) : NULL; - silc_free(name); - out: SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO); err: @@ -1045,7 +995,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join) SilcHmac hmac = NULL; SilcUInt32 id_len, len, list_count; unsigned char *id_string; - char *channel_name, *tmp; + char *channel_name, *channel_namec = NULL, *tmp; SilcUInt32 mode, created; SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL; SilcPublicKey founder_key = NULL; @@ -1134,8 +1084,12 @@ SILC_SERVER_CMD_REPLY_FUNC(join) silc_pkcs_public_key_payload_decode(tmp, len, &founder_key); /* See whether we already have the channel. */ + channel_namec = silc_identifier_check(channel_name, strlen(channel_name), + SILC_STRING_UTF8, 256, NULL); + if (!channel_namec) + goto out; entry = silc_idlist_find_channel_by_name(server->local_list, - channel_name, &cache); + channel_namec, &cache); if (!entry) { /* Add new channel */ @@ -1146,7 +1100,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join) /* If the channel is found from global list we must move it to the local list. */ entry = silc_idlist_find_channel_by_name(server->global_list, - channel_name, &cache); + channel_namec, &cache); if (entry) silc_idlist_del_channel(server->global_list, entry); @@ -1281,6 +1235,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join) out: SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN); err: + silc_free(channel_namec); if (hmac) silc_hmac_free(hmac); silc_free(client_id); @@ -1521,7 +1476,7 @@ SILC_SERVER_CMD_REPLY_FUNC(list) SilcChannelEntry channel; SilcIDCacheEntry cache; SilcUInt32 len; - unsigned char *tmp, *name, *topic; + unsigned char *tmp, *name, *namec = NULL, *topic; SilcUInt32 usercount = 0; bool global_list = FALSE; @@ -1538,12 +1493,17 @@ SILC_SERVER_CMD_REPLY_FUNC(list) if (tmp) SILC_GET32_MSB(usercount, tmp); + namec = silc_identifier_check(name, strlen(name), SILC_STRING_UTF8, + 256, NULL); + if (!namec) + goto out; + /* Add the channel entry if we do not have it already */ channel = silc_idlist_find_channel_by_name(server->local_list, - name, &cache); + namec, &cache); if (!channel) { channel = silc_idlist_find_channel_by_name(server->global_list, - name, &cache); + namec, &cache); global_list = TRUE; } if (!channel) { @@ -1587,6 +1547,7 @@ SILC_SERVER_CMD_REPLY_FUNC(list) SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST); silc_free(channel_id); err: + silc_free(namec); silc_server_command_reply_free(cmd); } diff --git a/apps/silcd/idlist.c b/apps/silcd/idlist.c index 91ac9cf2..e3f3df8a 100644 --- a/apps/silcd/idlist.c +++ b/apps/silcd/idlist.c @@ -119,9 +119,18 @@ silc_idlist_add_server(SilcIDList id_list, void *connection) { SilcServerEntry server; + char *server_namec = NULL; SILC_LOG_DEBUG(("Adding new server entry")); + /* Normalize name. This is cached, original is in server context. */ + if (server_name) { + server_namec = silc_identifier_check(server_name, strlen(server_name), + SILC_STRING_UTF8, 256, NULL); + if (!server_namec) + return NULL; + } + server = silc_calloc(1, sizeof(*server)); server->server_name = server_name; server->server_type = server_type; @@ -129,9 +138,10 @@ silc_idlist_add_server(SilcIDList id_list, server->router = router; server->connection = connection; - if (!silc_idcache_add(id_list->servers, server->server_name, + if (!silc_idcache_add(id_list->servers, server_namec, (void *)server->id, (void *)server, 0, NULL)) { silc_free(server); + silc_free(server_namec); return NULL; } @@ -171,7 +181,7 @@ silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id, return server; } -/* Find server by name */ +/* Find server by name. The 'name' must be normalized already. */ SilcServerEntry silc_idlist_find_server_by_name(SilcIDList id_list, char *name, @@ -259,6 +269,7 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id, { SilcIDCacheEntry id_cache = NULL; SilcServerEntry server; + char *name; if (!old_id || !new_id) return NULL; @@ -270,6 +281,7 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id, return NULL; server = (SilcServerEntry)id_cache->context; + name = strdup(id_cache->name); /* Remove the old entry and add a new one */ @@ -278,8 +290,7 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id, silc_free(server->id); server->id = new_id; - silc_idcache_add(id_list->servers, server->server_name, server->id, - server, 0, NULL); + silc_idcache_add(id_list->servers, name, server->id, server, 0, NULL); SILC_LOG_DEBUG(("Found")); @@ -337,12 +348,29 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, int expire) { SilcClientEntry client; + char *nicknamec = NULL, *usernamec = NULL; SILC_LOG_DEBUG(("Adding new client entry")); + /* Normalize name. This is cached, original is in client context. */ + if (nickname) { + nicknamec = silc_identifier_check(nickname, strlen(nickname), + SILC_STRING_UTF8, 128, NULL); + if (!nicknamec) + return NULL; + } + + /* Normalize username. */ + if (username) { + usernamec = silc_identifier_check(username, strlen(username), + SILC_STRING_UTF8, 128, NULL); + if (!usernamec) + return NULL; + } + client = silc_calloc(1, sizeof(*client)); client->nickname = nickname; - client->username = username; + client->username = usernamec; client->userinfo = userinfo; client->id = id; client->router = router; @@ -350,10 +378,12 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, client->channels = silc_hash_table_alloc(3, silc_hash_ptr, NULL, NULL, NULL, NULL, NULL, TRUE); - if (!silc_idcache_add(id_list->clients, nickname, (void *)client->id, + if (!silc_idcache_add(id_list->clients, nicknamec, (void *)client->id, (void *)client, expire, NULL)) { silc_hash_table_free(client->channels); silc_free(client); + silc_free(nicknamec); + silc_free(usernamec); return NULL; } @@ -368,7 +398,7 @@ int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry) SILC_LOG_DEBUG(("Start")); if (entry) { - /* Remove from cache */ + /* Remove from cache. Destructor callback deletes stuff. */ if (!silc_idcache_del_by_context(id_list->clients, entry)) { SILC_LOG_DEBUG(("Unknown client, did not delete")); return FALSE; @@ -376,7 +406,6 @@ int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry) assert(!silc_hash_table_count(entry->channels)); - /* Free data */ silc_free(entry->nickname); silc_free(entry->servername); silc_free(entry->username); @@ -394,8 +423,32 @@ int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry) return FALSE; } +/* ID Cache destructor */ + +void silc_idlist_client_destructor(SilcIDCache cache, + SilcIDCacheEntry entry) +{ + SilcClientEntry client; + + client = (SilcClientEntry)entry->context; + if (client) { + assert(!silc_hash_table_count(client->channels)); + silc_free(client->nickname); + silc_free(client->servername); + silc_free(client->username); + silc_free(client->userinfo); + silc_free(client->id); + silc_free(client->attrs); + silc_hash_table_free(client->channels); + + memset(client, 'A', sizeof(*client)); + silc_free(client); + } +} + /* Returns all clients matching requested nickname. Number of clients is - returned to `clients_count'. Caller must free the returned table. */ + returned to `clients_count'. Caller must free the returned table. + The 'nickname' must be normalized already. */ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname, char *server, @@ -427,7 +480,8 @@ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname, } /* Returns all clients matching requested nickname hash. Number of clients - is returned to `clients_count'. Caller must free the returned table. */ + is returned to `clients_count'. Caller must free the returned table. + The 'nickname' must be normalized already. */ int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname, SilcHash md5hash, @@ -517,12 +571,21 @@ silc_idlist_replace_client_id(SilcServer server, { SilcIDCacheEntry id_cache = NULL; SilcClientEntry client; + char *nicknamec = NULL; if (!old_id || !new_id) return NULL; SILC_LOG_DEBUG(("Replacing Client ID")); + /* Normalize name. This is cached, original is in client context. */ + if (nickname) { + nicknamec = silc_identifier_check(nickname, strlen(nickname), + SILC_STRING_UTF8, 128, NULL); + if (!nicknamec) + return NULL; + } + /* Do extended search since the normal ID comparison function for Client ID's compares only the hash from the Client ID and not the entire ID. The silc_hash_client_id_compare compares the entire @@ -548,14 +611,14 @@ silc_idlist_replace_client_id(SilcServer server, silc_free(client->id); silc_free(client->nickname); client->id = new_id; - client->nickname = nickname ? silc_memdup(nickname, strlen(nickname)) : NULL; + client->nickname = nickname ? strdup(nickname) : NULL; /* Check if anyone is watching new nickname */ if (server->server_type == SILC_ROUTER) silc_server_check_watcher_list(server, client, nickname, SILC_NOTIFY_TYPE_NICK_CHANGE); - if (!silc_idcache_add(id_list->clients, client->nickname, client->id, + if (!silc_idcache_add(id_list->clients, nicknamec, client->id, client, 0, NULL)) return NULL; @@ -564,27 +627,6 @@ silc_idlist_replace_client_id(SilcServer server, return client; } -/* Client cache entry destructor that is called when the cache is purged. */ - -void silc_idlist_client_destructor(SilcIDCache cache, - SilcIDCacheEntry entry) -{ - SilcClientEntry client; - - client = (SilcClientEntry)entry->context; - if (client) { - assert(!silc_hash_table_count(client->channels)); - silc_free(client->nickname); - silc_free(client->username); - silc_free(client->userinfo); - silc_free(client->id); - silc_free(client->attrs); - silc_hash_table_free(client->channels); - - memset(client, 'A', sizeof(*client)); - silc_free(client); - } -} /****************************************************************************** @@ -602,9 +644,18 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode, int expire) { SilcChannelEntry channel; + char *channel_namec = NULL; SILC_LOG_DEBUG(("Adding new channel %s", channel_name)); + /* Normalize name. This is cached, original is in client context. */ + if (channel_name) { + channel_namec = silc_identifier_check(channel_name, strlen(channel_name), + SILC_STRING_UTF8, 256, NULL); + if (!channel_namec) + return NULL; + } + channel = silc_calloc(1, sizeof(*channel)); channel->channel_name = channel_name; channel->mode = mode; @@ -622,11 +673,12 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode, channel->user_list = silc_hash_table_alloc(3, silc_hash_ptr, NULL, NULL, NULL, NULL, NULL, TRUE); - if (!silc_idcache_add(id_list->channels, channel->channel_name, + if (!silc_idcache_add(id_list->channels, channel_namec, (void *)channel->id, (void *)channel, expire, NULL)) { silc_hmac_free(channel->hmac); silc_hash_table_free(channel->user_list); silc_free(channel); + silc_free(channel_namec); return NULL; } @@ -706,7 +758,7 @@ int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry) } /* Finds channel by channel name. Channel names are unique and they - are not case-sensitive. */ + are not case-sensitive. The 'name' must be normalized already. */ SilcChannelEntry silc_idlist_find_channel_by_name(SilcIDList id_list, char *name, @@ -770,6 +822,7 @@ silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id, { SilcIDCacheEntry id_cache = NULL; SilcChannelEntry channel; + char *name; if (!old_id || !new_id) return NULL; @@ -781,6 +834,7 @@ silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id, return NULL; channel = (SilcChannelEntry)id_cache->context; + name = strdup(id_cache->name); /* Remove the old entry and add a new one */ @@ -789,8 +843,7 @@ silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id, silc_free(channel->id); channel->id = new_id; - silc_idcache_add(id_list->channels, channel->channel_name, channel->id, - channel, 0, NULL); + silc_idcache_add(id_list->channels, name, channel->id, channel, 0, NULL); SILC_LOG_DEBUG(("Replaced")); diff --git a/apps/silcd/idlist.h b/apps/silcd/idlist.h index dd2b8eb2..cff9c43c 100644 --- a/apps/silcd/idlist.h +++ b/apps/silcd/idlist.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2003 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 @@ -244,7 +244,10 @@ typedef struct SilcChannelClientEntryStruct { unsigned char *nickname - The nickname of the client. + The nickname of the client. This is nickname in original format, + not casefolded or normalized. However, it is checked to assure + that prohibited characters do not exist. The casefolded version + is in the ID Cache. char *servername @@ -367,7 +370,7 @@ struct SilcClientEntryStruct { reply identifier. */ SilcUInt16 resolve_cmd_ident; - /* we need this so nobody can resume more than once at the same time - + /* we need this so nobody can resume more than once at the same time - * server crashes, really odd behaviour, ... */ SilcClientEntry resuming_client; }; @@ -392,7 +395,10 @@ struct SilcClientEntryStruct { char *channel_name - Logical name of the channel. + Logical name of the channel. This is the original format, not + the casefolded or normalized. However, this is checked to assure + that prohibited characters do not exist. The casefolded version + is in the ID Cache. SilcUInt32 mode diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 01b072a0..42631642 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -2258,8 +2258,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, SilcUInt16 username_len; SilcUInt32 id_len, tmp_len; int ret; - char *hostname, *nickname, *tmp; - int nickfail = 0; + char *hostname, *nickname, *nicknamec; SILC_LOG_DEBUG(("Creating new client")); @@ -2328,9 +2327,9 @@ SilcClientEntry silc_server_new_client(SilcServer server, } /* Check for valid username string */ - tmp = silc_identifier_check(username, username_len, SILC_STRING_UTF8, 128, - &tmp_len); - if (!tmp) { + nicknamec = silc_identifier_check(username, username_len, + SILC_STRING_UTF8, 128, &tmp_len); + if (!nicknamec) { silc_free(username); silc_free(realname); SILC_LOG_ERROR(("Client %s (%s) sent bad username string, closing " @@ -2342,12 +2341,9 @@ SilcClientEntry silc_server_new_client(SilcServer server, silc_server_free_sock_user_data(server, sock, NULL); return NULL; } - silc_free(username); - username = tmp; - username_len = tmp_len; /* Nickname is initially same as username */ - nickname = silc_memdup(username, username_len); + nickname = strdup(username); /* Make sanity checks for the hostname of the client. If the hostname is provided in the `username' check that it is the same than the @@ -2437,18 +2433,14 @@ SilcClientEntry silc_server_new_client(SilcServer server, } /* Create Client ID */ - while (!silc_id_create_client_id(server, server->id, server->rng, - server->md5hash, nickname, - strlen(nickname), &client_id)) { - nickfail++; - if (nickfail > 9) { - silc_server_disconnect_remote(server, sock, - SILC_STATUS_ERR_BAD_NICKNAME, NULL); - if (sock->user_data) - silc_server_free_sock_user_data(server, sock, NULL); - return NULL; - } - snprintf(&nickname[strlen(nickname) - 1], 1, "%d", nickfail); + if (!silc_id_create_client_id(server, server->id, server->rng, + server->md5hash, nicknamec, + strlen(nicknamec), &client_id)) { + silc_server_disconnect_remote(server, sock, + SILC_STATUS_ERR_BAD_NICKNAME, NULL); + if (sock->user_data) + silc_server_free_sock_user_data(server, sock, NULL); + return NULL; } /* If client marked as anonymous, scramble the username and hostname */ @@ -2479,7 +2471,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, id_len = silc_id_get_len(client_id, SILC_ID_CLIENT); /* Add the client again to the ID cache */ - silc_idcache_add(server->local_list->clients, client->nickname, + silc_idcache_add(server->local_list->clients, nicknamec, client_id, client, 0, NULL); /* Notify our router about new client on the SILC network */ @@ -2525,7 +2517,7 @@ SilcServerEntry silc_server_new_server(SilcServer server, SilcServerEntry new_server, server_entry; SilcServerID *server_id; SilcIDListData idata; - unsigned char *server_name, *id_string; + unsigned char *server_name, *server_namec, *id_string; SilcUInt16 id_len, name_len; int ret; bool local = TRUE; @@ -2598,8 +2590,10 @@ SilcServerEntry silc_server_new_server(SilcServer server, return NULL; } - if (name_len > 256) - server_name[255] = '\0'; + if (name_len > 256) { + server_name[256] = '\0'; + name_len = 256; + } /* Get Server ID */ server_id = silc_id_str2id(id_string, id_len, SILC_ID_SERVER); @@ -2663,6 +2657,20 @@ SilcServerEntry silc_server_new_server(SilcServer server, } } + /* Check server name */ + server_namec = silc_identifier_check(server_name, strlen(server_name), + SILC_STRING_UTF8, 256, NULL); + if (!server_namec) { + SILC_LOG_ERROR(("Malformed server name from %s (%s)", + sock->ip, sock->hostname)); + silc_server_disconnect_remote(server, sock, + SILC_STATUS_ERR_OPERATION_ALLOWED, + "Malfromed server name"); + if (sock->user_data) + silc_server_free_sock_user_data(server, sock, NULL); + return NULL; + } + /* Update server entry */ idata->status |= SILC_IDLIST_STATUS_REGISTERED; new_server->server_name = server_name; @@ -2673,7 +2681,7 @@ SilcServerEntry silc_server_new_server(SilcServer server, /* Add again the entry to the ID cache. */ silc_idcache_add(local ? server->local_list->servers : - server->global_list->servers, server_name, server_id, + server->global_list->servers, server_namec, server_id, new_server, 0, NULL); /* Distribute the information about new server in the SILC network @@ -3053,7 +3061,7 @@ void silc_server_new_channel(SilcServer server, { SilcChannelPayload payload; SilcChannelID *channel_id; - char *channel_name; + char *channel_name, *channel_namec = NULL; SilcUInt32 name_len; unsigned char *id; SilcUInt32 id_len, cipher_len; @@ -3080,8 +3088,16 @@ void silc_server_new_channel(SilcServer server, } channel_name = silc_channel_get_name(payload, &name_len); - if (name_len > 256) - channel_name[255] = '\0'; + if (name_len > 256) { + channel_name[256] = '\0'; + name_len = 256; + } + + /* Check channel name */ + channel_namec = silc_identifier_check(channel_name, strlen(channel_name), + SILC_STRING_UTF8, 256, NULL); + if (!channel_namec) + return; id = silc_channel_get_id(payload, &id_len); @@ -3093,10 +3109,10 @@ void silc_server_new_channel(SilcServer server, /* Check that we don't already have this channel */ channel = silc_idlist_find_channel_by_name(server->local_list, - channel_name, NULL); + channel_namec, NULL); if (!channel) channel = silc_idlist_find_channel_by_name(server->global_list, - channel_name, NULL); + channel_namec, NULL); if (!channel) { SILC_LOG_DEBUG(("New channel id(%s) from [Router] %s", silc_id_render(channel_id, SILC_ID_CHANNEL), @@ -3127,10 +3143,10 @@ void silc_server_new_channel(SilcServer server, /* Check that we don't already have this channel */ channel = silc_idlist_find_channel_by_name(server->local_list, - channel_name, NULL); + channel_namec, NULL); if (!channel) channel = silc_idlist_find_channel_by_name(server->global_list, - channel_name, NULL); + channel_namec, NULL); /* If the channel does not exist, then create it. This creates a new key to the channel as well that we will send to the server. */ @@ -3317,6 +3333,7 @@ void silc_server_new_channel(SilcServer server, FALSE, TRUE); } + silc_free(channel_namec); silc_channel_payload_free(payload); } @@ -3629,9 +3646,9 @@ void silc_server_resume_client(SilcServer server, SilcIDCacheEntry id_cache = NULL; SilcClientEntry detached_client; SilcClientID *client_id = NULL; - unsigned char *id_string, *auth = NULL; + unsigned char *id_string, *auth = NULL, *nicknamec = NULL; SilcUInt16 id_len, auth_len = 0; - int ret, nickfail = 0; + int ret; bool resolved, local, nick_change = FALSE, resolve = FALSE; SilcChannelEntry channel; SilcHashTableList htl; @@ -3851,35 +3868,32 @@ void silc_server_resume_client(SilcServer server, return; } + /* Check nickname */ + nicknamec = silc_identifier_check(detached_client->nickname, + strlen(detached_client->nickname), + SILC_STRING_UTF8, 128, NULL); + if (!nicknamec) { + silc_server_disconnect_remote(server, sock, + SILC_STATUS_ERR_BAD_NICKNAME, + "Malformed nickname, cannot resume"); + if (sock->user_data) + silc_server_free_sock_user_data(server, sock, NULL); + return; + } + /* If the ID is not based in our ID then change it */ if (!SILC_ID_COMPARE(detached_client->id, server->id, server->id->ip.data_len)) { silc_free(client_id); - while (!silc_id_create_client_id(server, server->id, server->rng, - server->md5hash, - detached_client->nickname, - strlen(detached_client->nickname), - &client_id)) { - nickfail++; - if (nickfail > 9) { - silc_server_disconnect_remote(server, sock, - SILC_STATUS_ERR_BAD_NICKNAME, - "Resuming not possible"); - if (sock->user_data) - silc_server_free_sock_user_data(server, sock, NULL); - return; - } - if (nickfail < 2) { - detached_client->nickname = - silc_realloc(detached_client->nickname, - sizeof(*detached_client->nickname) * - (strlen(detached_client->nickname) + 2)); - detached_client-> - nickname[strlen(detached_client->nickname) - 1] = '\0'; - } - snprintf(&detached_client-> - nickname[strlen(detached_client->nickname) - 2], 1, - "%d", nickfail); + if (!silc_id_create_client_id(server, server->id, server->rng, + server->md5hash, nicknamec, + strlen(nicknamec), &client_id)) { + silc_server_disconnect_remote(server, sock, + SILC_STATUS_ERR_BAD_NICKNAME, + "Resuming not possible"); + if (sock->user_data) + silc_server_free_sock_user_data(server, sock, NULL); + return; } nick_change = TRUE; } @@ -4013,7 +4027,7 @@ void silc_server_resume_client(SilcServer server, silc_free(client->id); client->id = client_id; client_id = NULL; - silc_idcache_add(server->local_list->clients, client->nickname, + silc_idcache_add(server->local_list->clients, nicknamec, client->id, client, 0, NULL); /* Send some nice info to the client */ @@ -4110,6 +4124,17 @@ void silc_server_resume_client(SilcServer server, return; } + /* Check nickname */ + if (detached_client->nickname) { + nicknamec = silc_identifier_check(detached_client->nickname, + strlen(detached_client->nickname), + SILC_STRING_UTF8, 128, NULL); + if (!nicknamec) { + silc_free(client_id); + return; + } + } + SILC_LOG_DEBUG(("Resuming detached client")); /* If the sender of this packet is server and we are router we need to @@ -4184,8 +4209,7 @@ void silc_server_resume_client(SilcServer server, detached_client); silc_idcache_add(local && server->server_type == SILC_ROUTER ? server->local_list->clients : - server->global_list->clients, - detached_client->nickname, + server->global_list->clients, nicknamec, detached_client->id, detached_client, FALSE, NULL); /* Change the owner of the client */ diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 7f9dd5d5..6111c5f2 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -342,17 +342,23 @@ bool silc_server_init(SilcServer server) /* Initialize ID caches */ server->local_list->clients = - silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor); - server->local_list->servers = silc_idcache_alloc(0, SILC_ID_SERVER, NULL); - server->local_list->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL); + silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor, + FALSE, TRUE); + server->local_list->servers = + silc_idcache_alloc(0, SILC_ID_SERVER, NULL, FALSE, TRUE); + server->local_list->channels = + silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, FALSE, TRUE); /* These are allocated for normal server as well as these hold some global information that the server has fetched from its router. For router these are used as they are supposed to be used on router. */ server->global_list->clients = - silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor); - server->global_list->servers = silc_idcache_alloc(0, SILC_ID_SERVER, NULL); - server->global_list->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL); + silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor, + FALSE, TRUE); + server->global_list->servers = + silc_idcache_alloc(0, SILC_ID_SERVER, NULL, FALSE, TRUE); + server->global_list->channels = + silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, FALSE, TRUE); /* Init watcher lists */ server->watcher_list = @@ -427,20 +433,11 @@ bool silc_server_init(SilcServer server) if (!id) goto err; - /* Check server name */ - server->server_name = - silc_identifier_check(server->config->server_info->server_name, - strlen(server->config->server_info->server_name), - SILC_STRING_LOCALE, 256, NULL); - if (!server->server_name) { - SILC_LOG_ERROR(("Malformed server name string '%s'", - server->config->server_info->server_name)); - goto err; - } - server->id = id; server->id_string = silc_id_id2str(id, SILC_ID_SERVER); server->id_string_len = silc_id_get_len(id, SILC_ID_SERVER); + server->server_name = server->config->server_info->server_name; + server->config->server_info->server_name = NULL; /* Add ourselves to the server list. We don't have a router yet beacuse we haven't established a route yet. It will be done later. @@ -613,7 +610,7 @@ bool silc_server_rehash(SilcServer server) server->id_entry)) return FALSE; if (!silc_idcache_add(server->local_list->servers, - server->id_entry->server_name, + strdup(server->id_entry->server_name), server->id_entry->id, server->id_entry, 0, NULL)) return FALSE; } diff --git a/apps/silcd/server_query.c b/apps/silcd/server_query.c index 48ecd78d..7ccdd809 100644 --- a/apps/silcd/server_query.c +++ b/apps/silcd/server_query.c @@ -51,10 +51,10 @@ typedef struct { /* Query session context */ typedef struct { /* Queried data */ - char *nickname; /* Queried nickname */ + char *nickname; /* Queried nickname, normalized */ char *nick_server; /* Queried nickname's server */ - char *server_name; /* Queried server name */ - char *channel_name; /* Queried channel name */ + char *server_name; /* Queried server name, normalized */ + char *channel_name; /* Queried channel name, normalized */ SilcServerQueryID ids; /* Queried IDs */ SilcUInt32 ids_count; /* number of queried IDs */ SilcUInt32 reply_count; /* Requested reply count */ @@ -400,15 +400,18 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) } /* Check nickname */ - tmp = silc_identifier_check(query->nickname, strlen(query->nickname), - SILC_STRING_UTF8, 128, &tmp_len); - if (!tmp) { - silc_server_query_send_error(server, query, - SILC_STATUS_ERR_BAD_NICKNAME, 0); - silc_server_query_free(query); + if (query->nickname) { + tmp = silc_identifier_check(query->nickname, strlen(query->nickname), + SILC_STRING_UTF8, 128, &tmp_len); + if (!tmp) { + silc_server_query_send_error(server, query, + SILC_STATUS_ERR_BAD_NICKNAME, 0); + silc_server_query_free(query); + return; + } + silc_free(query->nickname); + query->nickname = tmp; } - silc_free(query->nickname); - query->nickname = tmp; } else { /* Parse the IDs included in the query */ @@ -484,6 +487,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) silc_server_query_send_error(server, query, SILC_STATUS_ERR_BAD_NICKNAME, 0); silc_server_query_free(query); + return; } silc_free(query->nickname); query->nickname = tmp; @@ -507,17 +511,45 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) !silc_parse_userfqdn(tmp, &query->nickname, &query->nick_server)) silc_server_query_add_error(server, query, 1, 1, SILC_STATUS_ERR_BAD_NICKNAME); + + /* Check nickname */ + tmp = silc_identifier_check(query->nickname, strlen(query->nickname), + SILC_STRING_UTF8, 128, &tmp_len); + silc_free(query->nickname); + if (!tmp) { + silc_server_query_add_error(server, query, 1, 1, + SILC_STATUS_ERR_BAD_NICKNAME); + query->nickname = NULL; + } else { + query->nickname = tmp; + } } /* Try get server name */ tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); - if (tmp) - query->server_name = silc_memdup(tmp, tmp_len); + if (tmp) { + /* Check server name */ + tmp = silc_identifier_check(tmp, tmp_len, SILC_STRING_UTF8, + 256, &tmp_len); + if (!tmp) + silc_server_query_add_error(server, query, 1, 1, + SILC_STATUS_ERR_BAD_SERVER); + else + query->server_name = tmp; + } /* Get channel name */ tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len); - if (tmp && tmp_len <= 256) - query->channel_name = silc_memdup(tmp, tmp_len); + if (tmp && tmp_len <= 256) { + /* Check channel name */ + tmp = silc_identifier_check(tmp, tmp_len, SILC_STRING_UTF8, + 256, &tmp_len); + if (!tmp) + silc_server_query_add_error(server, query, 1, 1, + SILC_STATUS_ERR_BAD_SERVER); + else + query->channel_name = tmp; + } if (!query->nickname && !query->server_name && !query->channel_name) { silc_server_query_send_error(server, query, diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index a65a2c19..b19f495d 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -1728,8 +1728,13 @@ bool silc_server_check_watcher_list(SilcServer server, /* Make hash from the nick, or take it from Client ID */ if (client->nickname) { - silc_hash_make(server->md5hash, client->nickname, - strlen(client->nickname), hash); + unsigned char *nickc; + nickc = silc_identifier_check(client->nickname, strlen(client->nickname), + SILC_STRING_UTF8, 128, NULL); + if (!nickc) + return FALSE; + silc_hash_make(server->md5hash, nickc, strlen(nickc), hash); + silc_free(nickc); } else { memset(hash, 0, sizeof(hash)); memcpy(hash, client->id->hash, sizeof(client->id->hash)); diff --git a/apps/silcd/serverid.c b/apps/silcd/serverid.c index aa1dee54..3d4ea8e0 100644 --- a/apps/silcd/serverid.c +++ b/apps/silcd/serverid.c @@ -67,7 +67,8 @@ bool silc_id_create_client_id(SilcServer server, *new_id = silc_calloc(1, sizeof(**new_id)); - /* Create hash of the nickanem */ + /* Create hash of the nickname (it's already checked as valid identifier + string). */ silc_hash_make(md5hash, nickname, nick_len, hash); /* Create the ID */ -- 2.24.0