X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=apps%2Fsilcd%2Fidlist.c;h=621c4c4ffccc8600c8db86416e5c3bf5b9b7c40c;hp=2562c0f03d39ec1db2f4c252dd78a0fc9d0c0e38;hb=c257b555225193e54d85daf541d29578b3c93882;hpb=f658940d02cf2fd893296b6a7825b42502573668 diff --git a/apps/silcd/idlist.c b/apps/silcd/idlist.c index 2562c0f0..621c4c4f 100644 --- a/apps/silcd/idlist.c +++ b/apps/silcd/idlist.c @@ -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 @@ -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,39 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, int expire) { SilcClientEntry client; + char *nicknamec = 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; + } + + /* Check username. */ + if (username) { + char *u = NULL, *h = NULL; + silc_parse_userfqdn(username, &u, &h); + if (!u) + return NULL; + if (!silc_identifier_verify(u, strlen(u), SILC_STRING_UTF8, 128)) { + silc_free(u); + silc_free(h); + return NULL; + } + if (h && !silc_identifier_verify(h, strlen(h), SILC_STRING_UTF8, 256)) { + silc_free(u); + silc_free(h); + return NULL; + } + } + client = silc_calloc(1, sizeof(*client)); client->nickname = nickname; - client->username = username; + client->username = username ? strdup(username) : NULL; client->userinfo = userinfo; client->id = id; client->router = router; @@ -350,10 +388,11 @@ 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); return NULL; } @@ -368,7 +407,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 +415,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 +432,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, @@ -419,7 +481,6 @@ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname, while (silc_idcache_list_next(list, &id_cache)) (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context; - silc_idcache_list_free(list); SILC_LOG_DEBUG(("Found total %d clients", *clients_count)); @@ -428,7 +489,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, @@ -439,13 +501,10 @@ int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname, SilcIDCacheEntry id_cache = NULL; unsigned char hash[32]; SilcClientID client_id; - char nick[128 + 1]; SILC_LOG_DEBUG(("Start")); - memset(nick, 0, sizeof(nick)); - silc_to_lower(nickname, nick, sizeof(nick) - 1); - silc_hash_make(md5hash, nick, strlen(nick), hash); + silc_hash_make(md5hash, nickname, strlen(nickname), hash); /* As the Client ID is hashed in the ID cache by hashing only the hash from the Client ID, we can do a lookup with only the hash not the @@ -521,12 +580,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 @@ -559,7 +627,7 @@ silc_idlist_replace_client_id(SilcServer server, 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; @@ -568,27 +636,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); - } -} /****************************************************************************** @@ -606,9 +653,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_channel_name_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; @@ -626,11 +682,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; } @@ -710,7 +767,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, @@ -774,6 +831,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; @@ -785,6 +843,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 */ @@ -793,8 +852,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"));