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