Added dynamic server connection support with WHOIS and IDENTIFY
[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 {
1061   SilcServerConnection conn;
1062   int count = 0;
1063
1064   if (!ip && !hostname)
1065     return 0;
1066
1067   silc_dlist_start(server->conns);
1068   while ((conn = silc_dlist_get(server->conns))) {
1069     if (((ip && !strcmp(conn->remote_host, ip)) ||
1070          (hostname && !strcmp(conn->remote_host, hostname))) &&
1071         conn->remote_port == port)
1072       count++;
1073   }
1074
1075   return count;
1076 }
1077
1078 /* SKR find callbcak */
1079
1080 static void find_callback(SilcSKR skr, SilcSKRFind find,
1081                           SilcSKRStatus status, SilcDList keys,
1082                           void *context)
1083 {
1084   SilcPublicKey *public_key = context;
1085   SilcSKRKey key;
1086
1087   if (keys) {
1088     silc_dlist_start(keys);
1089     key = silc_dlist_get(keys);
1090     *public_key = key->key;
1091     silc_dlist_uninit(keys);
1092   }
1093
1094   silc_skr_find_free(find);
1095 }
1096
1097 /* Get public key by key usage and key context. */
1098
1099 SilcPublicKey silc_server_get_public_key(SilcServer server,
1100                                          SilcSKRKeyUsage usage,
1101                                          void *key_context)
1102 {
1103   SilcSKRFind find;
1104   SilcPublicKey public_key = NULL;
1105
1106   SILC_LOG_DEBUG(("Start"));
1107
1108   find = silc_skr_find_alloc();
1109   if (!find)
1110     return NULL;
1111
1112   silc_skr_find_set_usage(find, usage);
1113   silc_skr_find_set_context(find, key_context);
1114   silc_skr_find(server->repository, server->schedule,
1115                 find, find_callback, &public_key);
1116
1117   return public_key;
1118 }
1119
1120 /* Find public key by client for identification purposes.  Finds keys
1121    with SILC_SKR_USAGE_IDENTIFICATION. */
1122
1123 SilcBool silc_server_get_public_key_by_client(SilcServer server,
1124                                               SilcClientEntry client,
1125                                               SilcPublicKey *public_key)
1126 {
1127   SilcPublicKey pubkey = NULL;
1128   SilcBool ret = FALSE;
1129
1130   pubkey = silc_server_get_public_key(server, SILC_SKR_USAGE_IDENTIFICATION,
1131                                       client);
1132   if (pubkey)
1133     ret = TRUE;
1134
1135   if (public_key)
1136     *public_key = pubkey;
1137
1138   return ret;
1139 }
1140
1141 /* Check whether the connection `sock' is allowed to connect to us.  This
1142    checks for example whether there is too much connections for this host,
1143    and required version for the host etc. */
1144
1145 SilcBool silc_server_connection_allowed(SilcServer server,
1146                                         SilcPacketStream sock,
1147                                         SilcConnectionType type,
1148                                         SilcServerConfigConnParams *global,
1149                                         SilcServerConfigConnParams *params,
1150                                         SilcSKE ske)
1151 {
1152   SilcUInt32 conn_number = (type == SILC_CONN_CLIENT ?
1153                             server->stat.my_clients :
1154                             type == SILC_CONN_SERVER ?
1155                             server->stat.my_servers :
1156                             server->stat.my_routers);
1157   SilcUInt32 num_sockets, max_hosts, max_per_host;
1158   SilcUInt32 r_protocol_version, l_protocol_version;
1159   SilcUInt32 r_software_version, l_software_version;
1160   char *r_vendor_version = NULL, *l_vendor_version;
1161   const char *hostname, *ip;
1162
1163   silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
1164                               NULL, &hostname, &ip, NULL);
1165
1166   SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1167
1168   /* Check version */
1169
1170   l_protocol_version =
1171     silc_version_to_num(params && params->version_protocol ?
1172                         params->version_protocol :
1173                         global->version_protocol);
1174   l_software_version =
1175     silc_version_to_num(params && params->version_software ?
1176                         params->version_software :
1177                         global->version_software);
1178   l_vendor_version = (params && params->version_software_vendor ?
1179                       params->version_software_vendor :
1180                       global->version_software_vendor);
1181
1182   if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1183                                     &r_software_version, NULL,
1184                                     &r_vendor_version)) {
1185     /* Match protocol version */
1186     if (l_protocol_version && r_protocol_version &&
1187         r_protocol_version < l_protocol_version) {
1188       SILC_LOG_INFO(("Connection %s (%s) is too old version",
1189                      hostname, ip));
1190       silc_server_disconnect_remote(server, sock,
1191                                     SILC_STATUS_ERR_BAD_VERSION,
1192                                     "You support too old protocol version");
1193       return FALSE;
1194     }
1195
1196     /* Math software version */
1197     if (l_software_version && r_software_version &&
1198         r_software_version < l_software_version) {
1199       SILC_LOG_INFO(("Connection %s (%s) is too old version",
1200                      hostname, ip));
1201       silc_server_disconnect_remote(server, sock,
1202                                     SILC_STATUS_ERR_BAD_VERSION,
1203                                     "You support too old software version");
1204       return FALSE;
1205     }
1206
1207     /* Regex match vendor version */
1208     if (l_vendor_version && r_vendor_version &&
1209         !silc_string_match(l_vendor_version, r_vendor_version)) {
1210       SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1211                      hostname, ip));
1212       silc_server_disconnect_remote(server, sock,
1213                                     SILC_STATUS_ERR_BAD_VERSION,
1214                                     "Your software is not supported");
1215       return FALSE;
1216     }
1217   }
1218   silc_free(r_vendor_version);
1219
1220   /* Check for maximum connections limit */
1221
1222   num_sockets = silc_server_num_sockets_by_ip(server, ip, type);
1223   max_hosts = (params ? params->connections_max : global->connections_max);
1224   max_per_host = (params ? params->connections_max_per_host :
1225                   global->connections_max_per_host);
1226
1227   if (max_hosts && conn_number >= max_hosts) {
1228     SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1229                    hostname, ip));
1230     silc_server_disconnect_remote(server, sock,
1231                                   SILC_STATUS_ERR_RESOURCE_LIMIT,
1232                                   "Server is full, try again later");
1233     return FALSE;
1234   }
1235
1236   if (num_sockets >= max_per_host) {
1237     SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1238                    hostname, ip));
1239     silc_server_disconnect_remote(server, sock,
1240                                   SILC_STATUS_ERR_RESOURCE_LIMIT,
1241                                   "Too many connections from your host");
1242     return FALSE;
1243   }
1244
1245   return TRUE;
1246 }
1247
1248 /* Checks that client has rights to add or remove channel modes. If any
1249    of the checks fails FALSE is returned. */
1250
1251 SilcBool silc_server_check_cmode_rights(SilcServer server,
1252                                         SilcChannelEntry channel,
1253                                         SilcChannelClientEntry client,
1254                                         SilcUInt32 mode)
1255 {
1256   SilcBool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1257   SilcBool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1258
1259   /* Check whether has rights to change anything */
1260   if (!is_op && !is_fo)
1261     return FALSE;
1262
1263   /* Check whether has rights to change everything */
1264   if (is_op && is_fo)
1265     return TRUE;
1266
1267   /* Founder implies operator */
1268   if (is_fo)
1269     is_op = TRUE;
1270
1271   /* We know that client is channel operator, check that they are not
1272      changing anything that requires channel founder rights. Rest of the
1273      modes are available automatically for channel operator. */
1274
1275   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1276     if (is_op && !is_fo)
1277       return FALSE;
1278   } else {
1279     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1280       if (is_op && !is_fo)
1281         return FALSE;
1282     }
1283   }
1284
1285   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1286     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1287       if (is_op && !is_fo)
1288         return FALSE;
1289     }
1290   } else {
1291     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1292       if (is_op && !is_fo)
1293         return FALSE;
1294     }
1295   }
1296
1297   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1298     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1299       if (is_op && !is_fo)
1300         return FALSE;
1301     }
1302   } else {
1303     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1304       if (is_op && !is_fo)
1305         return FALSE;
1306     }
1307   }
1308
1309   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1310     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1311       if (is_op && !is_fo)
1312         return FALSE;
1313     }
1314   } else {
1315     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1316       if (is_op && !is_fo)
1317         return FALSE;
1318     }
1319   }
1320
1321   if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1322     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1323       if (is_op && !is_fo)
1324         return FALSE;
1325     }
1326   } else {
1327     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1328       if (is_op && !is_fo)
1329         return FALSE;
1330     }
1331   }
1332
1333   if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1334     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1335       if (is_op && !is_fo)
1336         return FALSE;
1337     }
1338   } else {
1339     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1340       if (is_op && !is_fo)
1341         return FALSE;
1342     }
1343   }
1344
1345   if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1346     if (!(channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)) {
1347       if (is_op && !is_fo)
1348         return FALSE;
1349     }
1350   } else {
1351     if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1352       if (is_op && !is_fo)
1353         return FALSE;
1354     }
1355   }
1356
1357   return TRUE;
1358 }
1359
1360 /* Check that the client has rights to change its user mode.  Returns
1361    FALSE if setting some mode is not allowed. */
1362
1363 SilcBool silc_server_check_umode_rights(SilcServer server,
1364                                         SilcClientEntry client,
1365                                         SilcUInt32 mode)
1366 {
1367   SilcBool server_op = FALSE, router_op = FALSE;
1368
1369   if (mode & SILC_UMODE_SERVER_OPERATOR) {
1370     /* Cannot set server operator mode (must use OPER command) */
1371     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1372       return FALSE;
1373   } else {
1374     /* Remove the server operator rights */
1375     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1376       server_op = TRUE;
1377   }
1378
1379   if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1380     /* Cannot set router operator mode (must use SILCOPER command) */
1381     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1382       return FALSE;
1383   } else {
1384     /* Remove the router operator rights */
1385     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1386       router_op = TRUE;
1387   }
1388
1389   if (server_op)
1390     SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1391   if (router_op)
1392     SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1393
1394   return TRUE;
1395 }
1396
1397 /* This function is used to send the notify packets and motd to the
1398    incoming client connection. */
1399
1400 void silc_server_send_connect_notifys(SilcServer server,
1401                                       SilcPacketStream sock,
1402                                       SilcClientEntry client)
1403 {
1404   SilcCipher key;
1405
1406   SILC_LOG_DEBUG(("Send welcome notifys"));
1407
1408   /* Send some nice info to the client */
1409   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1410                           ("Welcome to the SILC Network %s",
1411                            client->username));
1412   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1413                           ("Your host is %s, running version %s",
1414                            server->server_name, server_version));
1415
1416   if (server->server_type == SILC_ROUTER) {
1417     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1418                             ("There are %d clients, %d servers and %d "
1419                              "routers in SILC Network",
1420                              server->stat.clients, server->stat.servers,
1421                              server->stat.routers));
1422   } else {
1423     if (server->stat.clients && server->stat.servers + 1)
1424       SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1425                               ("There are %d clients, %d servers and %d "
1426                                "routers in SILC Network",
1427                                server->stat.clients, server->stat.servers,
1428                                (server->standalone ? 0 :
1429                                 !server->stat.routers ? 1 :
1430                                 server->stat.routers)));
1431   }
1432
1433   if (server->stat.cell_clients && server->stat.cell_servers + 1)
1434     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1435                             ("There are %d clients on %d servers in our cell",
1436                              server->stat.cell_clients,
1437                              server->stat.cell_servers));
1438   if (server->server_type == SILC_ROUTER) {
1439     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1440                             ("I have %d clients, %d channels, %d servers and "
1441                              "%d routers",
1442                              server->stat.my_clients,
1443                              server->stat.my_channels,
1444                              server->stat.my_servers,
1445                              server->stat.my_routers));
1446   } else {
1447     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1448                             ("I have %d clients and %d channels formed",
1449                              server->stat.my_clients,
1450                              server->stat.my_channels));
1451   }
1452
1453   if (server->stat.server_ops || server->stat.router_ops)
1454     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1455                             ("There are %d server operators and %d router "
1456                              "operators online",
1457                              server->stat.server_ops,
1458                              server->stat.router_ops));
1459   if (server->stat.my_router_ops + server->stat.my_server_ops)
1460     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1461                             ("I have %d operators online",
1462                              server->stat.my_router_ops +
1463                              server->stat.my_server_ops));
1464
1465   silc_packet_get_keys(sock, &key, NULL, NULL, NULL);
1466   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1467                           ("Your connection is secured with %s cipher, "
1468                            "key length %d bits",
1469                            silc_cipher_get_name(key),
1470                            silc_cipher_get_key_len(key)));
1471   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1472                           ("Your current nickname is %s",
1473                            client->nickname));
1474
1475   /* Send motd */
1476   silc_server_send_motd(server, sock);
1477 }
1478
1479 /* Kill the client indicated by `remote_client' sending KILLED notify
1480    to the client, to all channels client has joined and to primary
1481    router if needed.  The killed client is also removed from all channels. */
1482
1483 void silc_server_kill_client(SilcServer server,
1484                              SilcClientEntry remote_client,
1485                              const char *comment,
1486                              void *killer_id,
1487                              SilcIdType killer_id_type)
1488 {
1489   SilcBuffer killed, killer;
1490
1491   SILC_LOG_DEBUG(("Killing client %s",
1492                   silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1493
1494   /* Send the KILL notify packets. First send it to the channel, then
1495      to our primary router and then directly to the client who is being
1496      killed right now. */
1497
1498   killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1499   killer = silc_id_payload_encode(killer_id, killer_id_type);
1500
1501   /* Send KILLED notify to the channels. It is not sent to the client
1502      as it will be sent differently destined directly to the client and not
1503      to the channel. */
1504   silc_server_send_notify_on_channels(server, remote_client,
1505                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
1506                                       3, killed->data, silc_buffer_len(killed),
1507                                       comment, comment ? strlen(comment) : 0,
1508                                       killer->data, silc_buffer_len(killer));
1509
1510   /* Send KILLED notify to primary route */
1511   silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1512                                  SILC_BROADCAST(server), remote_client->id,
1513                                  comment, killer_id, killer_id_type);
1514
1515   /* Send KILLED notify to the client directly */
1516   if (remote_client->connection || remote_client->router)
1517     silc_server_send_notify_killed(server, remote_client->connection ?
1518                                    remote_client->connection :
1519                                    remote_client->router->connection, FALSE,
1520                                    remote_client->id, comment,
1521                                    killer_id, killer_id_type);
1522
1523   /* Remove the client from all channels. This generates new keys to the
1524      channels as well. */
1525   silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1526                                    NULL, TRUE, TRUE);
1527
1528   /* Remove the client entry, If it is locally connected then we will also
1529      disconnect the client here */
1530   if (remote_client->connection) {
1531     /* Remove locally conneted client */
1532     SilcPacketStream sock = remote_client->connection;
1533     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1534     silc_server_close_connection(server, sock);
1535   } else {
1536     /* Update statistics */
1537     server->stat.clients--;
1538     if (server->stat.cell_clients)
1539       server->stat.cell_clients--;
1540     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1541     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1542
1543     /* Remove client's public key from repository, this will free it too. */
1544     if (remote_client->data.public_key) {
1545       silc_skr_del_public_key(server->repository,
1546                               remote_client->data.public_key, remote_client);
1547       remote_client->data.public_key = NULL;
1548     }
1549
1550     if (SILC_IS_LOCAL(remote_client)) {
1551       server->stat.my_clients--;
1552       silc_schedule_task_del_by_context(server->schedule, remote_client);
1553     }
1554
1555     /* Remove remote client */
1556     silc_idlist_del_data(remote_client);
1557     if (!silc_idlist_del_client(server->global_list, remote_client)) {
1558       /* Remove this client from watcher list if it is */
1559       silc_server_del_from_watcher_list(server, remote_client);
1560       silc_idlist_del_client(server->local_list, remote_client);
1561     }
1562   }
1563
1564   silc_buffer_free(killer);
1565   silc_buffer_free(killed);
1566 }
1567
1568 typedef struct {
1569   SilcServer server;
1570   SilcClientEntry client;
1571   SilcNotifyType notify;
1572   const char *new_nick;
1573 } WatcherNotifyContext;
1574
1575 static void
1576 silc_server_check_watcher_list_foreach(void *key, void *context,
1577                                        void *user_context)
1578 {
1579   WatcherNotifyContext *notify = user_context;
1580   SilcClientEntry entry = context;
1581   SilcPacketStream sock;
1582
1583   if (!context)
1584     return;
1585
1586   if (entry == notify->client)
1587     return;
1588
1589   sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1590                                       NULL, NULL);
1591   if (sock) {
1592     SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1593                     silc_id_render(entry->id, SILC_ID_CLIENT)));
1594
1595     /* Send the WATCH notify */
1596     silc_server_send_notify_watch(notify->server, sock, entry,
1597                                   notify->client,
1598                                   notify->new_nick ? notify->new_nick :
1599                                   (const char *)notify->client->nickname,
1600                                   notify->notify,
1601                                   notify->client->data.public_key);
1602   }
1603 }
1604
1605 /* This function checks whether the `client' nickname and/or 'client'
1606    public key is being watched by someone, and notifies the watcher of the
1607    notify change of notify type indicated by `notify'. */
1608
1609 SilcBool silc_server_check_watcher_list(SilcServer server,
1610                                         SilcClientEntry client,
1611                                         const char *new_nick,
1612                                         SilcNotifyType notify)
1613 {
1614   unsigned char hash[16];
1615   WatcherNotifyContext n;
1616
1617   SILC_LOG_DEBUG(("Checking watcher list %s",
1618                   client->nickname ? client->nickname : (unsigned char *)""));
1619
1620   /* If the watching is rejected by the client do nothing */
1621   if (client->mode & SILC_UMODE_REJECT_WATCHING)
1622     return FALSE;
1623
1624   /* Make hash from the nick, or take it from Client ID */
1625   if (client->nickname) {
1626     unsigned char *nickc;
1627     nickc = silc_identifier_check(client->nickname, strlen(client->nickname),
1628                                   SILC_STRING_UTF8, 128, NULL);
1629     if (!nickc)
1630       return FALSE;
1631     silc_hash_make(server->md5hash, nickc, strlen(nickc), hash);
1632     silc_free(nickc);
1633   } else {
1634     memset(hash, 0, sizeof(hash));
1635     memcpy(hash, client->id->hash, sizeof(client->id->hash));
1636   }
1637
1638   n.server = server;
1639   n.client = client;
1640   n.new_nick = new_nick;
1641   n.notify = notify;
1642
1643   /* Send notify to all watchers watching this nickname */
1644   silc_hash_table_find_foreach(server->watcher_list, hash,
1645                                silc_server_check_watcher_list_foreach, &n);
1646
1647   /* Send notify to all watchers watching this public key */
1648   if (client->data.public_key)
1649     silc_hash_table_find_foreach(server->watcher_list_pk,
1650                                  client->data.public_key,
1651                                  silc_server_check_watcher_list_foreach,
1652                                  &n);
1653
1654   return TRUE;
1655 }
1656
1657 /* Remove the `client' from watcher list. After calling this the `client'
1658    is not watching any nicknames. */
1659
1660 SilcBool silc_server_del_from_watcher_list(SilcServer server,
1661                                            SilcClientEntry client)
1662 {
1663   SilcHashTableList htl;
1664   void *key;
1665   SilcClientEntry entry;
1666   SilcBool found = FALSE;
1667
1668   silc_hash_table_list(server->watcher_list, &htl);
1669   while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1670     if (entry == client) {
1671       silc_hash_table_del_by_context(server->watcher_list, key, client);
1672
1673       if (client->id)
1674         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1675                         silc_id_render(client->id, SILC_ID_CLIENT)));
1676
1677       /* Now check whether there still exists entries with this key, if not
1678          then free the key to not leak memory. */
1679       if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1680         silc_free(key);
1681
1682       found = TRUE;
1683     }
1684   }
1685   silc_hash_table_list_reset(&htl);
1686
1687   silc_hash_table_list(server->watcher_list_pk, &htl);
1688   while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1689     if (entry == client) {
1690       silc_hash_table_del_by_context(server->watcher_list_pk, key, client);
1691
1692       if (client->id)
1693         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1694                         silc_id_render(client->id, SILC_ID_CLIENT)));
1695
1696       /* Now check whether there still exists entries with this key, if not
1697          then free the key to not leak memory. */
1698       if (!silc_hash_table_find(server->watcher_list_pk, key, NULL, NULL))
1699         silc_pkcs_public_key_free(key);
1700
1701       found = TRUE;
1702     }
1703   }
1704   silc_hash_table_list_reset(&htl);
1705
1706   return found;
1707 }
1708
1709 /* Force the client indicated by `chl' to change the channel user mode
1710    on channel indicated by `channel' to `forced_mode'. */
1711
1712 SilcBool silc_server_force_cumode_change(SilcServer server,
1713                                          SilcPacketStream sock,
1714                                          SilcChannelEntry channel,
1715                                          SilcChannelClientEntry chl,
1716                                          SilcUInt32 forced_mode)
1717 {
1718   SilcBuffer idp1, idp2;
1719   unsigned char cumode[4];
1720
1721   SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1722
1723   if (sock)
1724     silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1725                                    server->id, SILC_ID_SERVER,
1726                                    chl->client->id, NULL);
1727
1728   idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1729   idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1730   SILC_PUT32_MSB(forced_mode, cumode);
1731   silc_server_send_notify_to_channel(server, sock, channel, FALSE, TRUE,
1732                                      SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1733                                      3, idp1->data, silc_buffer_len(idp1),
1734                                      cumode, sizeof(cumode),
1735                                      idp2->data, silc_buffer_len(idp2));
1736   silc_buffer_free(idp1);
1737   silc_buffer_free(idp2);
1738
1739   return TRUE;
1740 }
1741
1742 /* This function can be used to match the invite and ban lists. */
1743
1744 SilcBool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1745                                      SilcUInt8 type, void *check)
1746 {
1747   unsigned char *tmp = NULL;
1748   SilcUInt32 len = 0, t;
1749   SilcHashTableList htl;
1750   SilcBuffer entry, idp = NULL, pkp = NULL;
1751   SilcBool ret = FALSE;
1752
1753   SILC_LOG_DEBUG(("Matching invite/ban"));
1754
1755   if (type < 1 || type > 3 || !check)
1756     return FALSE;
1757
1758   if (type == 1) {
1759     tmp = strdup((char *)check);
1760     if (!tmp)
1761       return FALSE;
1762   }
1763   if (type == 2) {
1764     pkp = silc_public_key_payload_encode(check);
1765     if (!pkp)
1766       return FALSE;
1767     tmp = pkp->data;
1768     len = silc_buffer_len(pkp);
1769   }
1770   if (type == 3) {
1771     idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
1772     if (!idp)
1773       return FALSE;
1774     tmp = idp->data;
1775     len = silc_buffer_len(idp);
1776   }
1777
1778   /* Compare the list */
1779   silc_hash_table_list(list, &htl);
1780   while (silc_hash_table_get(&htl, (void *)&t, (void *)&entry)) {
1781     if (type == t) {
1782       if (type == 1) {
1783         if (silc_string_match(entry->data, tmp)) {
1784           ret = TRUE;
1785           break;
1786         }
1787       } else if (!memcmp(entry->data, tmp, len)) {
1788         ret = TRUE;
1789         break;
1790       }
1791     }
1792   }
1793   silc_hash_table_list_reset(&htl);
1794
1795   if (type == 1)
1796     silc_free(tmp);
1797   silc_buffer_free(idp);
1798   silc_buffer_free(pkp);
1799   return ret;
1800 }
1801
1802 /* Process invite or ban information */
1803
1804 SilcBool silc_server_inviteban_process(SilcServer server,
1805                                        SilcHashTable list,
1806                                        SilcUInt8 action,
1807                                        SilcArgumentPayload args)
1808 {
1809   unsigned char *tmp;
1810   SilcUInt32 type, len;
1811   SilcBuffer tmp2;
1812   SilcHashTableList htl;
1813
1814   SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1815                   action == 0x01 ? "DEL" : "ADD"));
1816
1817   /* Add the information to invite list */
1818   if (action == 0x00 || action == 0x03) {
1819     /* Traverse all arguments and add to the hash table according to
1820        their type. */
1821     tmp = silc_argument_get_first_arg(args, &type, &len);
1822     while (tmp) {
1823       if (type == 1) {
1824         /* Check validity of the string.  Actually we should parse the
1825            whole string and verify all components individually. */
1826         if (!silc_utf8_valid(tmp, len) || !len) {
1827           tmp = silc_argument_get_next_arg(args, &type, &len);
1828           continue;
1829         }
1830         if (strchr(tmp, ',')) {
1831           tmp = silc_argument_get_next_arg(args, &type, &len);
1832           continue;
1833         }
1834
1835         /* Check if the string is added already */
1836         silc_hash_table_list(list, &htl);
1837         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1838           if (type == 1 && silc_string_match(tmp2->data, tmp)) {
1839             tmp = NULL;
1840             break;
1841           }
1842         }
1843         silc_hash_table_list_reset(&htl);
1844
1845         if (tmp) {
1846           /* Add the string to hash table */
1847           tmp2 = silc_buffer_alloc_size(len + 1);
1848           if (tmp[len - 1] == ',')
1849             tmp[len - 1] = '\0';
1850           silc_buffer_put(tmp2, tmp, len);
1851           silc_hash_table_add(list, (void *)1, tmp2);
1852         }
1853
1854       } else if (type == 2) {
1855         /* Public key.  Check first if the public key is already on the
1856            list and ignore it if it is, otherwise, add it to hash table. */
1857         SilcPublicKey pk;
1858
1859         /* Verify validity of the public key */
1860         if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1861           tmp = silc_argument_get_next_arg(args, &type, &len);
1862           continue;
1863         }
1864         silc_pkcs_public_key_free(pk);
1865
1866         /* Check if the public key is in the list already */
1867         silc_hash_table_list(list, &htl);
1868         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1869           if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1870             tmp = NULL;
1871             break;
1872           }
1873         }
1874         silc_hash_table_list_reset(&htl);
1875
1876         /* Add new public key to invite list */
1877         if (tmp) {
1878           tmp2 = silc_buffer_alloc_size(len);
1879           silc_buffer_put(tmp2, tmp, len);
1880           silc_hash_table_add(list, (void *)2, tmp2);
1881         }
1882
1883       } else if (type == 3) {
1884         /* Client ID */
1885
1886         /* Check if the ID is in the list already */
1887         silc_hash_table_list(list, &htl);
1888         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1889           if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1890             tmp = NULL;
1891             break;
1892           }
1893         }
1894         silc_hash_table_list_reset(&htl);
1895
1896         /* Add new Client ID to invite list */
1897         if (tmp) {
1898           tmp2 = silc_buffer_alloc_size(len);
1899           silc_buffer_put(tmp2, tmp, len);
1900           silc_hash_table_add(list, (void *)3, tmp2);
1901         }
1902       }
1903
1904       tmp = silc_argument_get_next_arg(args, &type, &len);
1905     }
1906   }
1907
1908   /* Delete information to invite list */
1909   if (action == 0x01 && list) {
1910     /* Now delete the arguments from invite list */
1911     tmp = silc_argument_get_first_arg(args, &type, &len);
1912     while (tmp) {
1913       if (type == 1) {
1914         /* Check validity of the string.  Actually we should parse the
1915            whole string and verify all components individually. */
1916         if (!silc_utf8_valid(tmp, len)) {
1917           tmp = silc_argument_get_next_arg(args, &type, &len);
1918           continue;
1919         }
1920         if (strchr(tmp, ',')) {
1921           tmp = silc_argument_get_next_arg(args, &type, &len);
1922           continue;
1923         }
1924
1925         /* Delete from the list */
1926         silc_hash_table_list(list, &htl);
1927         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1928           if (type == 1 && silc_string_match(tmp2->data, tmp)) {
1929             silc_hash_table_del_by_context(list, (void *)1, tmp2);
1930             break;
1931           }
1932         }
1933         silc_hash_table_list_reset(&htl);
1934
1935       } else if (type == 2) {
1936         /* Public key. */
1937         SilcPublicKey pk;
1938
1939         /* Verify validity of the public key */
1940         if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1941           tmp = silc_argument_get_next_arg(args, &type, &len);
1942           continue;
1943         }
1944         silc_pkcs_public_key_free(pk);
1945
1946         /* Delete from the invite list */
1947         silc_hash_table_list(list, &htl);
1948         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1949           if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1950             silc_hash_table_del_by_context(list, (void *)2, tmp2);
1951             break;
1952           }
1953         }
1954         silc_hash_table_list_reset(&htl);
1955
1956       } else if (type == 3) {
1957         /* Client ID */
1958
1959         /* Delete from the invite list */
1960         silc_hash_table_list(list, &htl);
1961         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1962           if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1963             silc_hash_table_del_by_context(list, (void *)3, tmp2);
1964             break;
1965           }
1966         }
1967         silc_hash_table_list_reset(&htl);
1968       }
1969
1970       tmp = silc_argument_get_next_arg(args, &type, &len);
1971     }
1972   }
1973
1974   return TRUE;
1975 }
1976
1977 /* Destructor for invite and ban list entrys */
1978
1979 void silc_server_inviteban_destruct(void *key, void *context,
1980                                     void *user_context)
1981 {
1982   silc_buffer_free(context);
1983 }
1984
1985 /* Creates connections accoring to configuration. */
1986
1987 void silc_server_create_connections(SilcServer server)
1988 {
1989   silc_schedule_task_del_by_callback(server->schedule,
1990                                      silc_server_connect_to_router);
1991   silc_schedule_task_add_timeout(server->schedule,
1992                                  silc_server_connect_to_router, server, 0, 1);
1993 }
1994
1995 static void
1996 silc_server_process_channel_pk_destruct(void *key, void *context,
1997                                         void *user_context)
1998 {
1999   silc_free(key);
2000   silc_pkcs_public_key_free(context);
2001 }
2002
2003 /* Processes a channel public key, either adds or removes it. */
2004
2005 SilcStatus
2006 silc_server_process_channel_pk(SilcServer server,
2007                                SilcChannelEntry channel,
2008                                SilcUInt32 type, const unsigned char *pk,
2009                                SilcUInt32 pk_len)
2010 {
2011   unsigned char pkhash[20];
2012   SilcPublicKey chpk;
2013
2014   SILC_LOG_DEBUG(("Processing channel public key"));
2015
2016   if (!pk || !pk_len)
2017     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2018
2019   /* Decode the public key */
2020   if (!silc_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
2021     return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
2022
2023   /* Create channel public key list (hash table) if needed */
2024   if (!channel->channel_pubkeys) {
2025     channel->channel_pubkeys =
2026       silc_hash_table_alloc(0, silc_hash_data, (void *)20,
2027                             silc_hash_data_compare, (void *)20,
2028                             silc_server_process_channel_pk_destruct, channel,
2029                             TRUE);
2030   }
2031
2032   /* Create SHA-1 digest of the public key data */
2033   silc_hash_make(server->sha1hash, pk + 4, pk_len - 4, pkhash);
2034
2035   if (type == 0x00) {
2036     /* Add new public key to channel public key list */
2037     SILC_LOG_DEBUG(("Add new channel public key to channel %s",
2038                     channel->channel_name));
2039
2040     /* Check for resource limit */
2041     if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
2042       silc_pkcs_public_key_free(chpk);
2043       return SILC_STATUS_ERR_RESOURCE_LIMIT;
2044     }
2045
2046     /* Add if doesn't exist already */
2047     if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2048                               NULL, NULL))
2049       silc_hash_table_add(channel->channel_pubkeys, silc_memdup(pkhash, 20),
2050                           chpk);
2051   } else if (type == 0x01) {
2052     /* Delete public key from channel public key list */
2053     SILC_LOG_DEBUG(("Delete a channel public key from channel %s",
2054                     channel->channel_name));
2055     if (!silc_hash_table_del(channel->channel_pubkeys, pkhash))
2056       silc_pkcs_public_key_free(chpk);
2057   } else {
2058     silc_pkcs_public_key_free(chpk);
2059     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2060   }
2061
2062   return SILC_STATUS_OK;
2063 }
2064
2065 /* Returns the channel public keys as Argument List payload. */
2066
2067 SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
2068                                            SilcChannelEntry channel,
2069                                            SilcBool announce,
2070                                            SilcBool delete)
2071 {
2072   SilcHashTableList htl;
2073   SilcBuffer list, pkp;
2074   SilcPublicKey pk;
2075
2076   SILC_LOG_DEBUG(("Encoding channel public keys list"));
2077
2078   if (!channel->channel_pubkeys ||
2079       !silc_hash_table_count(channel->channel_pubkeys))
2080     return NULL;
2081
2082   /* Encode the list */
2083   list = silc_buffer_alloc_size(2);
2084   silc_buffer_format(list,
2085                      SILC_STR_UI_SHORT(silc_hash_table_count(
2086                                        channel->channel_pubkeys)),
2087                      SILC_STR_END);
2088
2089   silc_hash_table_list(channel->channel_pubkeys, &htl);
2090   while (silc_hash_table_get(&htl, NULL, (void *)&pk)) {
2091     pkp = silc_public_key_payload_encode(pk);
2092     list = silc_argument_payload_encode_one(list, pkp->data,
2093                                             silc_buffer_len(pkp),
2094                                             announce ? 0x03 :
2095                                             delete ? 0x01 : 0x00);
2096     silc_buffer_free(pkp);
2097   }
2098   silc_hash_table_list_reset(&htl);
2099
2100   return list;
2101 }
2102
2103 /* Sets the channel public keys into channel from the list of public keys. */
2104
2105 SilcStatus silc_server_set_channel_pk_list(SilcServer server,
2106                                            SilcPacketStream sender,
2107                                            SilcChannelEntry channel,
2108                                            const unsigned char *pklist,
2109                                            SilcUInt32 pklist_len)
2110 {
2111   SilcUInt16 argc;
2112   SilcArgumentPayload args;
2113   unsigned char *chpk;
2114   SilcUInt32 chpklen, type;
2115   SilcStatus ret = SILC_STATUS_OK;
2116
2117   SILC_LOG_DEBUG(("Setting channel public keys list"));
2118
2119   if (!pklist || pklist_len < 2)
2120     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2121
2122   /* Get the argument from the Argument List Payload */
2123   SILC_GET16_MSB(argc, pklist);
2124   args = silc_argument_payload_parse(pklist + 2, pklist_len - 2, argc);
2125   if (!args)
2126     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2127
2128   /* Process the public keys one by one */
2129   chpk = silc_argument_get_first_arg(args, &type, &chpklen);
2130
2131   /* If announcing keys and we have them set already, do not allow this */
2132   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2133       server->server_type == SILC_ROUTER &&
2134       sender != SILC_PRIMARY_ROUTE(server)) {
2135     SILC_LOG_DEBUG(("Channel public key list set already, enforce our list"));
2136     silc_argument_payload_free(args);
2137     return SILC_STATUS_ERR_OPERATION_ALLOWED;
2138   }
2139
2140   /* If we are normal server and receive announcement list and we already
2141      have keys set, we replace the old list with the announced one. */
2142   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2143       server->server_type != SILC_ROUTER) {
2144     SilcBuffer sidp;
2145     unsigned char mask[4], ulimit[4];
2146
2147     SILC_LOG_DEBUG(("Router enforces its list, remove old list"));
2148     silc_hash_table_free(channel->channel_pubkeys);
2149     channel->channel_pubkeys = NULL;
2150
2151     /* Send notify that removes the old list */
2152     sidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2153     SILC_PUT32_MSB((channel->mode & (~SILC_CHANNEL_MODE_CHANNEL_AUTH)), mask);
2154     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2155       SILC_PUT32_MSB(channel->user_limit, ulimit);
2156     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2157                                        SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
2158                                        sidp->data, silc_buffer_len(sidp),
2159                                        mask, 4,
2160                                        channel->cipher,
2161                                        channel->cipher ?
2162                                        strlen(channel->cipher) : 0,
2163                                        channel->hmac_name,
2164                                        channel->hmac_name ?
2165                                        strlen(channel->hmac_name) : 0,
2166                                        channel->passphrase,
2167                                        channel->passphrase ?
2168                                        strlen(channel->passphrase) : 0,
2169                                        NULL, 0, NULL, 0,
2170                                        (channel->mode &
2171                                         SILC_CHANNEL_MODE_ULIMIT ?
2172                                         ulimit : NULL),
2173                                        (channel->mode &
2174                                         SILC_CHANNEL_MODE_ULIMIT ?
2175                                         sizeof(ulimit) : 0));
2176     silc_buffer_free(sidp);
2177   }
2178
2179   while (chpk) {
2180     if (type == 0x03)
2181       type = 0x00;
2182     ret = silc_server_process_channel_pk(server, channel, type,
2183                                          chpk, chpklen);
2184     if (ret != SILC_STATUS_OK)
2185       break;
2186     chpk = silc_argument_get_next_arg(args, &type, &chpklen);
2187   }
2188
2189   silc_argument_payload_free(args);
2190   return ret;
2191 }
2192
2193 /* Verifies the Authentication Payload `auth' with one of the public keys
2194    on the `channel' public key list. */
2195
2196 SilcBool silc_server_verify_channel_auth(SilcServer server,
2197                                          SilcChannelEntry channel,
2198                                          SilcClientID *client_id,
2199                                          const unsigned char *auth,
2200                                          SilcUInt32 auth_len)
2201 {
2202   SilcAuthPayload ap;
2203   SilcPublicKey chpk;
2204   unsigned char *pkhash;
2205   SilcUInt32 pkhash_len;
2206   SilcBool ret = FALSE;
2207
2208   SILC_LOG_DEBUG(("Verifying channel authentication"));
2209
2210   if (!auth || !auth_len || !channel->channel_pubkeys)
2211     return FALSE;
2212
2213   /* Get the hash from the auth data which tells us what public key we
2214      must use in verification. */
2215
2216   ap = silc_auth_payload_parse(auth, auth_len);
2217   if (!ap)
2218     return FALSE;
2219
2220   pkhash = silc_auth_get_public_data(ap, &pkhash_len);
2221   if (pkhash_len < 128)
2222     goto out;
2223
2224   /* Find the public key with the hash */
2225   if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2226                             NULL, (void *)&chpk)) {
2227     SILC_LOG_DEBUG(("Public key not found in channel public key list"));
2228     goto out;
2229   }
2230
2231   /* Verify the signature */
2232   if (!silc_auth_verify(ap, SILC_AUTH_PUBLIC_KEY, (void *)chpk, 0,
2233                         server->sha1hash, client_id, SILC_ID_CLIENT)) {
2234     SILC_LOG_DEBUG(("Authentication failed"));
2235     goto out;
2236   }
2237
2238   ret = TRUE;
2239
2240  out:
2241   silc_auth_payload_free(ap);
2242   return ret;
2243 }