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