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