silcd: show MAC in welcome notifys
[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   SilcHmac hmac;
1430
1431   SILC_LOG_DEBUG(("Send welcome notifys"));
1432
1433   /* Send some nice info to the client */
1434   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1435                           ("Welcome to the SILC Network %s",
1436                            client->username));
1437   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1438                           ("Your host is %s, running version %s",
1439                            server->server_name, server_version));
1440
1441   if (server->server_type == SILC_ROUTER) {
1442     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1443                             ("There are %d clients, %d servers and %d "
1444                              "routers in SILC Network",
1445                              server->stat.clients, server->stat.servers,
1446                              server->stat.routers));
1447   } else {
1448     if (server->stat.clients && server->stat.servers + 1)
1449       SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1450                               ("There are %d clients, %d servers and %d "
1451                                "routers in SILC Network",
1452                                server->stat.clients, server->stat.servers,
1453                                (server->standalone ? 0 :
1454                                 !server->stat.routers ? 1 :
1455                                 server->stat.routers)));
1456   }
1457
1458   if (server->stat.cell_clients && server->stat.cell_servers + 1)
1459     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1460                             ("There are %d clients on %d servers in our cell",
1461                              server->stat.cell_clients,
1462                              server->stat.cell_servers));
1463   if (server->server_type == SILC_ROUTER) {
1464     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1465                             ("I have %d clients, %d channels, %d servers and "
1466                              "%d routers",
1467                              server->stat.my_clients,
1468                              server->stat.my_channels,
1469                              server->stat.my_servers,
1470                              server->stat.my_routers));
1471   } else {
1472     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1473                             ("I have %d clients and %d channels formed",
1474                              server->stat.my_clients,
1475                              server->stat.my_channels));
1476   }
1477
1478   if (server->stat.server_ops || server->stat.router_ops)
1479     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1480                             ("There are %d server operators and %d router "
1481                              "operators online",
1482                              server->stat.server_ops,
1483                              server->stat.router_ops));
1484   if (server->stat.my_router_ops + server->stat.my_server_ops)
1485     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1486                             ("I have %d operators online",
1487                              server->stat.my_router_ops +
1488                              server->stat.my_server_ops));
1489
1490   silc_packet_get_keys(sock, &key, NULL, &hmac, NULL);
1491   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1492                           ("Your connection is secured with %s cipher "
1493                            "and %s MAC",
1494                            silc_cipher_get_name(key),
1495                            silc_hmac_get_name(hmac)));
1496   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1497                           ("Your current nickname is %s",
1498                            client->nickname));
1499
1500   /* Send motd */
1501   silc_server_send_motd(server, sock);
1502 }
1503
1504 /* Kill the client indicated by `remote_client' sending KILLED notify
1505    to the client, to all channels client has joined and to primary
1506    router if needed.  The killed client is also removed from all channels. */
1507
1508 void silc_server_kill_client(SilcServer server,
1509                              SilcClientEntry remote_client,
1510                              const char *comment,
1511                              void *killer_id,
1512                              SilcIdType killer_id_type)
1513 {
1514   SilcBuffer killed, killer;
1515
1516   SILC_LOG_DEBUG(("Killing client %s",
1517                   silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1518
1519   /* Send the KILL notify packets. First send it to the channel, then
1520      to our primary router and then directly to the client who is being
1521      killed right now. */
1522
1523   killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1524   killer = silc_id_payload_encode(killer_id, killer_id_type);
1525
1526   /* Send KILLED notify to the channels. It is not sent to the client
1527      as it will be sent differently destined directly to the client and not
1528      to the channel. */
1529   silc_server_send_notify_on_channels(server, remote_client,
1530                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
1531                                       3, killed->data, silc_buffer_len(killed),
1532                                       comment, comment ? strlen(comment) : 0,
1533                                       killer->data, silc_buffer_len(killer));
1534
1535   /* Send KILLED notify to primary route */
1536   silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1537                                  SILC_BROADCAST(server), remote_client->id,
1538                                  comment, killer_id, killer_id_type);
1539
1540   /* Send KILLED notify to the client directly */
1541   if (remote_client->connection || remote_client->router)
1542     silc_server_send_notify_killed(server, remote_client->connection ?
1543                                    remote_client->connection :
1544                                    remote_client->router->connection, FALSE,
1545                                    remote_client->id, comment,
1546                                    killer_id, killer_id_type);
1547
1548   /* Remove the client from all channels. This generates new keys to the
1549      channels as well. */
1550   silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1551                                    NULL, TRUE, TRUE);
1552
1553   /* Remove the client entry, If it is locally connected then we will also
1554      disconnect the client here */
1555   if (remote_client->connection) {
1556     /* Remove locally conneted client */
1557     SilcPacketStream sock = remote_client->connection;
1558
1559     if (sock)
1560       silc_packet_stream_ref(sock);
1561
1562     silc_server_free_sock_user_data(server, sock, NULL);
1563
1564     if (sock) {
1565       silc_packet_set_context(sock, NULL);
1566       silc_server_close_connection(server, sock);
1567       silc_packet_stream_unref(sock);
1568     }
1569   } else {
1570     /* Update statistics */
1571     SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
1572                     server->stat.clients - 1));
1573     SILC_VERIFY(server->stat.clients > 0);
1574     server->stat.clients--;
1575     if (server->stat.cell_clients)
1576       server->stat.cell_clients--;
1577     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1578     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1579
1580     /* Remove client's public key from repository, this will free it too. */
1581     if (remote_client->data.public_key) {
1582       silc_skr_del_public_key(server->repository,
1583                               remote_client->data.public_key, remote_client);
1584       remote_client->data.public_key = NULL;
1585     }
1586
1587     if (SILC_IS_LOCAL(remote_client)) {
1588       if (!remote_client->local_detached)
1589         server->stat.my_clients--;
1590       silc_schedule_task_del_by_context(server->schedule, remote_client);
1591     }
1592
1593     /* Remove remote client */
1594     silc_dlist_del(server->expired_clients, remote_client);
1595     silc_idlist_del_data(remote_client);
1596     if (!silc_idlist_del_client(server->global_list, remote_client)) {
1597       /* Remove this client from watcher list if it is */
1598       silc_server_del_from_watcher_list(server, remote_client);
1599       silc_idlist_del_client(server->local_list, remote_client);
1600     }
1601   }
1602
1603   silc_buffer_free(killer);
1604   silc_buffer_free(killed);
1605 }
1606
1607 typedef struct {
1608   SilcServer server;
1609   SilcClientEntry client;
1610   SilcNotifyType notify;
1611   const char *new_nick;
1612 } WatcherNotifyContext;
1613
1614 static void
1615 silc_server_check_watcher_list_foreach(void *key, void *context,
1616                                        void *user_context)
1617 {
1618   WatcherNotifyContext *notify = user_context;
1619   SilcClientEntry entry = context;
1620   SilcPacketStream sock;
1621
1622   if (!context)
1623     return;
1624
1625   if (entry == notify->client)
1626     return;
1627
1628   sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1629                                       NULL, NULL);
1630   if (sock) {
1631     SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1632                     silc_id_render(entry->id, SILC_ID_CLIENT)));
1633
1634     /* Send the WATCH notify */
1635     silc_server_send_notify_watch(notify->server, sock, entry,
1636                                   notify->client,
1637                                   notify->new_nick ? notify->new_nick :
1638                                   (const char *)notify->client->nickname,
1639                                   notify->notify,
1640                                   notify->client->data.public_key);
1641   }
1642 }
1643
1644 /* This function checks whether the `client' nickname and/or 'client'
1645    public key is being watched by someone, and notifies the watcher of the
1646    notify change of notify type indicated by `notify'. */
1647
1648 SilcBool silc_server_check_watcher_list(SilcServer server,
1649                                         SilcClientEntry client,
1650                                         const char *new_nick,
1651                                         SilcNotifyType notify)
1652 {
1653   unsigned char hash[16];
1654   WatcherNotifyContext n;
1655
1656   SILC_LOG_DEBUG(("Checking watcher list %s",
1657                   client->nickname ? client->nickname : (unsigned char *)""));
1658
1659   /* If the watching is rejected by the client do nothing */
1660   if (client->mode & SILC_UMODE_REJECT_WATCHING)
1661     return FALSE;
1662
1663   /* Make hash from the nick, or take it from Client ID */
1664   if (client->nickname) {
1665     unsigned char *nickc;
1666     nickc = silc_identifier_check(client->nickname, strlen(client->nickname),
1667                                   SILC_STRING_UTF8, 128, NULL);
1668     if (!nickc)
1669       return FALSE;
1670     silc_hash_make(server->md5hash, nickc, strlen(nickc), hash);
1671     silc_free(nickc);
1672   } else {
1673     memset(hash, 0, sizeof(hash));
1674     memcpy(hash, client->id->hash, sizeof(client->id->hash));
1675   }
1676
1677   n.server = server;
1678   n.client = client;
1679   n.new_nick = new_nick;
1680   n.notify = notify;
1681
1682   /* Send notify to all watchers watching this nickname */
1683   silc_hash_table_find_foreach(server->watcher_list, hash,
1684                                silc_server_check_watcher_list_foreach, &n);
1685
1686   /* Send notify to all watchers watching this public key */
1687   if (client->data.public_key)
1688     silc_hash_table_find_foreach(server->watcher_list_pk,
1689                                  client->data.public_key,
1690                                  silc_server_check_watcher_list_foreach,
1691                                  &n);
1692
1693   return TRUE;
1694 }
1695
1696 /* Remove the `client' from watcher list. After calling this the `client'
1697    is not watching any nicknames. */
1698
1699 SilcBool silc_server_del_from_watcher_list(SilcServer server,
1700                                            SilcClientEntry client)
1701 {
1702   SilcHashTableList htl;
1703   void *key;
1704   SilcClientEntry entry;
1705   SilcBool found = FALSE;
1706
1707   silc_hash_table_list(server->watcher_list, &htl);
1708   while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1709     if (entry == client) {
1710       silc_hash_table_del_by_context(server->watcher_list, key, client);
1711
1712       if (client->id)
1713         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1714                         silc_id_render(client->id, SILC_ID_CLIENT)));
1715
1716       /* Now check whether there still exists entries with this key, if not
1717          then free the key to not leak memory. */
1718       if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1719         silc_free(key);
1720
1721       found = TRUE;
1722     }
1723   }
1724   silc_hash_table_list_reset(&htl);
1725
1726   silc_hash_table_list(server->watcher_list_pk, &htl);
1727   while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1728     if (entry == client) {
1729       silc_hash_table_del_by_context(server->watcher_list_pk, key, client);
1730
1731       if (client->id)
1732         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1733                         silc_id_render(client->id, SILC_ID_CLIENT)));
1734
1735       /* Now check whether there still exists entries with this key, if not
1736          then free the key to not leak memory. */
1737       if (!silc_hash_table_find(server->watcher_list_pk, key, NULL, NULL))
1738         silc_pkcs_public_key_free(key);
1739
1740       found = TRUE;
1741     }
1742   }
1743   silc_hash_table_list_reset(&htl);
1744
1745   return found;
1746 }
1747
1748 /* Force the client indicated by `chl' to change the channel user mode
1749    on channel indicated by `channel' to `forced_mode'. */
1750
1751 SilcBool silc_server_force_cumode_change(SilcServer server,
1752                                          SilcPacketStream sock,
1753                                          SilcChannelEntry channel,
1754                                          SilcChannelClientEntry chl,
1755                                          SilcUInt32 forced_mode)
1756 {
1757   SilcBuffer idp1, idp2;
1758   unsigned char cumode[4];
1759
1760   SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1761
1762   if (sock)
1763     silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1764                                    server->id, SILC_ID_SERVER,
1765                                    chl->client->id, NULL);
1766
1767   idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1768   idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1769   SILC_PUT32_MSB(forced_mode, cumode);
1770   silc_server_send_notify_to_channel(server, sock, channel, FALSE, TRUE,
1771                                      SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1772                                      3, idp1->data, silc_buffer_len(idp1),
1773                                      cumode, sizeof(cumode),
1774                                      idp2->data, silc_buffer_len(idp2));
1775   silc_buffer_free(idp1);
1776   silc_buffer_free(idp2);
1777
1778   return TRUE;
1779 }
1780
1781 /* This function can be used to match the invite and ban lists. */
1782
1783 SilcBool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1784                                      SilcUInt8 type, void *check)
1785 {
1786   unsigned char *tmp = NULL;
1787   SilcUInt32 len = 0;
1788   SilcHashTableList htl;
1789   SilcBuffer entry, idp = NULL, pkp = NULL;
1790   SilcBool ret = FALSE;
1791   void *t;
1792
1793   SILC_LOG_DEBUG(("Matching invite/ban"));
1794
1795   if (type < 1 || type > 3 || !check)
1796     return FALSE;
1797
1798   if (type == 1) {
1799     tmp = strdup((char *)check);
1800     if (!tmp)
1801       return FALSE;
1802   }
1803   if (type == 2) {
1804     pkp = silc_public_key_payload_encode(check);
1805     if (!pkp)
1806       return FALSE;
1807     tmp = pkp->data;
1808     len = silc_buffer_len(pkp);
1809   }
1810   if (type == 3) {
1811     idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
1812     if (!idp)
1813       return FALSE;
1814     tmp = idp->data;
1815     len = silc_buffer_len(idp);
1816   }
1817
1818   /* Compare the list */
1819   silc_hash_table_list(list, &htl);
1820   while (silc_hash_table_get(&htl, (void *)&t, (void *)&entry)) {
1821     if (type == SILC_PTR_TO_32(t)) {
1822       if (type == 1) {
1823         if (silc_string_match(entry->data, tmp)) {
1824           ret = TRUE;
1825           break;
1826         }
1827       } else if (silc_buffer_len(entry) == len &&
1828                  !memcmp(entry->data, tmp, len)) {
1829         ret = TRUE;
1830         break;
1831       }
1832     }
1833   }
1834   silc_hash_table_list_reset(&htl);
1835
1836   if (type == 1)
1837     silc_free(tmp);
1838   silc_buffer_free(idp);
1839   silc_buffer_free(pkp);
1840   return ret;
1841 }
1842
1843 /* Process invite or ban information */
1844
1845 SilcBool silc_server_inviteban_process(SilcServer server,
1846                                        SilcHashTable list,
1847                                        SilcUInt8 action,
1848                                        SilcArgumentPayload args)
1849 {
1850   unsigned char *tmp;
1851   SilcUInt32 type, len;
1852   void *ptype;
1853   SilcBuffer tmp2;
1854   SilcHashTableList htl;
1855
1856   SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1857                   action == 0x01 ? "DEL" : "ADD"));
1858
1859   /* Add the information to invite list */
1860   if (action == 0x00 || action == 0x03) {
1861     /* Traverse all arguments and add to the hash table according to
1862        their type. */
1863     tmp = silc_argument_get_first_arg(args, &type, &len);
1864     while (tmp) {
1865       if (type == 1) {
1866         /* Check validity of the string.  Actually we should parse the
1867            whole string and verify all components individually. */
1868         if (!silc_utf8_valid(tmp, len) || !len) {
1869           tmp = silc_argument_get_next_arg(args, &type, &len);
1870           continue;
1871         }
1872         if (strchr(tmp, ',')) {
1873           tmp = silc_argument_get_next_arg(args, &type, &len);
1874           continue;
1875         }
1876
1877         /* Check if the string is added already */
1878         silc_hash_table_list(list, &htl);
1879         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1880           if (SILC_PTR_TO_32(ptype) == 1 &&
1881               silc_string_match(tmp2->data, tmp)) {
1882             tmp = NULL;
1883             break;
1884           }
1885         }
1886         silc_hash_table_list_reset(&htl);
1887
1888         if (tmp) {
1889           /* Add the string to hash table */
1890           tmp2 = silc_buffer_alloc_size(len + 1);
1891           if (tmp[len - 1] == ',')
1892             tmp[len - 1] = '\0';
1893           silc_buffer_put(tmp2, tmp, len);
1894           silc_hash_table_add(list, (void *)1, tmp2);
1895         }
1896
1897       } else if (type == 2) {
1898         /* Public key.  Check first if the public key is already on the
1899            list and ignore it if it is, otherwise, add it to hash table. */
1900         SilcPublicKey pk;
1901
1902         /* Verify validity of the public key */
1903         if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1904           tmp = silc_argument_get_next_arg(args, &type, &len);
1905           continue;
1906         }
1907         silc_pkcs_public_key_free(pk);
1908
1909         /* Check if the public key is in the list already */
1910         silc_hash_table_list(list, &htl);
1911         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1912           if (SILC_PTR_TO_32(ptype) == 2 && !memcmp(tmp2->data, tmp, len)) {
1913             tmp = NULL;
1914             break;
1915           }
1916         }
1917         silc_hash_table_list_reset(&htl);
1918
1919         /* Add new public key to invite list */
1920         if (tmp) {
1921           tmp2 = silc_buffer_alloc_size(len);
1922           silc_buffer_put(tmp2, tmp, len);
1923           silc_hash_table_add(list, (void *)2, tmp2);
1924         }
1925
1926       } else if (type == 3) {
1927         /* Client ID */
1928
1929         /* Check if the ID is in the list already */
1930         silc_hash_table_list(list, &htl);
1931         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1932           if (SILC_PTR_TO_32(ptype) == 3 && !memcmp(tmp2->data, tmp, len)) {
1933             tmp = NULL;
1934             break;
1935           }
1936         }
1937         silc_hash_table_list_reset(&htl);
1938
1939         /* Add new Client ID to invite list */
1940         if (tmp) {
1941           tmp2 = silc_buffer_alloc_size(len);
1942           silc_buffer_put(tmp2, tmp, len);
1943           silc_hash_table_add(list, (void *)3, tmp2);
1944         }
1945       }
1946
1947       tmp = silc_argument_get_next_arg(args, &type, &len);
1948     }
1949   }
1950
1951   /* Delete information to invite list */
1952   if (action == 0x01 && list) {
1953     /* Now delete the arguments from invite list */
1954     tmp = silc_argument_get_first_arg(args, &type, &len);
1955     while (tmp) {
1956       if (type == 1) {
1957         /* Check validity of the string.  Actually we should parse the
1958            whole string and verify all components individually. */
1959         if (!silc_utf8_valid(tmp, len)) {
1960           tmp = silc_argument_get_next_arg(args, &type, &len);
1961           continue;
1962         }
1963         if (strchr(tmp, ',')) {
1964           tmp = silc_argument_get_next_arg(args, &type, &len);
1965           continue;
1966         }
1967
1968         /* Delete from the list */
1969         silc_hash_table_list(list, &htl);
1970         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1971           if (SILC_PTR_TO_32(ptype) == 1 &&
1972               silc_string_match(tmp2->data, tmp)) {
1973             silc_hash_table_del_by_context(list, (void *)1, tmp2);
1974             break;
1975           }
1976         }
1977         silc_hash_table_list_reset(&htl);
1978
1979       } else if (type == 2) {
1980         /* Public key. */
1981         SilcPublicKey pk;
1982
1983         /* Verify validity of the public key */
1984         if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1985           tmp = silc_argument_get_next_arg(args, &type, &len);
1986           continue;
1987         }
1988         silc_pkcs_public_key_free(pk);
1989
1990         /* Delete from the invite list */
1991         silc_hash_table_list(list, &htl);
1992         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1993           if (SILC_PTR_TO_32(ptype) == 2 && !memcmp(tmp2->data, tmp, len)) {
1994             silc_hash_table_del_by_context(list, (void *)2, tmp2);
1995             break;
1996           }
1997         }
1998         silc_hash_table_list_reset(&htl);
1999
2000       } else if (type == 3) {
2001         /* Client ID */
2002
2003         /* Delete from the invite list */
2004         silc_hash_table_list(list, &htl);
2005         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
2006           if (SILC_PTR_TO_32(ptype) == 3 && !memcmp(tmp2->data, tmp, len)) {
2007             silc_hash_table_del_by_context(list, (void *)3, tmp2);
2008             break;
2009           }
2010         }
2011         silc_hash_table_list_reset(&htl);
2012       }
2013
2014       tmp = silc_argument_get_next_arg(args, &type, &len);
2015     }
2016   }
2017
2018   return TRUE;
2019 }
2020
2021 /* Destructor for invite and ban list entrys */
2022
2023 void silc_server_inviteban_destruct(void *key, void *context,
2024                                     void *user_context)
2025 {
2026   silc_buffer_free(context);
2027 }
2028
2029 /* Creates connections accoring to configuration. */
2030
2031 void silc_server_create_connections(SilcServer server)
2032 {
2033   silc_schedule_task_del_by_callback(server->schedule,
2034                                      silc_server_connect_to_router_retry);
2035   silc_schedule_task_del_by_callback(server->schedule,
2036                                      silc_server_connect_to_router);
2037   silc_schedule_task_add_timeout(server->schedule,
2038                                  silc_server_connect_to_router, server, 1, 0);
2039 }
2040
2041 static void
2042 silc_server_process_channel_pk_destruct(void *key, void *context,
2043                                         void *user_context)
2044 {
2045   silc_free(key);
2046   silc_pkcs_public_key_free(context);
2047 }
2048
2049 /* Processes a channel public key, either adds or removes it. */
2050
2051 SilcStatus
2052 silc_server_process_channel_pk(SilcServer server,
2053                                SilcChannelEntry channel,
2054                                SilcUInt32 type, const unsigned char *pk,
2055                                SilcUInt32 pk_len)
2056 {
2057   unsigned char pkhash[20];
2058   SilcPublicKey chpk;
2059
2060   SILC_LOG_DEBUG(("Processing channel public key"));
2061
2062   if (!pk || !pk_len)
2063     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2064
2065   /* Decode the public key */
2066   if (!silc_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
2067     return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
2068
2069   /* Create channel public key list (hash table) if needed */
2070   if (!channel->channel_pubkeys) {
2071     channel->channel_pubkeys =
2072       silc_hash_table_alloc(0, silc_hash_data, (void *)20,
2073                             silc_hash_data_compare, (void *)20,
2074                             silc_server_process_channel_pk_destruct, channel,
2075                             TRUE);
2076   }
2077
2078   /* Create SHA-1 digest of the public key data */
2079   silc_hash_make(server->sha1hash, pk + 4, pk_len - 4, pkhash);
2080
2081   if (type == 0x00) {
2082     /* Add new public key to channel public key list */
2083     SILC_LOG_DEBUG(("Add new channel public key to channel %s",
2084                     channel->channel_name));
2085
2086     /* Check for resource limit */
2087     if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
2088       silc_pkcs_public_key_free(chpk);
2089       return SILC_STATUS_ERR_RESOURCE_LIMIT;
2090     }
2091
2092     /* Add if doesn't exist already */
2093     if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2094                               NULL, NULL))
2095       silc_hash_table_add(channel->channel_pubkeys, silc_memdup(pkhash, 20),
2096                           chpk);
2097   } else if (type == 0x01) {
2098     /* Delete public key from channel public key list */
2099     SILC_LOG_DEBUG(("Delete a channel public key from channel %s",
2100                     channel->channel_name));
2101     if (!silc_hash_table_del(channel->channel_pubkeys, pkhash))
2102       silc_pkcs_public_key_free(chpk);
2103   } else {
2104     silc_pkcs_public_key_free(chpk);
2105     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2106   }
2107
2108   return SILC_STATUS_OK;
2109 }
2110
2111 /* Returns the channel public keys as Argument List payload. */
2112
2113 SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
2114                                            SilcChannelEntry channel,
2115                                            SilcBool announce,
2116                                            SilcBool delete)
2117 {
2118   SilcHashTableList htl;
2119   SilcBuffer list, pkp;
2120   SilcPublicKey pk;
2121
2122   SILC_LOG_DEBUG(("Encoding channel public keys list"));
2123
2124   if (!channel->channel_pubkeys ||
2125       !silc_hash_table_count(channel->channel_pubkeys))
2126     return NULL;
2127
2128   /* Encode the list */
2129   list = silc_buffer_alloc_size(2);
2130   silc_buffer_format(list,
2131                      SILC_STR_UI_SHORT(silc_hash_table_count(
2132                                        channel->channel_pubkeys)),
2133                      SILC_STR_END);
2134
2135   silc_hash_table_list(channel->channel_pubkeys, &htl);
2136   while (silc_hash_table_get(&htl, NULL, (void *)&pk)) {
2137     pkp = silc_public_key_payload_encode(pk);
2138     if (!pkp)
2139       continue;
2140     list = silc_argument_payload_encode_one(list, pkp->data,
2141                                             silc_buffer_len(pkp),
2142                                             announce ? 0x03 :
2143                                             delete ? 0x01 : 0x00);
2144     silc_buffer_free(pkp);
2145   }
2146   silc_hash_table_list_reset(&htl);
2147
2148   return list;
2149 }
2150
2151 /* Sets the channel public keys into channel from the list of public keys. */
2152
2153 SilcStatus silc_server_set_channel_pk_list(SilcServer server,
2154                                            SilcPacketStream sender,
2155                                            SilcChannelEntry channel,
2156                                            const unsigned char *pklist,
2157                                            SilcUInt32 pklist_len)
2158 {
2159   SilcUInt16 argc;
2160   SilcArgumentPayload args;
2161   unsigned char *chpk;
2162   SilcUInt32 chpklen, type;
2163   SilcStatus ret = SILC_STATUS_OK;
2164
2165   SILC_LOG_DEBUG(("Setting channel public keys list"));
2166
2167   if (!pklist || pklist_len < 2)
2168     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2169
2170   /* Get the argument from the Argument List Payload */
2171   SILC_GET16_MSB(argc, pklist);
2172   args = silc_argument_payload_parse(pklist + 2, pklist_len - 2, argc);
2173   if (!args)
2174     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2175
2176   /* Process the public keys one by one */
2177   chpk = silc_argument_get_first_arg(args, &type, &chpklen);
2178
2179   /* If announcing keys and we have them set already, do not allow this */
2180   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2181       server->server_type == SILC_ROUTER &&
2182       sender != SILC_PRIMARY_ROUTE(server)) {
2183     SILC_LOG_DEBUG(("Channel public key list set already, enforce our list"));
2184     silc_argument_payload_free(args);
2185     return SILC_STATUS_ERR_OPERATION_ALLOWED;
2186   }
2187
2188   /* If we are normal server and receive announcement list and we already
2189      have keys set, we replace the old list with the announced one. */
2190   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2191       server->server_type != SILC_ROUTER) {
2192     SilcBuffer sidp;
2193     unsigned char mask[4], ulimit[4];
2194
2195     SILC_LOG_DEBUG(("Router enforces its list, remove old list"));
2196     silc_hash_table_free(channel->channel_pubkeys);
2197     channel->channel_pubkeys = NULL;
2198
2199     /* Send notify that removes the old list */
2200     sidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2201     SILC_PUT32_MSB((channel->mode & (~SILC_CHANNEL_MODE_CHANNEL_AUTH)), mask);
2202     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2203       SILC_PUT32_MSB(channel->user_limit, ulimit);
2204     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2205                                        SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
2206                                        sidp->data, silc_buffer_len(sidp),
2207                                        mask, 4,
2208                                        channel->cipher,
2209                                        channel->cipher ?
2210                                        strlen(channel->cipher) : 0,
2211                                        channel->hmac_name,
2212                                        channel->hmac_name ?
2213                                        strlen(channel->hmac_name) : 0,
2214                                        channel->passphrase,
2215                                        channel->passphrase ?
2216                                        strlen(channel->passphrase) : 0,
2217                                        NULL, 0, NULL, 0,
2218                                        (channel->mode &
2219                                         SILC_CHANNEL_MODE_ULIMIT ?
2220                                         ulimit : NULL),
2221                                        (channel->mode &
2222                                         SILC_CHANNEL_MODE_ULIMIT ?
2223                                         sizeof(ulimit) : 0));
2224     silc_buffer_free(sidp);
2225   }
2226
2227   while (chpk) {
2228     if (type == 0x03)
2229       type = 0x00;
2230     ret = silc_server_process_channel_pk(server, channel, type,
2231                                          chpk, chpklen);
2232     if (ret != SILC_STATUS_OK)
2233       break;
2234     chpk = silc_argument_get_next_arg(args, &type, &chpklen);
2235   }
2236
2237   silc_argument_payload_free(args);
2238   return ret;
2239 }
2240
2241 /* Verifies the Authentication Payload `auth' with one of the public keys
2242    on the `channel' public key list. */
2243
2244 SilcBool silc_server_verify_channel_auth(SilcServer server,
2245                                          SilcChannelEntry channel,
2246                                          SilcClientID *client_id,
2247                                          const unsigned char *auth,
2248                                          SilcUInt32 auth_len)
2249 {
2250   SilcAuthPayload ap;
2251   SilcPublicKey chpk;
2252   unsigned char *pkhash;
2253   SilcUInt32 pkhash_len;
2254   SilcBool ret = FALSE;
2255
2256   SILC_LOG_DEBUG(("Verifying channel authentication"));
2257
2258   if (!auth || !auth_len || !channel->channel_pubkeys)
2259     return FALSE;
2260
2261   /* Get the hash from the auth data which tells us what public key we
2262      must use in verification. */
2263
2264   ap = silc_auth_payload_parse(auth, auth_len);
2265   if (!ap)
2266     return FALSE;
2267
2268   pkhash = silc_auth_get_public_data(ap, &pkhash_len);
2269   if (pkhash_len < 128)
2270     goto out;
2271
2272   /* Find the public key with the hash */
2273   if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2274                             NULL, (void *)&chpk)) {
2275     SILC_LOG_DEBUG(("Public key not found in channel public key list"));
2276     goto out;
2277   }
2278
2279   /* Verify the signature */
2280   if (!silc_auth_verify(ap, SILC_AUTH_PUBLIC_KEY, (void *)chpk, 0,
2281                         server->sha1hash, client_id, SILC_ID_CLIENT)) {
2282     SILC_LOG_DEBUG(("Authentication failed"));
2283     goto out;
2284   }
2285
2286   ret = TRUE;
2287
2288  out:
2289   silc_auth_payload_free(ap);
2290   return ret;
2291 }