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