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