Major rewrite of ID Cache system. Support added for the new
[silc.git] / apps / silcd / idlist.c
1 /*
2
3   idlist.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
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.
13   
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.
18
19 */
20 /*
21  * $Id$
22  * $Log$
23  * Revision 1.5  2000/07/12 05:59:41  priikone
24  *      Major rewrite of ID Cache system. Support added for the new
25  *      ID cache system. Major rewrite of ID List stuff on server.  All
26  *      SilcXXXList's are now called SilcXXXEntry's and they are pointers
27  *      by default. A lot rewritten ID list functions.
28  *
29  * Revision 1.4  2000/07/06 07:16:13  priikone
30  *      Added SilcPublicKey's
31  *
32  * Revision 1.3  2000/07/05 06:14:01  priikone
33  *      Global costemic changes.
34  *
35  * Revision 1.2  2000/07/03 05:52:11  priikone
36  *      Fixed typo and a bug.
37  *
38  * Revision 1.1.1.1  2000/06/27 11:36:56  priikone
39  *      Imported from internal CVS/Added Log headers.
40  *
41  *
42  */
43
44 #include "serverincludes.h"
45 #include "idlist.h"
46
47 /******************************************************************************
48
49                           Server entry functions
50
51 ******************************************************************************/
52
53 /* Add new server entry. This adds the new server entry to ID cache and
54    returns the allocated entry object or NULL on error. This is called
55    when new server connects to us. We also add ourselves to cache with
56    this function. */
57
58 SilcServerEntry 
59 silc_idlist_add_server(SilcIDList id_list, 
60                        char *server_name, int server_type,
61                        SilcServerID *id, SilcServerEntry router,
62                        SilcCipher send_key, SilcCipher receive_key,
63                        SilcPKCS pkcs, SilcHmac hmac, 
64                        SilcPublicKey public_key, void *connection)
65 {
66   SilcServerEntry server;
67
68   SILC_LOG_DEBUG(("Adding new server entry"));
69
70   server = silc_calloc(1, sizeof(*server));
71   server->server_name = server_name;
72   server->server_type = server_type;
73   server->id = id;
74   server->router = router;
75   server->send_key = send_key;
76   server->receive_key = receive_key;
77   server->pkcs = pkcs;
78   server->hmac = hmac;
79   server->public_key = public_key;
80   server->connection = connection;
81
82   if (!silc_idcache_add(id_list->servers, server->server_name, SILC_ID_SERVER,
83                         (void *)server->id, (void *)server, TRUE)) {
84     silc_free(server);
85     return NULL;
86   }
87
88   return server;
89 }
90
91 /******************************************************************************
92
93                           Client entry functions
94
95 ******************************************************************************/
96
97 /* Add new client entry. This adds the client entry to ID cache system
98    and returns the allocated client entry or NULL on error.  This is
99    called when new client connection is accepted to the server. */
100
101 SilcClientEntry
102 silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
103                        char *userinfo, SilcClientID *id, 
104                        SilcServerEntry router,
105                        SilcCipher send_key, SilcCipher receive_key,
106                        SilcPKCS pkcs, SilcHmac hmac, 
107                        SilcPublicKey public_key, void *connection)
108 {
109   SilcClientEntry client;
110
111   SILC_LOG_DEBUG(("Adding new client entry"));
112
113   client = silc_calloc(1, sizeof(*client));
114   client->nickname = nickname;
115   client->username = username;
116   client->userinfo = userinfo;
117   client->id = id;
118   client->router = router;
119   client->send_key = send_key;
120   client->receive_key = receive_key;
121   client->pkcs = pkcs;
122   client->hmac = hmac;
123   client->public_key = public_key;
124   client->connection = connection;
125
126   if (!silc_idcache_add(id_list->clients, client->nickname, SILC_ID_CLIENT,
127                         (void *)client->id, (void *)client, TRUE)) {
128     silc_free(client);
129     return NULL;
130   }
131
132   return client;
133 }
134
135 /* Free client entry. This free's everything and removes the entry
136    from ID cache. */
137
138 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
139 {
140   if (entry) {
141     /* Remove from cache */
142     if (entry->id)
143       silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT, 
144                              (void *)entry->id);
145
146     /* Free data */
147     if (entry->nickname)
148       silc_free(entry->nickname);
149     if (entry->username)
150       silc_free(entry->username);
151     if (entry->userinfo)
152       silc_free(entry->userinfo);
153     if (entry->id)
154       silc_free(entry->id);
155     if (entry->send_key)
156       silc_cipher_free(entry->send_key);
157     if (entry->receive_key)
158       silc_cipher_free(entry->receive_key);
159     if (entry->pkcs)
160       silc_pkcs_free(entry->pkcs);
161     if (entry->public_key)
162       silc_pkcs_public_key_free(entry->public_key);
163     if (entry->hmac)
164       silc_hmac_free(entry->hmac);
165     if (entry->hmac_key) {
166       memset(entry->hmac_key, 0, entry->hmac_key_len);
167       silc_free(entry->hmac_key);
168     }
169   }
170 }
171
172 /* Finds client entry by nickname. */
173
174 SilcClientEntry
175 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
176                                     char *server)
177 {
178   SilcIDCacheList list = NULL;
179   SilcIDCacheEntry id_cache = NULL;
180   SilcClientEntry client = NULL;
181
182   SILC_LOG_DEBUG(("Finding client by nickname"));
183
184   if (server) {
185     if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
186       return NULL;
187
188 #if 0
189     while (silc_idcache_list_next(list, &id_cache)) {
190       client = (SilcClientEntry)id_cache->context;
191
192       if (!strcmp(server, XXX, strlen(server)))
193         break;
194
195       client = NULL;
196     }
197 #endif
198
199    if (!client)
200      return NULL;
201
202    silc_idcache_list_free(list);
203   } else {
204     if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
205       return NULL;
206
207     client = (SilcClientEntry)id_cache->context;
208   }
209
210   return client;
211 }
212
213 /* Finds client by nickname hash. */
214
215 SilcClientEntry
216 silc_idlist_find_client_by_hash(SilcIDList id_list, unsigned char *hash,
217                                 SilcHash md5hash)
218 {
219
220   return NULL;
221 }
222
223 /* Finds client by Client ID */
224
225 SilcClientEntry
226 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id)
227 {
228   SilcIDCacheEntry id_cache = NULL;
229   SilcClientEntry client;
230
231   if (!id)
232     return NULL;
233
234   SILC_LOG_DEBUG(("Finding client by ID"));
235
236   if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id, 
237                                    SILC_ID_CLIENT, &id_cache))
238     return NULL;
239
240   client = (SilcClientEntry)id_cache->context;
241
242   return client;
243 }
244
245 /******************************************************************************
246
247                           Channel entry functions
248
249 ******************************************************************************/
250
251 /* Add new channel entry. This add the new channel entry to the ID cache
252    system and returns the allocated entry or NULL on error. */
253
254 SilcChannelEntry
255 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
256                         SilcChannelID *id, SilcServerEntry router,
257                         SilcCipher channel_key)
258 {
259   SilcChannelEntry channel;
260
261   channel = silc_calloc(1, sizeof(*channel));
262   channel->channel_name = channel_name;
263   channel->mode = mode;
264   channel->id = id;
265   channel->router = router;
266   channel->channel_key = channel_key;
267
268   if (!silc_idcache_add(id_list->channels, channel->channel_name, 
269                         SILC_ID_CHANNEL, (void *)channel->id, 
270                         (void *)channel, TRUE)) {
271     silc_free(channel);
272     return NULL;
273   }
274
275   return channel;
276 }
277
278 /* Free channel entry.  This free's everything. */
279
280 void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
281 {
282   if (entry) {
283     /* Remove from cache */
284     if (entry->id)
285       silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL, 
286                              (void *)entry->id);
287
288     /* Free data */
289     if (entry->channel_name)
290       silc_free(entry->channel_name);
291     if (entry->id)
292       silc_free(entry->id);
293     if (entry->topic)
294       silc_free(entry->topic);
295     if (entry->channel_key)
296       silc_cipher_free(entry->channel_key);
297     if (entry->key) {
298       memset(entry->key, 0, entry->key_len / 8);
299       silc_free(entry->key);
300     }
301     memset(entry->iv, 0, sizeof(entry->iv));
302
303     if (entry->user_list_count)
304       silc_free(entry->user_list);
305   }
306 }
307
308 /* Finds channel by channel name. Channel names are unique and they
309    are not case-sensitive. */
310
311 SilcChannelEntry
312 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name)
313 {
314   SilcIDCacheList list = NULL;
315   SilcIDCacheEntry id_cache = NULL;
316   SilcChannelEntry channel;
317
318   SILC_LOG_DEBUG(("Finding channel by name"));
319
320   if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
321     return NULL;
322   
323   if (!silc_idcache_list_first(list, &id_cache))
324     return NULL;
325
326   channel = (SilcChannelEntry)id_cache->context;
327
328   silc_idcache_list_free(list);
329
330   return channel;
331 }
332
333 /* Finds channel by Channel ID. */
334
335 SilcChannelEntry
336 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id)
337 {
338   SilcIDCacheEntry id_cache = NULL;
339   SilcChannelEntry channel;
340
341   if (!id)
342     return NULL;
343
344   SILC_LOG_DEBUG(("Finding channel by ID"));
345
346   if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id, 
347                                    SILC_ID_CHANNEL, &id_cache))
348     return NULL;
349
350   channel = (SilcChannelEntry)id_cache->context;
351
352   return channel;
353 }