5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
25 /******************************************************************************
29 ******************************************************************************/
31 /* This function is used to add keys and stuff to common ID entry data
34 void silc_idlist_add_data(void *entry, SilcIDListData idata)
36 SilcIDListData data = (SilcIDListData)entry;
37 data->send_key = idata->send_key;
38 data->receive_key = idata->receive_key;
39 data->hmac = idata->hmac;
40 data->hmac_key = idata->hmac_key;
41 data->hmac_key_len = idata->hmac_key_len;
42 data->pkcs = idata->pkcs;
43 data->public_key = idata->public_key;
44 data->last_receive = idata->last_receive;
45 data->last_sent = idata->last_sent;
46 data->registered = idata->registered;
49 /* Free's all data in the common ID entry data structure. */
51 void silc_idlist_del_data(void *entry)
53 SilcIDListData idata = (SilcIDListData)entry;
55 silc_cipher_free(idata->send_key);
56 if (idata->receive_key)
57 silc_cipher_free(idata->receive_key);
59 silc_hmac_free(idata->hmac);
60 if (idata->hmac_key) {
61 memset(idata->hmac_key, 0, idata->hmac_key_len);
62 silc_free(idata->hmac_key);
65 silc_pkcs_free(idata->pkcs);
66 if (idata->public_key)
67 silc_pkcs_public_key_free(idata->public_key);
70 /******************************************************************************
72 Server entry functions
74 ******************************************************************************/
76 /* Add new server entry. This adds the new server entry to ID cache and
77 returns the allocated entry object or NULL on error. This is called
78 when new server connects to us. We also add ourselves to cache with
82 silc_idlist_add_server(SilcIDList id_list,
83 char *server_name, int server_type,
84 SilcServerID *id, SilcServerEntry router,
87 SilcServerEntry server;
89 SILC_LOG_DEBUG(("Adding new server entry"));
91 server = silc_calloc(1, sizeof(*server));
92 server->server_name = server_name;
93 server->server_type = server_type;
95 server->router = router;
96 server->connection = connection;
98 if (!silc_idcache_add(id_list->servers, server->server_name, SILC_ID_SERVER,
99 (void *)server->id, (void *)server, TRUE)) {
107 /* Finds server by Server ID */
110 silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id,
111 SilcIDCacheEntry *ret_entry)
113 SilcIDCacheEntry id_cache = NULL;
114 SilcServerEntry server;
119 SILC_LOG_DEBUG(("Finding server by ID"));
121 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id,
122 SILC_ID_SERVER, &id_cache))
125 server = (SilcServerEntry)id_cache->context;
128 *ret_entry = id_cache;
133 /* Replaces old Server ID with new one */
136 silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
137 SilcServerID *new_id)
139 SilcIDCacheEntry id_cache = NULL;
140 SilcServerEntry server;
142 if (!old_id || !new_id)
145 SILC_LOG_DEBUG(("Replacing Server ID"));
147 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id,
148 SILC_ID_SERVER, &id_cache))
151 server = (SilcServerEntry)id_cache->context;
152 silc_free(server->id);
154 id_cache->id = (void *)new_id;
159 /******************************************************************************
161 Client entry functions
163 ******************************************************************************/
165 /* Add new client entry. This adds the client entry to ID cache system
166 and returns the allocated client entry or NULL on error. This is
167 called when new client connection is accepted to the server. */
170 silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
171 char *userinfo, SilcClientID *id,
172 SilcServerEntry router, void *connection)
174 SilcClientEntry client;
176 SILC_LOG_DEBUG(("Adding new client entry"));
178 client = silc_calloc(1, sizeof(*client));
179 client->nickname = nickname;
180 client->username = username;
181 client->userinfo = userinfo;
183 client->router = router;
184 client->connection = connection;
185 silc_list_init(client->channels, struct SilcChannelClientEntryStruct,
188 if (!silc_idcache_add(id_list->clients, client->nickname, SILC_ID_CLIENT,
189 (void *)client->id, (void *)client, TRUE)) {
197 /* Free client entry. This free's everything and removes the entry
198 from ID cache. Call silc_idlist_del_data before calling this one. */
200 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
203 /* Remove from cache */
205 silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
210 silc_free(entry->nickname);
212 silc_free(entry->username);
214 silc_free(entry->userinfo);
216 silc_free(entry->id);
220 /* Returns all clients matching requested nickname. Number of clients is
221 returned to `clients_count'. Caller must free the returned table. */
224 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
225 char *server, unsigned int *clients_count)
227 SilcIDCacheList list = NULL;
228 SilcIDCacheEntry id_cache = NULL;
229 SilcClientEntry *clients;
232 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
235 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
238 silc_idcache_list_first(list, &id_cache);
239 clients[i++] = (SilcClientEntry)id_cache->context;
241 while (silc_idcache_list_next(list, &id_cache))
242 clients[i++] = (SilcClientEntry)id_cache->context;
244 silc_idcache_list_free(list);
252 /* Returns all clients matching requested nickname. Number of clients is
253 returned to `clients_count'. Caller must free the returned table. */
256 silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
258 unsigned int *clients_count)
260 SilcIDCacheList list = NULL;
261 SilcIDCacheEntry id_cache = NULL;
262 SilcClientEntry *clients;
263 unsigned char hash[32];
266 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
268 if (!silc_idcache_find_by_data(id_list->clients, hash, &list))
271 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
274 silc_idcache_list_first(list, &id_cache);
275 clients[i++] = (SilcClientEntry)id_cache->context;
277 while (silc_idcache_list_next(list, &id_cache))
278 clients[i++] = (SilcClientEntry)id_cache->context;
280 silc_idcache_list_free(list);
288 /* Finds client entry by nickname. */
291 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
292 char *server, SilcIDCacheEntry *ret_entry)
294 SilcIDCacheList list = NULL;
295 SilcIDCacheEntry id_cache = NULL;
296 SilcClientEntry client = NULL;
298 SILC_LOG_DEBUG(("Finding client by nickname"));
301 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
305 while (silc_idcache_list_next(list, &id_cache)) {
306 client = (SilcClientEntry)id_cache->context;
308 if (!strcmp(server, XXX, strlen(server)))
315 silc_idcache_list_free(list);
320 if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
323 client = (SilcClientEntry)id_cache->context;
326 *ret_entry = id_cache;
332 /* Finds client by nickname hash. */
335 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
336 SilcHash md5hash, SilcIDCacheEntry *ret_entry)
338 SilcIDCacheList list = NULL;
339 SilcIDCacheEntry id_cache = NULL;
340 SilcClientEntry client = NULL;
341 unsigned char hash[32];
343 SILC_LOG_DEBUG(("Finding client by hash"));
345 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
347 if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
348 SILC_ID_CLIENT, &list))
351 if (!silc_idcache_list_first(list, &id_cache)) {
352 silc_idcache_list_free(list);
357 client = (SilcClientEntry)id_cache->context;
359 if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
365 if (!silc_idcache_list_next(list, &id_cache))
369 silc_idcache_list_free(list);
372 *ret_entry = id_cache;
377 /* Finds client by Client ID */
380 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
381 SilcIDCacheEntry *ret_entry)
383 SilcIDCacheEntry id_cache = NULL;
384 SilcClientEntry client;
389 SILC_LOG_DEBUG(("Finding client by ID"));
391 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id,
392 SILC_ID_CLIENT, &id_cache))
395 client = (SilcClientEntry)id_cache->context;
398 *ret_entry = id_cache;
403 /* Replaces old Client ID with new one */
406 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
407 SilcClientID *new_id)
409 SilcIDCacheEntry id_cache = NULL;
410 SilcClientEntry client;
412 if (!old_id || !new_id)
415 SILC_LOG_DEBUG(("Replacing Client ID"));
417 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id,
418 SILC_ID_CLIENT, &id_cache))
421 client = (SilcClientEntry)id_cache->context;
422 silc_free(client->id);
424 id_cache->id = (void *)new_id;
426 /* If the old ID Cache data was the hash value of the old Client ID
427 replace it with the hash of new Client ID */
428 if (id_cache->data && !SILC_ID_COMPARE_HASH(old_id, id_cache->data)) {
429 silc_free(id_cache->data);
430 id_cache->data = silc_calloc(sizeof(new_id->hash),
431 sizeof(unsigned char));
432 memcpy(id_cache->data, new_id->hash, sizeof(new_id->hash));
433 silc_idcache_sort_by_data(id_list->clients);
440 /******************************************************************************
442 Channel entry functions
444 ******************************************************************************/
446 /* Add new channel entry. This add the new channel entry to the ID cache
447 system and returns the allocated entry or NULL on error. */
450 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
451 SilcChannelID *id, SilcServerEntry router,
452 SilcCipher channel_key)
454 SilcChannelEntry channel;
456 channel = silc_calloc(1, sizeof(*channel));
457 channel->channel_name = channel_name;
458 channel->mode = mode;
460 channel->router = router;
461 channel->channel_key = channel_key;
462 silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct,
465 if (!silc_idcache_add(id_list->channels, channel->channel_name,
466 SILC_ID_CHANNEL, (void *)channel->id,
467 (void *)channel, TRUE)) {
475 /* Free channel entry. This free's everything. */
477 void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
480 SilcChannelClientEntry chl;
482 /* Remove from cache */
484 silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
488 if (entry->channel_name)
489 silc_free(entry->channel_name);
491 silc_free(entry->id);
493 silc_free(entry->topic);
494 if (entry->channel_key)
495 silc_cipher_free(entry->channel_key);
497 memset(entry->key, 0, entry->key_len / 8);
498 silc_free(entry->key);
500 memset(entry->iv, 0, sizeof(entry->iv));
502 silc_list_start(entry->user_list);
503 while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
504 silc_list_del(entry->user_list, chl);
510 /* Finds channel by channel name. Channel names are unique and they
511 are not case-sensitive. */
514 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
515 SilcIDCacheEntry *ret_entry)
517 SilcIDCacheList list = NULL;
518 SilcIDCacheEntry id_cache = NULL;
519 SilcChannelEntry channel;
521 SILC_LOG_DEBUG(("Finding channel by name"));
523 if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
526 if (!silc_idcache_list_first(list, &id_cache)) {
527 silc_idcache_list_free(list);
531 channel = (SilcChannelEntry)id_cache->context;
534 *ret_entry = id_cache;
536 silc_idcache_list_free(list);
541 /* Finds channel by Channel ID. */
544 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
545 SilcIDCacheEntry *ret_entry)
547 SilcIDCacheEntry id_cache = NULL;
548 SilcChannelEntry channel;
553 SILC_LOG_DEBUG(("Finding channel by ID"));
555 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id,
556 SILC_ID_CHANNEL, &id_cache))
559 channel = (SilcChannelEntry)id_cache->context;
562 *ret_entry = id_cache;