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(("Server ID (%s)",
120 silc_id_render(id, SILC_ID_SERVER)));
122 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id,
123 SILC_ID_SERVER, &id_cache))
126 server = (SilcServerEntry)id_cache->context;
129 *ret_entry = id_cache;
134 /* Replaces old Server ID with new one */
137 silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
138 SilcServerID *new_id)
140 SilcIDCacheEntry id_cache = NULL;
141 SilcServerEntry server;
143 if (!old_id || !new_id)
146 SILC_LOG_DEBUG(("Replacing Server ID"));
148 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id,
149 SILC_ID_SERVER, &id_cache))
152 server = (SilcServerEntry)id_cache->context;
153 silc_free(server->id);
155 id_cache->id = (void *)new_id;
160 /* Removes and free's server entry from ID list */
162 void silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
165 /* Remove from cache */
167 silc_idcache_del_by_id(id_list->servers, SILC_ID_SERVER,
171 if (entry->server_name)
172 silc_free(entry->server_name);
174 silc_free(entry->id);
178 /******************************************************************************
180 Client entry functions
182 ******************************************************************************/
184 /* Add new client entry. This adds the client entry to ID cache system
185 and returns the allocated client entry or NULL on error. This is
186 called when new client connection is accepted to the server. */
189 silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
190 char *username, char *userinfo, SilcClientID *id,
191 SilcServerEntry router, void *connection)
193 SilcClientEntry client;
195 SILC_LOG_DEBUG(("Adding new client entry"));
197 client = silc_calloc(1, sizeof(*client));
198 client->nickname = nickname;
199 client->username = username;
200 client->userinfo = userinfo;
202 client->router = router;
203 client->connection = connection;
204 silc_list_init(client->channels, struct SilcChannelClientEntryStruct,
207 if (!silc_idcache_add(id_list->clients, nickname, SILC_ID_CLIENT,
208 (void *)client->id, (void *)client, TRUE)) {
216 /* Free client entry. This free's everything and removes the entry
217 from ID cache. Call silc_idlist_del_data before calling this one. */
219 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
222 /* Remove from cache */
224 silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
229 silc_free(entry->nickname);
231 silc_free(entry->username);
233 silc_free(entry->userinfo);
235 silc_free(entry->id);
239 /* Returns all clients matching requested nickname. Number of clients is
240 returned to `clients_count'. Caller must free the returned table. */
243 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
244 char *server, unsigned int *clients_count)
246 SilcIDCacheList list = NULL;
247 SilcIDCacheEntry id_cache = NULL;
248 SilcClientEntry *clients;
251 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
254 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
257 silc_idcache_list_first(list, &id_cache);
258 clients[i++] = (SilcClientEntry)id_cache->context;
260 while (silc_idcache_list_next(list, &id_cache))
261 clients[i++] = (SilcClientEntry)id_cache->context;
263 silc_idcache_list_free(list);
271 /* Returns all clients matching requested nickname. Number of clients is
272 returned to `clients_count'. Caller must free the returned table. */
275 silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
277 unsigned int *clients_count)
279 SilcIDCacheList list = NULL;
280 SilcIDCacheEntry id_cache = NULL;
281 SilcClientEntry *clients;
282 unsigned char hash[32];
285 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
287 if (!silc_idcache_find_by_data(id_list->clients, hash, &list))
290 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
293 silc_idcache_list_first(list, &id_cache);
294 clients[i++] = (SilcClientEntry)id_cache->context;
296 while (silc_idcache_list_next(list, &id_cache))
297 clients[i++] = (SilcClientEntry)id_cache->context;
299 silc_idcache_list_free(list);
307 /* Finds client entry by nickname. */
310 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
311 char *server, SilcIDCacheEntry *ret_entry)
313 SilcIDCacheList list = NULL;
314 SilcIDCacheEntry id_cache = NULL;
315 SilcClientEntry client = NULL;
317 SILC_LOG_DEBUG(("Client by nickname"));
320 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
324 while (silc_idcache_list_next(list, &id_cache)) {
325 client = (SilcClientEntry)id_cache->context;
327 if (!strcmp(server, XXX, strlen(server)))
334 silc_idcache_list_free(list);
339 if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
342 client = (SilcClientEntry)id_cache->context;
345 *ret_entry = id_cache;
348 SILC_LOG_DEBUG(("Found"));
353 /* Finds client by nickname hash. */
356 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
357 SilcHash md5hash, SilcIDCacheEntry *ret_entry)
359 SilcIDCacheList list = NULL;
360 SilcIDCacheEntry id_cache = NULL;
361 SilcClientEntry client = NULL;
362 unsigned char hash[32];
364 SILC_LOG_DEBUG(("Client by hash"));
366 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
368 if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
369 SILC_ID_CLIENT, &list))
372 if (!silc_idcache_list_first(list, &id_cache)) {
373 silc_idcache_list_free(list);
378 client = (SilcClientEntry)id_cache->context;
380 if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
386 if (!silc_idcache_list_next(list, &id_cache))
390 silc_idcache_list_free(list);
393 *ret_entry = id_cache;
395 SILC_LOG_DEBUG(("Found"));
400 /* Finds client by Client ID */
403 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
404 SilcIDCacheEntry *ret_entry)
406 SilcIDCacheEntry id_cache = NULL;
407 SilcClientEntry client;
412 SILC_LOG_DEBUG(("Client ID (%s)",
413 silc_id_render(id, SILC_ID_CLIENT)));
415 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id,
416 SILC_ID_CLIENT, &id_cache))
419 client = (SilcClientEntry)id_cache->context;
422 *ret_entry = id_cache;
424 SILC_LOG_DEBUG(("Found"));
429 /* Replaces old Client ID with new one */
432 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
433 SilcClientID *new_id)
435 SilcIDCacheEntry id_cache = NULL;
436 SilcClientEntry client;
438 if (!old_id || !new_id)
441 SILC_LOG_DEBUG(("Replacing Client ID"));
443 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id,
444 SILC_ID_CLIENT, &id_cache))
447 client = (SilcClientEntry)id_cache->context;
448 silc_free(client->id);
450 id_cache->id = (void *)new_id;
452 /* If the old ID Cache data was the hash value of the old Client ID
453 replace it with the hash of new Client ID */
454 if (id_cache->data && !SILC_ID_COMPARE_HASH(old_id, id_cache->data)) {
455 silc_free(id_cache->data);
456 id_cache->data = silc_calloc(sizeof(new_id->hash), sizeof(unsigned char));
457 memcpy(id_cache->data, new_id->hash, sizeof(new_id->hash));
458 silc_idcache_sort_by_data(id_list->clients);
465 /******************************************************************************
467 Channel entry functions
469 ******************************************************************************/
471 /* Add new channel entry. This add the new channel entry to the ID cache
472 system and returns the allocated entry or NULL on error. */
475 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
476 SilcChannelID *id, SilcServerEntry router,
477 SilcCipher channel_key)
479 SilcChannelEntry channel;
481 channel = silc_calloc(1, sizeof(*channel));
482 channel->channel_name = channel_name;
483 channel->mode = mode;
485 channel->router = router;
486 channel->channel_key = channel_key;
487 silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct,
490 if (!silc_idcache_add(id_list->channels, channel->channel_name,
491 SILC_ID_CHANNEL, (void *)channel->id,
492 (void *)channel, TRUE)) {
500 /* Free channel entry. This free's everything. */
502 void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
505 SilcChannelClientEntry chl;
507 /* Remove from cache */
509 silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
513 if (entry->channel_name)
514 silc_free(entry->channel_name);
516 silc_free(entry->id);
518 silc_free(entry->topic);
519 if (entry->channel_key)
520 silc_cipher_free(entry->channel_key);
522 memset(entry->key, 0, entry->key_len / 8);
523 silc_free(entry->key);
525 memset(entry->iv, 0, sizeof(entry->iv));
527 silc_list_start(entry->user_list);
528 while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
529 silc_list_del(entry->user_list, chl);
535 /* Finds channel by channel name. Channel names are unique and they
536 are not case-sensitive. */
539 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
540 SilcIDCacheEntry *ret_entry)
542 SilcIDCacheList list = NULL;
543 SilcIDCacheEntry id_cache = NULL;
544 SilcChannelEntry channel;
546 SILC_LOG_DEBUG(("Channel by name"));
548 if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
551 if (!silc_idcache_list_first(list, &id_cache)) {
552 silc_idcache_list_free(list);
556 channel = (SilcChannelEntry)id_cache->context;
559 *ret_entry = id_cache;
561 silc_idcache_list_free(list);
563 SILC_LOG_DEBUG(("Found"));
568 /* Finds channel by Channel ID. */
571 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
572 SilcIDCacheEntry *ret_entry)
574 SilcIDCacheEntry id_cache = NULL;
575 SilcChannelEntry channel;
580 SILC_LOG_DEBUG(("Channel ID (%s)",
581 silc_id_render(id, SILC_ID_CHANNEL)));
583 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id,
584 SILC_ID_CHANNEL, &id_cache))
587 channel = (SilcChannelEntry)id_cache->context;
590 *ret_entry = id_cache;
592 SILC_LOG_DEBUG(("Found"));