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