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