1bc86f7c769bc8b1a00729e8ac19e4154c67ed29
[silc.git] / apps / silcd / server_util.c
1 /*
2
3   server_util.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2003 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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "serverincludes.h"
22 #include "server_internal.h"
23
24 extern char *server_version;
25
26 /* Removes the client from channels and possibly removes the channels
27    as well.  After removing those channels that exist, their channel
28    keys are regnerated. This is called only by the function
29    silc_server_remove_clients_by_server. */
30
31 static void
32 silc_server_remove_clients_channels(SilcServer server,
33                                     SilcServerEntry server_entry,
34                                     SilcHashTable clients,
35                                     SilcClientEntry client,
36                                     SilcHashTable channels)
37 {
38   SilcChannelEntry channel;
39   SilcChannelClientEntry chl, chl2;
40   SilcHashTableList htl, htl2;
41
42   if (!client)
43     return;
44
45   SILC_LOG_DEBUG(("Remove client %s from all channels",
46                  client->nickname ? client->nickname :
47                   (unsigned char *)""));
48
49   if (silc_hash_table_find(clients, client, NULL, NULL))
50     silc_hash_table_del(clients, client);
51
52   /* Remove the client from all channels. The client is removed from
53      the channels' user list. */
54   silc_hash_table_list(client->channels, &htl);
55   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
56     channel = chl->channel;
57
58     /* Remove channel if this is last client leaving the channel, unless
59        the channel is permanent. */
60     if (server->server_type != SILC_SERVER &&
61         silc_hash_table_count(channel->user_list) < 2) {
62       if (silc_hash_table_find(channels, channel, NULL, NULL))
63         silc_hash_table_del(channels, channel);
64       silc_schedule_task_del_by_context(server->schedule, channel->rekey);
65       silc_server_channel_delete(server, channel);
66       continue;
67     }
68
69     silc_hash_table_del(client->channels, channel);
70     silc_hash_table_del(channel->user_list, chl->client);
71     channel->user_count--;
72
73     /* If there is no global users on the channel anymore mark the channel
74        as local channel. Do not check if the removed client is local client. */
75     if (server->server_type != SILC_ROUTER && channel->global_users &&
76         chl->client->router && !silc_server_channel_has_global(channel))
77       channel->global_users = FALSE;
78
79     silc_free(chl);
80
81     /* Update statistics */
82     if (SILC_IS_LOCAL(client))
83       server->stat.my_chanclients--;
84     if (server->server_type == SILC_ROUTER) {
85       server->stat.cell_chanclients--;
86       server->stat.chanclients--;
87     }
88
89     /* If there is not at least one local user on the channel then we don't
90        need the channel entry anymore, we can remove it safely, unless the
91        channel is permanent channel */
92     if (server->server_type == SILC_SERVER &&
93         !silc_server_channel_has_local(channel)) {
94       if (silc_hash_table_find(channels, channel, NULL, NULL))
95         silc_hash_table_del(channels, channel);
96       silc_schedule_task_del_by_context(server->schedule, channel->rekey);
97       silc_server_channel_delete(server, channel);
98       continue;
99     }
100
101     /* Mark other local clients to the table of clients whom will receive
102        the SERVER_SIGNOFF notify. */
103     silc_hash_table_list(channel->user_list, &htl2);
104     while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
105       SilcClientEntry c = chl2->client;
106       if (!c)
107         continue;
108
109       /* Add client to table, if it's not from the signoff server */
110       if (c->router != server_entry &&
111           !silc_hash_table_find(clients, c, NULL, NULL))
112         silc_hash_table_add(clients, c, c);
113     }
114     silc_hash_table_list_reset(&htl2);
115
116     /* Add the channel to the the channels list to regenerate the
117        channel key */
118     if (!silc_hash_table_find(channels, channel, NULL, NULL))
119       silc_hash_table_add(channels, channel, channel);
120   }
121   silc_hash_table_list_reset(&htl);
122 }
123
124 /* This function removes all client entries that are originated from
125    `router' and are owned by `entry'.  `router' and `entry' can be same
126    too.  If `server_signoff' is TRUE then SERVER_SIGNOFF notify is
127    distributed to our local clients. */
128
129 bool silc_server_remove_clients_by_server(SilcServer server,
130                                           SilcServerEntry router,
131                                           SilcServerEntry entry,
132                                           bool server_signoff)
133 {
134   SilcIDCacheList list = NULL;
135   SilcIDCacheEntry id_cache = NULL;
136   SilcClientEntry client = NULL;
137   SilcBuffer idp;
138   unsigned char **argv = NULL;
139   SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
140   SilcHashTableList htl;
141   SilcChannelEntry channel;
142   SilcHashTable channels, clients;
143   int i;
144
145   if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
146     return FALSE;
147
148   SILC_LOG_DEBUG(("Removing clients by %s",
149                   entry->server_name ? entry->server_name : "server"));
150
151   if (!router)
152     router = entry;
153
154   /* Allocate the hash table that holds the channels that require
155      channel key re-generation after we've removed this server's clients
156      from the channels. */
157   channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
158                                    NULL, NULL, TRUE);
159   clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
160                                   NULL, NULL, TRUE);
161
162   if (server_signoff) {
163     idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
164     argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
165     argv_lens = silc_realloc(argv_lens,  sizeof(*argv_lens) * (argc + 1));
166     argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
167     argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
168     memcpy(argv[argc], idp->data, idp->len);
169     argv_lens[argc] = idp->len;
170     argv_types[argc] = argc + 1;
171     argc++;
172     silc_buffer_free(idp);
173   }
174
175   if (silc_idcache_get_all(server->local_list->clients, &list)) {
176     if (silc_idcache_list_first(list, &id_cache)) {
177       while (id_cache) {
178         client = (SilcClientEntry)id_cache->context;
179
180         /* If client is not registered, is not originated from `router'
181            and is not owned by `entry', skip it. */
182         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
183             client->router != router ||
184             (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
185                                                  client->id->ip.data_len))) {
186           if (!silc_idcache_list_next(list, &id_cache))
187             break;
188           else
189             continue;
190         }
191
192         if (server_signoff) {
193           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
194           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
195           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
196                                    (argc + 1));
197           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
198                                     (argc + 1));
199           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
200           memcpy(argv[argc], idp->data, idp->len);
201           argv_lens[argc] = idp->len;
202           argv_types[argc] = argc + 1;
203           argc++;
204           silc_buffer_free(idp);
205         }
206
207         /* Update statistics */
208         server->stat.clients--;
209         if (server->stat.cell_clients)
210           server->stat.cell_clients--;
211         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
212         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
213
214         silc_server_remove_clients_channels(server, entry, clients,
215                                             client, channels);
216         silc_server_del_from_watcher_list(server, client);
217
218         /* Remove the client entry */
219         if (!server_signoff) {
220           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
221           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
222         } else {
223           silc_idlist_del_data(client);
224           silc_idlist_del_client(server->local_list, client);
225         }
226
227         if (!silc_idcache_list_next(list, &id_cache))
228           break;
229       }
230     }
231     silc_idcache_list_free(list);
232   }
233
234   if (silc_idcache_get_all(server->global_list->clients, &list)) {
235
236     if (silc_idcache_list_first(list, &id_cache)) {
237       while (id_cache) {
238         client = (SilcClientEntry)id_cache->context;
239
240         /* If client is not registered, is not originated from `router'
241            and is not owned by `entry', skip it. */
242         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
243             client->router != router ||
244             (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
245                                                  client->id->ip.data_len))) {
246           if (!silc_idcache_list_next(list, &id_cache))
247             break;
248           else
249             continue;
250         }
251
252         if (server_signoff) {
253           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
254           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
255           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
256                                    (argc + 1));
257           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
258                                     (argc + 1));
259           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
260           memcpy(argv[argc], idp->data, idp->len);
261           argv_lens[argc] = idp->len;
262           argv_types[argc] = argc + 1;
263           argc++;
264           silc_buffer_free(idp);
265         }
266
267         /* Update statistics */
268         server->stat.clients--;
269         if (server->stat.cell_clients)
270           server->stat.cell_clients--;
271         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
272         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
273
274         silc_server_remove_clients_channels(server, entry, clients,
275                                             client, channels);
276         silc_server_del_from_watcher_list(server, client);
277
278         /* Remove the client entry */
279         if (!server_signoff) {
280           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
281           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
282         } else {
283           silc_idlist_del_data(client);
284           silc_idlist_del_client(server->global_list, client);
285         }
286
287         if (!silc_idcache_list_next(list, &id_cache))
288           break;
289       }
290     }
291     silc_idcache_list_free(list);
292   }
293
294   /* Return now if we are shutting down */
295   if (server->server_shutdown) {
296     silc_hash_table_free(channels);
297
298     if (server_signoff) {
299       for (i = 0; i < argc; i++)
300         silc_free(argv[i]);
301       silc_free(argv);
302       silc_free(argv_lens);
303       silc_free(argv_types);
304       silc_hash_table_free(clients);
305     }
306     return TRUE;
307   }
308
309   /* Send the SERVER_SIGNOFF notify */
310   if (server_signoff) {
311     SilcBuffer args, not;
312
313     SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
314                     silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
315
316     /* Send SERVER_SIGNOFF notify to our primary router */
317     if (server->router != entry) {
318       args = silc_argument_payload_encode(1, argv, argv_lens,
319                                           argv_types);
320       silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
321                                    SILC_BROADCAST(server),
322                                    SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
323                                    argc, args);
324       silc_buffer_free(args);
325     }
326
327     /* Send to local clients. We also send the list of client ID's that
328        is to be removed for those servers that would like to use that list. */
329     args = silc_argument_payload_encode(argc, argv, argv_lens,
330                                         argv_types);
331     not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
332                                           argc, args);
333     silc_server_packet_send_clients(server, clients,
334                                     SILC_PACKET_NOTIFY, 0, FALSE,
335                                     not->data, not->len, FALSE);
336
337     /* Send notify also to local backup routers */
338     silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
339                             not->data, not->len, FALSE, TRUE);
340
341     silc_buffer_free(args);
342     silc_buffer_free(not);
343     for (i = 0; i < argc; i++)
344       silc_free(argv[i]);
345     silc_free(argv);
346     silc_free(argv_lens);
347     silc_free(argv_types);
348     silc_hash_table_free(clients);
349   }
350
351   /* We must now re-generate the channel key for all channels that had
352      this server's client(s) on the channel. As they left the channel we
353      must re-generate the channel key. */
354   silc_hash_table_list(channels, &htl);
355   while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
356     if (!silc_server_create_channel_key(server, channel, 0)) {
357       silc_hash_table_list_reset(&htl);
358       silc_hash_table_free(channels);
359       return FALSE;
360     }
361
362     /* Do not send the channel key if private channel key mode is set */
363     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->channel_key)
364       continue;
365
366     silc_server_send_channel_key(server, NULL, channel,
367                                  server->server_type == SILC_ROUTER ?
368                                  FALSE : !server->standalone);
369   }
370   silc_hash_table_list_reset(&htl);
371   silc_hash_table_free(channels);
372
373   return TRUE;
374 }
375
376 static SilcServerEntry
377 silc_server_update_clients_by_real_server(SilcServer server,
378                                           SilcServerEntry from,
379                                           SilcServerEntry to,
380                                           SilcClientEntry client,
381                                           bool local,
382                                           SilcIDCacheEntry client_cache)
383 {
384   SilcServerEntry server_entry;
385   SilcIDCacheEntry id_cache = NULL;
386   SilcIDCacheList list;
387   bool tolocal = (to == server->id_entry);
388
389   if (!silc_idcache_get_all(server->local_list->servers, &list))
390     return NULL;
391
392   if (silc_idcache_list_first(list, &id_cache)) {
393     while (id_cache) {
394       server_entry = (SilcServerEntry)id_cache->context;
395       if (server_entry != from &&
396           (tolocal || server_entry != server->id_entry) &&
397           SILC_ID_COMPARE(server_entry->id, client->id,
398                           client->id->ip.data_len)) {
399         SILC_LOG_DEBUG(("Found (local) %s",
400                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
401
402         if (!server_entry->data.send_key && server_entry->router) {
403           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
404           /* If the client is not marked as local then move it to local list
405              since the server is local. */
406           if (!local) {
407             SILC_LOG_DEBUG(("Moving client to local list"));
408             silc_idcache_add(server->local_list->clients, client_cache->name,
409                              client_cache->id, client_cache->context,
410                              client_cache->expire, NULL);
411             silc_idcache_del_by_context(server->global_list->clients, client);
412           }
413           server_entry = server_entry->router;
414         } else {
415           /* If the client is not marked as local then move it to local list
416              since the server is local. */
417           if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
418             SILC_LOG_DEBUG(("Moving client to local list"));
419             silc_idcache_add(server->local_list->clients, client_cache->name,
420                              client_cache->id, client_cache->context,
421                              client_cache->expire, NULL);
422             silc_idcache_del_by_context(server->global_list->clients, client);
423           }
424         }
425
426         silc_idcache_list_free(list);
427         return server_entry;
428       }
429
430       if (!silc_idcache_list_next(list, &id_cache))
431         break;
432     }
433   }
434
435   silc_idcache_list_free(list);
436
437   if (!silc_idcache_get_all(server->global_list->servers, &list))
438     return NULL;
439
440   if (silc_idcache_list_first(list, &id_cache)) {
441     while (id_cache) {
442       server_entry = (SilcServerEntry)id_cache->context;
443       if (server_entry != from && server_entry != server->id_entry &&
444           (tolocal || server_entry != server->id_entry) &&
445           SILC_ID_COMPARE(server_entry->id, client->id,
446                           client->id->ip.data_len)) {
447         SILC_LOG_DEBUG(("Found (global) %s",
448                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
449
450         if (!server_entry->data.send_key && server_entry->router) {
451           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
452           /* If the client is marked as local then move it to global list
453              since the server is global. */
454           if (local) {
455             SILC_LOG_DEBUG(("Moving client to global list"));
456             silc_idcache_add(server->global_list->clients, client_cache->name,
457                              client_cache->id, client_cache->context, 0, NULL);
458             silc_idcache_del_by_context(server->local_list->clients, client);
459           }
460           server_entry = server_entry->router;
461         } else {
462           /* If the client is marked as local then move it to global list
463              since the server is global. */
464           if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
465             SILC_LOG_DEBUG(("Moving client to global list"));
466             silc_idcache_add(server->global_list->clients, client_cache->name,
467                              client_cache->id, client_cache->context, 0, NULL);
468             silc_idcache_del_by_context(server->local_list->clients, client);
469           }
470         }
471
472         silc_idcache_list_free(list);
473         return server_entry;
474       }
475
476       if (!silc_idcache_list_next(list, &id_cache))
477         break;
478     }
479   }
480
481   silc_idcache_list_free(list);
482
483   return NULL;
484 }
485
486 /* Updates the clients that are originated from the `from' to be originated
487    from the `to'. If the `resolve_real_server' is TRUE then this will
488    attempt to figure out which clients really are originated from the
489    `from' and which are originated from a server that we have connection
490    to, when we've acting as backup router. If it is FALSE the `to' will
491    be the new source. */
492
493 void silc_server_update_clients_by_server(SilcServer server,
494                                           SilcServerEntry from,
495                                           SilcServerEntry to,
496                                           bool resolve_real_server)
497 {
498   SilcIDCacheList list = NULL;
499   SilcIDCacheEntry id_cache = NULL;
500   SilcClientEntry client = NULL;
501   bool local;
502
503   local = FALSE;
504   if (silc_idcache_get_all(server->global_list->clients, &list)) {
505     if (silc_idcache_list_first(list, &id_cache)) {
506       while (id_cache) {
507         client = (SilcClientEntry)id_cache->context;
508
509         /* If entry is disabled skip it.  If entry is local to us, do not
510            switch it to anyone else, it is ours so skip it. */
511         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
512             SILC_IS_LOCAL(client)) {
513           if (!silc_idcache_list_next(list, &id_cache))
514             break;
515           else
516             continue;
517         }
518
519         SILC_LOG_DEBUG(("Client %s",
520                         silc_id_render(client->id, SILC_ID_CLIENT)));
521         if (client->router)
522           SILC_LOG_DEBUG(("Client->router %s",
523                           silc_id_render(client->router->id, SILC_ID_SERVER)));
524
525         if (from) {
526           if (client->router == from) {
527             if (resolve_real_server) {
528               client->router =
529                 silc_server_update_clients_by_real_server(server, from, to,
530                                                           client, local,
531                                                           id_cache);
532               if (!client->router) {
533                 if (server->server_type == SILC_ROUTER)
534                   client->router = from;
535                 else
536                   client->router = to;
537               }
538             } else {
539               client->router = to;
540             }
541           }
542         } else {
543           /* All are changed */
544           client->router = to;
545         }
546
547         if (client->router)
548           SILC_LOG_DEBUG(("Client changed to %s",
549                           silc_id_render(client->router->id, SILC_ID_SERVER)));
550
551         if (!silc_idcache_list_next(list, &id_cache))
552           break;
553       }
554     }
555     silc_idcache_list_free(list);
556   }
557
558   local = TRUE;
559   if (silc_idcache_get_all(server->local_list->clients, &list)) {
560     if (silc_idcache_list_first(list, &id_cache)) {
561       while (id_cache) {
562         client = (SilcClientEntry)id_cache->context;
563
564         /* If entry is disabled skip it.  If entry is local to us, do not
565            switch it to anyone else, it is ours so skip it. */
566         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
567             SILC_IS_LOCAL(client)) {
568           if (!silc_idcache_list_next(list, &id_cache))
569             break;
570           else
571             continue;
572         }
573
574         SILC_LOG_DEBUG(("Client %s",
575                         silc_id_render(client->id, SILC_ID_CLIENT)));
576         if (client->router)
577           SILC_LOG_DEBUG(("Client->router %s",
578                           silc_id_render(client->router->id, SILC_ID_SERVER)));
579
580         if (from) {
581           if (client->router == from) {
582             if (resolve_real_server) {
583               client->router =
584                 silc_server_update_clients_by_real_server(server, from, to,
585                                                           client, local,
586                                                           id_cache);
587               if (!client->router)
588                 client->router = from;
589             } else {
590               client->router = to;
591             }
592           }
593         } else {
594           /* All are changed */
595           client->router = to;
596         }
597
598         if (client->router)
599           SILC_LOG_DEBUG(("Client changed to %s",
600                           silc_id_render(client->router->id, SILC_ID_SERVER)));
601
602         if (!silc_idcache_list_next(list, &id_cache))
603           break;
604       }
605     }
606     silc_idcache_list_free(list);
607   }
608 }
609
610 /* Updates servers that are from `from' to be originated from `to'.  This
611    will also update the server's connection to `to's connection. */
612
613 void silc_server_update_servers_by_server(SilcServer server,
614                                           SilcServerEntry from,
615                                           SilcServerEntry to)
616 {
617   SilcIDCacheList list = NULL;
618   SilcIDCacheEntry id_cache = NULL;
619   SilcServerEntry server_entry = NULL;
620
621   SILC_LOG_DEBUG(("Updating servers"));
622
623   if (silc_idcache_get_all(server->local_list->servers, &list)) {
624     if (silc_idcache_list_first(list, &id_cache)) {
625       while (id_cache) {
626         server_entry = (SilcServerEntry)id_cache->context;
627
628         /* If entry is local to us, do not switch it to any anyone else,
629            it is ours. */
630         if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
631             server_entry == from) {
632           if (!silc_idcache_list_next(list, &id_cache))
633             break;
634           else
635             continue;
636         }
637
638         /* If we are standalone router, any server that is not directly
639            connected to cannot exist anymore.  If we are not standalone
640            we update it correctly. */
641         if (server->server_type == SILC_ROUTER && server->standalone) {
642           silc_server_backup_del(server, server_entry);
643           silc_server_backup_replaced_del(server, server_entry);
644           silc_idlist_del_data(server_entry);
645           silc_idlist_del_server(server->local_list, server_entry);
646           server->stat.servers--;
647           server->stat.cell_servers--;
648         } else {
649           /* XXX if we are not standalone, do a check from local config
650              whether this server is in our cell, but not connected to
651              us (in which case we must remove it). */
652
653           if (server_entry->router == from) {
654             SILC_LOG_DEBUG(("Updating server (local) %s",
655                             server_entry->server_name ?
656                             server_entry->server_name : ""));
657             server_entry->router = to;
658             server_entry->connection = to->connection;
659           }
660         }
661
662         if (!silc_idcache_list_next(list, &id_cache))
663           break;
664       }
665     }
666     silc_idcache_list_free(list);
667   }
668
669   if (silc_idcache_get_all(server->global_list->servers, &list)) {
670     if (silc_idcache_list_first(list, &id_cache)) {
671       while (id_cache) {
672         server_entry = (SilcServerEntry)id_cache->context;
673
674         /* If entry is local to us, do not switch it to anyone else,
675            it is ours. */
676         if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
677             server_entry == from) {
678           if (!silc_idcache_list_next(list, &id_cache))
679             break;
680           else
681             continue;
682         }
683
684         /* If we are standalone router, any server that is not directly
685            connected to cannot exist anymore.  If we are not standalone
686            we update it correctly. */
687         if (server->server_type == SILC_ROUTER && server->standalone) {
688           silc_server_backup_del(server, server_entry);
689           silc_server_backup_replaced_del(server, server_entry);
690           silc_idlist_del_data(server_entry);
691           silc_idlist_del_server(server->global_list, server_entry);
692           server->stat.servers--;
693           server->stat.cell_servers--;
694         } else {
695           /* XXX if we are not standalone, do a check from local config
696              whether this server is in our cell, but not connected to
697              us (in which case we must remove it). */
698
699           if (server_entry->router == from) {
700             SILC_LOG_DEBUG(("Updating server (global) %s",
701                             server_entry->server_name ?
702                             server_entry->server_name : ""));
703             server_entry->router = to;
704             server_entry->connection = to->connection;
705           }
706         }
707
708         if (!silc_idcache_list_next(list, &id_cache))
709           break;
710       }
711     }
712     silc_idcache_list_free(list);
713   }
714 }
715
716
717 /* Toggles the enabled/disabled status of local server connections.  Packets
718    can be sent to the servers when `toggle_enabled' is TRUE and will be
719    dropped if `toggle_enabled' is FALSE, after this function is called. */
720
721 void silc_server_local_servers_toggle_enabled(SilcServer server,
722                                               bool toggle_enabled)
723 {
724   SilcIDCacheList list = NULL;
725   SilcIDCacheEntry id_cache = NULL;
726   SilcServerEntry server_entry = NULL;
727
728   if (silc_idcache_get_all(server->local_list->servers, &list)) {
729     if (silc_idcache_list_first(list, &id_cache)) {
730       while (id_cache) {
731         server_entry = (SilcServerEntry)id_cache->context;
732         if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
733           if (!silc_idcache_list_next(list, &id_cache))
734             break;
735           else
736             continue;
737         }
738
739         if (toggle_enabled)
740           server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
741         else
742           server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
743
744         if (!silc_idcache_list_next(list, &id_cache))
745           break;
746       }
747     }
748     silc_idcache_list_free(list);
749   }
750
751   if (silc_idcache_get_all(server->global_list->servers, &list)) {
752     if (silc_idcache_list_first(list, &id_cache)) {
753       while (id_cache) {
754         server_entry = (SilcServerEntry)id_cache->context;
755         if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
756           if (!silc_idcache_list_next(list, &id_cache))
757             break;
758           else
759             continue;
760         }
761
762         if (toggle_enabled)
763           server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
764         else
765           server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
766
767         if (!silc_idcache_list_next(list, &id_cache))
768           break;
769       }
770     }
771     silc_idcache_list_free(list);
772   }
773 }
774
775 /* Removes servers that are originated from the `from'.  The server
776    entry is deleted in this function.  If `remove_clients' is TRUE then
777    all clients originated from the server are removed too, and server
778    signoff is sent.  Note that this does not remove the `from'.  This
779    also does not remove locally connected servers. */
780
781 void silc_server_remove_servers_by_server(SilcServer server,
782                                           SilcServerEntry from,
783                                           bool remove_clients)
784 {
785   SilcIDCacheList list = NULL;
786   SilcIDCacheEntry id_cache = NULL;
787   SilcServerEntry server_entry = NULL;
788
789   SILC_LOG_DEBUG(("Removing servers by %s",
790                   from->server_name ? from->server_name : "server"));
791
792   if (silc_idcache_get_all(server->local_list->servers, &list)) {
793     if (silc_idcache_list_first(list, &id_cache)) {
794       while (id_cache) {
795         server_entry = (SilcServerEntry)id_cache->context;
796         if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
797           server_entry->router != from || server_entry == from) {
798           if (!silc_idcache_list_next(list, &id_cache))
799             break;
800           else
801             continue;
802         }
803
804         /* Remove clients owned by this server */
805         if (remove_clients)
806           silc_server_remove_clients_by_server(server, from, server_entry,
807                                                TRUE);
808
809         /* Remove the server */
810         silc_idlist_del_server(server->local_list, server_entry);
811
812         if (!silc_idcache_list_next(list, &id_cache))
813           break;
814       }
815     }
816     silc_idcache_list_free(list);
817   }
818
819   if (silc_idcache_get_all(server->global_list->servers, &list)) {
820     if (silc_idcache_list_first(list, &id_cache)) {
821       while (id_cache) {
822         server_entry = (SilcServerEntry)id_cache->context;
823         if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
824           server_entry->router != from || server_entry == from) {
825           if (!silc_idcache_list_next(list, &id_cache))
826             break;
827           else
828             continue;
829         }
830
831         /* Remove clients owned by this server */
832         if (remove_clients)
833           silc_server_remove_clients_by_server(server, from, server_entry,
834                                                TRUE);
835
836         /* Remove the server */
837         silc_idlist_del_server(server->global_list, server_entry);
838
839         if (!silc_idcache_list_next(list, &id_cache))
840           break;
841       }
842     }
843     silc_idcache_list_free(list);
844   }
845 }
846
847 /* Removes channels that are from `from. */
848
849 void silc_server_remove_channels_by_server(SilcServer server,
850                                            SilcServerEntry from)
851 {
852   SilcIDCacheList list = NULL;
853   SilcIDCacheEntry id_cache = NULL;
854   SilcChannelEntry channel = NULL;
855
856   SILC_LOG_DEBUG(("Removing channels by server"));
857
858   if (silc_idcache_get_all(server->global_list->channels, &list)) {
859     if (silc_idcache_list_first(list, &id_cache)) {
860       while (id_cache) {
861         channel = (SilcChannelEntry)id_cache->context;
862         if (channel->router == from)
863           silc_idlist_del_channel(server->global_list, channel);
864         if (!silc_idcache_list_next(list, &id_cache))
865           break;
866       }
867     }
868     silc_idcache_list_free(list);
869   }
870 }
871
872 /* Updates channels that are from `from' to be originated from `to'.  */
873
874 void silc_server_update_channels_by_server(SilcServer server,
875                                            SilcServerEntry from,
876                                            SilcServerEntry to)
877 {
878   SilcIDCacheList list = NULL;
879   SilcIDCacheEntry id_cache = NULL;
880   SilcChannelEntry channel = NULL;
881
882   SILC_LOG_DEBUG(("Updating channels by server"));
883
884   if (silc_idcache_get_all(server->global_list->channels, &list)) {
885     if (silc_idcache_list_first(list, &id_cache)) {
886       while (id_cache) {
887         channel = (SilcChannelEntry)id_cache->context;
888         if (channel->router == from)
889           channel->router = to;
890         if (!silc_idcache_list_next(list, &id_cache))
891           break;
892       }
893     }
894     silc_idcache_list_free(list);
895   }
896 }
897
898 /* Checks whether given channel has global users.  If it does this returns
899    TRUE and FALSE if there is only locally connected clients on the channel. */
900
901 bool silc_server_channel_has_global(SilcChannelEntry channel)
902 {
903   SilcChannelClientEntry chl;
904   SilcHashTableList htl;
905
906   silc_hash_table_list(channel->user_list, &htl);
907   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
908     if (chl->client->router) {
909       silc_hash_table_list_reset(&htl);
910       return TRUE;
911     }
912   }
913   silc_hash_table_list_reset(&htl);
914
915   return FALSE;
916 }
917
918 /* Checks whether given channel has locally connected users.  If it does this
919    returns TRUE and FALSE if there is not one locally connected client. */
920
921 bool silc_server_channel_has_local(SilcChannelEntry channel)
922 {
923   SilcChannelClientEntry chl;
924   SilcHashTableList htl;
925
926   silc_hash_table_list(channel->user_list, &htl);
927   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
928     if (SILC_IS_LOCAL(chl->client)) {
929       silc_hash_table_list_reset(&htl);
930       return TRUE;
931     }
932   }
933   silc_hash_table_list_reset(&htl);
934
935   return FALSE;
936 }
937
938 /* This function removes the channel and all users on the channel, unless
939    the channel is permanent.  In this case the channel is disabled but all
940    users are removed from the channel.  Returns TRUE if the channel is
941    destroyed totally, and FALSE if it is permanent and remains. */
942
943 bool silc_server_channel_delete(SilcServer server,
944                                 SilcChannelEntry channel)
945 {
946   SilcChannelClientEntry chl;
947   SilcHashTableList htl;
948   bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
949
950   if (delchan) {
951     /* Update statistics */
952     if (server->server_type == SILC_ROUTER)
953       server->stat.chanclients -= channel->user_count;
954
955     /* Totally delete the channel and all users on the channel. The
956        users are deleted automatically in silc_idlist_del_channel. */
957     silc_schedule_task_del_by_context(server->schedule, channel->rekey);
958     if (silc_idlist_del_channel(server->local_list, channel)) {
959       server->stat.my_channels--;
960       if (server->server_type == SILC_ROUTER) {
961         server->stat.channels--;
962         server->stat.cell_channels--;
963       }
964     } else {
965       if (silc_idlist_del_channel(server->global_list, channel))
966         if (server->server_type == SILC_ROUTER)
967           server->stat.channels--;
968     }
969
970     return FALSE;
971   }
972
973   /* Channel is permanent, do not remove it, remove only users */
974   channel->disabled = TRUE;
975   silc_hash_table_list(channel->user_list, &htl);
976   while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
977     silc_hash_table_del(chl->client->channels, channel);
978     silc_hash_table_del(channel->user_list, chl->client);
979     channel->user_count--;
980
981     /* Update statistics */
982     if (SILC_IS_LOCAL(chl->client))
983       server->stat.my_chanclients--;
984     if (server->server_type == SILC_ROUTER) {
985       server->stat.cell_chanclients--;
986       server->stat.chanclients--;
987     }
988
989     silc_free(chl);
990   }
991   silc_hash_table_list_reset(&htl);
992
993   SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
994
995   return TRUE;
996 }
997
998 /* Returns TRUE if the given client is on the channel.  FALSE if not.
999    This works because we assure that the user list on the channel is
1000    always in up to date thus we can only check the channel list from
1001    `client' which is faster than checking the user list from `channel'. */
1002
1003 bool silc_server_client_on_channel(SilcClientEntry client,
1004                                    SilcChannelEntry channel,
1005                                    SilcChannelClientEntry *chl)
1006 {
1007   if (!client || !channel)
1008     return FALSE;
1009
1010   return silc_hash_table_find(client->channels, channel, NULL,
1011                               (void **)chl);
1012 }
1013
1014 /* Checks string for bad characters and returns TRUE if they are found. */
1015
1016 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
1017 {
1018   int i;
1019
1020   for (i = 0; i < name_len; i++) {
1021     if (!isascii(name[i]))
1022       return TRUE;
1023     if (name[i] <= 32) return TRUE;
1024     if (name[i] == ' ') return TRUE;
1025     if (name[i] == '*') return TRUE;
1026     if (name[i] == '?') return TRUE;
1027     if (name[i] == ',') return TRUE;
1028     if (name[i] == '@') return TRUE;
1029     if (name[i] == '!') return TRUE;
1030   }
1031
1032   return FALSE;
1033 }
1034
1035 /* Same as silc_server_name_bad_chars but check for channel names. */
1036
1037 bool silc_server_name_bad_chchars(const char *name, SilcUInt32 name_len)
1038 {
1039   int i;
1040
1041   for (i = 0; i < name_len; i++) {
1042     if (!isascii(name[i]))
1043       return TRUE;
1044     if (name[i] <= 32) return TRUE;
1045     if (name[i] == ' ') return TRUE;
1046     if (name[i] == '*') return TRUE;
1047     if (name[i] == '?') return TRUE;
1048     if (name[i] == ',') return TRUE;
1049   }
1050
1051   return FALSE;
1052 }
1053
1054 /* Modifies the `name' if it includes bad characters and returns new
1055    allocated name that does not include bad characters. */
1056
1057 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
1058 {
1059   int i;
1060   char *newname = strdup(name);
1061
1062   for (i = 0; i < name_len; i++) {
1063     if (!isascii(newname[i])) newname[i] = '_';
1064     if (newname[i] <= 32) newname[i] = '_';
1065     if (newname[i] == ' ') newname[i] = '_';
1066     if (newname[i] == '*') newname[i] = '_';
1067     if (newname[i] == '?') newname[i] = '_';
1068     if (newname[i] == ',') newname[i] = '_';
1069   }
1070
1071   return newname;
1072 }
1073
1074 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
1075    socket connections with the IP address does not exist. */
1076
1077 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1078                                          SilcSocketType type)
1079 {
1080   int i, count;
1081
1082   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1083     if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1084         !strcmp(server->sockets[i]->ip, ip) &&
1085         server->sockets[i]->type == type)
1086       count++;
1087   }
1088
1089   return count;
1090 }
1091
1092 /* Find number of sockets by IP address indicated by remote host, indicatd
1093    by `ip' or `hostname', `port', and `type'.  Returns 0 if socket connections
1094    does not exist. If `ip' is provided then `hostname' is ignored. */
1095
1096 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1097                                              const char *ip,
1098                                              const char *hostname,
1099                                              SilcUInt16 port,
1100                                              SilcSocketType type)
1101 {
1102   int i, count;
1103
1104   if (!ip && !hostname)
1105     return 0;
1106
1107   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1108     if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1109         ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
1110          (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
1111         server->sockets[i]->port == port &&
1112         server->sockets[i]->type == type)
1113       count++;
1114   }
1115
1116   return count;
1117 }
1118
1119 /* Finds locally cached public key by the public key received in the SKE.
1120    If we have it locally cached then we trust it and will use it in the
1121    authentication protocol.  Returns the locally cached public key or NULL
1122    if we do not find the public key.  */
1123
1124 SilcPublicKey silc_server_find_public_key(SilcServer server,
1125                                           SilcHashTable local_public_keys,
1126                                           SilcPublicKey remote_public_key)
1127 {
1128   SilcPublicKey cached_key;
1129
1130   SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
1131                   silc_hash_table_count(local_public_keys)));
1132
1133   if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
1134                                 (void **)&cached_key, NULL,
1135                                 silc_hash_public_key, NULL,
1136                                 silc_hash_public_key_compare, NULL)) {
1137     SILC_LOG_ERROR(("Public key not found"));
1138     return NULL;
1139   }
1140
1141   SILC_LOG_DEBUG(("Found public key"));
1142
1143   return cached_key;
1144 }
1145
1146 /* This returns the first public key from the table of public keys.  This
1147    is used only in cases where single public key exists in the table and
1148    we want to get a pointer to it.  For public key tables that has multiple
1149    keys in it the silc_server_find_public_key must be used. */
1150
1151 SilcPublicKey silc_server_get_public_key(SilcServer server,
1152                                          SilcHashTable local_public_keys)
1153 {
1154   SilcPublicKey cached_key;
1155   SilcHashTableList htl;
1156
1157   SILC_LOG_DEBUG(("Start"));
1158
1159   assert(silc_hash_table_count(local_public_keys) < 2);
1160
1161   silc_hash_table_list(local_public_keys, &htl);
1162   if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key)) {
1163     silc_hash_table_list_reset(&htl);
1164     return NULL;
1165   }
1166   silc_hash_table_list_reset(&htl);
1167
1168   return cached_key;
1169 }
1170
1171 /* Check whether the connection `sock' is allowed to connect to us.  This
1172    checks for example whether there is too much connections for this host,
1173    and required version for the host etc. */
1174
1175 bool silc_server_connection_allowed(SilcServer server,
1176                                     SilcSocketConnection sock,
1177                                     SilcSocketType type,
1178                                     SilcServerConfigConnParams *global,
1179                                     SilcServerConfigConnParams *params,
1180                                     SilcSKE ske)
1181 {
1182   SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1183                             server->stat.my_clients :
1184                             type == SILC_SOCKET_TYPE_SERVER ?
1185                             server->stat.my_servers :
1186                             server->stat.my_routers);
1187   SilcUInt32 num_sockets, max_hosts, max_per_host;
1188   SilcUInt32 r_protocol_version, l_protocol_version;
1189   SilcUInt32 r_software_version, l_software_version;
1190   char *r_vendor_version = NULL, *l_vendor_version;
1191
1192   SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1193
1194   /* Check version */
1195
1196   l_protocol_version =
1197     silc_version_to_num(params && params->version_protocol ?
1198                         params->version_protocol :
1199                         global->version_protocol);
1200   l_software_version =
1201     silc_version_to_num(params && params->version_software ?
1202                         params->version_software :
1203                         global->version_software);
1204   l_vendor_version = (params && params->version_software_vendor ?
1205                       params->version_software_vendor :
1206                       global->version_software_vendor);
1207
1208   if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1209                                     &r_software_version, NULL,
1210                                     &r_vendor_version)) {
1211     sock->version = r_protocol_version;
1212
1213     /* Match protocol version */
1214     if (l_protocol_version && r_protocol_version &&
1215         r_protocol_version < l_protocol_version) {
1216       SILC_LOG_INFO(("Connection %s (%s) is too old version",
1217                      sock->hostname, sock->ip));
1218       sock->protocol = NULL;
1219       silc_server_disconnect_remote(server, sock,
1220                                     SILC_STATUS_ERR_BAD_VERSION,
1221                                     "You support too old protocol version");
1222       return FALSE;
1223     }
1224
1225     /* Math software version */
1226     if (l_software_version && r_software_version &&
1227         r_software_version < l_software_version) {
1228       SILC_LOG_INFO(("Connection %s (%s) is too old version",
1229                      sock->hostname, sock->ip));
1230       sock->protocol = NULL;
1231       silc_server_disconnect_remote(server, sock,
1232                                     SILC_STATUS_ERR_BAD_VERSION,
1233                                     "You support too old software version");
1234       return FALSE;
1235     }
1236
1237     /* Regex match vendor version */
1238     if (l_vendor_version && r_vendor_version &&
1239         !silc_string_match(l_vendor_version, r_vendor_version)) {
1240       SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1241                      sock->hostname, sock->ip));
1242       sock->protocol = NULL;
1243       silc_server_disconnect_remote(server, sock,
1244                                     SILC_STATUS_ERR_BAD_VERSION,
1245                                     "Your software is not supported");
1246       return FALSE;
1247     }
1248   }
1249   silc_free(r_vendor_version);
1250
1251   /* Check for maximum connections limit */
1252
1253   num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1254   max_hosts = (params ? params->connections_max : global->connections_max);
1255   max_per_host = (params ? params->connections_max_per_host :
1256                   global->connections_max_per_host);
1257
1258   if (max_hosts && conn_number >= max_hosts) {
1259     SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1260                    sock->hostname, sock->ip));
1261     sock->protocol = NULL;
1262     silc_server_disconnect_remote(server, sock,
1263                                   SILC_STATUS_ERR_RESOURCE_LIMIT,
1264                                   "Server is full, try again later");
1265     return FALSE;
1266   }
1267
1268   if (num_sockets >= max_per_host) {
1269     SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1270                    sock->hostname, sock->ip));
1271     sock->protocol = NULL;
1272     silc_server_disconnect_remote(server, sock,
1273                                   SILC_STATUS_ERR_RESOURCE_LIMIT,
1274                                   "Too many connections from your host");
1275     return FALSE;
1276   }
1277
1278   return TRUE;
1279 }
1280
1281 /* Checks that client has rights to add or remove channel modes. If any
1282    of the checks fails FALSE is returned. */
1283
1284 bool silc_server_check_cmode_rights(SilcServer server,
1285                                     SilcChannelEntry channel,
1286                                     SilcChannelClientEntry client,
1287                                     SilcUInt32 mode)
1288 {
1289   bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1290   bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1291
1292   /* Check whether has rights to change anything */
1293   if (!is_op && !is_fo)
1294     return FALSE;
1295
1296   /* Check whether has rights to change everything */
1297   if (is_op && is_fo)
1298     return TRUE;
1299
1300   /* Founder implies operator */
1301   if (is_fo)
1302     is_op = TRUE;
1303
1304   /* We know that client is channel operator, check that they are not
1305      changing anything that requires channel founder rights. Rest of the
1306      modes are available automatically for channel operator. */
1307
1308   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1309     if (is_op && !is_fo)
1310       return FALSE;
1311   } else {
1312     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1313       if (is_op && !is_fo)
1314         return FALSE;
1315     }
1316   }
1317
1318   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1319     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1320       if (is_op && !is_fo)
1321         return FALSE;
1322     }
1323   } else {
1324     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1325       if (is_op && !is_fo)
1326         return FALSE;
1327     }
1328   }
1329
1330   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1331     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1332       if (is_op && !is_fo)
1333         return FALSE;
1334     }
1335   } else {
1336     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1337       if (is_op && !is_fo)
1338         return FALSE;
1339     }
1340   }
1341
1342   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1343     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1344       if (is_op && !is_fo)
1345         return FALSE;
1346     }
1347   } else {
1348     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1349       if (is_op && !is_fo)
1350         return FALSE;
1351     }
1352   }
1353
1354   if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1355     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1356       if (is_op && !is_fo)
1357         return FALSE;
1358     }
1359   } else {
1360     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1361       if (is_op && !is_fo)
1362         return FALSE;
1363     }
1364   }
1365
1366   if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1367     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1368       if (is_op && !is_fo)
1369         return FALSE;
1370     }
1371   } else {
1372     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1373       if (is_op && !is_fo)
1374         return FALSE;
1375     }
1376   }
1377
1378   if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1379     if (!(channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)) {
1380       if (is_op && !is_fo)
1381         return FALSE;
1382     }
1383   } else {
1384     if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1385       if (is_op && !is_fo)
1386         return FALSE;
1387     }
1388   }
1389
1390   return TRUE;
1391 }
1392
1393 /* Check that the client has rights to change its user mode.  Returns
1394    FALSE if setting some mode is not allowed. */
1395
1396 bool silc_server_check_umode_rights(SilcServer server,
1397                                     SilcClientEntry client,
1398                                     SilcUInt32 mode)
1399 {
1400   bool server_op = FALSE, router_op = FALSE;
1401
1402   if (mode & SILC_UMODE_SERVER_OPERATOR) {
1403     /* Cannot set server operator mode (must use OPER command) */
1404     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1405       return FALSE;
1406   } else {
1407     /* Remove the server operator rights */
1408     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1409       server_op = TRUE;
1410   }
1411
1412   if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1413     /* Cannot set router operator mode (must use SILCOPER command) */
1414     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1415       return FALSE;
1416   } else {
1417     /* Remove the router operator rights */
1418     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1419       router_op = TRUE;
1420   }
1421
1422   if (server_op)
1423     SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1424   if (router_op)
1425     SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1426
1427   return TRUE;
1428 }
1429
1430 /* This function is used to send the notify packets and motd to the
1431    incoming client connection. */
1432
1433 void silc_server_send_connect_notifys(SilcServer server,
1434                                       SilcSocketConnection sock,
1435                                       SilcClientEntry client)
1436 {
1437   SilcIDListData idata = (SilcIDListData)client;
1438
1439   SILC_LOG_DEBUG(("Send welcome notifys"));
1440
1441   /* Send some nice info to the client */
1442   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1443                           ("Welcome to the SILC Network %s",
1444                            client->username));
1445   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1446                           ("Your host is %s, running version %s",
1447                            server->server_name, server_version));
1448
1449   if (server->server_type == SILC_ROUTER) {
1450     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1451                             ("There are %d clients, %d servers and %d "
1452                              "routers in SILC Network",
1453                              server->stat.clients, server->stat.servers,
1454                              server->stat.routers));
1455   } else {
1456     if (server->stat.clients && server->stat.servers + 1)
1457       SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1458                               ("There are %d clients, %d servers and %d "
1459                                "routers in SILC Network",
1460                                server->stat.clients, server->stat.servers,
1461                                (server->standalone ? 0 :
1462                                 !server->stat.routers ? 1 :
1463                                 server->stat.routers)));
1464   }
1465
1466   if (server->stat.cell_clients && server->stat.cell_servers + 1)
1467     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1468                             ("There are %d clients on %d server in our cell",
1469                              server->stat.cell_clients,
1470                              server->stat.cell_servers));
1471   if (server->server_type == SILC_ROUTER) {
1472     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1473                             ("I have %d clients, %d channels, %d servers and "
1474                              "%d routers",
1475                              server->stat.my_clients,
1476                              server->stat.my_channels,
1477                              server->stat.my_servers,
1478                              server->stat.my_routers));
1479   } else {
1480     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1481                             ("I have %d clients and %d channels formed",
1482                              server->stat.my_clients,
1483                              server->stat.my_channels));
1484   }
1485
1486   if (server->stat.server_ops || server->stat.router_ops)
1487     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1488                             ("There are %d server operators and %d router "
1489                              "operators online",
1490                              server->stat.server_ops,
1491                              server->stat.router_ops));
1492   if (server->stat.my_router_ops + server->stat.my_server_ops)
1493     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1494                             ("I have %d operators online",
1495                              server->stat.my_router_ops +
1496                              server->stat.my_server_ops));
1497
1498   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1499                           ("Your connection is secured with %s cipher, "
1500                            "key length %d bits",
1501                            silc_cipher_get_name(idata->send_key),
1502                            silc_cipher_get_key_len(idata->send_key)));
1503   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1504                           ("Your current nickname is %s",
1505                            client->nickname));
1506
1507   /* Send motd */
1508   silc_server_send_motd(server, sock);
1509 }
1510
1511 /* Kill the client indicated by `remote_client' sending KILLED notify
1512    to the client, to all channels client has joined and to primary
1513    router if needed.  The killed client is also removed from all channels. */
1514
1515 void silc_server_kill_client(SilcServer server,
1516                              SilcClientEntry remote_client,
1517                              const char *comment,
1518                              void *killer_id,
1519                              SilcIdType killer_id_type)
1520 {
1521   SilcBuffer killed, killer;
1522
1523   SILC_LOG_DEBUG(("Killing client %s",
1524                   silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1525
1526   /* Send the KILL notify packets. First send it to the channel, then
1527      to our primary router and then directly to the client who is being
1528      killed right now. */
1529
1530   killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1531   killer = silc_id_payload_encode(killer_id, killer_id_type);
1532
1533   /* Send KILLED notify to the channels. It is not sent to the client
1534      as it will be sent differently destined directly to the client and not
1535      to the channel. */
1536   silc_server_send_notify_on_channels(server, remote_client,
1537                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
1538                                       3, killed->data, killed->len,
1539                                       comment, comment ? strlen(comment) : 0,
1540                                       killer->data, killer->len);
1541
1542   /* Send KILLED notify to primary route */
1543   silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1544                                  SILC_BROADCAST(server), remote_client->id,
1545                                  comment, killer_id, killer_id_type);
1546
1547   /* Send KILLED notify to the client directly */
1548   if (remote_client->connection || remote_client->router)
1549     silc_server_send_notify_killed(server, remote_client->connection ?
1550                                    remote_client->connection :
1551                                    remote_client->router->connection, FALSE,
1552                                    remote_client->id, comment,
1553                                    killer_id, killer_id_type);
1554
1555   /* Remove the client from all channels. This generates new keys to the
1556      channels as well. */
1557   silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1558                                    NULL, TRUE, TRUE);
1559
1560   /* Remove the client entry, If it is locally connected then we will also
1561      disconnect the client here */
1562   if (remote_client->connection) {
1563     /* Remove locally conneted client */
1564     SilcSocketConnection sock = remote_client->connection;
1565     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1566     silc_server_close_connection(server, sock);
1567   } else {
1568     /* Update statistics */
1569     server->stat.clients--;
1570     if (server->stat.cell_clients)
1571       server->stat.cell_clients--;
1572     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1573     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1574
1575     if (SILC_IS_LOCAL(remote_client)) {
1576       server->stat.my_clients--;
1577       silc_schedule_task_del_by_context(server->schedule, remote_client);
1578       silc_idlist_del_data(remote_client);
1579     }
1580
1581     /* Remove remote client */
1582     silc_idlist_del_data(remote_client);
1583     if (!silc_idlist_del_client(server->global_list, remote_client)) {
1584       /* Remove this client from watcher list if it is */
1585       silc_server_del_from_watcher_list(server, remote_client);
1586       silc_idlist_del_client(server->local_list, remote_client);
1587     }
1588   }
1589
1590   silc_buffer_free(killer);
1591   silc_buffer_free(killed);
1592 }
1593
1594 typedef struct {
1595   SilcServer server;
1596   SilcClientEntry client;
1597   SilcNotifyType notify;
1598   const char *new_nick;
1599 } WatcherNotifyContext;
1600
1601 static void
1602 silc_server_check_watcher_list_foreach(void *key, void *context,
1603                                        void *user_context)
1604 {
1605   WatcherNotifyContext *notify = user_context;
1606   SilcClientEntry entry = context;
1607   SilcSocketConnection sock;
1608
1609   if (!context)
1610     return;
1611
1612   if (entry == notify->client)
1613     return;
1614
1615   sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1616                                       NULL, NULL);
1617   if (sock) {
1618     SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1619                     silc_id_render(entry->id, SILC_ID_CLIENT)));
1620
1621     /* Send the WATCH notify */
1622     silc_server_send_notify_watch(notify->server, sock, entry,
1623                                   notify->client,
1624                                   notify->new_nick ? notify->new_nick :
1625                                   (const char *)notify->client->nickname,
1626                                   notify->notify);
1627   }
1628 }
1629
1630 /* This function checks whether the `client' nickname is being watched
1631    by someone, and notifies the watcher of the notify change of notify
1632    type indicated by `notify'. */
1633
1634 bool silc_server_check_watcher_list(SilcServer server,
1635                                     SilcClientEntry client,
1636                                     const char *new_nick,
1637                                     SilcNotifyType notify)
1638 {
1639   unsigned char hash[16];
1640   WatcherNotifyContext n;
1641
1642   SILC_LOG_DEBUG(("Checking watcher list %s",
1643                   client->nickname ? client->nickname : (unsigned char *)""));
1644
1645   /* If the watching is rejected by the client do nothing */
1646   if (client->mode & SILC_UMODE_REJECT_WATCHING)
1647     return FALSE;
1648
1649   /* Make hash from the nick, or take it from Client ID */
1650   if (client->nickname) {
1651     char nick[128 + 1];
1652     memset(nick, 0, sizeof(nick));
1653     silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1654     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1655   } else {
1656     memset(hash, 0, sizeof(hash));
1657     memcpy(hash, client->id->hash, sizeof(client->id->hash));
1658   }
1659
1660   n.server = server;
1661   n.client = client;
1662   n.new_nick = new_nick;
1663   n.notify = notify;
1664
1665   /* Send notify to all watchers */
1666   silc_hash_table_find_foreach(server->watcher_list, hash,
1667                                silc_server_check_watcher_list_foreach, &n);
1668
1669   return TRUE;
1670 }
1671
1672 /* Remove the `client' from watcher list. After calling this the `client'
1673    is not watching any nicknames. */
1674
1675 bool silc_server_del_from_watcher_list(SilcServer server,
1676                                        SilcClientEntry client)
1677 {
1678   SilcHashTableList htl;
1679   void *key;
1680   SilcClientEntry entry;
1681   bool found = FALSE;
1682
1683   silc_hash_table_list(server->watcher_list, &htl);
1684   while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1685     if (entry == client) {
1686       silc_hash_table_del_by_context(server->watcher_list, key, client);
1687
1688       if (client->id)
1689         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1690                         silc_id_render(client->id, SILC_ID_CLIENT)));
1691
1692       /* Now check whether there still exists entries with this key, if not
1693          then free the key to not leak memory. */
1694       if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1695         silc_free(key);
1696
1697       found = TRUE;
1698     }
1699   }
1700   silc_hash_table_list_reset(&htl);
1701
1702   return found;
1703 }
1704
1705 /* Force the client indicated by `chl' to change the channel user mode
1706    on channel indicated by `channel' to `forced_mode'. */
1707
1708 bool silc_server_force_cumode_change(SilcServer server,
1709                                      SilcSocketConnection sock,
1710                                      SilcChannelEntry channel,
1711                                      SilcChannelClientEntry chl,
1712                                      SilcUInt32 forced_mode)
1713 {
1714   SilcBuffer idp1, idp2;
1715   unsigned char cumode[4];
1716
1717   SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1718
1719   if (sock)
1720     silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1721                                    server->id, SILC_ID_SERVER,
1722                                    chl->client->id, NULL);
1723
1724   idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1725   idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1726   SILC_PUT32_MSB(forced_mode, cumode);
1727   silc_server_send_notify_to_channel(server, sock, channel, FALSE, TRUE,
1728                                      SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1729                                      3, idp1->data, idp1->len,
1730                                      cumode, sizeof(cumode),
1731                                      idp2->data, idp2->len);
1732   silc_buffer_free(idp1);
1733   silc_buffer_free(idp2);
1734
1735   return TRUE;
1736 }
1737
1738 /* Find active socket connection by the IP address and port indicated by
1739    `ip' and `port', and socket connection type of `type'. */
1740
1741 SilcSocketConnection
1742 silc_server_find_socket_by_host(SilcServer server,
1743                                 SilcSocketType type,
1744                                 const char *ip, SilcUInt16 port)
1745 {
1746   int i;
1747
1748   for (i = 0; i < server->config->param.connections_max; i++) {
1749     if (!server->sockets[i])
1750       continue;
1751     if (!strcmp(server->sockets[i]->ip, ip) &&
1752         (!port || server->sockets[i]->port == port) &&
1753         server->sockets[i]->type == type)
1754       return server->sockets[i];
1755   }
1756
1757   return NULL;
1758 }
1759
1760 /* This function can be used to match the invite and ban lists. */
1761
1762 bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1763                                  SilcUInt8 type, void *check)
1764 {
1765   unsigned char *tmp = NULL;
1766   SilcUInt32 len = 0, t;
1767   SilcHashTableList htl;
1768   SilcBuffer entry, idp = NULL, pkp = NULL;
1769   bool ret = FALSE;
1770
1771   if (type < 1 || type > 3 || !check)
1772     return FALSE;
1773
1774   if (type == 1) {
1775     tmp = strdup((char *)check);
1776     if (!tmp)
1777       return FALSE;
1778   }
1779   if (type == 2) {
1780     pkp = silc_pkcs_public_key_payload_encode(check);
1781     if (!pkp)
1782       return FALSE;
1783     tmp = pkp->data;
1784     len = pkp->len;
1785   }
1786   if (type == 3) {
1787     idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
1788     if (!idp)
1789       return FALSE;
1790     tmp = idp->data;
1791     len = idp->len;
1792   }
1793
1794   /* Compare the list */
1795   silc_hash_table_list(list, &htl);
1796   while (silc_hash_table_get(&htl, (void **)&t, (void **)&entry)) {
1797     if (type == t) {
1798       if (type == 1) {
1799         if (silc_string_match(entry->data, tmp)) {
1800           ret = TRUE;
1801           break;
1802         }
1803       } else if (!memcmp(entry->data, tmp, len)) {
1804         ret = TRUE;
1805         break;
1806       }
1807     }
1808   }
1809   silc_hash_table_list_reset(&htl);
1810
1811   if (type == 1)
1812     silc_free(tmp);
1813   silc_buffer_free(idp);
1814   silc_buffer_free(pkp);
1815   return ret;
1816 }
1817
1818 /* Process invite or ban information */
1819
1820 void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
1821                                    SilcUInt8 action, SilcArgumentPayload args)
1822 {
1823   unsigned char *tmp;
1824   SilcUInt32 type, len;
1825   SilcBuffer tmp2;
1826   SilcHashTableList htl;
1827
1828   SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1829                   action == 0x01 ? "DEL" : "ADD"));
1830
1831   /* Add the information to invite list */
1832   if (action == 0x00 || action == 0x03) {
1833     /* Traverse all arguments and add to the hash table according to
1834        their type. */
1835     tmp = silc_argument_get_first_arg(args, &type, &len);
1836     while (tmp) {
1837       if (type == 1) {
1838         /* Invite string.  Get the old invite string from hash table
1839            and append this at the end of the existing one. */
1840         if (!silc_hash_table_find(list, (void *)1, NULL, (void **)&tmp2)) {
1841           tmp2 = silc_calloc(1, sizeof(*tmp2));
1842           silc_hash_table_add(list, (void *)1, tmp2);
1843         }
1844
1845         /* Check that the string is not part of invite string already */
1846         if (action == 0x00) {
1847           if (silc_string_match(tmp2->data, tmp))
1848             break;
1849
1850           if (len) {
1851             if (tmp[len - 1] == ',')
1852               tmp[len - 1] = '\0';
1853             silc_buffer_strformat(tmp2, tmp, SILC_STR_END);
1854             silc_buffer_strformat(tmp2, ",", SILC_STR_END);
1855           }
1856         } else {
1857           /* Announced list.  Check each entry in the list */
1858           unsigned char e[256];
1859           char *start, *end, *n, *rtmp;
1860           int i, k;
1861
1862           rtmp = silc_memdup(tmp, len);
1863           for (i = 0, k = 0; i < len; i++) {
1864             if (tmp[i] != ',')
1865               continue;
1866
1867             memset(e, 0, sizeof(e));
1868             silc_strncat(e, sizeof(e), tmp + k, i - k);
1869             if (!silc_string_match(tmp2->data, e)) {
1870               k = i + 1;
1871               continue;
1872             }
1873
1874             /* Matches.  Delete it since we have it already */
1875             start = strstr(rtmp, e);
1876             if (start && strlen(start) >= (i - k)) {
1877               end = start + (i - k);
1878               n = silc_calloc(strlen(rtmp) - (i - k), sizeof(*n));
1879               strncat(n, rtmp, start - rtmp);
1880               if (strlen(end) > 1)
1881                 strncat(n, end + 1, ((rtmp + strlen(rtmp)) - end) - 1);
1882               silc_free(rtmp);
1883               rtmp = n;
1884             }
1885
1886             k = i + 1;
1887           }
1888
1889           /* Save the part that we didn't already have. */
1890           if (strlen(rtmp) > 1) {
1891             silc_buffer_strformat(tmp2, rtmp, SILC_STR_END);
1892             silc_buffer_strformat(tmp2, ",", SILC_STR_END);
1893           }
1894           silc_free(rtmp);
1895         }
1896
1897       } else if (type == 2) {
1898         /* Public key.  Check first if the public key is already on the
1899            list and ignore it if it is, otherwise, add it to hash table. */
1900
1901         /* Check if the public key is in the list already */
1902         silc_hash_table_list(list, &htl);
1903         while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1904           if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1905             tmp = NULL;
1906             break;
1907           }
1908         }
1909         silc_hash_table_list_reset(&htl);
1910
1911         /* Add new public key to invite list */
1912         if (tmp) {
1913           tmp2 = silc_buffer_alloc_size(len);
1914           silc_buffer_put(tmp2, tmp, len);
1915           silc_hash_table_add(list, (void *)2, tmp2);
1916         }
1917
1918       } else if (type == 3) {
1919         /* Client ID */
1920
1921         /* Check if the ID is in the list already */
1922         silc_hash_table_list(list, &htl);
1923         while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1924           if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1925             tmp = NULL;
1926             break;
1927           }
1928         }
1929         silc_hash_table_list_reset(&htl);
1930
1931         /* Add new Client ID to invite list */
1932         if (tmp) {
1933           tmp2 = silc_buffer_alloc_size(len);
1934           silc_buffer_put(tmp2, tmp, len);
1935           silc_hash_table_add(list, (void *)3, tmp2);
1936         }
1937       }
1938
1939       tmp = silc_argument_get_next_arg(args, &type, &len);
1940     }
1941   }
1942
1943   /* Delete information to invite list */
1944   if (action == 0x01 && list) {
1945     /* Now delete the arguments from invite list */
1946     tmp = silc_argument_get_first_arg(args, &type, &len);
1947     while (tmp) {
1948       if (type == 1) {
1949         /* Invite string.  Get the old string from hash table and delete
1950            the requested string. */
1951         char *string = NULL, *start, *end, *n;
1952
1953         if (silc_hash_table_find(list, (void *)1, NULL, (void **)&tmp2)) {
1954           string = tmp2->head;
1955           if (tmp2->truelen && !strncmp(string, tmp, tmp2->truelen - 1)) {
1956             /* Delete entire string */
1957             silc_hash_table_del(list, (void *)1);
1958           } else if (tmp2->truelen) {
1959             /* Delete part of the string */
1960             start = strstr(string, tmp);
1961             if (start && strlen(start) >= len) {
1962               end = start + len;
1963               n = silc_calloc(strlen(string) - len, sizeof(*n));
1964               strncat(n, string, start - string);
1965               if (strlen(end) > 1)
1966                 strncat(n, end + 1, ((string + strlen(string)) - end) - 1);
1967               silc_free(tmp2->head);
1968               silc_buffer_set(tmp2, n, strlen(n));
1969             }
1970           }
1971         }
1972
1973       } else if (type == 2) {
1974         /* Public key. */
1975
1976         /* Delete from the invite list */
1977         silc_hash_table_list(list, &htl);
1978         while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1979           if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1980             silc_hash_table_del_by_context(list, (void *)2, tmp2);
1981             break;
1982           }
1983         }
1984         silc_hash_table_list_reset(&htl);
1985
1986       } else if (type == 3) {
1987         /* Client ID */
1988
1989         /* Delete from the invite list */
1990         silc_hash_table_list(list, &htl);
1991         while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1992           if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1993             silc_hash_table_del_by_context(list, (void *)3, tmp2);
1994             break;
1995           }
1996         }
1997         silc_hash_table_list_reset(&htl);
1998       }
1999
2000       tmp = silc_argument_get_next_arg(args, &type, &len);
2001     }
2002   }
2003 }
2004
2005 /* Destructor for invite and ban list entrys */
2006
2007 void silc_server_inviteban_destruct(void *key, void *context,
2008                                     void *user_context)
2009 {
2010   silc_buffer_free(context);
2011 }
2012
2013 /* Creates connections accoring to configuration. */
2014
2015 void silc_server_create_connections(SilcServer server)
2016 {
2017   silc_schedule_task_del_by_callback(server->schedule,
2018                                      silc_server_connect_to_router);
2019   silc_schedule_task_add(server->schedule, 0,
2020                          silc_server_connect_to_router, server, 0, 1,
2021                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
2022 }
2023
2024 static void
2025 silc_server_process_channel_pk_destruct(void *key, void *context,
2026                                         void *user_context)
2027 {
2028   silc_free(key);
2029   silc_pkcs_public_key_free(context);
2030 }
2031
2032 /* Processes a channel public key, either adds or removes it. */
2033
2034 SilcStatus
2035 silc_server_process_channel_pk(SilcServer server,
2036                                SilcChannelEntry channel,
2037                                SilcUInt32 type, const unsigned char *pk,
2038                                SilcUInt32 pk_len)
2039 {
2040   unsigned char pkhash[20];
2041   SilcPublicKey chpk;
2042
2043   SILC_LOG_DEBUG(("Processing channel public key"));
2044
2045   if (!pk || !pk_len)
2046     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2047
2048   /* Decode the public key */
2049   if (!silc_pkcs_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
2050     return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
2051
2052   /* Create channel public key list (hash table) if needed */
2053   if (!channel->channel_pubkeys) {
2054     channel->channel_pubkeys =
2055       silc_hash_table_alloc(0, silc_hash_data, (void *)20,
2056                             silc_hash_data_compare, (void *)20,
2057                             silc_server_process_channel_pk_destruct, channel,
2058                             TRUE);
2059   }
2060
2061   /* Create SHA-1 digest of the public key data */
2062   silc_hash_make(server->sha1hash, pk + 4, pk_len - 4, pkhash);
2063
2064   if (type == 0x00) {
2065     /* Add new public key to channel public key list */
2066     SILC_LOG_DEBUG(("Add new channel public key to channel %s",
2067                     channel->channel_name));
2068
2069     /* Check for resource limit */
2070     if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
2071       silc_pkcs_public_key_free(chpk);
2072       return SILC_STATUS_ERR_RESOURCE_LIMIT;
2073     }
2074
2075     /* Add if doesn't exist already */
2076     if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2077                               NULL, NULL))
2078       silc_hash_table_add(channel->channel_pubkeys, silc_memdup(pkhash, 20),
2079                           chpk);
2080   } else if (type == 0x01) {
2081     /* Delete public key from channel public key list */
2082     SILC_LOG_DEBUG(("Delete a channel public key from channel %s",
2083                     channel->channel_name));
2084     if (!silc_hash_table_del(channel->channel_pubkeys, pkhash))
2085       silc_pkcs_public_key_free(chpk);
2086   } else {
2087     silc_pkcs_public_key_free(chpk);
2088     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2089   }
2090
2091   return SILC_STATUS_OK;
2092 }
2093
2094 /* Returns the channel public keys as Argument List payload. */
2095
2096 SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
2097                                            SilcChannelEntry channel,
2098                                            bool announce,
2099                                            bool delete)
2100 {
2101   SilcHashTableList htl;
2102   SilcBuffer list, pkp;
2103   SilcPublicKey pk;
2104
2105   SILC_LOG_DEBUG(("Encoding channel public keys list"));
2106
2107   if (!channel->channel_pubkeys ||
2108       !silc_hash_table_count(channel->channel_pubkeys))
2109     return NULL;
2110
2111   /* Encode the list */
2112   list = silc_buffer_alloc_size(2);
2113   silc_buffer_format(list,
2114                      SILC_STR_UI_SHORT(silc_hash_table_count(
2115                                        channel->channel_pubkeys)),
2116                      SILC_STR_END);
2117
2118   silc_hash_table_list(channel->channel_pubkeys, &htl);
2119   while (silc_hash_table_get(&htl, NULL, (void **)&pk)) {
2120     pkp = silc_pkcs_public_key_payload_encode(pk);
2121     list = silc_argument_payload_encode_one(list, pkp->data, pkp->len,
2122                                             announce ? 0x03 :
2123                                             delete ? 0x01 : 0x00);
2124     silc_buffer_free(pkp);
2125   }
2126   silc_hash_table_list_reset(&htl);
2127
2128   return list;
2129 }
2130
2131 /* Sets the channel public keys into channel from the list of public keys. */
2132
2133 SilcStatus silc_server_set_channel_pk_list(SilcServer server,
2134                                            SilcSocketConnection sender,
2135                                            SilcChannelEntry channel,
2136                                            const unsigned char *pklist,
2137                                            SilcUInt32 pklist_len)
2138 {
2139   SilcUInt16 argc;
2140   SilcArgumentPayload args;
2141   unsigned char *chpk;
2142   SilcUInt32 chpklen, type;
2143   SilcStatus ret = SILC_STATUS_OK;
2144
2145   SILC_LOG_DEBUG(("Setting channel public keys list"));
2146
2147   if (!pklist || pklist_len < 2)
2148     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2149
2150   /* Get the argument from the Argument List Payload */
2151   SILC_GET16_MSB(argc, pklist);
2152   args = silc_argument_payload_parse(pklist + 2, pklist_len - 2, argc);
2153   if (!args)
2154     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2155
2156   /* Process the public keys one by one */
2157   chpk = silc_argument_get_first_arg(args, &type, &chpklen);
2158
2159   /* If announcing keys and we have them set already, do not allow this */
2160   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2161       server->server_type == SILC_ROUTER &&
2162       sender != SILC_PRIMARY_ROUTE(server)) {
2163     SILC_LOG_DEBUG(("Channel public key list set already, enforce our list"));
2164     silc_argument_payload_free(args);
2165     return SILC_STATUS_ERR_OPERATION_ALLOWED;
2166   }
2167
2168   /* If we are normal server and receive announcement list and we already
2169      have keys set, we replace the old list with the announced one. */
2170   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2171       server->server_type != SILC_ROUTER) {
2172     SilcBuffer sidp;
2173     unsigned char mask[4];
2174
2175     SILC_LOG_DEBUG(("Router enforces its list, remove old list"));
2176     silc_hash_table_free(channel->channel_pubkeys);
2177     channel->channel_pubkeys = NULL;
2178
2179     /* Send notify that removes the old list */
2180     sidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2181     SILC_PUT32_MSB((channel->mode & (~SILC_CHANNEL_MODE_CHANNEL_AUTH)), mask);
2182     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2183                                        SILC_NOTIFY_TYPE_CMODE_CHANGE, 7,
2184                                        sidp->data, sidp->len,
2185                                        mask, 4,
2186                                        channel->cipher,
2187                                        channel->cipher ?
2188                                        strlen(channel->cipher) : 0,
2189                                        channel->hmac_name,
2190                                        channel->hmac_name ?
2191                                        strlen(channel->hmac_name) : 0,
2192                                        channel->passphrase,
2193                                        channel->passphrase ?
2194                                        strlen(channel->passphrase) : 0,
2195                                        NULL, 0, NULL, 0);
2196     silc_buffer_free(sidp);
2197   }
2198
2199   while (chpk) {
2200     if (type == 0x03)
2201       type = 0x00;
2202     ret = silc_server_process_channel_pk(server, channel, type,
2203                                          chpk, chpklen);
2204     if (ret != SILC_STATUS_OK)
2205       break;
2206     chpk = silc_argument_get_next_arg(args, &type, &chpklen);
2207   }
2208
2209   silc_argument_payload_free(args);
2210   return ret;
2211 }
2212
2213 /* Verifies the Authentication Payload `auth' with one of the public keys
2214    on the `channel' public key list. */
2215
2216 bool silc_server_verify_channel_auth(SilcServer server,
2217                                      SilcChannelEntry channel,
2218                                      SilcClientID *client_id,
2219                                      const unsigned char *auth,
2220                                      SilcUInt32 auth_len)
2221 {
2222   SilcAuthPayload ap;
2223   SilcPublicKey chpk;
2224   unsigned char *pkhash;
2225   SilcUInt32 pkhash_len;
2226   bool ret = FALSE;
2227
2228   SILC_LOG_DEBUG(("Verifying channel authentication"));
2229
2230   if (!auth || !auth_len || !channel->channel_pubkeys)
2231     return FALSE;
2232
2233   /* Get the hash from the auth data which tells us what public key we
2234      must use in verification. */
2235
2236   ap = silc_auth_payload_parse(auth, auth_len);
2237   if (!ap)
2238     return FALSE;
2239
2240   pkhash = silc_auth_get_public_data(ap, &pkhash_len);
2241   if (pkhash_len < 128)
2242     goto out;
2243
2244   /* Find the public key with the hash */
2245   if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2246                             NULL, (void **)&chpk)) {
2247     SILC_LOG_DEBUG(("Public key not found in channel public key list"));
2248     goto out;
2249   }
2250
2251   /* Verify the signature */
2252   if (!silc_auth_verify(ap, SILC_AUTH_PUBLIC_KEY, (void *)chpk, 0,
2253                         server->sha1hash, client_id, SILC_ID_CLIENT)) {
2254     SILC_LOG_DEBUG(("Authentication failed"));
2255     goto out;
2256   }
2257
2258   ret = TRUE;
2259
2260  out:
2261   silc_auth_payload_free(ap);
2262   return ret;
2263 }