Fix double free in silcd.
[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
1551     if (sock)
1552       silc_packet_stream_ref(sock);
1553
1554     silc_server_free_sock_user_data(server, sock, NULL);
1555
1556     if (sock) {
1557       silc_packet_set_context(sock, NULL);
1558       silc_server_close_connection(server, sock);
1559       silc_packet_stream_unref(sock);
1560     }
1561   } else {
1562     /* Update statistics */
1563     server->stat.clients--;
1564     if (server->stat.cell_clients)
1565       server->stat.cell_clients--;
1566     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1567     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1568
1569     /* Remove client's public key from repository, this will free it too. */
1570     if (remote_client->data.public_key) {
1571       silc_skr_del_public_key(server->repository,
1572                               remote_client->data.public_key, remote_client);
1573       remote_client->data.public_key = NULL;
1574     }
1575
1576     if (SILC_IS_LOCAL(remote_client)) {
1577       server->stat.my_clients--;
1578       silc_schedule_task_del_by_context(server->schedule, remote_client);
1579     }
1580
1581     /* Remove remote client */
1582     silc_dlist_del(server->expired_clients, remote_client);
1583     silc_idlist_del_data(remote_client);
1584     if (!silc_idlist_del_client(server->global_list, remote_client)) {
1585       /* Remove this client from watcher list if it is */
1586       silc_server_del_from_watcher_list(server, remote_client);
1587       silc_idlist_del_client(server->local_list, remote_client);
1588     }
1589   }
1590
1591   silc_buffer_free(killer);
1592   silc_buffer_free(killed);
1593 }
1594
1595 typedef struct {
1596   SilcServer server;
1597   SilcClientEntry client;
1598   SilcNotifyType notify;
1599   const char *new_nick;
1600 } WatcherNotifyContext;
1601
1602 static void
1603 silc_server_check_watcher_list_foreach(void *key, void *context,
1604                                        void *user_context)
1605 {
1606   WatcherNotifyContext *notify = user_context;
1607   SilcClientEntry entry = context;
1608   SilcPacketStream sock;
1609
1610   if (!context)
1611     return;
1612
1613   if (entry == notify->client)
1614     return;
1615
1616   sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1617                                       NULL, NULL);
1618   if (sock) {
1619     SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1620                     silc_id_render(entry->id, SILC_ID_CLIENT)));
1621
1622     /* Send the WATCH notify */
1623     silc_server_send_notify_watch(notify->server, sock, entry,
1624                                   notify->client,
1625                                   notify->new_nick ? notify->new_nick :
1626                                   (const char *)notify->client->nickname,
1627                                   notify->notify,
1628                                   notify->client->data.public_key);
1629   }
1630 }
1631
1632 /* This function checks whether the `client' nickname and/or 'client'
1633    public key is being watched by someone, and notifies the watcher of the
1634    notify change of notify type indicated by `notify'. */
1635
1636 SilcBool silc_server_check_watcher_list(SilcServer server,
1637                                         SilcClientEntry client,
1638                                         const char *new_nick,
1639                                         SilcNotifyType notify)
1640 {
1641   unsigned char hash[16];
1642   WatcherNotifyContext n;
1643
1644   SILC_LOG_DEBUG(("Checking watcher list %s",
1645                   client->nickname ? client->nickname : (unsigned char *)""));
1646
1647   /* If the watching is rejected by the client do nothing */
1648   if (client->mode & SILC_UMODE_REJECT_WATCHING)
1649     return FALSE;
1650
1651   /* Make hash from the nick, or take it from Client ID */
1652   if (client->nickname) {
1653     unsigned char *nickc;
1654     nickc = silc_identifier_check(client->nickname, strlen(client->nickname),
1655                                   SILC_STRING_UTF8, 128, NULL);
1656     if (!nickc)
1657       return FALSE;
1658     silc_hash_make(server->md5hash, nickc, strlen(nickc), hash);
1659     silc_free(nickc);
1660   } else {
1661     memset(hash, 0, sizeof(hash));
1662     memcpy(hash, client->id->hash, sizeof(client->id->hash));
1663   }
1664
1665   n.server = server;
1666   n.client = client;
1667   n.new_nick = new_nick;
1668   n.notify = notify;
1669
1670   /* Send notify to all watchers watching this nickname */
1671   silc_hash_table_find_foreach(server->watcher_list, hash,
1672                                silc_server_check_watcher_list_foreach, &n);
1673
1674   /* Send notify to all watchers watching this public key */
1675   if (client->data.public_key)
1676     silc_hash_table_find_foreach(server->watcher_list_pk,
1677                                  client->data.public_key,
1678                                  silc_server_check_watcher_list_foreach,
1679                                  &n);
1680
1681   return TRUE;
1682 }
1683
1684 /* Remove the `client' from watcher list. After calling this the `client'
1685    is not watching any nicknames. */
1686
1687 SilcBool silc_server_del_from_watcher_list(SilcServer server,
1688                                            SilcClientEntry client)
1689 {
1690   SilcHashTableList htl;
1691   void *key;
1692   SilcClientEntry entry;
1693   SilcBool found = FALSE;
1694
1695   silc_hash_table_list(server->watcher_list, &htl);
1696   while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1697     if (entry == client) {
1698       silc_hash_table_del_by_context(server->watcher_list, key, client);
1699
1700       if (client->id)
1701         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1702                         silc_id_render(client->id, SILC_ID_CLIENT)));
1703
1704       /* Now check whether there still exists entries with this key, if not
1705          then free the key to not leak memory. */
1706       if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1707         silc_free(key);
1708
1709       found = TRUE;
1710     }
1711   }
1712   silc_hash_table_list_reset(&htl);
1713
1714   silc_hash_table_list(server->watcher_list_pk, &htl);
1715   while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1716     if (entry == client) {
1717       silc_hash_table_del_by_context(server->watcher_list_pk, key, client);
1718
1719       if (client->id)
1720         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1721                         silc_id_render(client->id, SILC_ID_CLIENT)));
1722
1723       /* Now check whether there still exists entries with this key, if not
1724          then free the key to not leak memory. */
1725       if (!silc_hash_table_find(server->watcher_list_pk, key, NULL, NULL))
1726         silc_pkcs_public_key_free(key);
1727
1728       found = TRUE;
1729     }
1730   }
1731   silc_hash_table_list_reset(&htl);
1732
1733   return found;
1734 }
1735
1736 /* Force the client indicated by `chl' to change the channel user mode
1737    on channel indicated by `channel' to `forced_mode'. */
1738
1739 SilcBool silc_server_force_cumode_change(SilcServer server,
1740                                          SilcPacketStream sock,
1741                                          SilcChannelEntry channel,
1742                                          SilcChannelClientEntry chl,
1743                                          SilcUInt32 forced_mode)
1744 {
1745   SilcBuffer idp1, idp2;
1746   unsigned char cumode[4];
1747
1748   SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1749
1750   if (sock)
1751     silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1752                                    server->id, SILC_ID_SERVER,
1753                                    chl->client->id, NULL);
1754
1755   idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1756   idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1757   SILC_PUT32_MSB(forced_mode, cumode);
1758   silc_server_send_notify_to_channel(server, sock, channel, FALSE, TRUE,
1759                                      SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1760                                      3, idp1->data, silc_buffer_len(idp1),
1761                                      cumode, sizeof(cumode),
1762                                      idp2->data, silc_buffer_len(idp2));
1763   silc_buffer_free(idp1);
1764   silc_buffer_free(idp2);
1765
1766   return TRUE;
1767 }
1768
1769 /* This function can be used to match the invite and ban lists. */
1770
1771 SilcBool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1772                                      SilcUInt8 type, void *check)
1773 {
1774   unsigned char *tmp = NULL;
1775   SilcUInt32 len = 0;
1776   SilcHashTableList htl;
1777   SilcBuffer entry, idp = NULL, pkp = NULL;
1778   SilcBool ret = FALSE;
1779   void *t;
1780
1781   SILC_LOG_DEBUG(("Matching invite/ban"));
1782
1783   if (type < 1 || type > 3 || !check)
1784     return FALSE;
1785
1786   if (type == 1) {
1787     tmp = strdup((char *)check);
1788     if (!tmp)
1789       return FALSE;
1790   }
1791   if (type == 2) {
1792     pkp = silc_public_key_payload_encode(check);
1793     if (!pkp)
1794       return FALSE;
1795     tmp = pkp->data;
1796     len = silc_buffer_len(pkp);
1797   }
1798   if (type == 3) {
1799     idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
1800     if (!idp)
1801       return FALSE;
1802     tmp = idp->data;
1803     len = silc_buffer_len(idp);
1804   }
1805
1806   /* Compare the list */
1807   silc_hash_table_list(list, &htl);
1808   while (silc_hash_table_get(&htl, (void *)&t, (void *)&entry)) {
1809     if (type == SILC_PTR_TO_32(t)) {
1810       if (type == 1) {
1811         if (silc_string_match(entry->data, tmp)) {
1812           ret = TRUE;
1813           break;
1814         }
1815       } else if (silc_buffer_len(entry) == len &&
1816                  !memcmp(entry->data, tmp, len)) {
1817         ret = TRUE;
1818         break;
1819       }
1820     }
1821   }
1822   silc_hash_table_list_reset(&htl);
1823
1824   if (type == 1)
1825     silc_free(tmp);
1826   silc_buffer_free(idp);
1827   silc_buffer_free(pkp);
1828   return ret;
1829 }
1830
1831 /* Process invite or ban information */
1832
1833 SilcBool silc_server_inviteban_process(SilcServer server,
1834                                        SilcHashTable list,
1835                                        SilcUInt8 action,
1836                                        SilcArgumentPayload args)
1837 {
1838   unsigned char *tmp;
1839   SilcUInt32 type, len;
1840   void *ptype;
1841   SilcBuffer tmp2;
1842   SilcHashTableList htl;
1843
1844   SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1845                   action == 0x01 ? "DEL" : "ADD"));
1846
1847   /* Add the information to invite list */
1848   if (action == 0x00 || action == 0x03) {
1849     /* Traverse all arguments and add to the hash table according to
1850        their type. */
1851     tmp = silc_argument_get_first_arg(args, &type, &len);
1852     while (tmp) {
1853       if (type == 1) {
1854         /* Check validity of the string.  Actually we should parse the
1855            whole string and verify all components individually. */
1856         if (!silc_utf8_valid(tmp, len) || !len) {
1857           tmp = silc_argument_get_next_arg(args, &type, &len);
1858           continue;
1859         }
1860         if (strchr(tmp, ',')) {
1861           tmp = silc_argument_get_next_arg(args, &type, &len);
1862           continue;
1863         }
1864
1865         /* Check if the string is added already */
1866         silc_hash_table_list(list, &htl);
1867         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1868           if (SILC_PTR_TO_32(ptype) == 1 &&
1869               silc_string_match(tmp2->data, tmp)) {
1870             tmp = NULL;
1871             break;
1872           }
1873         }
1874         silc_hash_table_list_reset(&htl);
1875
1876         if (tmp) {
1877           /* Add the string to hash table */
1878           tmp2 = silc_buffer_alloc_size(len + 1);
1879           if (tmp[len - 1] == ',')
1880             tmp[len - 1] = '\0';
1881           silc_buffer_put(tmp2, tmp, len);
1882           silc_hash_table_add(list, (void *)1, tmp2);
1883         }
1884
1885       } else if (type == 2) {
1886         /* Public key.  Check first if the public key is already on the
1887            list and ignore it if it is, otherwise, add it to hash table. */
1888         SilcPublicKey pk;
1889
1890         /* Verify validity of the public key */
1891         if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1892           tmp = silc_argument_get_next_arg(args, &type, &len);
1893           continue;
1894         }
1895         silc_pkcs_public_key_free(pk);
1896
1897         /* Check if the public key is in the list already */
1898         silc_hash_table_list(list, &htl);
1899         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1900           if (SILC_PTR_TO_32(ptype) == 2 && !memcmp(tmp2->data, tmp, len)) {
1901             tmp = NULL;
1902             break;
1903           }
1904         }
1905         silc_hash_table_list_reset(&htl);
1906
1907         /* Add new public key to invite list */
1908         if (tmp) {
1909           tmp2 = silc_buffer_alloc_size(len);
1910           silc_buffer_put(tmp2, tmp, len);
1911           silc_hash_table_add(list, (void *)2, tmp2);
1912         }
1913
1914       } else if (type == 3) {
1915         /* Client ID */
1916
1917         /* Check if the ID is in the list already */
1918         silc_hash_table_list(list, &htl);
1919         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1920           if (SILC_PTR_TO_32(ptype) == 3 && !memcmp(tmp2->data, tmp, len)) {
1921             tmp = NULL;
1922             break;
1923           }
1924         }
1925         silc_hash_table_list_reset(&htl);
1926
1927         /* Add new Client ID to invite list */
1928         if (tmp) {
1929           tmp2 = silc_buffer_alloc_size(len);
1930           silc_buffer_put(tmp2, tmp, len);
1931           silc_hash_table_add(list, (void *)3, tmp2);
1932         }
1933       }
1934
1935       tmp = silc_argument_get_next_arg(args, &type, &len);
1936     }
1937   }
1938
1939   /* Delete information to invite list */
1940   if (action == 0x01 && list) {
1941     /* Now delete the arguments from invite list */
1942     tmp = silc_argument_get_first_arg(args, &type, &len);
1943     while (tmp) {
1944       if (type == 1) {
1945         /* Check validity of the string.  Actually we should parse the
1946            whole string and verify all components individually. */
1947         if (!silc_utf8_valid(tmp, len)) {
1948           tmp = silc_argument_get_next_arg(args, &type, &len);
1949           continue;
1950         }
1951         if (strchr(tmp, ',')) {
1952           tmp = silc_argument_get_next_arg(args, &type, &len);
1953           continue;
1954         }
1955
1956         /* Delete from the list */
1957         silc_hash_table_list(list, &htl);
1958         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1959           if (SILC_PTR_TO_32(ptype) == 1 &&
1960               silc_string_match(tmp2->data, tmp)) {
1961             silc_hash_table_del_by_context(list, (void *)1, tmp2);
1962             break;
1963           }
1964         }
1965         silc_hash_table_list_reset(&htl);
1966
1967       } else if (type == 2) {
1968         /* Public key. */
1969         SilcPublicKey pk;
1970
1971         /* Verify validity of the public key */
1972         if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1973           tmp = silc_argument_get_next_arg(args, &type, &len);
1974           continue;
1975         }
1976         silc_pkcs_public_key_free(pk);
1977
1978         /* Delete from the invite list */
1979         silc_hash_table_list(list, &htl);
1980         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1981           if (SILC_PTR_TO_32(ptype) == 2 && !memcmp(tmp2->data, tmp, len)) {
1982             silc_hash_table_del_by_context(list, (void *)2, tmp2);
1983             break;
1984           }
1985         }
1986         silc_hash_table_list_reset(&htl);
1987
1988       } else if (type == 3) {
1989         /* Client ID */
1990
1991         /* Delete from the invite list */
1992         silc_hash_table_list(list, &htl);
1993         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1994           if (SILC_PTR_TO_32(ptype) == 3 && !memcmp(tmp2->data, tmp, len)) {
1995             silc_hash_table_del_by_context(list, (void *)3, tmp2);
1996             break;
1997           }
1998         }
1999         silc_hash_table_list_reset(&htl);
2000       }
2001
2002       tmp = silc_argument_get_next_arg(args, &type, &len);
2003     }
2004   }
2005
2006   return TRUE;
2007 }
2008
2009 /* Destructor for invite and ban list entrys */
2010
2011 void silc_server_inviteban_destruct(void *key, void *context,
2012                                     void *user_context)
2013 {
2014   silc_buffer_free(context);
2015 }
2016
2017 /* Creates connections accoring to configuration. */
2018
2019 void silc_server_create_connections(SilcServer server)
2020 {
2021   silc_schedule_task_del_by_callback(server->schedule,
2022                                      silc_server_connect_to_router);
2023   silc_schedule_task_add_timeout(server->schedule,
2024                                  silc_server_connect_to_router, server, 1, 0);
2025 }
2026
2027 static void
2028 silc_server_process_channel_pk_destruct(void *key, void *context,
2029                                         void *user_context)
2030 {
2031   silc_free(key);
2032   silc_pkcs_public_key_free(context);
2033 }
2034
2035 /* Processes a channel public key, either adds or removes it. */
2036
2037 SilcStatus
2038 silc_server_process_channel_pk(SilcServer server,
2039                                SilcChannelEntry channel,
2040                                SilcUInt32 type, const unsigned char *pk,
2041                                SilcUInt32 pk_len)
2042 {
2043   unsigned char pkhash[20];
2044   SilcPublicKey chpk;
2045
2046   SILC_LOG_DEBUG(("Processing channel public key"));
2047
2048   if (!pk || !pk_len)
2049     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2050
2051   /* Decode the public key */
2052   if (!silc_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
2053     return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
2054
2055   /* Create channel public key list (hash table) if needed */
2056   if (!channel->channel_pubkeys) {
2057     channel->channel_pubkeys =
2058       silc_hash_table_alloc(0, silc_hash_data, (void *)20,
2059                             silc_hash_data_compare, (void *)20,
2060                             silc_server_process_channel_pk_destruct, channel,
2061                             TRUE);
2062   }
2063
2064   /* Create SHA-1 digest of the public key data */
2065   silc_hash_make(server->sha1hash, pk + 4, pk_len - 4, pkhash);
2066
2067   if (type == 0x00) {
2068     /* Add new public key to channel public key list */
2069     SILC_LOG_DEBUG(("Add new channel public key to channel %s",
2070                     channel->channel_name));
2071
2072     /* Check for resource limit */
2073     if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
2074       silc_pkcs_public_key_free(chpk);
2075       return SILC_STATUS_ERR_RESOURCE_LIMIT;
2076     }
2077
2078     /* Add if doesn't exist already */
2079     if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2080                               NULL, NULL))
2081       silc_hash_table_add(channel->channel_pubkeys, silc_memdup(pkhash, 20),
2082                           chpk);
2083   } else if (type == 0x01) {
2084     /* Delete public key from channel public key list */
2085     SILC_LOG_DEBUG(("Delete a channel public key from channel %s",
2086                     channel->channel_name));
2087     if (!silc_hash_table_del(channel->channel_pubkeys, pkhash))
2088       silc_pkcs_public_key_free(chpk);
2089   } else {
2090     silc_pkcs_public_key_free(chpk);
2091     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2092   }
2093
2094   return SILC_STATUS_OK;
2095 }
2096
2097 /* Returns the channel public keys as Argument List payload. */
2098
2099 SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
2100                                            SilcChannelEntry channel,
2101                                            SilcBool announce,
2102                                            SilcBool delete)
2103 {
2104   SilcHashTableList htl;
2105   SilcBuffer list, pkp;
2106   SilcPublicKey pk;
2107
2108   SILC_LOG_DEBUG(("Encoding channel public keys list"));
2109
2110   if (!channel->channel_pubkeys ||
2111       !silc_hash_table_count(channel->channel_pubkeys))
2112     return NULL;
2113
2114   /* Encode the list */
2115   list = silc_buffer_alloc_size(2);
2116   silc_buffer_format(list,
2117                      SILC_STR_UI_SHORT(silc_hash_table_count(
2118                                        channel->channel_pubkeys)),
2119                      SILC_STR_END);
2120
2121   silc_hash_table_list(channel->channel_pubkeys, &htl);
2122   while (silc_hash_table_get(&htl, NULL, (void *)&pk)) {
2123     pkp = silc_public_key_payload_encode(pk);
2124     if (!pkp)
2125       continue;
2126     list = silc_argument_payload_encode_one(list, pkp->data,
2127                                             silc_buffer_len(pkp),
2128                                             announce ? 0x03 :
2129                                             delete ? 0x01 : 0x00);
2130     silc_buffer_free(pkp);
2131   }
2132   silc_hash_table_list_reset(&htl);
2133
2134   return list;
2135 }
2136
2137 /* Sets the channel public keys into channel from the list of public keys. */
2138
2139 SilcStatus silc_server_set_channel_pk_list(SilcServer server,
2140                                            SilcPacketStream sender,
2141                                            SilcChannelEntry channel,
2142                                            const unsigned char *pklist,
2143                                            SilcUInt32 pklist_len)
2144 {
2145   SilcUInt16 argc;
2146   SilcArgumentPayload args;
2147   unsigned char *chpk;
2148   SilcUInt32 chpklen, type;
2149   SilcStatus ret = SILC_STATUS_OK;
2150
2151   SILC_LOG_DEBUG(("Setting channel public keys list"));
2152
2153   if (!pklist || pklist_len < 2)
2154     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2155
2156   /* Get the argument from the Argument List Payload */
2157   SILC_GET16_MSB(argc, pklist);
2158   args = silc_argument_payload_parse(pklist + 2, pklist_len - 2, argc);
2159   if (!args)
2160     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2161
2162   /* Process the public keys one by one */
2163   chpk = silc_argument_get_first_arg(args, &type, &chpklen);
2164
2165   /* If announcing keys and we have them set already, do not allow this */
2166   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2167       server->server_type == SILC_ROUTER &&
2168       sender != SILC_PRIMARY_ROUTE(server)) {
2169     SILC_LOG_DEBUG(("Channel public key list set already, enforce our list"));
2170     silc_argument_payload_free(args);
2171     return SILC_STATUS_ERR_OPERATION_ALLOWED;
2172   }
2173
2174   /* If we are normal server and receive announcement list and we already
2175      have keys set, we replace the old list with the announced one. */
2176   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2177       server->server_type != SILC_ROUTER) {
2178     SilcBuffer sidp;
2179     unsigned char mask[4], ulimit[4];
2180
2181     SILC_LOG_DEBUG(("Router enforces its list, remove old list"));
2182     silc_hash_table_free(channel->channel_pubkeys);
2183     channel->channel_pubkeys = NULL;
2184
2185     /* Send notify that removes the old list */
2186     sidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2187     SILC_PUT32_MSB((channel->mode & (~SILC_CHANNEL_MODE_CHANNEL_AUTH)), mask);
2188     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2189       SILC_PUT32_MSB(channel->user_limit, ulimit);
2190     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2191                                        SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
2192                                        sidp->data, silc_buffer_len(sidp),
2193                                        mask, 4,
2194                                        channel->cipher,
2195                                        channel->cipher ?
2196                                        strlen(channel->cipher) : 0,
2197                                        channel->hmac_name,
2198                                        channel->hmac_name ?
2199                                        strlen(channel->hmac_name) : 0,
2200                                        channel->passphrase,
2201                                        channel->passphrase ?
2202                                        strlen(channel->passphrase) : 0,
2203                                        NULL, 0, NULL, 0,
2204                                        (channel->mode &
2205                                         SILC_CHANNEL_MODE_ULIMIT ?
2206                                         ulimit : NULL),
2207                                        (channel->mode &
2208                                         SILC_CHANNEL_MODE_ULIMIT ?
2209                                         sizeof(ulimit) : 0));
2210     silc_buffer_free(sidp);
2211   }
2212
2213   while (chpk) {
2214     if (type == 0x03)
2215       type = 0x00;
2216     ret = silc_server_process_channel_pk(server, channel, type,
2217                                          chpk, chpklen);
2218     if (ret != SILC_STATUS_OK)
2219       break;
2220     chpk = silc_argument_get_next_arg(args, &type, &chpklen);
2221   }
2222
2223   silc_argument_payload_free(args);
2224   return ret;
2225 }
2226
2227 /* Verifies the Authentication Payload `auth' with one of the public keys
2228    on the `channel' public key list. */
2229
2230 SilcBool silc_server_verify_channel_auth(SilcServer server,
2231                                          SilcChannelEntry channel,
2232                                          SilcClientID *client_id,
2233                                          const unsigned char *auth,
2234                                          SilcUInt32 auth_len)
2235 {
2236   SilcAuthPayload ap;
2237   SilcPublicKey chpk;
2238   unsigned char *pkhash;
2239   SilcUInt32 pkhash_len;
2240   SilcBool ret = FALSE;
2241
2242   SILC_LOG_DEBUG(("Verifying channel authentication"));
2243
2244   if (!auth || !auth_len || !channel->channel_pubkeys)
2245     return FALSE;
2246
2247   /* Get the hash from the auth data which tells us what public key we
2248      must use in verification. */
2249
2250   ap = silc_auth_payload_parse(auth, auth_len);
2251   if (!ap)
2252     return FALSE;
2253
2254   pkhash = silc_auth_get_public_data(ap, &pkhash_len);
2255   if (pkhash_len < 128)
2256     goto out;
2257
2258   /* Find the public key with the hash */
2259   if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2260                             NULL, (void *)&chpk)) {
2261     SILC_LOG_DEBUG(("Public key not found in channel public key list"));
2262     goto out;
2263   }
2264
2265   /* Verify the signature */
2266   if (!silc_auth_verify(ap, SILC_AUTH_PUBLIC_KEY, (void *)chpk, 0,
2267                         server->sha1hash, client_id, SILC_ID_CLIENT)) {
2268     SILC_LOG_DEBUG(("Authentication failed"));
2269     goto out;
2270   }
2271
2272   ret = TRUE;
2273
2274  out:
2275   silc_auth_payload_free(ap);
2276   return ret;
2277 }