5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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. If The
187 `router' is provided then the all server routines assume that the client
188 is not directly connected local client but it has router set and is
189 remote. If this is the case then `connection' must be NULL. If, on the
190 other hand, the `connection' is provided then the client is assumed
191 to be directly connected local client and `router' must be NULL. */
194 silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
195 char *username, char *userinfo, SilcClientID *id,
196 SilcServerEntry router, void *connection)
198 SilcClientEntry client;
200 SILC_LOG_DEBUG(("Adding new client entry"));
202 client = silc_calloc(1, sizeof(*client));
203 client->nickname = nickname;
204 client->username = username;
205 client->userinfo = userinfo;
207 client->router = router;
208 client->connection = connection;
209 silc_list_init(client->channels, struct SilcChannelClientEntryStruct,
212 if (!silc_idcache_add(id_list->clients, nickname, SILC_ID_CLIENT,
213 (void *)client->id, (void *)client, TRUE)) {
221 /* Free client entry. This free's everything and removes the entry
222 from ID cache. Call silc_idlist_del_data before calling this one. */
224 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
227 /* Remove from cache */
229 silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
234 silc_free(entry->nickname);
236 silc_free(entry->username);
238 silc_free(entry->userinfo);
240 silc_free(entry->id);
244 /* Returns all clients matching requested nickname. Number of clients is
245 returned to `clients_count'. Caller must free the returned table. */
248 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
249 char *server, unsigned int *clients_count)
251 SilcIDCacheList list = NULL;
252 SilcIDCacheEntry id_cache = NULL;
253 SilcClientEntry *clients;
256 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
259 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
262 silc_idcache_list_first(list, &id_cache);
263 clients[i++] = (SilcClientEntry)id_cache->context;
265 while (silc_idcache_list_next(list, &id_cache))
266 clients[i++] = (SilcClientEntry)id_cache->context;
268 silc_idcache_list_free(list);
276 /* Returns all clients matching requested nickname. Number of clients is
277 returned to `clients_count'. Caller must free the returned table. */
280 silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
282 unsigned int *clients_count)
284 SilcIDCacheList list = NULL;
285 SilcIDCacheEntry id_cache = NULL;
286 SilcClientEntry *clients;
287 unsigned char hash[32];
290 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
292 if (!silc_idcache_find_by_data(id_list->clients, hash, &list))
295 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
298 silc_idcache_list_first(list, &id_cache);
299 clients[i++] = (SilcClientEntry)id_cache->context;
301 while (silc_idcache_list_next(list, &id_cache))
302 clients[i++] = (SilcClientEntry)id_cache->context;
304 silc_idcache_list_free(list);
312 /* Finds client entry by nickname. */
315 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
316 char *server, SilcIDCacheEntry *ret_entry)
318 SilcIDCacheList list = NULL;
319 SilcIDCacheEntry id_cache = NULL;
320 SilcClientEntry client = NULL;
322 SILC_LOG_DEBUG(("Client by nickname"));
325 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
329 while (silc_idcache_list_next(list, &id_cache)) {
330 client = (SilcClientEntry)id_cache->context;
332 if (!strcmp(server, XXX, strlen(server)))
339 silc_idcache_list_free(list);
344 if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
347 client = (SilcClientEntry)id_cache->context;
350 *ret_entry = id_cache;
353 SILC_LOG_DEBUG(("Found"));
358 /* Finds client by nickname hash. */
361 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
362 SilcHash md5hash, SilcIDCacheEntry *ret_entry)
364 SilcIDCacheList list = NULL;
365 SilcIDCacheEntry id_cache = NULL;
366 SilcClientEntry client = NULL;
367 unsigned char hash[32];
369 SILC_LOG_DEBUG(("Client by hash"));
371 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
373 if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
374 SILC_ID_CLIENT, &list))
377 if (!silc_idcache_list_first(list, &id_cache)) {
378 silc_idcache_list_free(list);
383 client = (SilcClientEntry)id_cache->context;
385 if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
391 if (!silc_idcache_list_next(list, &id_cache))
395 silc_idcache_list_free(list);
398 *ret_entry = id_cache;
400 SILC_LOG_DEBUG(("Found"));
405 /* Finds client by Client ID */
408 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
409 SilcIDCacheEntry *ret_entry)
411 SilcIDCacheEntry id_cache = NULL;
412 SilcClientEntry client;
417 SILC_LOG_DEBUG(("Client ID (%s)",
418 silc_id_render(id, SILC_ID_CLIENT)));
420 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id,
421 SILC_ID_CLIENT, &id_cache))
424 client = (SilcClientEntry)id_cache->context;
427 *ret_entry = id_cache;
429 SILC_LOG_DEBUG(("Found"));
434 /* Replaces old Client ID with new one */
437 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
438 SilcClientID *new_id)
440 SilcIDCacheEntry id_cache = NULL;
441 SilcClientEntry client;
443 if (!old_id || !new_id)
446 SILC_LOG_DEBUG(("Replacing Client ID"));
448 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id,
449 SILC_ID_CLIENT, &id_cache))
452 client = (SilcClientEntry)id_cache->context;
453 silc_free(client->id);
455 id_cache->id = (void *)new_id;
457 /* If the old ID Cache data was the hash value of the old Client ID
458 replace it with the hash of new Client ID */
459 if (id_cache->data && !SILC_ID_COMPARE_HASH(old_id, id_cache->data)) {
460 silc_free(id_cache->data);
461 id_cache->data = silc_calloc(sizeof(new_id->hash), sizeof(unsigned char));
462 memcpy(id_cache->data, new_id->hash, sizeof(new_id->hash));
463 silc_idcache_sort_by_data(id_list->clients);
470 /******************************************************************************
472 Channel entry functions
474 ******************************************************************************/
476 /* Add new channel entry. This add the new channel entry to the ID cache
477 system and returns the allocated entry or NULL on error. */
480 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
481 SilcChannelID *id, SilcServerEntry router,
482 SilcCipher channel_key)
484 SilcChannelEntry channel;
486 channel = silc_calloc(1, sizeof(*channel));
487 channel->channel_name = channel_name;
488 channel->mode = mode;
490 channel->router = router;
491 channel->channel_key = channel_key;
492 silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct,
495 if (!silc_idcache_add(id_list->channels, channel->channel_name,
496 SILC_ID_CHANNEL, (void *)channel->id,
497 (void *)channel, TRUE)) {
505 /* Free channel entry. This free's everything. */
507 void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
510 SilcChannelClientEntry chl;
512 /* Remove from cache */
514 silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
518 if (entry->channel_name)
519 silc_free(entry->channel_name);
521 silc_free(entry->id);
523 silc_free(entry->topic);
524 if (entry->channel_key)
525 silc_cipher_free(entry->channel_key);
527 memset(entry->key, 0, entry->key_len / 8);
528 silc_free(entry->key);
530 memset(entry->iv, 0, sizeof(entry->iv));
532 silc_list_start(entry->user_list);
533 while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
534 silc_list_del(entry->user_list, chl);
540 /* Finds channel by channel name. Channel names are unique and they
541 are not case-sensitive. */
544 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
545 SilcIDCacheEntry *ret_entry)
547 SilcIDCacheList list = NULL;
548 SilcIDCacheEntry id_cache = NULL;
549 SilcChannelEntry channel;
551 SILC_LOG_DEBUG(("Channel by name"));
553 if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
556 if (!silc_idcache_list_first(list, &id_cache)) {
557 silc_idcache_list_free(list);
561 channel = (SilcChannelEntry)id_cache->context;
564 *ret_entry = id_cache;
566 silc_idcache_list_free(list);
568 SILC_LOG_DEBUG(("Found"));
573 /* Finds channel by Channel ID. */
576 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
577 SilcIDCacheEntry *ret_entry)
579 SilcIDCacheEntry id_cache = NULL;
580 SilcChannelEntry channel;
585 SILC_LOG_DEBUG(("Channel ID (%s)",
586 silc_id_render(id, SILC_ID_CHANNEL)));
588 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id,
589 SILC_ID_CHANNEL, &id_cache))
592 channel = (SilcChannelEntry)id_cache->context;
595 *ret_entry = id_cache;
597 SILC_LOG_DEBUG(("Found"));