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