X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fidlist.c;h=1c75d7181bf0b8a73af4a9ed3c5562771a8ec2eb;hb=805fddcf6431e784f9f77114782a90c9d12f9cbe;hp=883319034af96adfdf022ebde913794e5ea572c1;hpb=f6115845375d1a0bc605df690ebcd728db995bb6;p=silc.git diff --git a/apps/silcd/idlist.c b/apps/silcd/idlist.c index 88331903..1c75d718 100644 --- a/apps/silcd/idlist.c +++ b/apps/silcd/idlist.c @@ -4,13 +4,13 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2002 Pekka Riikonen + Copyright (C) 1997 - 2007 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 the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -34,13 +34,9 @@ void silc_idlist_add_data(void *entry, SilcIDListData idata) { - SilcIDListData data = (SilcIDListData)entry; - data->send_key = idata->send_key; - data->receive_key = idata->receive_key; - data->hmac_send = idata->hmac_send; - data->hmac_receive = idata->hmac_receive; - data->psn_send = idata->psn_send; - data->psn_receive = idata->psn_receive; + SilcIDListData data = entry; + data->conn_type = idata->conn_type; + data->sconn = idata->sconn; data->hash = idata->hash; data->public_key = idata->public_key; memcpy(data->fingerprint, idata->fingerprint, sizeof(data->fingerprint)); @@ -48,7 +44,6 @@ void silc_idlist_add_data(void *entry, SilcIDListData idata) data->last_receive = idata->last_receive; data->last_sent = idata->last_sent; data->status = idata->status; - data->created = time(0); /* Update creation time */ } @@ -57,50 +52,14 @@ void silc_idlist_add_data(void *entry, SilcIDListData idata) void silc_idlist_del_data(void *entry) { SilcIDListData idata = (SilcIDListData)entry; - if (idata->send_key) - silc_cipher_free(idata->send_key); - if (idata->receive_key) - silc_cipher_free(idata->receive_key); - if (idata->rekey) { - if (idata->rekey->send_enc_key) { - memset(idata->rekey->send_enc_key, 0, idata->rekey->enc_key_len); - silc_free(idata->rekey->send_enc_key); - } - silc_free(idata->rekey); - } - if (idata->hmac_send) - silc_hmac_free(idata->hmac_send); - if (idata->hmac_receive) - silc_hmac_free(idata->hmac_receive); + if (idata->hash) silc_hash_free(idata->hash); - if (idata->public_key) - silc_pkcs_public_key_free(idata->public_key); - - idata->send_key = NULL; - idata->receive_key = NULL; - idata->rekey = NULL; - idata->hmac_send = NULL; - idata->hmac_receive = NULL; + idata->hash = NULL; idata->public_key = NULL; } -/* Purges ID cache */ - -SILC_TASK_CALLBACK_GLOBAL(silc_idlist_purge) -{ - SilcIDListPurge i = (SilcIDListPurge)context; - - SILC_LOG_DEBUG(("Purging cache")); - - silc_idcache_purge(i->cache); - silc_schedule_task_add(i->schedule, 0, - silc_idlist_purge, - (void *)i, i->timeout, 0, - SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW); -} - /****************************************************************************** Server entry functions @@ -112,16 +71,25 @@ SILC_TASK_CALLBACK_GLOBAL(silc_idlist_purge) when new server connects to us. We also add ourselves to cache with this function. */ -SilcServerEntry -silc_idlist_add_server(SilcIDList id_list, +SilcServerEntry +silc_idlist_add_server(SilcIDList id_list, char *server_name, int server_type, SilcServerID *id, SilcServerEntry router, 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 +97,10 @@ silc_idlist_add_server(SilcIDList id_list, server->router = router; server->connection = connection; - if (!silc_idcache_add(id_list->servers, server->server_name, - (void *)server->id, (void *)server, 0, NULL)) { + if (!silc_idcache_add(id_list->servers, server_namec, + (void *)server->id, (void *)server)) { silc_free(server); + silc_free(server_namec); return NULL; } @@ -142,7 +111,7 @@ silc_idlist_add_server(SilcIDList id_list, SilcServerEntry silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id, - bool registered, SilcIDCacheEntry *ret_entry) + SilcBool registered, SilcIDCacheEntry *ret_entry) { SilcIDCacheEntry id_cache = NULL; SilcServerEntry server; @@ -153,13 +122,12 @@ silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id, SILC_LOG_DEBUG(("Server ID (%s)", silc_id_render(id, SILC_ID_SERVER))); - if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id, - &id_cache)) + if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id, &id_cache)) return NULL; server = (SilcServerEntry)id_cache->context; - if (server && registered && + if (server && registered && !(server->data.status & SILC_IDLIST_STATUS_REGISTERED)) return NULL; @@ -171,11 +139,12 @@ 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, - bool registered, SilcIDCacheEntry *ret_entry) + SilcBool registered, + SilcIDCacheEntry *ret_entry) { SilcIDCacheEntry id_cache = NULL; SilcServerEntry server; @@ -186,7 +155,7 @@ silc_idlist_find_server_by_name(SilcIDList id_list, char *name, return NULL; server = (SilcServerEntry)id_cache->context; - + if (server && registered && !(server->data.status & SILC_IDLIST_STATUS_REGISTERED)) return NULL; @@ -203,41 +172,37 @@ silc_idlist_find_server_by_name(SilcIDList id_list, char *name, SilcServerEntry silc_idlist_find_server_by_conn(SilcIDList id_list, char *hostname, - int port, bool registered, + int port, SilcBool registered, SilcIDCacheEntry *ret_entry) { - SilcIDCacheList list = NULL; + SilcList list; SilcIDCacheEntry id_cache = NULL; SilcServerEntry server = NULL; - SilcSocketConnection sock; - + SilcPacketStream sock; + const char *host = NULL, *ip = NULL; + SILC_LOG_DEBUG(("Server by hostname %s and port %d", hostname, port)); if (!silc_idcache_get_all(id_list->servers, &list)) return NULL; - if (!silc_idcache_list_first(list, &id_cache)) { - silc_idcache_list_free(list); - return NULL; - } - - while (id_cache) { - server = (SilcServerEntry)id_cache->context; - sock = (SilcSocketConnection)server->connection; - - if (sock && ((sock->hostname && !strcasecmp(sock->hostname, hostname)) || - (sock->ip && !strcasecmp(sock->ip, hostname))) - && sock->port == port) - break; + silc_list_start(list); + while ((id_cache = silc_list_get(list))) { + server = id_cache->context; + sock = server->connection; + + if (sock && silc_socket_stream_get_info( + silc_packet_stream_get_stream(sock), + NULL, &host, &ip, NULL)) { + if (((host && !strcasecmp(host, hostname)) || + (ip && !strcasecmp(ip, hostname))) && + server->id->port == SILC_SWAB_16(port)) + break; + } id_cache = NULL; server = NULL; - - if (!silc_idcache_list_next(list, &id_cache)) - break; } - - silc_idcache_list_free(list); if (server && registered && !(server->data.status & SILC_IDLIST_STATUS_REGISTERED)) @@ -251,7 +216,7 @@ silc_idlist_find_server_by_conn(SilcIDList id_list, char *hostname, return server; } -/* Replaces old Server ID with new one */ +/* Replaces old Server ID with new one */ SilcServerEntry silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id, @@ -259,27 +224,24 @@ 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; SILC_LOG_DEBUG(("Replacing Server ID")); - if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id, - &id_cache)) + if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id, &id_cache)) return NULL; server = (SilcServerEntry)id_cache->context; + name = strdup(id_cache->name); /* Remove the old entry and add a new one */ - silc_idcache_del_by_id(id_list->servers, (void *)server->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_del_by_id(id_list->servers, (void *)server->id, NULL); + *server->id = *new_id; + silc_idcache_add(id_list->servers, name, server->id, server); SILC_LOG_DEBUG(("Found")); @@ -292,11 +254,15 @@ int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry) { if (entry) { /* Remove from cache */ - if (!silc_idcache_del_by_context(id_list->servers, entry)) + if (!silc_idcache_del_by_context(id_list->servers, entry, NULL)) { + SILC_LOG_DEBUG(("Unknown server, did not delete")); return FALSE; + } - SILC_LOG_DEBUG(("Deleting server %s", entry->server_name ? - entry->server_name : "")); + SILC_LOG_DEBUG(("Deleting server %s id %s", entry->server_name ? + entry->server_name : "", + entry->id ? + silc_id_render(entry->id, SILC_ID_SERVER) : "")); /* Free data */ silc_free(entry->server_name); @@ -311,6 +277,16 @@ int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry) return FALSE; } +/* ID Cache destructor */ + +void silc_idlist_server_destructor(SilcIDCache cache, + SilcIDCacheEntry entry, + void *dest_context, + void *app_context) +{ + silc_free(entry->name); +} + /****************************************************************************** Client entry functions @@ -327,18 +303,43 @@ int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry) to be directly connected local client and `router' must be NULL. */ SilcClientEntry -silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, - char *userinfo, SilcClientID *id, - SilcServerEntry router, void *connection, - int expire) +silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, + char *userinfo, SilcClientID *id, + SilcServerEntry router, void *connection) { 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[128 + 1], h[256 + 1]; + int ret; + + ret = silc_parse_userfqdn(username, u, sizeof(u), h, sizeof(h)); + if (!ret) + return NULL; + if (!silc_identifier_verify(u, strlen(u), SILC_STRING_UTF8, 128)) + return NULL; + if (ret > 1 && !silc_identifier_verify(h, strlen(h), + SILC_STRING_UTF8, 256)) + return NULL; + } + client = silc_calloc(1, sizeof(*client)); + if (!client) + return NULL; client->nickname = nickname; - client->username = username; + client->username = username ? strdup(username) : NULL; client->userinfo = userinfo; client->id = id; client->router = router; @@ -346,10 +347,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, - (void *)client, expire, NULL)) { + if (!silc_idcache_add(id_list->clients, nicknamec, (void *)client->id, + (void *)client)) { silc_hash_table_free(client->channels); silc_free(client); + silc_free(nicknamec); return NULL; } @@ -361,41 +363,61 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry) { - SILC_LOG_DEBUG(("Start")); + SILC_LOG_DEBUG(("Delete client %p", entry)); if (entry) { - /* Remove from cache */ - if (!silc_idcache_del_by_context(id_list->clients, entry)) + /* Delete client, destructor will free data */ + if (!silc_idcache_del_by_context(id_list->clients, entry, NULL)) { + SILC_LOG_DEBUG(("Unknown client, did not delete")); return FALSE; + } + return TRUE; + } - assert(!silc_hash_table_count(entry->channels)); + return FALSE; +} - /* Free data */ - silc_free(entry->nickname); - silc_free(entry->servername); - silc_free(entry->username); - silc_free(entry->userinfo); - silc_free(entry->id); - silc_hash_table_free(entry->channels); +/* ID Cache destructor */ - memset(entry, 'F', sizeof(*entry)); - silc_free(entry); +void silc_idlist_client_destructor(SilcIDCache cache, + SilcIDCacheEntry entry, + void *dest_context, + void *app_context) +{ + SilcServer server = dest_context; + SilcClientEntry client; - return TRUE; - } + client = (SilcClientEntry)entry->context; + if (client) { + /* Remove client's public key from repository, this will free it too. */ + if (client->data.public_key) + silc_skr_del_public_key(server->repository, client->data.public_key, + client); - return FALSE; + 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, + char *server, SilcClientEntry **clients, SilcUInt32 *clients_count) { - SilcIDCacheList list = NULL; + SilcList list; SilcIDCacheEntry id_cache = NULL; SILC_LOG_DEBUG(("Start")); @@ -403,42 +425,38 @@ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname, if (!silc_idcache_find_by_name(id_list->clients, nickname, &list)) return FALSE; - *clients = silc_realloc(*clients, - (silc_idcache_list_count(list) + *clients_count) * + *clients = silc_realloc(*clients, + (silc_list_count(list) + *clients_count) * sizeof(**clients)); - silc_idcache_list_first(list, &id_cache); - (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context; + silc_list_start(list); + while ((id_cache = silc_list_get(list))) + (*clients)[(*clients_count)++] = id_cache->context; - 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)); return TRUE; } /* 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, +int silc_idlist_get_clients_by_hash(SilcIDList id_list, + char *nickname, char *server, SilcHash md5hash, SilcClientEntry **clients, SilcUInt32 *clients_count) { - SilcIDCacheList list = NULL; + SilcList list; SilcIDCacheEntry id_cache = NULL; - unsigned char hash[32]; + unsigned char hash[SILC_HASH_MAXLEN]; SilcClientID client_id; - char nick[128 + 1]; + SilcClientEntry client_entry; 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 @@ -449,18 +467,29 @@ int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname, if (!silc_idcache_find_by_id(id_list->clients, &client_id, &list)) return FALSE; - *clients = silc_realloc(*clients, - (silc_idcache_list_count(list) + *clients_count) * + /* If server is specified, narrow the search with it. */ + if (server) { + silc_list_start(list); + while ((id_cache = silc_list_get(list))) { + client_entry = id_cache->context; + if (!client_entry->servername) + continue; + if (!silc_utf8_strcasecmp(client_entry->servername, server)) + silc_list_del(list, id_cache); + } + } + + if (!silc_list_count(list)) + return FALSE; + + *clients = silc_realloc(*clients, + (silc_list_count(list) + *clients_count) * sizeof(**clients)); - silc_idcache_list_first(list, &id_cache); - (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context; + silc_list_start(list); + while ((id_cache = silc_list_get(list))) + (*clients)[(*clients_count)++] = id_cache->context; - 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)); return TRUE; @@ -470,7 +499,7 @@ int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname, SilcClientEntry silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id, - bool registered, SilcIDCacheEntry *ret_entry) + SilcBool registered, SilcIDCacheEntry *ret_entry) { SilcIDCacheEntry id_cache = NULL; SilcClientEntry client; @@ -478,17 +507,11 @@ silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id, if (!id) return NULL; - SILC_LOG_DEBUG(("Client ID (%s)", + SILC_LOG_DEBUG(("Client ID (%s)", silc_id_render(id, SILC_ID_CLIENT))); - /* 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 - Client ID as we want to find one specific Client ID. */ - if (!silc_idcache_find_by_id_one_ext(id_list->clients, (void *)id, - NULL, NULL, - silc_hash_client_id_compare, NULL, - &id_cache)) + /* Find the exact client with the exact Client ID */ + if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id, &id_cache)) return NULL; client = (SilcClientEntry)id_cache->context; @@ -514,37 +537,38 @@ 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")); - /* 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 - Client ID as we want to find one specific Client ID. */ - if (!silc_idcache_find_by_id_one_ext(id_list->clients, (void *)old_id, - NULL, NULL, - silc_hash_client_id_compare, NULL, - &id_cache)) + /* 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; + } + + /* Find exact client with exact Client ID */ + if (!silc_idcache_find_by_id_one(id_list->clients, old_id, &id_cache)) return NULL; client = (SilcClientEntry)id_cache->context; - /* Remove the old entry and add a new one */ - - if (!silc_idcache_del_by_context(id_list->clients, client)) - return NULL; - /* Check if anyone is watching old nickname */ if (server->server_type == SILC_ROUTER) silc_server_check_watcher_list(server, client, nickname, SILC_NOTIFY_TYPE_NICK_CHANGE); - silc_free(client->id); + /* Replace */ + if (!silc_idcache_update(id_list->clients, id_cache, new_id, nicknamec, + TRUE)) + return NULL; + silc_free(client->nickname); - client->id = new_id; client->nickname = nickname ? strdup(nickname) : NULL; /* Check if anyone is watching new nickname */ @@ -552,35 +576,11 @@ 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, - client, 0, NULL)) - return NULL; - SILC_LOG_DEBUG(("Replaced")); 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_hash_table_free(client->channels); - - memset(client, 'A', sizeof(*client)); - silc_free(client); - } -} /****************************************************************************** @@ -594,19 +594,29 @@ void silc_idlist_client_destructor(SilcIDCache cache, SilcChannelEntry silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode, SilcChannelID *id, SilcServerEntry router, - SilcCipher channel_key, SilcHmac hmac, - int expire) + SilcCipher send_key, SilcCipher receive_key, + SilcHmac hmac) { 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; channel->id = id; channel->router = router; - channel->channel_key = channel_key; + channel->send_key = send_key; + channel->receive_key = receive_key; channel->hmac = hmac; channel->created = channel->updated = time(0); if (!channel->hmac) @@ -618,17 +628,28 @@ 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, - (void *)channel->id, (void *)channel, expire, NULL)) { + if (!silc_idcache_add(id_list->channels, channel_namec, + (void *)channel->id, (void *)channel)) { silc_hmac_free(channel->hmac); silc_hash_table_free(channel->user_list); silc_free(channel); + silc_free(channel_namec); return NULL; } return channel; } +/* ID Cache destructor */ + +void silc_idlist_channel_destructor(SilcIDCache cache, + SilcIDCacheEntry entry, + void *dest_context, + void *app_context) +{ + silc_free(entry->name); +} + /* Foreach callbcak to free all users from the channel when deleting a channel entry. */ @@ -653,13 +674,15 @@ int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry) { if (entry) { /* Remove from cache */ - if (!silc_idcache_del_by_context(id_list->channels, entry)) + if (!silc_idcache_del_by_context(id_list->channels, entry, NULL)) { + SILC_LOG_DEBUG(("Unknown channel, did not delete")); return FALSE; + } SILC_LOG_DEBUG(("Deleting channel %s", entry->channel_name)); /* Free all client entrys from the users list. The silc_hash_table_free - will free all the entries so they are not freed at the foreach + will free all the entries so they are not freed at the foreach callback. */ silc_hash_table_foreach(entry->user_list, silc_idlist_del_channel_foreach, NULL); @@ -669,8 +692,16 @@ int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry) silc_free(entry->channel_name); silc_free(entry->id); silc_free(entry->topic); - if (entry->channel_key) - silc_cipher_free(entry->channel_key); + + if (entry->invite_list) + silc_hash_table_free(entry->invite_list); + if (entry->ban_list) + silc_hash_table_free(entry->ban_list); + + if (entry->send_key) + silc_cipher_free(entry->send_key); + if (entry->receive_key) + silc_cipher_free(entry->receive_key); if (entry->key) { memset(entry->key, 0, entry->key_len / 8); silc_free(entry->key); @@ -682,6 +713,8 @@ int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry) silc_free(entry->rekey); if (entry->founder_key) silc_pkcs_public_key_free(entry->founder_key); + if (entry->channel_pubkeys) + silc_hash_table_free(entry->channel_pubkeys); memset(entry, 'F', sizeof(*entry)); silc_free(entry); @@ -692,7 +725,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, @@ -756,27 +789,25 @@ 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; SILC_LOG_DEBUG(("Replacing Channel ID")); - if (!silc_idcache_find_by_id_one(id_list->channels, (void *)old_id, + if (!silc_idcache_find_by_id_one(id_list->channels, (void *)old_id, &id_cache)) return NULL; channel = (SilcChannelEntry)id_cache->context; + name = strdup(id_cache->name); /* Remove the old entry and add a new one */ - silc_idcache_del_by_id(id_list->channels, (void *)channel->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_del_by_id(id_list->channels, (void *)channel->id, NULL); + *channel->id = *new_id; + silc_idcache_add(id_list->channels, name, channel->id, channel); SILC_LOG_DEBUG(("Replaced")); @@ -793,7 +824,7 @@ SilcChannelEntry * silc_idlist_get_channels(SilcIDList id_list, SilcChannelID *channel_id, SilcUInt32 *channels_count) { - SilcIDCacheList list = NULL; + SilcList list; SilcIDCacheEntry id_cache = NULL; SilcChannelEntry *channels = NULL; int i = 0; @@ -804,16 +835,12 @@ silc_idlist_get_channels(SilcIDList id_list, SilcChannelID *channel_id, if (!silc_idcache_get_all(id_list->channels, &list)) return NULL; - channels = silc_calloc(silc_idcache_list_count(list), sizeof(*channels)); - + channels = silc_calloc(silc_list_count(list), sizeof(*channels)); + i = 0; - silc_idcache_list_first(list, &id_cache); - channels[i++] = (SilcChannelEntry)id_cache->context; - - while (silc_idcache_list_next(list, &id_cache)) + silc_list_start(list); + while ((id_cache = silc_list_get(list))) channels[i++] = (SilcChannelEntry)id_cache->context; - - silc_idcache_list_free(list); } else { if (!silc_idcache_find_by_id_one(id_list->channels, channel_id, &id_cache)) return NULL;