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