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