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