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