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