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