to context's and normalized version to cache.
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;
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
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);
/* 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) {
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];
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;
}
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;
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;
/* 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;
/* 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,
/* 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,
}
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;
}
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);
/* 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;
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))) {
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)
silc_free(id);
out:
- silc_free(channel_name);
+ silc_free(channel_namec);
silc_server_command_free(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,
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;
}
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 :
/* 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);
}
}
}
- silc_free(username);
return TRUE;
}
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,
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. */
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
silc_free(nick);
- silc_free(username);
return FALSE;
}
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);
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);
}
}
silc_free(client_id);
- silc_free(username);
return TRUE;
}
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) {
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;
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 :
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) {
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) {
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),
server->router, NULL, NULL, 0);
if (!channel) {
silc_free(channel_id);
+ silc_free(info);
goto error;
}
+ silc_free(info);
channel_id = NULL;
}
SilcServerEntry entry;
SilcServerID *server_id;
SilcUInt32 tmp_len;
- unsigned char *tmp, *name = NULL;
+ unsigned char *tmp, *name;
COMMAND_CHECK_STATUS;
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) {
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;
entry->server_info = tmp ? strdup(tmp) : NULL;
- silc_free(name);
-
out:
SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
err:
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;
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 */
/* 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);
out:
SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
err:
+ silc_free(channel_namec);
if (hmac)
silc_hmac_free(hmac);
silc_free(client_id);
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;
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) {
SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
silc_free(channel_id);
err:
+ silc_free(namec);
silc_server_command_reply_free(cmd);
}
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;
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;
}
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,
{
SilcIDCacheEntry id_cache = NULL;
SilcServerEntry server;
+ char *name;
if (!old_id || !new_id)
return NULL;
return NULL;
server = (SilcServerEntry)id_cache->context;
+ name = strdup(id_cache->name);
/* Remove the old entry and add a new one */
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"));
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;
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;
}
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;
assert(!silc_hash_table_count(entry->channels));
- /* Free data */
silc_free(entry->nickname);
silc_free(entry->servername);
silc_free(entry->username);
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,
}
/* 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,
{
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
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;
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);
- }
-}
/******************************************************************************
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;
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;
}
}
/* 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,
{
SilcIDCacheEntry id_cache = NULL;
SilcChannelEntry channel;
+ char *name;
if (!old_id || !new_id)
return NULL;
return NULL;
channel = (SilcChannelEntry)id_cache->context;
+ name = strdup(id_cache->name);
/* Remove the old entry and add a new one */
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"));
Author: Pekka Riikonen <priikone@silcnet.org>
- 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
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
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;
};
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
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"));
}
/* 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 "
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
}
/* 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 */
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 */
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;
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);
}
}
+ /* 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;
/* 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
{
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;
}
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);
/* 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),
/* 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. */
FALSE, TRUE);
}
+ silc_free(channel_namec);
silc_channel_payload_free(payload);
}
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;
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;
}
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 */
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
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 */
/* 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 =
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.
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;
}
/* 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 */
}
/* 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 */
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_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,
/* 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));
*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 */