X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fidlist.c;h=e302b6e6bf3ddfed204cdd7fee49e633c4dff14e;hb=52e57c880aba9c5e89f59d962eb9af75670b76e0;hp=621c4c4ffccc8600c8db86416e5c3bf5b9b7c40c;hpb=c257b555225193e54d85daf541d29578b3c93882;p=silc.git diff --git a/apps/silcd/idlist.c b/apps/silcd/idlist.c index 621c4c4f..e302b6e6 100644 --- a/apps/silcd/idlist.c +++ b/apps/silcd/idlist.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2005 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 @@ -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,16 @@ 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) -{ - SilcServer server = app_context; - SilcIDListPurge i = (SilcIDListPurge)context; - - SILC_LOG_DEBUG(("Purging cache")); - - silc_idcache_purge(i->cache); - silc_schedule_task_add(server->schedule, 0, silc_idlist_purge, - (void *)i, i->timeout, 0, - SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW); -} - /****************************************************************************** Server entry functions @@ -139,7 +100,7 @@ silc_idlist_add_server(SilcIDList id_list, server->connection = connection; if (!silc_idcache_add(id_list->servers, server_namec, - (void *)server->id, (void *)server, 0, NULL)) { + (void *)server->id, (void *)server)) { silc_free(server); silc_free(server_namec); return NULL; @@ -152,7 +113,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; @@ -163,8 +124,7 @@ 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; @@ -185,7 +145,8 @@ silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id, 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; @@ -213,42 +174,38 @@ 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))) - && server->id->port == SILC_SWAB_16(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)) return NULL; @@ -276,8 +233,7 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id, 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; @@ -285,12 +241,9 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id, /* 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, 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")); @@ -303,7 +256,7 @@ 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; } @@ -326,6 +279,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 @@ -344,8 +307,7 @@ int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry) SilcClientEntry silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, char *userinfo, SilcClientID *id, - SilcServerEntry router, void *connection, - int expire) + SilcServerEntry router, void *connection) { SilcClientEntry client; char *nicknamec = NULL; @@ -362,20 +324,17 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, /* Check username. */ if (username) { - char *u = NULL, *h = NULL; - silc_parse_userfqdn(username, &u, &h); + char u[128 + 1], h[256 + 1]; + int ret; + + ret = silc_parse_userfqdn(username, u, sizeof(u), h, sizeof(h)); if (!u) return NULL; - if (!silc_identifier_verify(u, strlen(u), SILC_STRING_UTF8, 128)) { - silc_free(u); - silc_free(h); + if (!silc_identifier_verify(u, strlen(u), SILC_STRING_UTF8, 128)) return NULL; - } - if (h && !silc_identifier_verify(h, strlen(h), SILC_STRING_UTF8, 256)) { - silc_free(u); - silc_free(h); + if (ret > 1 && !silc_identifier_verify(h, strlen(h), + SILC_STRING_UTF8, 256)) return NULL; - } } client = silc_calloc(1, sizeof(*client)); @@ -389,7 +348,7 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, NULL, NULL, NULL, NULL, TRUE); if (!silc_idcache_add(id_list->clients, nicknamec, (void *)client->id, - (void *)client, expire, NULL)) { + (void *)client)) { silc_hash_table_free(client->channels); silc_free(client); silc_free(nicknamec); @@ -404,28 +363,14 @@ 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. Destructor callback deletes stuff. */ - 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; } - - assert(!silc_hash_table_count(entry->channels)); - - silc_free(entry->nickname); - silc_free(entry->servername); - silc_free(entry->username); - silc_free(entry->userinfo); - silc_free(entry->id); - silc_free(entry->attrs); - silc_hash_table_free(entry->channels); - - memset(entry, 'F', sizeof(*entry)); - silc_free(entry); - return TRUE; } @@ -435,12 +380,20 @@ int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry) /* ID Cache destructor */ void silc_idlist_client_destructor(SilcIDCache cache, - SilcIDCacheEntry entry) + SilcIDCacheEntry entry, + void *dest_context, + void *app_context) { + SilcServer server = dest_context; SilcClientEntry client; 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); + assert(!silc_hash_table_count(client->channels)); silc_free(client->nickname); silc_free(client->servername); @@ -464,7 +417,7 @@ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname, SilcClientEntry **clients, SilcUInt32 *clients_count) { - SilcIDCacheList list = NULL; + SilcList list; SilcIDCacheEntry id_cache = NULL; SILC_LOG_DEBUG(("Start")); @@ -473,15 +426,12 @@ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname, return FALSE; *clients = silc_realloc(*clients, - (silc_idcache_list_count(list) + *clients_count) * + (silc_list_count(list) + *clients_count) * sizeof(**clients)); - silc_idcache_list_first(list, &id_cache); - (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context; - - while (silc_idcache_list_next(list, &id_cache)) - (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context; - silc_idcache_list_free(list); + silc_list_start(list); + while ((id_cache = silc_list_get(list))) + (*clients)[(*clients_count)++] = id_cache->context; SILC_LOG_DEBUG(("Found total %d clients", *clients_count)); @@ -492,15 +442,17 @@ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname, 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; + SilcClientEntry client_entry; SILC_LOG_DEBUG(("Start")); @@ -515,17 +467,28 @@ 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) * - sizeof(**clients)); + /* 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); + } + } - silc_idcache_list_first(list, &id_cache); - (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context; + if (!silc_list_count(list)) + return FALSE; - while (silc_idcache_list_next(list, &id_cache)) - (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context; + *clients = silc_realloc(*clients, + (silc_list_count(list) + *clients_count) * + sizeof(**clients)); - silc_idcache_list_free(list); + silc_list_start(list); + while ((id_cache = silc_list_get(list))) + (*clients)[(*clients_count)++] = id_cache->context; SILC_LOG_DEBUG(("Found total %d clients", *clients_count)); @@ -536,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; @@ -547,14 +510,8 @@ silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id, 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; @@ -595,31 +552,23 @@ silc_idlist_replace_client_id(SilcServer server, 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 - 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)) + /* 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 */ @@ -627,10 +576,6 @@ 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, nicknamec, client->id, - client, 0, NULL)) - return NULL; - SILC_LOG_DEBUG(("Replaced")); return client; @@ -649,8 +594,8 @@ silc_idlist_replace_client_id(SilcServer server, 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; @@ -670,7 +615,8 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode, 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) @@ -683,7 +629,7 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode, NULL, NULL, NULL, TRUE); if (!silc_idcache_add(id_list->channels, channel_namec, - (void *)channel->id, (void *)channel, expire, NULL)) { + (void *)channel->id, (void *)channel)) { silc_hmac_free(channel->hmac); silc_hash_table_free(channel->user_list); silc_free(channel); @@ -694,6 +640,16 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode, 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. */ @@ -718,7 +674,7 @@ 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; } @@ -742,8 +698,10 @@ int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry) if (entry->ban_list) silc_hash_table_free(entry->ban_list); - if (entry->channel_key) - silc_cipher_free(entry->channel_key); + 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); @@ -847,12 +805,9 @@ silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id, /* 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, 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")); @@ -869,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; @@ -880,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;