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);
176 memset(entry, 'F', sizeof(*entry));
181 /******************************************************************************
183 Client entry functions
185 ******************************************************************************/
187 /* Add new client entry. This adds the client entry to ID cache system
188 and returns the allocated client entry or NULL on error. This is
189 called when new client connection is accepted to the server. If The
190 `router' is provided then the all server routines assume that the client
191 is not directly connected local client but it has router set and is
192 remote. If this is the case then `connection' must be NULL. If, on the
193 other hand, the `connection' is provided then the client is assumed
194 to be directly connected local client and `router' must be NULL. */
197 silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
198 char *username, char *userinfo, SilcClientID *id,
199 SilcServerEntry router, void *connection)
201 SilcClientEntry client;
203 SILC_LOG_DEBUG(("Adding new client entry"));
205 client = silc_calloc(1, sizeof(*client));
206 client->nickname = nickname;
207 client->username = username;
208 client->userinfo = userinfo;
210 client->router = router;
211 client->connection = connection;
212 silc_list_init(client->channels, struct SilcChannelClientEntryStruct,
215 if (!silc_idcache_add(id_list->clients, nickname, SILC_ID_CLIENT,
216 (void *)client->id, (void *)client, TRUE)) {
224 /* Free client entry. This free's everything and removes the entry
225 from ID cache. Call silc_idlist_del_data before calling this one. */
227 int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
230 /* Remove from cache */
232 if (!silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
238 silc_free(entry->nickname);
240 silc_free(entry->username);
242 silc_free(entry->userinfo);
244 silc_free(entry->id);
246 memset(entry, 'F', sizeof(*entry));
255 /* Returns all clients matching requested nickname. Number of clients is
256 returned to `clients_count'. Caller must free the returned table. */
259 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
260 char *server, unsigned int *clients_count)
262 SilcIDCacheList list = NULL;
263 SilcIDCacheEntry id_cache = NULL;
264 SilcClientEntry *clients;
267 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
270 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
273 silc_idcache_list_first(list, &id_cache);
274 clients[i++] = (SilcClientEntry)id_cache->context;
276 while (silc_idcache_list_next(list, &id_cache))
277 clients[i++] = (SilcClientEntry)id_cache->context;
279 silc_idcache_list_free(list);
287 /* Returns all clients matching requested nickname. Number of clients is
288 returned to `clients_count'. Caller must free the returned table. */
291 silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
293 unsigned int *clients_count)
295 SilcIDCacheList list = NULL;
296 SilcIDCacheEntry id_cache = NULL;
297 SilcClientEntry *clients;
298 unsigned char hash[32];
301 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
303 if (!silc_idcache_find_by_data(id_list->clients, hash, &list))
306 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
309 silc_idcache_list_first(list, &id_cache);
310 clients[i++] = (SilcClientEntry)id_cache->context;
312 while (silc_idcache_list_next(list, &id_cache))
313 clients[i++] = (SilcClientEntry)id_cache->context;
315 silc_idcache_list_free(list);
323 /* Finds client entry by nickname. */
326 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
327 char *server, SilcIDCacheEntry *ret_entry)
329 SilcIDCacheList list = NULL;
330 SilcIDCacheEntry id_cache = NULL;
331 SilcClientEntry client = NULL;
333 SILC_LOG_DEBUG(("Client by nickname"));
336 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
340 while (silc_idcache_list_next(list, &id_cache)) {
341 client = (SilcClientEntry)id_cache->context;
343 if (!strcmp(server, XXX, strlen(server)))
350 silc_idcache_list_free(list);
355 if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
358 client = (SilcClientEntry)id_cache->context;
361 *ret_entry = id_cache;
364 SILC_LOG_DEBUG(("Found"));
369 /* Finds client by nickname hash. */
372 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
373 SilcHash md5hash, SilcIDCacheEntry *ret_entry)
375 SilcIDCacheList list = NULL;
376 SilcIDCacheEntry id_cache = NULL;
377 SilcClientEntry client = NULL;
378 unsigned char hash[32];
380 SILC_LOG_DEBUG(("Client by hash"));
382 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
384 if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
385 SILC_ID_CLIENT, &list))
388 if (!silc_idcache_list_first(list, &id_cache)) {
389 silc_idcache_list_free(list);
394 client = (SilcClientEntry)id_cache->context;
396 if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
402 if (!silc_idcache_list_next(list, &id_cache))
406 silc_idcache_list_free(list);
409 *ret_entry = id_cache;
411 SILC_LOG_DEBUG(("Found"));
416 /* Finds client by Client ID */
419 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
420 SilcIDCacheEntry *ret_entry)
422 SilcIDCacheEntry id_cache = NULL;
423 SilcClientEntry client;
428 SILC_LOG_DEBUG(("Client ID (%s)",
429 silc_id_render(id, SILC_ID_CLIENT)));
431 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id,
432 SILC_ID_CLIENT, &id_cache))
435 client = (SilcClientEntry)id_cache->context;
438 *ret_entry = id_cache;
440 SILC_LOG_DEBUG(("Found"));
445 /* Replaces old Client ID with new one */
448 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
449 SilcClientID *new_id)
451 SilcIDCacheEntry id_cache = NULL;
452 SilcClientEntry client;
454 if (!old_id || !new_id)
457 SILC_LOG_DEBUG(("Replacing Client ID"));
459 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id,
460 SILC_ID_CLIENT, &id_cache))
463 client = (SilcClientEntry)id_cache->context;
464 silc_free(client->id);
466 id_cache->id = (void *)new_id;
468 /* If the old ID Cache data was the hash value of the old Client ID
469 replace it with the hash of new Client ID */
470 if (id_cache->data && !SILC_ID_COMPARE_HASH(old_id, id_cache->data)) {
471 silc_free(id_cache->data);
472 id_cache->data = silc_calloc(sizeof(new_id->hash), sizeof(unsigned char));
473 memcpy(id_cache->data, new_id->hash, sizeof(new_id->hash));
474 silc_idcache_sort_by_data(id_list->clients);
477 SILC_LOG_DEBUG(("Replaced"));
483 /******************************************************************************
485 Channel entry functions
487 ******************************************************************************/
489 /* Add new channel entry. This add the new channel entry to the ID cache
490 system and returns the allocated entry or NULL on error. */
493 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
494 SilcChannelID *id, SilcServerEntry router,
495 SilcCipher channel_key)
497 SilcChannelEntry channel;
499 channel = silc_calloc(1, sizeof(*channel));
500 channel->channel_name = channel_name;
501 channel->mode = mode;
503 channel->router = router;
504 channel->channel_key = channel_key;
505 silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct,
508 if (!silc_idcache_add(id_list->channels, channel->channel_name,
509 SILC_ID_CHANNEL, (void *)channel->id,
510 (void *)channel, TRUE)) {
518 /* Free channel entry. This free's everything. */
520 int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
523 SilcChannelClientEntry chl;
525 /* Remove from cache */
527 if (!silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
532 if (entry->channel_name)
533 silc_free(entry->channel_name);
535 silc_free(entry->id);
537 silc_free(entry->topic);
538 if (entry->channel_key)
539 silc_cipher_free(entry->channel_key);
541 memset(entry->key, 0, entry->key_len / 8);
542 silc_free(entry->key);
545 silc_list_start(entry->user_list);
546 while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
547 silc_list_del(entry->user_list, chl);
551 memset(entry, 'F', sizeof(*entry));
559 /* Finds channel by channel name. Channel names are unique and they
560 are not case-sensitive. */
563 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
564 SilcIDCacheEntry *ret_entry)
566 SilcIDCacheList list = NULL;
567 SilcIDCacheEntry id_cache = NULL;
568 SilcChannelEntry channel;
570 SILC_LOG_DEBUG(("Channel by name"));
572 if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
575 if (!silc_idcache_list_first(list, &id_cache)) {
576 silc_idcache_list_free(list);
580 channel = (SilcChannelEntry)id_cache->context;
583 *ret_entry = id_cache;
585 silc_idcache_list_free(list);
587 SILC_LOG_DEBUG(("Found"));
592 /* Finds channel by Channel ID. */
595 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
596 SilcIDCacheEntry *ret_entry)
598 SilcIDCacheEntry id_cache = NULL;
599 SilcChannelEntry channel;
604 SILC_LOG_DEBUG(("Channel ID (%s)",
605 silc_id_render(id, SILC_ID_CHANNEL)));
607 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id,
608 SILC_ID_CHANNEL, &id_cache))
611 channel = (SilcChannelEntry)id_cache->context;
614 *ret_entry = id_cache;
616 SILC_LOG_DEBUG(("Found"));
621 /* Replaces old Channel ID with new one. This is done when router forces
622 normal server to change Channel ID. */
625 silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id,
626 SilcChannelID *new_id)
628 SilcIDCacheEntry id_cache = NULL;
629 SilcChannelEntry channel;
631 if (!old_id || !new_id)
634 SILC_LOG_DEBUG(("Replacing Channel ID"));
636 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)old_id,
637 SILC_ID_CHANNEL, &id_cache))
640 channel = (SilcChannelEntry)id_cache->context;
641 silc_free(channel->id);
642 channel->id = new_id;
643 id_cache->id = (void *)new_id;