Fixed many 64-bit alignment issues from 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       return FALSE;
1199     }
1200
1201     /* Math software version */
1202     if (l_software_version && r_software_version &&
1203         r_software_version < l_software_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 software version");
1209       return FALSE;
1210     }
1211
1212     /* Regex match vendor version */
1213     if (l_vendor_version && r_vendor_version &&
1214         !silc_string_match(l_vendor_version, r_vendor_version)) {
1215       SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1216                      hostname, ip));
1217       silc_server_disconnect_remote(server, sock,
1218                                     SILC_STATUS_ERR_BAD_VERSION,
1219                                     "Your software is not supported");
1220       return FALSE;
1221     }
1222   }
1223   silc_free(r_vendor_version);
1224
1225   /* Check for maximum connections limit */
1226
1227   num_sockets = silc_server_num_sockets_by_ip(server, ip, type);
1228   max_hosts = (params ? params->connections_max : global->connections_max);
1229   max_per_host = (params ? params->connections_max_per_host :
1230                   global->connections_max_per_host);
1231
1232   if (max_hosts && conn_number >= max_hosts) {
1233     SILC_LOG_DEBUG(("Server is full, %d >= %d", conn_number, max_hosts));
1234     SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1235                    hostname, ip));
1236     silc_server_disconnect_remote(server, sock,
1237                                   SILC_STATUS_ERR_RESOURCE_LIMIT,
1238                                   "Server is full, try again later");
1239     return FALSE;
1240   }
1241
1242   if (num_sockets >= max_per_host) {
1243     SILC_LOG_DEBUG(("Too many connections, %d >= %d", num_sockets,
1244                     max_per_host));
1245     SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1246                    hostname, ip));
1247     silc_server_disconnect_remote(server, sock,
1248                                   SILC_STATUS_ERR_RESOURCE_LIMIT,
1249                                   "Too many connections from your host");
1250     return FALSE;
1251   }
1252
1253   return TRUE;
1254 }
1255
1256 /* Checks that client has rights to add or remove channel modes. If any
1257    of the checks fails FALSE is returned. */
1258
1259 SilcBool silc_server_check_cmode_rights(SilcServer server,
1260                                         SilcChannelEntry channel,
1261                                         SilcChannelClientEntry client,
1262                                         SilcUInt32 mode)
1263 {
1264   SilcBool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1265   SilcBool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1266
1267   /* Check whether has rights to change anything */
1268   if (!is_op && !is_fo)
1269     return FALSE;
1270
1271   /* Check whether has rights to change everything */
1272   if (is_op && is_fo)
1273     return TRUE;
1274
1275   /* Founder implies operator */
1276   if (is_fo)
1277     is_op = TRUE;
1278
1279   /* We know that client is channel operator, check that they are not
1280      changing anything that requires channel founder rights. Rest of the
1281      modes are available automatically for channel operator. */
1282
1283   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1284     if (is_op && !is_fo)
1285       return FALSE;
1286   } else {
1287     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1288       if (is_op && !is_fo)
1289         return FALSE;
1290     }
1291   }
1292
1293   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1294     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1295       if (is_op && !is_fo)
1296         return FALSE;
1297     }
1298   } else {
1299     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1300       if (is_op && !is_fo)
1301         return FALSE;
1302     }
1303   }
1304
1305   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1306     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1307       if (is_op && !is_fo)
1308         return FALSE;
1309     }
1310   } else {
1311     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1312       if (is_op && !is_fo)
1313         return FALSE;
1314     }
1315   }
1316
1317   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1318     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1319       if (is_op && !is_fo)
1320         return FALSE;
1321     }
1322   } else {
1323     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1324       if (is_op && !is_fo)
1325         return FALSE;
1326     }
1327   }
1328
1329   if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1330     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1331       if (is_op && !is_fo)
1332         return FALSE;
1333     }
1334   } else {
1335     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1336       if (is_op && !is_fo)
1337         return FALSE;
1338     }
1339   }
1340
1341   if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1342     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1343       if (is_op && !is_fo)
1344         return FALSE;
1345     }
1346   } else {
1347     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1348       if (is_op && !is_fo)
1349         return FALSE;
1350     }
1351   }
1352
1353   if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1354     if (!(channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)) {
1355       if (is_op && !is_fo)
1356         return FALSE;
1357     }
1358   } else {
1359     if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1360       if (is_op && !is_fo)
1361         return FALSE;
1362     }
1363   }
1364
1365   return TRUE;
1366 }
1367
1368 /* Check that the client has rights to change its user mode.  Returns
1369    FALSE if setting some mode is not allowed. */
1370
1371 SilcBool silc_server_check_umode_rights(SilcServer server,
1372                                         SilcClientEntry client,
1373                                         SilcUInt32 mode)
1374 {
1375   SilcBool server_op = FALSE, router_op = FALSE;
1376
1377   if (mode & SILC_UMODE_SERVER_OPERATOR) {
1378     /* Cannot set server operator mode (must use OPER command) */
1379     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1380       return FALSE;
1381   } else {
1382     /* Remove the server operator rights */
1383     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1384       server_op = TRUE;
1385   }
1386
1387   if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1388     /* Cannot set router operator mode (must use SILCOPER command) */
1389     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1390       return FALSE;
1391   } else {
1392     /* Remove the router operator rights */
1393     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1394       router_op = TRUE;
1395   }
1396
1397   if (server_op)
1398     SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1399   if (router_op)
1400     SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1401
1402   return TRUE;
1403 }
1404
1405 /* This function is used to send the notify packets and motd to the
1406    incoming client connection. */
1407
1408 void silc_server_send_connect_notifys(SilcServer server,
1409                                       SilcPacketStream sock,
1410                                       SilcClientEntry client)
1411 {
1412   SilcCipher key;
1413
1414   SILC_LOG_DEBUG(("Send welcome notifys"));
1415
1416   /* Send some nice info to the client */
1417   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1418                           ("Welcome to the SILC Network %s",
1419                            client->username));
1420   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1421                           ("Your host is %s, running version %s",
1422                            server->server_name, server_version));
1423
1424   if (server->server_type == SILC_ROUTER) {
1425     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1426                             ("There are %d clients, %d servers and %d "
1427                              "routers in SILC Network",
1428                              server->stat.clients, server->stat.servers,
1429                              server->stat.routers));
1430   } else {
1431     if (server->stat.clients && server->stat.servers + 1)
1432       SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1433                               ("There are %d clients, %d servers and %d "
1434                                "routers in SILC Network",
1435                                server->stat.clients, server->stat.servers,
1436                                (server->standalone ? 0 :
1437                                 !server->stat.routers ? 1 :
1438                                 server->stat.routers)));
1439   }
1440
1441   if (server->stat.cell_clients && server->stat.cell_servers + 1)
1442     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1443                             ("There are %d clients on %d servers in our cell",
1444                              server->stat.cell_clients,
1445                              server->stat.cell_servers));
1446   if (server->server_type == SILC_ROUTER) {
1447     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1448                             ("I have %d clients, %d channels, %d servers and "
1449                              "%d routers",
1450                              server->stat.my_clients,
1451                              server->stat.my_channels,
1452                              server->stat.my_servers,
1453                              server->stat.my_routers));
1454   } else {
1455     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1456                             ("I have %d clients and %d channels formed",
1457                              server->stat.my_clients,
1458                              server->stat.my_channels));
1459   }
1460
1461   if (server->stat.server_ops || server->stat.router_ops)
1462     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1463                             ("There are %d server operators and %d router "
1464                              "operators online",
1465                              server->stat.server_ops,
1466                              server->stat.router_ops));
1467   if (server->stat.my_router_ops + server->stat.my_server_ops)
1468     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1469                             ("I have %d operators online",
1470                              server->stat.my_router_ops +
1471                              server->stat.my_server_ops));
1472
1473   silc_packet_get_keys(sock, &key, NULL, NULL, NULL);
1474   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1475                           ("Your connection is secured with %s cipher, "
1476                            "key length %d bits",
1477                            silc_cipher_get_name(key),
1478                            silc_cipher_get_key_len(key)));
1479   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1480                           ("Your current nickname is %s",
1481                            client->nickname));
1482
1483   /* Send motd */
1484   silc_server_send_motd(server, sock);
1485 }
1486
1487 /* Kill the client indicated by `remote_client' sending KILLED notify
1488    to the client, to all channels client has joined and to primary
1489    router if needed.  The killed client is also removed from all channels. */
1490
1491 void silc_server_kill_client(SilcServer server,
1492                              SilcClientEntry remote_client,
1493                              const char *comment,
1494                              void *killer_id,
1495                              SilcIdType killer_id_type)
1496 {
1497   SilcBuffer killed, killer;
1498
1499   SILC_LOG_DEBUG(("Killing client %s",
1500                   silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1501
1502   /* Send the KILL notify packets. First send it to the channel, then
1503      to our primary router and then directly to the client who is being
1504      killed right now. */
1505
1506   killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1507   killer = silc_id_payload_encode(killer_id, killer_id_type);
1508
1509   /* Send KILLED notify to the channels. It is not sent to the client
1510      as it will be sent differently destined directly to the client and not
1511      to the channel. */
1512   silc_server_send_notify_on_channels(server, remote_client,
1513                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
1514                                       3, killed->data, silc_buffer_len(killed),
1515                                       comment, comment ? strlen(comment) : 0,
1516                                       killer->data, silc_buffer_len(killer));
1517
1518   /* Send KILLED notify to primary route */
1519   silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1520                                  SILC_BROADCAST(server), remote_client->id,
1521                                  comment, killer_id, killer_id_type);
1522
1523   /* Send KILLED notify to the client directly */
1524   if (remote_client->connection || remote_client->router)
1525     silc_server_send_notify_killed(server, remote_client->connection ?
1526                                    remote_client->connection :
1527                                    remote_client->router->connection, FALSE,
1528                                    remote_client->id, comment,
1529                                    killer_id, killer_id_type);
1530
1531   /* Remove the client from all channels. This generates new keys to the
1532      channels as well. */
1533   silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1534                                    NULL, TRUE, TRUE);
1535
1536   /* Remove the client entry, If it is locally connected then we will also
1537      disconnect the client here */
1538   if (remote_client->connection) {
1539     /* Remove locally conneted client */
1540     SilcPacketStream sock = remote_client->connection;
1541     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1542     silc_server_close_connection(server, sock);
1543   } else {
1544     /* Update statistics */
1545     server->stat.clients--;
1546     if (server->stat.cell_clients)
1547       server->stat.cell_clients--;
1548     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1549     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1550
1551     /* Remove client's public key from repository, this will free it too. */
1552     if (remote_client->data.public_key) {
1553       silc_skr_del_public_key(server->repository,
1554                               remote_client->data.public_key, remote_client);
1555       remote_client->data.public_key = NULL;
1556     }
1557
1558     if (SILC_IS_LOCAL(remote_client)) {
1559       server->stat.my_clients--;
1560       silc_schedule_task_del_by_context(server->schedule, remote_client);
1561     }
1562
1563     /* Remove remote client */
1564     silc_idlist_del_data(remote_client);
1565     if (!silc_idlist_del_client(server->global_list, remote_client)) {
1566       /* Remove this client from watcher list if it is */
1567       silc_server_del_from_watcher_list(server, remote_client);
1568       silc_idlist_del_client(server->local_list, remote_client);
1569     }
1570   }
1571
1572   silc_buffer_free(killer);
1573   silc_buffer_free(killed);
1574 }
1575
1576 typedef struct {
1577   SilcServer server;
1578   SilcClientEntry client;
1579   SilcNotifyType notify;
1580   const char *new_nick;
1581 } WatcherNotifyContext;
1582
1583 static void
1584 silc_server_check_watcher_list_foreach(void *key, void *context,
1585                                        void *user_context)
1586 {
1587   WatcherNotifyContext *notify = user_context;
1588   SilcClientEntry entry = context;
1589   SilcPacketStream sock;
1590
1591   if (!context)
1592     return;
1593
1594   if (entry == notify->client)
1595     return;
1596
1597   sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1598                                       NULL, NULL);
1599   if (sock) {
1600     SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1601                     silc_id_render(entry->id, SILC_ID_CLIENT)));
1602
1603     /* Send the WATCH notify */
1604     silc_server_send_notify_watch(notify->server, sock, entry,
1605                                   notify->client,
1606                                   notify->new_nick ? notify->new_nick :
1607                                   (const char *)notify->client->nickname,
1608                                   notify->notify,
1609                                   notify->client->data.public_key);
1610   }
1611 }
1612
1613 /* This function checks whether the `client' nickname and/or 'client'
1614    public key is being watched by someone, and notifies the watcher of the
1615    notify change of notify type indicated by `notify'. */
1616
1617 SilcBool silc_server_check_watcher_list(SilcServer server,
1618                                         SilcClientEntry client,
1619                                         const char *new_nick,
1620                                         SilcNotifyType notify)
1621 {
1622   unsigned char hash[16];
1623   WatcherNotifyContext n;
1624
1625   SILC_LOG_DEBUG(("Checking watcher list %s",
1626                   client->nickname ? client->nickname : (unsigned char *)""));
1627
1628   /* If the watching is rejected by the client do nothing */
1629   if (client->mode & SILC_UMODE_REJECT_WATCHING)
1630     return FALSE;
1631
1632   /* Make hash from the nick, or take it from Client ID */
1633   if (client->nickname) {
1634     unsigned char *nickc;
1635     nickc = silc_identifier_check(client->nickname, strlen(client->nickname),
1636                                   SILC_STRING_UTF8, 128, NULL);
1637     if (!nickc)
1638       return FALSE;
1639     silc_hash_make(server->md5hash, nickc, strlen(nickc), hash);
1640     silc_free(nickc);
1641   } else {
1642     memset(hash, 0, sizeof(hash));
1643     memcpy(hash, client->id->hash, sizeof(client->id->hash));
1644   }
1645
1646   n.server = server;
1647   n.client = client;
1648   n.new_nick = new_nick;
1649   n.notify = notify;
1650
1651   /* Send notify to all watchers watching this nickname */
1652   silc_hash_table_find_foreach(server->watcher_list, hash,
1653                                silc_server_check_watcher_list_foreach, &n);
1654
1655   /* Send notify to all watchers watching this public key */
1656   if (client->data.public_key)
1657     silc_hash_table_find_foreach(server->watcher_list_pk,
1658                                  client->data.public_key,
1659                                  silc_server_check_watcher_list_foreach,
1660                                  &n);
1661
1662   return TRUE;
1663 }
1664
1665 /* Remove the `client' from watcher list. After calling this the `client'
1666    is not watching any nicknames. */
1667
1668 SilcBool silc_server_del_from_watcher_list(SilcServer server,
1669                                            SilcClientEntry client)
1670 {
1671   SilcHashTableList htl;
1672   void *key;
1673   SilcClientEntry entry;
1674   SilcBool found = FALSE;
1675
1676   silc_hash_table_list(server->watcher_list, &htl);
1677   while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1678     if (entry == client) {
1679       silc_hash_table_del_by_context(server->watcher_list, key, client);
1680
1681       if (client->id)
1682         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1683                         silc_id_render(client->id, SILC_ID_CLIENT)));
1684
1685       /* Now check whether there still exists entries with this key, if not
1686          then free the key to not leak memory. */
1687       if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1688         silc_free(key);
1689
1690       found = TRUE;
1691     }
1692   }
1693   silc_hash_table_list_reset(&htl);
1694
1695   silc_hash_table_list(server->watcher_list_pk, &htl);
1696   while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1697     if (entry == client) {
1698       silc_hash_table_del_by_context(server->watcher_list_pk, key, client);
1699
1700       if (client->id)
1701         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1702                         silc_id_render(client->id, SILC_ID_CLIENT)));
1703
1704       /* Now check whether there still exists entries with this key, if not
1705          then free the key to not leak memory. */
1706       if (!silc_hash_table_find(server->watcher_list_pk, key, NULL, NULL))
1707         silc_pkcs_public_key_free(key);
1708
1709       found = TRUE;
1710     }
1711   }
1712   silc_hash_table_list_reset(&htl);
1713
1714   return found;
1715 }
1716
1717 /* Force the client indicated by `chl' to change the channel user mode
1718    on channel indicated by `channel' to `forced_mode'. */
1719
1720 SilcBool silc_server_force_cumode_change(SilcServer server,
1721                                          SilcPacketStream sock,
1722                                          SilcChannelEntry channel,
1723                                          SilcChannelClientEntry chl,
1724                                          SilcUInt32 forced_mode)
1725 {
1726   SilcBuffer idp1, idp2;
1727   unsigned char cumode[4];
1728
1729   SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1730
1731   if (sock)
1732     silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1733                                    server->id, SILC_ID_SERVER,
1734                                    chl->client->id, NULL);
1735
1736   idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1737   idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1738   SILC_PUT32_MSB(forced_mode, cumode);
1739   silc_server_send_notify_to_channel(server, sock, channel, FALSE, TRUE,
1740                                      SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1741                                      3, idp1->data, silc_buffer_len(idp1),
1742                                      cumode, sizeof(cumode),
1743                                      idp2->data, silc_buffer_len(idp2));
1744   silc_buffer_free(idp1);
1745   silc_buffer_free(idp2);
1746
1747   return TRUE;
1748 }
1749
1750 /* This function can be used to match the invite and ban lists. */
1751
1752 SilcBool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1753                                      SilcUInt8 type, void *check)
1754 {
1755   unsigned char *tmp = NULL;
1756   SilcUInt32 len = 0;
1757   SilcHashTableList htl;
1758   SilcBuffer entry, idp = NULL, pkp = NULL;
1759   SilcBool ret = FALSE;
1760   void *t;
1761
1762   SILC_LOG_DEBUG(("Matching invite/ban"));
1763
1764   if (type < 1 || type > 3 || !check)
1765     return FALSE;
1766
1767   if (type == 1) {
1768     tmp = strdup((char *)check);
1769     if (!tmp)
1770       return FALSE;
1771   }
1772   if (type == 2) {
1773     pkp = silc_public_key_payload_encode(check);
1774     if (!pkp)
1775       return FALSE;
1776     tmp = pkp->data;
1777     len = silc_buffer_len(pkp);
1778   }
1779   if (type == 3) {
1780     idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
1781     if (!idp)
1782       return FALSE;
1783     tmp = idp->data;
1784     len = silc_buffer_len(idp);
1785   }
1786
1787   /* Compare the list */
1788   silc_hash_table_list(list, &htl);
1789   while (silc_hash_table_get(&htl, (void *)&t, (void *)&entry)) {
1790     if (type == SILC_PTR_TO_32(t)) {
1791       if (type == 1) {
1792         if (silc_string_match(entry->data, tmp)) {
1793           ret = TRUE;
1794           break;
1795         }
1796       } else if (silc_buffer_len(entry) == len &&
1797                  !memcmp(entry->data, tmp, len)) {
1798         ret = TRUE;
1799         break;
1800       }
1801     }
1802   }
1803   silc_hash_table_list_reset(&htl);
1804
1805   if (type == 1)
1806     silc_free(tmp);
1807   silc_buffer_free(idp);
1808   silc_buffer_free(pkp);
1809   return ret;
1810 }
1811
1812 /* Process invite or ban information */
1813
1814 SilcBool silc_server_inviteban_process(SilcServer server,
1815                                        SilcHashTable list,
1816                                        SilcUInt8 action,
1817                                        SilcArgumentPayload args)
1818 {
1819   unsigned char *tmp;
1820   SilcUInt32 type, len;
1821   void *ptype;
1822   SilcBuffer tmp2;
1823   SilcHashTableList htl;
1824
1825   SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1826                   action == 0x01 ? "DEL" : "ADD"));
1827
1828   /* Add the information to invite list */
1829   if (action == 0x00 || action == 0x03) {
1830     /* Traverse all arguments and add to the hash table according to
1831        their type. */
1832     tmp = silc_argument_get_first_arg(args, &type, &len);
1833     while (tmp) {
1834       if (type == 1) {
1835         /* Check validity of the string.  Actually we should parse the
1836            whole string and verify all components individually. */
1837         if (!silc_utf8_valid(tmp, len) || !len) {
1838           tmp = silc_argument_get_next_arg(args, &type, &len);
1839           continue;
1840         }
1841         if (strchr(tmp, ',')) {
1842           tmp = silc_argument_get_next_arg(args, &type, &len);
1843           continue;
1844         }
1845
1846         /* Check if the string is added already */
1847         silc_hash_table_list(list, &htl);
1848         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1849           if (SILC_PTR_TO_32(ptype) == 1 &&
1850               silc_string_match(tmp2->data, tmp)) {
1851             tmp = NULL;
1852             break;
1853           }
1854         }
1855         silc_hash_table_list_reset(&htl);
1856
1857         if (tmp) {
1858           /* Add the string to hash table */
1859           tmp2 = silc_buffer_alloc_size(len + 1);
1860           if (tmp[len - 1] == ',')
1861             tmp[len - 1] = '\0';
1862           silc_buffer_put(tmp2, tmp, len);
1863           silc_hash_table_add(list, (void *)1, tmp2);
1864         }
1865
1866       } else if (type == 2) {
1867         /* Public key.  Check first if the public key is already on the
1868            list and ignore it if it is, otherwise, add it to hash table. */
1869         SilcPublicKey pk;
1870
1871         /* Verify validity of the public key */
1872         if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1873           tmp = silc_argument_get_next_arg(args, &type, &len);
1874           continue;
1875         }
1876         silc_pkcs_public_key_free(pk);
1877
1878         /* Check if the public key is in the list already */
1879         silc_hash_table_list(list, &htl);
1880         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1881           if (SILC_PTR_TO_32(ptype) == 2 && !memcmp(tmp2->data, tmp, len)) {
1882             tmp = NULL;
1883             break;
1884           }
1885         }
1886         silc_hash_table_list_reset(&htl);
1887
1888         /* Add new public key to invite list */
1889         if (tmp) {
1890           tmp2 = silc_buffer_alloc_size(len);
1891           silc_buffer_put(tmp2, tmp, len);
1892           silc_hash_table_add(list, (void *)2, tmp2);
1893         }
1894
1895       } else if (type == 3) {
1896         /* Client ID */
1897
1898         /* Check if the ID is in the list already */
1899         silc_hash_table_list(list, &htl);
1900         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1901           if (SILC_PTR_TO_32(ptype) == 3 && !memcmp(tmp2->data, tmp, len)) {
1902             tmp = NULL;
1903             break;
1904           }
1905         }
1906         silc_hash_table_list_reset(&htl);
1907
1908         /* Add new Client ID to invite list */
1909         if (tmp) {
1910           tmp2 = silc_buffer_alloc_size(len);
1911           silc_buffer_put(tmp2, tmp, len);
1912           silc_hash_table_add(list, (void *)3, tmp2);
1913         }
1914       }
1915
1916       tmp = silc_argument_get_next_arg(args, &type, &len);
1917     }
1918   }
1919
1920   /* Delete information to invite list */
1921   if (action == 0x01 && list) {
1922     /* Now delete the arguments from invite list */
1923     tmp = silc_argument_get_first_arg(args, &type, &len);
1924     while (tmp) {
1925       if (type == 1) {
1926         /* Check validity of the string.  Actually we should parse the
1927            whole string and verify all components individually. */
1928         if (!silc_utf8_valid(tmp, len)) {
1929           tmp = silc_argument_get_next_arg(args, &type, &len);
1930           continue;
1931         }
1932         if (strchr(tmp, ',')) {
1933           tmp = silc_argument_get_next_arg(args, &type, &len);
1934           continue;
1935         }
1936
1937         /* Delete from the list */
1938         silc_hash_table_list(list, &htl);
1939         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1940           if (SILC_PTR_TO_32(ptype) == 1 &&
1941               silc_string_match(tmp2->data, tmp)) {
1942             silc_hash_table_del_by_context(list, (void *)1, tmp2);
1943             break;
1944           }
1945         }
1946         silc_hash_table_list_reset(&htl);
1947
1948       } else if (type == 2) {
1949         /* Public key. */
1950         SilcPublicKey pk;
1951
1952         /* Verify validity of the public key */
1953         if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1954           tmp = silc_argument_get_next_arg(args, &type, &len);
1955           continue;
1956         }
1957         silc_pkcs_public_key_free(pk);
1958
1959         /* Delete from the invite list */
1960         silc_hash_table_list(list, &htl);
1961         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1962           if (SILC_PTR_TO_32(ptype) == 2 && !memcmp(tmp2->data, tmp, len)) {
1963             silc_hash_table_del_by_context(list, (void *)2, tmp2);
1964             break;
1965           }
1966         }
1967         silc_hash_table_list_reset(&htl);
1968
1969       } else if (type == 3) {
1970         /* Client ID */
1971
1972         /* Delete from the invite list */
1973         silc_hash_table_list(list, &htl);
1974         while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1975           if (SILC_PTR_TO_32(ptype) == 3 && !memcmp(tmp2->data, tmp, len)) {
1976             silc_hash_table_del_by_context(list, (void *)3, tmp2);
1977             break;
1978           }
1979         }
1980         silc_hash_table_list_reset(&htl);
1981       }
1982
1983       tmp = silc_argument_get_next_arg(args, &type, &len);
1984     }
1985   }
1986
1987   return TRUE;
1988 }
1989
1990 /* Destructor for invite and ban list entrys */
1991
1992 void silc_server_inviteban_destruct(void *key, void *context,
1993                                     void *user_context)
1994 {
1995   silc_buffer_free(context);
1996 }
1997
1998 /* Creates connections accoring to configuration. */
1999
2000 void silc_server_create_connections(SilcServer server)
2001 {
2002   silc_schedule_task_del_by_callback(server->schedule,
2003                                      silc_server_connect_to_router);
2004   silc_schedule_task_add_timeout(server->schedule,
2005                                  silc_server_connect_to_router, server, 1, 0);
2006 }
2007
2008 static void
2009 silc_server_process_channel_pk_destruct(void *key, void *context,
2010                                         void *user_context)
2011 {
2012   silc_free(key);
2013   silc_pkcs_public_key_free(context);
2014 }
2015
2016 /* Processes a channel public key, either adds or removes it. */
2017
2018 SilcStatus
2019 silc_server_process_channel_pk(SilcServer server,
2020                                SilcChannelEntry channel,
2021                                SilcUInt32 type, const unsigned char *pk,
2022                                SilcUInt32 pk_len)
2023 {
2024   unsigned char pkhash[20];
2025   SilcPublicKey chpk;
2026
2027   SILC_LOG_DEBUG(("Processing channel public key"));
2028
2029   if (!pk || !pk_len)
2030     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2031
2032   /* Decode the public key */
2033   if (!silc_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
2034     return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
2035
2036   /* Create channel public key list (hash table) if needed */
2037   if (!channel->channel_pubkeys) {
2038     channel->channel_pubkeys =
2039       silc_hash_table_alloc(0, silc_hash_data, (void *)20,
2040                             silc_hash_data_compare, (void *)20,
2041                             silc_server_process_channel_pk_destruct, channel,
2042                             TRUE);
2043   }
2044
2045   /* Create SHA-1 digest of the public key data */
2046   silc_hash_make(server->sha1hash, pk + 4, pk_len - 4, pkhash);
2047
2048   if (type == 0x00) {
2049     /* Add new public key to channel public key list */
2050     SILC_LOG_DEBUG(("Add new channel public key to channel %s",
2051                     channel->channel_name));
2052
2053     /* Check for resource limit */
2054     if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
2055       silc_pkcs_public_key_free(chpk);
2056       return SILC_STATUS_ERR_RESOURCE_LIMIT;
2057     }
2058
2059     /* Add if doesn't exist already */
2060     if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2061                               NULL, NULL))
2062       silc_hash_table_add(channel->channel_pubkeys, silc_memdup(pkhash, 20),
2063                           chpk);
2064   } else if (type == 0x01) {
2065     /* Delete public key from channel public key list */
2066     SILC_LOG_DEBUG(("Delete a channel public key from channel %s",
2067                     channel->channel_name));
2068     if (!silc_hash_table_del(channel->channel_pubkeys, pkhash))
2069       silc_pkcs_public_key_free(chpk);
2070   } else {
2071     silc_pkcs_public_key_free(chpk);
2072     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2073   }
2074
2075   return SILC_STATUS_OK;
2076 }
2077
2078 /* Returns the channel public keys as Argument List payload. */
2079
2080 SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
2081                                            SilcChannelEntry channel,
2082                                            SilcBool announce,
2083                                            SilcBool delete)
2084 {
2085   SilcHashTableList htl;
2086   SilcBuffer list, pkp;
2087   SilcPublicKey pk;
2088
2089   SILC_LOG_DEBUG(("Encoding channel public keys list"));
2090
2091   if (!channel->channel_pubkeys ||
2092       !silc_hash_table_count(channel->channel_pubkeys))
2093     return NULL;
2094
2095   /* Encode the list */
2096   list = silc_buffer_alloc_size(2);
2097   silc_buffer_format(list,
2098                      SILC_STR_UI_SHORT(silc_hash_table_count(
2099                                        channel->channel_pubkeys)),
2100                      SILC_STR_END);
2101
2102   silc_hash_table_list(channel->channel_pubkeys, &htl);
2103   while (silc_hash_table_get(&htl, NULL, (void *)&pk)) {
2104     pkp = silc_public_key_payload_encode(pk);
2105     list = silc_argument_payload_encode_one(list, pkp->data,
2106                                             silc_buffer_len(pkp),
2107                                             announce ? 0x03 :
2108                                             delete ? 0x01 : 0x00);
2109     silc_buffer_free(pkp);
2110   }
2111   silc_hash_table_list_reset(&htl);
2112
2113   return list;
2114 }
2115
2116 /* Sets the channel public keys into channel from the list of public keys. */
2117
2118 SilcStatus silc_server_set_channel_pk_list(SilcServer server,
2119                                            SilcPacketStream sender,
2120                                            SilcChannelEntry channel,
2121                                            const unsigned char *pklist,
2122                                            SilcUInt32 pklist_len)
2123 {
2124   SilcUInt16 argc;
2125   SilcArgumentPayload args;
2126   unsigned char *chpk;
2127   SilcUInt32 chpklen, type;
2128   SilcStatus ret = SILC_STATUS_OK;
2129
2130   SILC_LOG_DEBUG(("Setting channel public keys list"));
2131
2132   if (!pklist || pklist_len < 2)
2133     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2134
2135   /* Get the argument from the Argument List Payload */
2136   SILC_GET16_MSB(argc, pklist);
2137   args = silc_argument_payload_parse(pklist + 2, pklist_len - 2, argc);
2138   if (!args)
2139     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2140
2141   /* Process the public keys one by one */
2142   chpk = silc_argument_get_first_arg(args, &type, &chpklen);
2143
2144   /* If announcing keys and we have them set already, do not allow this */
2145   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2146       server->server_type == SILC_ROUTER &&
2147       sender != SILC_PRIMARY_ROUTE(server)) {
2148     SILC_LOG_DEBUG(("Channel public key list set already, enforce our list"));
2149     silc_argument_payload_free(args);
2150     return SILC_STATUS_ERR_OPERATION_ALLOWED;
2151   }
2152
2153   /* If we are normal server and receive announcement list and we already
2154      have keys set, we replace the old list with the announced one. */
2155   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2156       server->server_type != SILC_ROUTER) {
2157     SilcBuffer sidp;
2158     unsigned char mask[4], ulimit[4];
2159
2160     SILC_LOG_DEBUG(("Router enforces its list, remove old list"));
2161     silc_hash_table_free(channel->channel_pubkeys);
2162     channel->channel_pubkeys = NULL;
2163
2164     /* Send notify that removes the old list */
2165     sidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2166     SILC_PUT32_MSB((channel->mode & (~SILC_CHANNEL_MODE_CHANNEL_AUTH)), mask);
2167     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2168       SILC_PUT32_MSB(channel->user_limit, ulimit);
2169     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2170                                        SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
2171                                        sidp->data, silc_buffer_len(sidp),
2172                                        mask, 4,
2173                                        channel->cipher,
2174                                        channel->cipher ?
2175                                        strlen(channel->cipher) : 0,
2176                                        channel->hmac_name,
2177                                        channel->hmac_name ?
2178                                        strlen(channel->hmac_name) : 0,
2179                                        channel->passphrase,
2180                                        channel->passphrase ?
2181                                        strlen(channel->passphrase) : 0,
2182                                        NULL, 0, NULL, 0,
2183                                        (channel->mode &
2184                                         SILC_CHANNEL_MODE_ULIMIT ?
2185                                         ulimit : NULL),
2186                                        (channel->mode &
2187                                         SILC_CHANNEL_MODE_ULIMIT ?
2188                                         sizeof(ulimit) : 0));
2189     silc_buffer_free(sidp);
2190   }
2191
2192   while (chpk) {
2193     if (type == 0x03)
2194       type = 0x00;
2195     ret = silc_server_process_channel_pk(server, channel, type,
2196                                          chpk, chpklen);
2197     if (ret != SILC_STATUS_OK)
2198       break;
2199     chpk = silc_argument_get_next_arg(args, &type, &chpklen);
2200   }
2201
2202   silc_argument_payload_free(args);
2203   return ret;
2204 }
2205
2206 /* Verifies the Authentication Payload `auth' with one of the public keys
2207    on the `channel' public key list. */
2208
2209 SilcBool silc_server_verify_channel_auth(SilcServer server,
2210                                          SilcChannelEntry channel,
2211                                          SilcClientID *client_id,
2212                                          const unsigned char *auth,
2213                                          SilcUInt32 auth_len)
2214 {
2215   SilcAuthPayload ap;
2216   SilcPublicKey chpk;
2217   unsigned char *pkhash;
2218   SilcUInt32 pkhash_len;
2219   SilcBool ret = FALSE;
2220
2221   SILC_LOG_DEBUG(("Verifying channel authentication"));
2222
2223   if (!auth || !auth_len || !channel->channel_pubkeys)
2224     return FALSE;
2225
2226   /* Get the hash from the auth data which tells us what public key we
2227      must use in verification. */
2228
2229   ap = silc_auth_payload_parse(auth, auth_len);
2230   if (!ap)
2231     return FALSE;
2232
2233   pkhash = silc_auth_get_public_data(ap, &pkhash_len);
2234   if (pkhash_len < 128)
2235     goto out;
2236
2237   /* Find the public key with the hash */
2238   if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2239                             NULL, (void *)&chpk)) {
2240     SILC_LOG_DEBUG(("Public key not found in channel public key list"));
2241     goto out;
2242   }
2243
2244   /* Verify the signature */
2245   if (!silc_auth_verify(ap, SILC_AUTH_PUBLIC_KEY, (void *)chpk, 0,
2246                         server->sha1hash, client_id, SILC_ID_CLIENT)) {
2247     SILC_LOG_DEBUG(("Authentication failed"));
2248     goto out;
2249   }
2250
2251   ret = TRUE;
2252
2253  out:
2254   silc_auth_payload_free(ap);
2255   return ret;
2256 }