Added SilcPublicKey's
[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.4  2000/07/06 07:16:13  priikone
24  *      Added SilcPublicKey's
25  *
26  * Revision 1.3  2000/07/05 06:14:01  priikone
27  *      Global costemic changes.
28  *
29  * Revision 1.2  2000/07/03 05:52:11  priikone
30  *      Fixed typo and a bug.
31  *
32  * Revision 1.1.1.1  2000/06/27 11:36:56  priikone
33  *      Imported from internal CVS/Added Log headers.
34  *
35  *
36  */
37
38 #include "serverincludes.h"
39 #include "idlist.h"
40
41 /* Adds a new server to the list. The pointer sent as argument is allocated
42    and returned. */
43
44 void silc_idlist_add_server(SilcServerList **list, 
45                             char *server_name, int server_type,
46                             SilcServerID *id, SilcServerList *router,
47                             SilcCipher send_key, SilcCipher receive_key,
48                             SilcPKCS public_key, SilcHmac hmac, 
49                             SilcServerList **new_idlist)
50 {
51   SilcServerList *last, *idlist;
52
53   SILC_LOG_DEBUG(("Adding new server to id list"));
54
55   idlist = silc_calloc(1, sizeof(*idlist));
56   if (idlist == NULL) {
57     SILC_LOG_ERROR(("Could not allocate new server list object"));
58     *new_idlist = NULL;
59     return;
60   }
61
62   /* Set the pointers */
63   idlist->server_name = server_name;
64   idlist->server_type = server_type;
65   idlist->id = id;
66   idlist->router = router;
67   idlist->send_key = send_key;
68   idlist->receive_key = receive_key;
69   idlist->pkcs = public_key;
70   idlist->hmac = hmac;
71   idlist->next = idlist;
72   idlist->prev = idlist;
73
74   /* First on the list? */
75   if (!*list) {
76     *list = idlist;
77     *new_idlist = idlist;
78     return;
79   }
80
81   /* Add it to the list */
82   last = (*list)->prev;
83   last->next = idlist;
84   (*list)->prev = idlist;
85   idlist->next = (*list);
86   idlist->prev = last;
87
88   if (new_idlist)
89     *new_idlist = idlist;
90 }
91
92 /* Adds a new client to the client list. This is called when new client 
93    connection is accepted to the server. This adds all the relevant data 
94    about the client and session with it to the list. This list is 
95    referenced for example when sending message to the client. */
96
97 void silc_idlist_add_client(SilcClientList **list, char *nickname,
98                             char *username, char *userinfo,
99                             SilcClientID *id, SilcServerList *router,
100                             SilcCipher send_key, SilcCipher receive_key,
101                             SilcPKCS public_key, SilcHmac hmac, 
102                             SilcClientList **new_idlist)
103 {
104   SilcClientList *last, *idlist;
105
106   SILC_LOG_DEBUG(("Adding new client to id list"));
107
108   idlist = silc_calloc(1, sizeof(*idlist));
109   if (idlist == NULL) {
110     SILC_LOG_ERROR(("Could not allocate new client list object"));
111     return;
112   }
113
114   /* Set the pointers */
115   idlist->nickname = nickname;
116   idlist->username = username;
117   idlist->userinfo = userinfo;
118   idlist->id = id;
119   idlist->router = router;
120   idlist->send_key = send_key;
121   idlist->receive_key = receive_key;
122   idlist->pkcs = public_key;
123   idlist->hmac = hmac;
124   idlist->next = idlist;
125   idlist->prev = idlist;
126
127   /* First on the list? */
128   if (!(*list)) {
129     *list = idlist;
130     if (new_idlist)
131       *new_idlist = idlist;
132     return;
133   }
134
135   /* Add it to the list */
136   last = (*list)->prev;
137   last->next = idlist;
138   (*list)->prev = idlist;
139   idlist->next = *list;
140   idlist->prev = last;
141
142   if (new_idlist)
143     *new_idlist = idlist;
144 }
145
146 /* Free client entry.  This free's everything. */
147
148 void silc_idlist_del_client(SilcClientList **list, SilcClientList *entry)
149 {
150   if (entry) {
151     if (entry->nickname)
152       silc_free(entry->nickname);
153     if (entry->username)
154       silc_free(entry->username);
155     if (entry->userinfo)
156       silc_free(entry->userinfo);
157     if (entry->id)
158       silc_free(entry->id);
159     if (entry->send_key)
160       silc_cipher_free(entry->send_key);
161     if (entry->receive_key)
162       silc_cipher_free(entry->receive_key);
163     if (entry->pkcs)
164       silc_pkcs_free(entry->pkcs);
165     if (entry->hmac)
166       silc_hmac_free(entry->hmac);
167     if (entry->hmac_key) {
168       memset(entry->hmac_key, 0, entry->hmac_key_len);
169       silc_free(entry->hmac_key);
170     }
171
172     /* Last one in list? */
173     if (*list == entry && entry->next == entry) {
174       *list = NULL;
175       silc_free(entry);
176       return;
177     }
178
179     /* At the start of list? */
180     if (*list == entry && entry->next != entry) {
181       *list = entry->next;
182       entry->next->prev = entry->prev;
183       entry->prev->next = *list;
184       silc_free(entry);
185       return;
186     }
187
188     /* Remove from list */
189     entry->prev->next = entry->next;
190     entry->next->prev = entry->prev;
191     silc_free(entry);
192     return;
193   }
194 }
195
196 SilcClientList *
197 silc_idlist_find_client_by_nickname(SilcClientList *list,
198                                     char *nickname,
199                                     char *server)
200 {
201   SilcClientList *first, *entry;
202
203   SILC_LOG_DEBUG(("Finding client by nickname"));
204
205   if (!list)
206     return NULL;
207
208   first = entry = list;
209   if (!strcmp(entry->nickname, nickname)) {
210     SILC_LOG_DEBUG(("Found"));
211     return entry;
212   }
213   entry = entry->next;
214
215   while(entry != first) {
216     if (!strcmp(entry->nickname, nickname)) {
217       SILC_LOG_DEBUG(("Found"));
218       return entry;
219     }
220
221     entry = entry->next;
222   }
223
224   return NULL;
225 }
226
227 SilcClientList *
228 silc_idlist_find_client_by_hash(SilcClientList *list,
229                                 char *nickname, SilcHash md5hash)
230 {
231   SilcClientList *first, *entry;
232   unsigned char hash[16];
233
234   SILC_LOG_DEBUG(("Finding client by nickname hash"));
235
236   if (!list)
237     return NULL;
238
239   /* Make hash of the nickname */
240   silc_hash_make(md5hash, nickname, strlen(nickname), hash);
241
242   first = entry = list;
243   if (entry && !SILC_ID_COMPARE_HASH(entry->id, hash)) {
244     SILC_LOG_DEBUG(("Found"));
245     return entry;
246   }
247   entry = entry->next;
248
249   while(entry != first) {
250     if (entry && !SILC_ID_COMPARE_HASH(entry->id, hash)) {
251       SILC_LOG_DEBUG(("Found"));
252       return entry;
253     }
254
255     entry = entry->next;
256   }
257
258   return NULL;
259 }
260
261 SilcClientList *
262 silc_idlist_find_client_by_id(SilcClientList *list, SilcClientID *id)
263 {
264   SilcClientList *first, *entry;
265
266   SILC_LOG_DEBUG(("Finding client by Client ID"));
267
268   if (!list)
269     return NULL;
270
271   first = entry = list;
272   if (entry && !SILC_ID_CLIENT_COMPARE(entry->id, id)) {
273     SILC_LOG_DEBUG(("Found"));
274     return entry;
275   }
276   entry = entry->next;
277
278   while(entry != first) {
279     if (entry && !SILC_ID_CLIENT_COMPARE(entry->id, id)) {
280       SILC_LOG_DEBUG(("Found"));
281       return entry;
282     }
283
284     entry = entry->next;
285   }
286
287   return NULL;
288 }
289
290 /* Adds new channel to the list. */
291
292 void silc_idlist_add_channel(SilcChannelList **list, 
293                              char *channel_name, int mode,
294                              SilcChannelID *id, SilcServerList *router,
295                              SilcCipher channel_key,
296                              SilcChannelList **new_idlist)
297 {
298   SilcChannelList *last, *idlist;
299
300   SILC_LOG_DEBUG(("Adding new channel to id list"));
301
302   idlist = silc_calloc(1, sizeof(*idlist));
303   if (idlist == NULL) {
304     SILC_LOG_ERROR(("Could not allocate new channel list object"));
305     return;
306   }
307
308   /* Set the pointers */
309   idlist->channel_name = channel_name;
310   idlist->mode = mode;
311   idlist->id = id;
312   idlist->router = router;
313   idlist->channel_key = channel_key;
314   idlist->next = idlist;
315   idlist->prev = idlist;
316
317   /* First on the list? */
318   if (!*list) {
319     *list = idlist;
320     if (new_idlist)
321       *new_idlist = idlist;
322     return;
323   }
324
325   /* Add it to the list */
326   last = (*list)->prev;
327   last->next = idlist;
328   (*list)->prev = idlist;
329   idlist->next = (*list);
330   idlist->prev = last;
331
332   if (new_idlist)
333     *new_idlist = idlist;
334 }
335
336 SilcChannelList *
337 silc_idlist_find_channel_by_id(SilcChannelList *list, SilcChannelID *id)
338 {
339   SilcChannelList *first, *entry;
340
341   SILC_LOG_DEBUG(("Finding channel by Channel ID"));
342
343   if (!list)
344     return NULL;
345
346   first = entry = list;
347   if (entry && !SILC_ID_CHANNEL_COMPARE(entry->id, id)) {
348     SILC_LOG_DEBUG(("Found"));
349     return entry;
350   }
351   entry = entry->next;
352
353   while(entry != first) {
354     if (entry && !SILC_ID_CHANNEL_COMPARE(entry->id, id)) {
355       SILC_LOG_DEBUG(("Found"));
356       return entry;
357     }
358
359     entry = entry->next;
360   }
361
362   return NULL;
363 }
364
365 /* Free channel entry.  This free's everything. */
366
367 void silc_idlist_del_channel(SilcChannelList **list, SilcChannelList *entry)
368 {
369   if (entry) {
370     if (entry->channel_name)
371       silc_free(entry->channel_name);
372     if (entry->id)
373       silc_free(entry->id);
374     if (entry->topic)
375       silc_free(entry->topic);
376     if (entry->channel_key)
377       silc_cipher_free(entry->channel_key);
378     if (entry->key) {
379       memset(entry->key, 0, entry->key_len / 8);
380       silc_free(entry->key);
381     }
382     memset(entry->iv, 0, sizeof(entry->iv));
383
384     if (entry->user_list_count)
385       silc_free(entry->user_list);
386
387     /* Last one in list? */
388     if (*list == entry && entry->next == entry) {
389       *list = NULL;
390       silc_free(entry);
391       return;
392     }
393
394     /* At the start of list? */
395     if (*list == entry && entry->next != entry) {
396       *list = entry->next;
397       entry->next->prev = entry->prev;
398       entry->prev->next = *list;
399       silc_free(entry);
400       return;
401     }
402
403     /* Remove from list */
404     entry->prev->next = entry->next;
405     entry->next->prev = entry->prev;
406     silc_free(entry);
407     return;
408   }
409 }