More preliminary changes for 1.1 Server. Fixed quitting,
[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 - 2005, 2007 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         argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
193         argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
194                                  (argc + 1));
195         argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
196                                   (argc + 1));
197         argv[argc] = silc_calloc(silc_buffer_len(idp), sizeof(*argv[0]));
198         memcpy(argv[argc], idp->data, silc_buffer_len(idp));
199         argv_lens[argc] = silc_buffer_len(idp);
200         argv_types[argc] = argc + 1;
201         argc++;
202         silc_buffer_free(idp);
203       }
204
205       /* Update statistics */
206       server->stat.clients--;
207       if (server->stat.cell_clients)
208         server->stat.cell_clients--;
209       SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
210       SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
211
212       if (client->data.public_key)
213         silc_hash_table_del_by_context(server->pk_hash,
214                                        client->data.public_key,
215                                        client);
216       silc_server_remove_clients_channels(server, entry, clients,
217                                           client, channels);
218       silc_server_del_from_watcher_list(server, client);
219
220       /* Remove the client entry */
221       if (!server_signoff) {
222         client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
223         client->mode = 0;
224         client->router = NULL;
225         client->connection = NULL;
226       } else {
227         silc_idlist_del_data(client);
228         silc_idlist_del_client(server->local_list, client);
229       }
230     }
231   }
232
233   if (silc_idcache_get_all(server->global_list->clients, &list)) {
234     silc_list_start(list);
235     while ((id_cache = silc_list_get(list))) {
236       client = (SilcClientEntry)id_cache->context;
237
238       /* If client is not registered, is not originated from `router'
239          and is not owned by `entry', skip it. */
240       if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
241           client->router != router ||
242           (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
243                                                client->id->ip.data_len))) {
244         continue;
245       }
246
247       if (server_signoff) {
248         idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
249         argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
250         argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
251                                  (argc + 1));
252         argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
253                                   (argc + 1));
254         argv[argc] = silc_calloc(silc_buffer_len(idp), sizeof(*argv[0]));
255         memcpy(argv[argc], idp->data, silc_buffer_len(idp));
256         argv_lens[argc] = silc_buffer_len(idp);
257         argv_types[argc] = argc + 1;
258         argc++;
259         silc_buffer_free(idp);
260       }
261
262       /* Update statistics */
263       server->stat.clients--;
264       if (server->stat.cell_clients)
265         server->stat.cell_clients--;
266       SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
267       SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
268
269       if (client->data.public_key)
270         silc_hash_table_del_by_context(server->pk_hash,
271                                        client->data.public_key,
272                                        client);
273       silc_server_remove_clients_channels(server, entry, clients,
274                                           client, channels);
275       silc_server_del_from_watcher_list(server, client);
276
277       /* Remove the client entry */
278       if (!server_signoff) {
279         client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
280         client->mode = 0;
281         client->router = NULL;
282         client->connection = NULL;
283       } else {
284         silc_idlist_del_data(client);
285         silc_idlist_del_client(server->global_list, client);
286       }
287     }
288   }
289
290   /* Return now if we are shutting down */
291   if (server->server_shutdown) {
292     silc_hash_table_free(channels);
293
294     if (server_signoff) {
295       for (i = 0; i < argc; i++)
296         silc_free(argv[i]);
297       silc_free(argv);
298       silc_free(argv_lens);
299       silc_free(argv_types);
300       silc_hash_table_free(clients);
301     }
302     return TRUE;
303   }
304
305   /* Send the SERVER_SIGNOFF notify */
306   if (server_signoff) {
307     SilcBuffer args, not;
308
309     SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
310                     silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
311
312     /* Send SERVER_SIGNOFF notify to our primary router */
313     if (server->router != entry) {
314       args = silc_argument_payload_encode(1, argv, argv_lens,
315                                           argv_types);
316       silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
317                                    SILC_BROADCAST(server),
318                                    SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
319                                    argc, args);
320       silc_buffer_free(args);
321     }
322
323     /* Send to local clients. We also send the list of client ID's that
324        is to be removed for those servers that would like to use that list. */
325     args = silc_argument_payload_encode(argc, argv, argv_lens,
326                                         argv_types);
327     not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
328                                           argc, args);
329     silc_server_packet_send_clients(server, clients,
330                                     SILC_PACKET_NOTIFY, 0, FALSE,
331                                     not->data, silc_buffer_len(not));
332
333     /* Send notify also to local backup routers */
334     silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
335                             not->data, silc_buffer_len(not), FALSE, TRUE);
336
337     silc_buffer_free(args);
338     silc_buffer_free(not);
339     for (i = 0; i < argc; i++)
340       silc_free(argv[i]);
341     silc_free(argv);
342     silc_free(argv_lens);
343     silc_free(argv_types);
344     silc_hash_table_free(clients);
345   }
346
347   /* We must now re-generate the channel key for all channels that had
348      this server's client(s) on the channel. As they left the channel we
349      must re-generate the channel key. */
350   silc_hash_table_list(channels, &htl);
351   while (silc_hash_table_get(&htl, NULL, (void *)&channel)) {
352     if (!silc_server_create_channel_key(server, channel, 0)) {
353       silc_hash_table_list_reset(&htl);
354       silc_hash_table_free(channels);
355       return FALSE;
356     }
357
358     /* Do not send the channel key if private channel key mode is set */
359     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->send_key)
360       continue;
361
362     silc_server_send_channel_key(server, NULL, channel,
363                                  server->server_type == SILC_ROUTER ?
364                                  FALSE : !server->standalone);
365   }
366   silc_hash_table_list_reset(&htl);
367   silc_hash_table_free(channels);
368
369   return TRUE;
370 }
371
372 static SilcServerEntry
373 silc_server_update_clients_by_real_server(SilcServer server,
374                                           SilcServerEntry from,
375                                           SilcServerEntry to,
376                                           SilcClientEntry client,
377                                           SilcBool local,
378                                           SilcIDCacheEntry client_cache)
379 {
380   SilcServerEntry server_entry;
381   SilcIDCacheEntry id_cache = NULL;
382   SilcList list;
383   SilcBool tolocal = (to == server->id_entry);
384
385   SILC_LOG_DEBUG(("Start"));
386
387   if (!silc_idcache_get_all(server->local_list->servers, &list))
388     return NULL;
389
390   silc_list_start(list);
391   while ((id_cache = silc_list_get(list))) {
392     server_entry = (SilcServerEntry)id_cache->context;
393     if (server_entry != from &&
394         (tolocal || server_entry != server->id_entry) &&
395         SILC_ID_COMPARE(server_entry->id, client->id,
396                         client->id->ip.data_len)) {
397       SILC_LOG_DEBUG(("Found (local) %s",
398                       silc_id_render(server_entry->id, SILC_ID_SERVER)));
399
400       if (!SILC_IS_LOCAL(server_entry) && server_entry->router) {
401         SILC_LOG_DEBUG(("Server not locally connected, use its router"));
402         /* If the client is not marked as local then move it to local list
403            since the server is local. */
404         if (!local) {
405           SILC_LOG_DEBUG(("Moving client to local list"));
406           silc_idcache_add(server->local_list->clients, client_cache->name,
407                            client_cache->id, client_cache->context);
408           silc_idcache_del_by_context(server->global_list->clients, client,
409                                       NULL);
410         }
411         server_entry = server_entry->router;
412       } else {
413         SILC_LOG_DEBUG(("Server locally connected"));
414         /* If the client is not marked as local then move it to local list
415            since the server is local. */
416         if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
417           SILC_LOG_DEBUG(("Moving client to local list"));
418           silc_idcache_add(server->local_list->clients, client_cache->name,
419                            client_cache->id, client_cache->context);
420           silc_idcache_del_by_context(server->global_list->clients, client,
421                                       NULL);
422
423         } else if (server->server_type == SILC_BACKUP_ROUTER && local) {
424           /* If we are backup router and this client is on local list, we
425              must move it to global list, as it is not currently local to
426              us (we are not primary). */
427           SILC_LOG_DEBUG(("Moving client to global list"));
428           silc_idcache_add(server->global_list->clients, client_cache->name,
429                            client_cache->id, client_cache->context);
430           silc_idcache_del_by_context(server->local_list->clients, client,
431                                       NULL);
432         }
433       }
434
435       return server_entry;
436     }
437   }
438
439   if (!silc_idcache_get_all(server->global_list->servers, &list))
440     return NULL;
441
442   silc_list_start(list);
443   while ((id_cache = silc_list_get(list))) {
444     server_entry = (SilcServerEntry)id_cache->context;
445     if (server_entry != from && server_entry != server->id_entry &&
446         (tolocal || server_entry != server->id_entry) &&
447         SILC_ID_COMPARE(server_entry->id, client->id,
448                         client->id->ip.data_len)) {
449       SILC_LOG_DEBUG(("Found (global) %s",
450                       silc_id_render(server_entry->id, SILC_ID_SERVER)));
451
452       if (!SILC_IS_LOCAL(server_entry) && server_entry->router) {
453         SILC_LOG_DEBUG(("Server not locally connected, use its router"));
454         /* If the client is marked as local then move it to global list
455            since the server is global. */
456         if (local) {
457           SILC_LOG_DEBUG(("Moving client to global list"));
458           silc_idcache_add(server->global_list->clients, client_cache->name,
459                            client_cache->id, client_cache->context);
460           silc_idcache_del_by_context(server->local_list->clients, client,
461                                       NULL);
462         }
463         server_entry = server_entry->router;
464       } else {
465         SILC_LOG_DEBUG(("Server locally connected"));
466         /* If the client is marked as local then move it to global list
467            since the server is global. */
468         if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
469           SILC_LOG_DEBUG(("Moving client to global list"));
470           silc_idcache_add(server->global_list->clients, client_cache->name,
471                            client_cache->id, client_cache->context);
472           silc_idcache_del_by_context(server->local_list->clients, client,
473                                       NULL);
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)
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)
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 {
1049   SilcServerConnection conn;
1050   int count = 0;
1051
1052   if (!ip && !hostname)
1053     return 0;
1054
1055   silc_dlist_start(server->conns);
1056   while ((conn = silc_dlist_get(server->conns))) {
1057     if (((ip && !strcmp(conn->remote_host, ip)) ||
1058          (hostname && !strcmp(conn->remote_host, hostname))) &&
1059         conn->remote_port == port)
1060       count++;
1061   }
1062
1063   return count;
1064 }
1065
1066 /* SKR find callbcak */
1067
1068 static void find_callback(SilcSKR skr, SilcSKRFind find,
1069                           SilcSKRStatus status, SilcDList keys,
1070                           void *context)
1071 {
1072   SilcPublicKey *public_key = context;
1073   SilcSKRKey key;
1074
1075   if (keys) {
1076     silc_dlist_start(keys);
1077     key = silc_dlist_get(keys);
1078     *public_key = key->key;
1079     silc_dlist_uninit(keys);
1080   }
1081
1082   silc_skr_find_free(find);
1083 }
1084
1085 /* Get public key. For public key tables that has multiple keys in it the
1086    silc_server_find_public_key must be used. */
1087
1088 SilcPublicKey silc_server_get_public_key(SilcServer server,
1089                                          SilcSKRKeyUsage usage,
1090                                          void *key_context)
1091 {
1092   SilcSKRFind find;
1093   SilcPublicKey public_key = NULL;
1094
1095   SILC_LOG_DEBUG(("Start"));
1096
1097   find = silc_skr_find_alloc();
1098   if (!find)
1099     return NULL;
1100
1101   silc_skr_find_set_usage(find, usage);
1102   silc_skr_find_set_context(find, key_context);
1103   silc_skr_find(server->repository, server->schedule,
1104                 find, find_callback, &public_key);
1105
1106   return public_key;
1107 }
1108
1109 /* Find public key by client for identification purposes.  Finds keys
1110    with SILC_SKR_USAGE_IDENTIFICATION. */
1111
1112 SilcBool silc_server_get_public_key_by_client(SilcServer server,
1113                                               SilcClientEntry client,
1114                                               SilcPublicKey *public_key)
1115 {
1116   SilcPublicKey pubkey = NULL;
1117   SilcBool ret = FALSE;
1118
1119   pubkey = silc_server_get_public_key(server, SILC_SKR_USAGE_IDENTIFICATION,
1120                                       client);
1121   if (pubkey)
1122     ret = TRUE;
1123
1124   if (public_key)
1125     *public_key = pubkey;
1126
1127   return ret;
1128 }
1129
1130 /* Check whether the connection `sock' is allowed to connect to us.  This
1131    checks for example whether there is too much connections for this host,
1132    and required version for the host etc. */
1133
1134 SilcBool silc_server_connection_allowed(SilcServer server,
1135                                         SilcPacketStream sock,
1136                                         SilcConnectionType type,
1137                                         SilcServerConfigConnParams *global,
1138                                         SilcServerConfigConnParams *params,
1139                                         SilcSKE ske)
1140 {
1141   SilcUInt32 conn_number = (type == SILC_CONN_CLIENT ?
1142                             server->stat.my_clients :
1143                             type == SILC_CONN_SERVER ?
1144                             server->stat.my_servers :
1145                             server->stat.my_routers);
1146   SilcUInt32 num_sockets, max_hosts, max_per_host;
1147   SilcUInt32 r_protocol_version, l_protocol_version;
1148   SilcUInt32 r_software_version, l_software_version;
1149   char *r_vendor_version = NULL, *l_vendor_version;
1150   const char *hostname, *ip;
1151
1152   silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
1153                               NULL, &hostname, &ip, NULL);
1154
1155   SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1156
1157   /* Check version */
1158
1159   l_protocol_version =
1160     silc_version_to_num(params && params->version_protocol ?
1161                         params->version_protocol :
1162                         global->version_protocol);
1163   l_software_version =
1164     silc_version_to_num(params && params->version_software ?
1165                         params->version_software :
1166                         global->version_software);
1167   l_vendor_version = (params && params->version_software_vendor ?
1168                       params->version_software_vendor :
1169                       global->version_software_vendor);
1170
1171   if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1172                                     &r_software_version, NULL,
1173                                     &r_vendor_version)) {
1174     /* Match protocol version */
1175     if (l_protocol_version && r_protocol_version &&
1176         r_protocol_version < l_protocol_version) {
1177       SILC_LOG_INFO(("Connection %s (%s) is too old version",
1178                      hostname, ip));
1179       silc_server_disconnect_remote(server, sock,
1180                                     SILC_STATUS_ERR_BAD_VERSION,
1181                                     "You support too old protocol version");
1182       return FALSE;
1183     }
1184
1185     /* Math software version */
1186     if (l_software_version && r_software_version &&
1187         r_software_version < l_software_version) {
1188       SILC_LOG_INFO(("Connection %s (%s) is too old version",
1189                      hostname, ip));
1190       silc_server_disconnect_remote(server, sock,
1191                                     SILC_STATUS_ERR_BAD_VERSION,
1192                                     "You support too old software version");
1193       return FALSE;
1194     }
1195
1196     /* Regex match vendor version */
1197     if (l_vendor_version && r_vendor_version &&
1198         !silc_string_match(l_vendor_version, r_vendor_version)) {
1199       SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1200                      hostname, ip));
1201       silc_server_disconnect_remote(server, sock,
1202                                     SILC_STATUS_ERR_BAD_VERSION,
1203                                     "Your software is not supported");
1204       return FALSE;
1205     }
1206   }
1207   silc_free(r_vendor_version);
1208
1209   /* Check for maximum connections limit */
1210
1211   num_sockets = silc_server_num_sockets_by_ip(server, ip, type);
1212   max_hosts = (params ? params->connections_max : global->connections_max);
1213   max_per_host = (params ? params->connections_max_per_host :
1214                   global->connections_max_per_host);
1215
1216   if (max_hosts && conn_number >= max_hosts) {
1217     SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1218                    hostname, ip));
1219     silc_server_disconnect_remote(server, sock,
1220                                   SILC_STATUS_ERR_RESOURCE_LIMIT,
1221                                   "Server is full, try again later");
1222     return FALSE;
1223   }
1224
1225   if (num_sockets >= max_per_host) {
1226     SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1227                    hostname, ip));
1228     silc_server_disconnect_remote(server, sock,
1229                                   SILC_STATUS_ERR_RESOURCE_LIMIT,
1230                                   "Too many connections from your host");
1231     return FALSE;
1232   }
1233
1234   return TRUE;
1235 }
1236
1237 /* Checks that client has rights to add or remove channel modes. If any
1238    of the checks fails FALSE is returned. */
1239
1240 SilcBool silc_server_check_cmode_rights(SilcServer server,
1241                                     SilcChannelEntry channel,
1242                                     SilcChannelClientEntry client,
1243                                     SilcUInt32 mode)
1244 {
1245   SilcBool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1246   SilcBool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1247
1248   /* Check whether has rights to change anything */
1249   if (!is_op && !is_fo)
1250     return FALSE;
1251
1252   /* Check whether has rights to change everything */
1253   if (is_op && is_fo)
1254     return TRUE;
1255
1256   /* Founder implies operator */
1257   if (is_fo)
1258     is_op = TRUE;
1259
1260   /* We know that client is channel operator, check that they are not
1261      changing anything that requires channel founder rights. Rest of the
1262      modes are available automatically for channel operator. */
1263
1264   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1265     if (is_op && !is_fo)
1266       return FALSE;
1267   } else {
1268     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1269       if (is_op && !is_fo)
1270         return FALSE;
1271     }
1272   }
1273
1274   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1275     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1276       if (is_op && !is_fo)
1277         return FALSE;
1278     }
1279   } else {
1280     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1281       if (is_op && !is_fo)
1282         return FALSE;
1283     }
1284   }
1285
1286   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1287     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1288       if (is_op && !is_fo)
1289         return FALSE;
1290     }
1291   } else {
1292     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1293       if (is_op && !is_fo)
1294         return FALSE;
1295     }
1296   }
1297
1298   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1299     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1300       if (is_op && !is_fo)
1301         return FALSE;
1302     }
1303   } else {
1304     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1305       if (is_op && !is_fo)
1306         return FALSE;
1307     }
1308   }
1309
1310   if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1311     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1312       if (is_op && !is_fo)
1313         return FALSE;
1314     }
1315   } else {
1316     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1317       if (is_op && !is_fo)
1318         return FALSE;
1319     }
1320   }
1321
1322   if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1323     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1324       if (is_op && !is_fo)
1325         return FALSE;
1326     }
1327   } else {
1328     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1329       if (is_op && !is_fo)
1330         return FALSE;
1331     }
1332   }
1333
1334   if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1335     if (!(channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)) {
1336       if (is_op && !is_fo)
1337         return FALSE;
1338     }
1339   } else {
1340     if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1341       if (is_op && !is_fo)
1342         return FALSE;
1343     }
1344   }
1345
1346   return TRUE;
1347 }
1348
1349 /* Check that the client has rights to change its user mode.  Returns
1350    FALSE if setting some mode is not allowed. */
1351
1352 SilcBool silc_server_check_umode_rights(SilcServer server,
1353                                     SilcClientEntry client,
1354                                     SilcUInt32 mode)
1355 {
1356   SilcBool server_op = FALSE, router_op = FALSE;
1357
1358   if (mode & SILC_UMODE_SERVER_OPERATOR) {
1359     /* Cannot set server operator mode (must use OPER command) */
1360     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1361       return FALSE;
1362   } else {
1363     /* Remove the server operator rights */
1364     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1365       server_op = TRUE;
1366   }
1367
1368   if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1369     /* Cannot set router operator mode (must use SILCOPER command) */
1370     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1371       return FALSE;
1372   } else {
1373     /* Remove the router operator rights */
1374     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1375       router_op = TRUE;
1376   }
1377
1378   if (server_op)
1379     SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1380   if (router_op)
1381     SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1382
1383   return TRUE;
1384 }
1385
1386 /* This function is used to send the notify packets and motd to the
1387    incoming client connection. */
1388
1389 void silc_server_send_connect_notifys(SilcServer server,
1390                                       SilcPacketStream sock,
1391                                       SilcClientEntry client)
1392 {
1393   SilcCipher key;
1394
1395   SILC_LOG_DEBUG(("Send welcome notifys"));
1396
1397   /* Send some nice info to the client */
1398   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1399                           ("Welcome to the SILC Network %s",
1400                            client->username));
1401   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1402                           ("Your host is %s, running version %s",
1403                            server->server_name, server_version));
1404
1405   if (server->server_type == SILC_ROUTER) {
1406     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1407                             ("There are %d clients, %d servers and %d "
1408                              "routers in SILC Network",
1409                              server->stat.clients, server->stat.servers,
1410                              server->stat.routers));
1411   } else {
1412     if (server->stat.clients && server->stat.servers + 1)
1413       SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1414                               ("There are %d clients, %d servers and %d "
1415                                "routers in SILC Network",
1416                                server->stat.clients, server->stat.servers,
1417                                (server->standalone ? 0 :
1418                                 !server->stat.routers ? 1 :
1419                                 server->stat.routers)));
1420   }
1421
1422   if (server->stat.cell_clients && server->stat.cell_servers + 1)
1423     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1424                             ("There are %d clients on %d servers in our cell",
1425                              server->stat.cell_clients,
1426                              server->stat.cell_servers));
1427   if (server->server_type == SILC_ROUTER) {
1428     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1429                             ("I have %d clients, %d channels, %d servers and "
1430                              "%d routers",
1431                              server->stat.my_clients,
1432                              server->stat.my_channels,
1433                              server->stat.my_servers,
1434                              server->stat.my_routers));
1435   } else {
1436     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1437                             ("I have %d clients and %d channels formed",
1438                              server->stat.my_clients,
1439                              server->stat.my_channels));
1440   }
1441
1442   if (server->stat.server_ops || server->stat.router_ops)
1443     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1444                             ("There are %d server operators and %d router "
1445                              "operators online",
1446                              server->stat.server_ops,
1447                              server->stat.router_ops));
1448   if (server->stat.my_router_ops + server->stat.my_server_ops)
1449     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1450                             ("I have %d operators online",
1451                              server->stat.my_router_ops +
1452                              server->stat.my_server_ops));
1453
1454   silc_packet_get_keys(sock, &key, NULL, NULL, NULL);
1455   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1456                           ("Your connection is secured with %s cipher, "
1457                            "key length %d bits",
1458                            silc_cipher_get_name(key),
1459                            silc_cipher_get_key_len(key)));
1460   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1461                           ("Your current nickname is %s",
1462                            client->nickname));
1463
1464   /* Send motd */
1465   silc_server_send_motd(server, sock);
1466 }
1467
1468 /* Kill the client indicated by `remote_client' sending KILLED notify
1469    to the client, to all channels client has joined and to primary
1470    router if needed.  The killed client is also removed from all channels. */
1471
1472 void silc_server_kill_client(SilcServer server,
1473                              SilcClientEntry remote_client,
1474                              const char *comment,
1475                              void *killer_id,
1476                              SilcIdType killer_id_type)
1477 {
1478   SilcBuffer killed, killer;
1479
1480   SILC_LOG_DEBUG(("Killing client %s",
1481                   silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1482
1483   /* Send the KILL notify packets. First send it to the channel, then
1484      to our primary router and then directly to the client who is being
1485      killed right now. */
1486
1487   killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1488   killer = silc_id_payload_encode(killer_id, killer_id_type);
1489
1490   /* Send KILLED notify to the channels. It is not sent to the client
1491      as it will be sent differently destined directly to the client and not
1492      to the channel. */
1493   silc_server_send_notify_on_channels(server, remote_client,
1494                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
1495                                       3, killed->data, silc_buffer_len(killed),
1496                                       comment, comment ? strlen(comment) : 0,
1497                                       killer->data, silc_buffer_len(killer));
1498
1499   /* Send KILLED notify to primary route */
1500   silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1501                                  SILC_BROADCAST(server), remote_client->id,
1502                                  comment, killer_id, killer_id_type);
1503
1504   /* Send KILLED notify to the client directly */
1505   if (remote_client->connection || remote_client->router)
1506     silc_server_send_notify_killed(server, remote_client->connection ?
1507                                    remote_client->connection :
1508                                    remote_client->router->connection, FALSE,
1509                                    remote_client->id, comment,
1510                                    killer_id, killer_id_type);
1511
1512   /* Remove the client from all channels. This generates new keys to the
1513      channels as well. */
1514   silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1515                                    NULL, TRUE, TRUE);
1516
1517   /* Remove the client entry, If it is locally connected then we will also
1518      disconnect the client here */
1519   if (remote_client->connection) {
1520     /* Remove locally conneted client */
1521     SilcPacketStream sock = remote_client->connection;
1522     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1523     silc_server_close_connection(server, sock);
1524   } else {
1525     /* Update statistics */
1526     server->stat.clients--;
1527     if (server->stat.cell_clients)
1528       server->stat.cell_clients--;
1529     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1530     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1531
1532     if (remote_client->data.public_key)
1533       silc_hash_table_del_by_context(server->pk_hash,
1534                                      remote_client->data.public_key,
1535                                      remote_client);
1536
1537     if (SILC_IS_LOCAL(remote_client)) {
1538       server->stat.my_clients--;
1539       silc_schedule_task_del_by_context(server->schedule, remote_client);
1540     }
1541
1542     /* Remove remote client */
1543     silc_idlist_del_data(remote_client);
1544     if (!silc_idlist_del_client(server->global_list, remote_client)) {
1545       /* Remove this client from watcher list if it is */
1546       silc_server_del_from_watcher_list(server, remote_client);
1547       silc_idlist_del_client(server->local_list, remote_client);
1548     }
1549   }
1550
1551   silc_buffer_free(killer);
1552   silc_buffer_free(killed);
1553 }
1554
1555 typedef struct {
1556   SilcServer server;
1557   SilcClientEntry client;
1558   SilcNotifyType notify;
1559   const char *new_nick;
1560 } WatcherNotifyContext;
1561
1562 static void
1563 silc_server_check_watcher_list_foreach(void *key, void *context,
1564                                        void *user_context)
1565 {
1566   WatcherNotifyContext *notify = user_context;
1567   SilcClientEntry entry = context;
1568   SilcPacketStream sock;
1569
1570   if (!context)
1571     return;
1572
1573   if (entry == notify->client)
1574     return;
1575
1576   sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1577                                       NULL, NULL);
1578   if (sock) {
1579     SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1580                     silc_id_render(entry->id, SILC_ID_CLIENT)));
1581
1582     /* Send the WATCH notify */
1583     silc_server_send_notify_watch(notify->server, sock, entry,
1584                                   notify->client,
1585                                   notify->new_nick ? notify->new_nick :
1586                                   (const char *)notify->client->nickname,
1587                                   notify->notify,
1588                                   notify->client->data.public_key);
1589   }
1590 }
1591
1592 /* This function checks whether the `client' nickname and/or 'client'
1593    public key is being watched by someone, and notifies the watcher of the
1594    notify change of notify type indicated by `notify'. */
1595
1596 SilcBool silc_server_check_watcher_list(SilcServer server,
1597                                     SilcClientEntry client,
1598                                     const char *new_nick,
1599                                     SilcNotifyType notify)
1600 {
1601   unsigned char hash[16];
1602   WatcherNotifyContext n;
1603
1604   SILC_LOG_DEBUG(("Checking watcher list %s",
1605                   client->nickname ? client->nickname : (unsigned char *)""));
1606
1607   /* If the watching is rejected by the client do nothing */
1608   if (client->mode & SILC_UMODE_REJECT_WATCHING)
1609     return FALSE;
1610
1611   /* Make hash from the nick, or take it from Client ID */
1612   if (client->nickname) {
1613     unsigned char *nickc;
1614     nickc = silc_identifier_check(client->nickname, strlen(client->nickname),
1615                                   SILC_STRING_UTF8, 128, NULL);
1616     if (!nickc)
1617       return FALSE;
1618     silc_hash_make(server->md5hash, nickc, strlen(nickc), hash);
1619     silc_free(nickc);
1620   } else {
1621     memset(hash, 0, sizeof(hash));
1622     memcpy(hash, client->id->hash, sizeof(client->id->hash));
1623   }
1624
1625   n.server = server;
1626   n.client = client;
1627   n.new_nick = new_nick;
1628   n.notify = notify;
1629
1630   /* Send notify to all watchers watching this nickname */
1631   silc_hash_table_find_foreach(server->watcher_list, hash,
1632                                silc_server_check_watcher_list_foreach, &n);
1633
1634   /* Send notify to all watchers watching this public key */
1635   if (client->data.public_key)
1636     silc_hash_table_find_foreach(server->watcher_list_pk,
1637                                  client->data.public_key,
1638                                  silc_server_check_watcher_list_foreach,
1639                                  &n);
1640
1641   return TRUE;
1642 }
1643
1644 /* Remove the `client' from watcher list. After calling this the `client'
1645    is not watching any nicknames. */
1646
1647 SilcBool silc_server_del_from_watcher_list(SilcServer server,
1648                                        SilcClientEntry client)
1649 {
1650   SilcHashTableList htl;
1651   void *key;
1652   SilcClientEntry entry;
1653   SilcBool found = FALSE;
1654
1655   silc_hash_table_list(server->watcher_list, &htl);
1656   while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1657     if (entry == client) {
1658       silc_hash_table_del_by_context(server->watcher_list, key, client);
1659
1660       if (client->id)
1661         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1662                         silc_id_render(client->id, SILC_ID_CLIENT)));
1663
1664       /* Now check whether there still exists entries with this key, if not
1665          then free the key to not leak memory. */
1666       if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1667         silc_free(key);
1668
1669       found = TRUE;
1670     }
1671   }
1672   silc_hash_table_list_reset(&htl);
1673
1674   silc_hash_table_list(server->watcher_list_pk, &htl);
1675   while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1676     if (entry == client) {
1677       silc_hash_table_del_by_context(server->watcher_list_pk, key, client);
1678
1679       if (client->id)
1680         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1681                         silc_id_render(client->id, SILC_ID_CLIENT)));
1682
1683       /* Now check whether there still exists entries with this key, if not
1684          then free the key to not leak memory. */
1685       if (!silc_hash_table_find(server->watcher_list_pk, key, NULL, NULL))
1686         silc_pkcs_public_key_free(key);
1687
1688       found = TRUE;
1689     }
1690   }
1691   silc_hash_table_list_reset(&htl);
1692
1693   return found;
1694 }
1695
1696 /* Force the client indicated by `chl' to change the channel user mode
1697    on channel indicated by `channel' to `forced_mode'. */
1698
1699 SilcBool silc_server_force_cumode_change(SilcServer server,
1700                                          SilcPacketStream sock,
1701                                          SilcChannelEntry channel,
1702                                          SilcChannelClientEntry chl,
1703                                          SilcUInt32 forced_mode)
1704 {
1705   SilcBuffer idp1, idp2;
1706   unsigned char cumode[4];
1707
1708   SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1709
1710   if (sock)
1711     silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1712                                    server->id, SILC_ID_SERVER,
1713                                    chl->client->id, NULL);
1714
1715   idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1716   idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1717   SILC_PUT32_MSB(forced_mode, cumode);
1718   silc_server_send_notify_to_channel(server, sock, channel, FALSE, TRUE,
1719                                      SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1720                                      3, idp1->data, silc_buffer_len(idp1),
1721                                      cumode, sizeof(cumode),
1722                                      idp2->data, silc_buffer_len(idp2));
1723   silc_buffer_free(idp1);
1724   silc_buffer_free(idp2);
1725
1726   return TRUE;
1727 }
1728
1729 /* This function can be used to match the invite and ban lists. */
1730
1731 SilcBool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1732                                      SilcUInt8 type, void *check)
1733 {
1734   unsigned char *tmp = NULL;
1735   SilcUInt32 len = 0, t;
1736   SilcHashTableList htl;
1737   SilcBuffer entry, idp = NULL, pkp = NULL;
1738   SilcBool ret = FALSE;
1739
1740   SILC_LOG_DEBUG(("Matching invite/ban"));
1741
1742   if (type < 1 || type > 3 || !check)
1743     return FALSE;
1744
1745   if (type == 1) {
1746     tmp = strdup((char *)check);
1747     if (!tmp)
1748       return FALSE;
1749   }
1750   if (type == 2) {
1751     pkp = silc_public_key_payload_encode(check);
1752     if (!pkp)
1753       return FALSE;
1754     tmp = pkp->data;
1755     len = silc_buffer_len(pkp);
1756   }
1757   if (type == 3) {
1758     idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
1759     if (!idp)
1760       return FALSE;
1761     tmp = idp->data;
1762     len = silc_buffer_len(idp);
1763   }
1764
1765   /* Compare the list */
1766   silc_hash_table_list(list, &htl);
1767   while (silc_hash_table_get(&htl, (void *)&t, (void *)&entry)) {
1768     if (type == t) {
1769       if (type == 1) {
1770         if (silc_string_match(entry->data, tmp)) {
1771           ret = TRUE;
1772           break;
1773         }
1774       } else if (!memcmp(entry->data, tmp, len)) {
1775         ret = TRUE;
1776         break;
1777       }
1778     }
1779   }
1780   silc_hash_table_list_reset(&htl);
1781
1782   if (type == 1)
1783     silc_free(tmp);
1784   silc_buffer_free(idp);
1785   silc_buffer_free(pkp);
1786   return ret;
1787 }
1788
1789 /* Process invite or ban information */
1790
1791 SilcBool silc_server_inviteban_process(SilcServer server, SilcHashTable list,
1792                                    SilcUInt8 action, SilcArgumentPayload args)
1793 {
1794   unsigned char *tmp;
1795   SilcUInt32 type, len;
1796   SilcBuffer tmp2;
1797   SilcHashTableList htl;
1798
1799   SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1800                   action == 0x01 ? "DEL" : "ADD"));
1801
1802   /* Add the information to invite list */
1803   if (action == 0x00 || action == 0x03) {
1804     /* Traverse all arguments and add to the hash table according to
1805        their type. */
1806     tmp = silc_argument_get_first_arg(args, &type, &len);
1807     while (tmp) {
1808       if (type == 1) {
1809         /* Check validity of the string.  Actually we should parse the
1810            whole string and verify all components individually. */
1811         if (!silc_utf8_valid(tmp, len) || !len) {
1812           tmp = silc_argument_get_next_arg(args, &type, &len);
1813           continue;
1814         }
1815         if (strchr(tmp, ',')) {
1816           tmp = silc_argument_get_next_arg(args, &type, &len);
1817           continue;
1818         }
1819
1820         /* Check if the string is added already */
1821         silc_hash_table_list(list, &htl);
1822         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1823           if (type == 1 && silc_string_match(tmp2->data, tmp)) {
1824             tmp = NULL;
1825             break;
1826           }
1827         }
1828         silc_hash_table_list_reset(&htl);
1829
1830         if (tmp) {
1831           /* Add the string to hash table */
1832           tmp2 = silc_buffer_alloc_size(len + 1);
1833           if (tmp[len - 1] == ',')
1834             tmp[len - 1] = '\0';
1835           silc_buffer_put(tmp2, tmp, len);
1836           silc_hash_table_add(list, (void *)1, tmp2);
1837         }
1838
1839       } else if (type == 2) {
1840         /* Public key.  Check first if the public key is already on the
1841            list and ignore it if it is, otherwise, add it to hash table. */
1842         SilcPublicKey pk;
1843
1844         /* Verify validity of the public key */
1845         if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1846           tmp = silc_argument_get_next_arg(args, &type, &len);
1847           continue;
1848         }
1849         silc_pkcs_public_key_free(pk);
1850
1851         /* Check if the public key is in the list already */
1852         silc_hash_table_list(list, &htl);
1853         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1854           if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1855             tmp = NULL;
1856             break;
1857           }
1858         }
1859         silc_hash_table_list_reset(&htl);
1860
1861         /* Add new public key to invite list */
1862         if (tmp) {
1863           tmp2 = silc_buffer_alloc_size(len);
1864           silc_buffer_put(tmp2, tmp, len);
1865           silc_hash_table_add(list, (void *)2, tmp2);
1866         }
1867
1868       } else if (type == 3) {
1869         /* Client ID */
1870
1871         /* Check if the ID is in the list already */
1872         silc_hash_table_list(list, &htl);
1873         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1874           if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1875             tmp = NULL;
1876             break;
1877           }
1878         }
1879         silc_hash_table_list_reset(&htl);
1880
1881         /* Add new Client ID to invite list */
1882         if (tmp) {
1883           tmp2 = silc_buffer_alloc_size(len);
1884           silc_buffer_put(tmp2, tmp, len);
1885           silc_hash_table_add(list, (void *)3, tmp2);
1886         }
1887       }
1888
1889       tmp = silc_argument_get_next_arg(args, &type, &len);
1890     }
1891   }
1892
1893   /* Delete information to invite list */
1894   if (action == 0x01 && list) {
1895     /* Now delete the arguments from invite list */
1896     tmp = silc_argument_get_first_arg(args, &type, &len);
1897     while (tmp) {
1898       if (type == 1) {
1899         /* Check validity of the string.  Actually we should parse the
1900            whole string and verify all components individually. */
1901         if (!silc_utf8_valid(tmp, len)) {
1902           tmp = silc_argument_get_next_arg(args, &type, &len);
1903           continue;
1904         }
1905         if (strchr(tmp, ',')) {
1906           tmp = silc_argument_get_next_arg(args, &type, &len);
1907           continue;
1908         }
1909
1910         /* Delete from the list */
1911         silc_hash_table_list(list, &htl);
1912         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1913           if (type == 1 && silc_string_match(tmp2->data, tmp)) {
1914             silc_hash_table_del_by_context(list, (void *)1, tmp2);
1915             break;
1916           }
1917         }
1918         silc_hash_table_list_reset(&htl);
1919
1920       } else if (type == 2) {
1921         /* Public key. */
1922         SilcPublicKey pk;
1923
1924         /* Verify validity of the public key */
1925         if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1926           tmp = silc_argument_get_next_arg(args, &type, &len);
1927           continue;
1928         }
1929         silc_pkcs_public_key_free(pk);
1930
1931         /* Delete from the invite list */
1932         silc_hash_table_list(list, &htl);
1933         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1934           if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1935             silc_hash_table_del_by_context(list, (void *)2, tmp2);
1936             break;
1937           }
1938         }
1939         silc_hash_table_list_reset(&htl);
1940
1941       } else if (type == 3) {
1942         /* Client ID */
1943
1944         /* Delete from the invite list */
1945         silc_hash_table_list(list, &htl);
1946         while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1947           if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1948             silc_hash_table_del_by_context(list, (void *)3, tmp2);
1949             break;
1950           }
1951         }
1952         silc_hash_table_list_reset(&htl);
1953       }
1954
1955       tmp = silc_argument_get_next_arg(args, &type, &len);
1956     }
1957   }
1958
1959   return TRUE;
1960 }
1961
1962 /* Destructor for invite and ban list entrys */
1963
1964 void silc_server_inviteban_destruct(void *key, void *context,
1965                                     void *user_context)
1966 {
1967   silc_buffer_free(context);
1968 }
1969
1970 /* Creates connections accoring to configuration. */
1971
1972 void silc_server_create_connections(SilcServer server)
1973 {
1974   silc_schedule_task_del_by_callback(server->schedule,
1975                                      silc_server_connect_to_router);
1976   silc_schedule_task_add_timeout(server->schedule,
1977                                  silc_server_connect_to_router, server, 0, 1);
1978 }
1979
1980 static void
1981 silc_server_process_channel_pk_destruct(void *key, void *context,
1982                                         void *user_context)
1983 {
1984   silc_free(key);
1985   silc_pkcs_public_key_free(context);
1986 }
1987
1988 /* Processes a channel public key, either adds or removes it. */
1989
1990 SilcStatus
1991 silc_server_process_channel_pk(SilcServer server,
1992                                SilcChannelEntry channel,
1993                                SilcUInt32 type, const unsigned char *pk,
1994                                SilcUInt32 pk_len)
1995 {
1996   unsigned char pkhash[20];
1997   SilcPublicKey chpk;
1998
1999   SILC_LOG_DEBUG(("Processing channel public key"));
2000
2001   if (!pk || !pk_len)
2002     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2003
2004   /* Decode the public key */
2005   if (!silc_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
2006     return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
2007
2008   /* Create channel public key list (hash table) if needed */
2009   if (!channel->channel_pubkeys) {
2010     channel->channel_pubkeys =
2011       silc_hash_table_alloc(0, silc_hash_data, (void *)20,
2012                             silc_hash_data_compare, (void *)20,
2013                             silc_server_process_channel_pk_destruct, channel,
2014                             TRUE);
2015   }
2016
2017   /* Create SHA-1 digest of the public key data */
2018   silc_hash_make(server->sha1hash, pk + 4, pk_len - 4, pkhash);
2019
2020   if (type == 0x00) {
2021     /* Add new public key to channel public key list */
2022     SILC_LOG_DEBUG(("Add new channel public key to channel %s",
2023                     channel->channel_name));
2024
2025     /* Check for resource limit */
2026     if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
2027       silc_pkcs_public_key_free(chpk);
2028       return SILC_STATUS_ERR_RESOURCE_LIMIT;
2029     }
2030
2031     /* Add if doesn't exist already */
2032     if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2033                               NULL, NULL))
2034       silc_hash_table_add(channel->channel_pubkeys, silc_memdup(pkhash, 20),
2035                           chpk);
2036   } else if (type == 0x01) {
2037     /* Delete public key from channel public key list */
2038     SILC_LOG_DEBUG(("Delete a channel public key from channel %s",
2039                     channel->channel_name));
2040     if (!silc_hash_table_del(channel->channel_pubkeys, pkhash))
2041       silc_pkcs_public_key_free(chpk);
2042   } else {
2043     silc_pkcs_public_key_free(chpk);
2044     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2045   }
2046
2047   return SILC_STATUS_OK;
2048 }
2049
2050 /* Returns the channel public keys as Argument List payload. */
2051
2052 SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
2053                                            SilcChannelEntry channel,
2054                                            SilcBool announce,
2055                                            SilcBool delete)
2056 {
2057   SilcHashTableList htl;
2058   SilcBuffer list, pkp;
2059   SilcPublicKey pk;
2060
2061   SILC_LOG_DEBUG(("Encoding channel public keys list"));
2062
2063   if (!channel->channel_pubkeys ||
2064       !silc_hash_table_count(channel->channel_pubkeys))
2065     return NULL;
2066
2067   /* Encode the list */
2068   list = silc_buffer_alloc_size(2);
2069   silc_buffer_format(list,
2070                      SILC_STR_UI_SHORT(silc_hash_table_count(
2071                                        channel->channel_pubkeys)),
2072                      SILC_STR_END);
2073
2074   silc_hash_table_list(channel->channel_pubkeys, &htl);
2075   while (silc_hash_table_get(&htl, NULL, (void *)&pk)) {
2076     pkp = silc_public_key_payload_encode(pk);
2077     list = silc_argument_payload_encode_one(list, pkp->data,
2078                                             silc_buffer_len(pkp),
2079                                             announce ? 0x03 :
2080                                             delete ? 0x01 : 0x00);
2081     silc_buffer_free(pkp);
2082   }
2083   silc_hash_table_list_reset(&htl);
2084
2085   return list;
2086 }
2087
2088 /* Sets the channel public keys into channel from the list of public keys. */
2089
2090 SilcStatus silc_server_set_channel_pk_list(SilcServer server,
2091                                            SilcPacketStream sender,
2092                                            SilcChannelEntry channel,
2093                                            const unsigned char *pklist,
2094                                            SilcUInt32 pklist_len)
2095 {
2096   SilcUInt16 argc;
2097   SilcArgumentPayload args;
2098   unsigned char *chpk;
2099   SilcUInt32 chpklen, type;
2100   SilcStatus ret = SILC_STATUS_OK;
2101
2102   SILC_LOG_DEBUG(("Setting channel public keys list"));
2103
2104   if (!pklist || pklist_len < 2)
2105     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2106
2107   /* Get the argument from the Argument List Payload */
2108   SILC_GET16_MSB(argc, pklist);
2109   args = silc_argument_payload_parse(pklist + 2, pklist_len - 2, argc);
2110   if (!args)
2111     return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2112
2113   /* Process the public keys one by one */
2114   chpk = silc_argument_get_first_arg(args, &type, &chpklen);
2115
2116   /* If announcing keys and we have them set already, do not allow this */
2117   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2118       server->server_type == SILC_ROUTER &&
2119       sender != SILC_PRIMARY_ROUTE(server)) {
2120     SILC_LOG_DEBUG(("Channel public key list set already, enforce our list"));
2121     silc_argument_payload_free(args);
2122     return SILC_STATUS_ERR_OPERATION_ALLOWED;
2123   }
2124
2125   /* If we are normal server and receive announcement list and we already
2126      have keys set, we replace the old list with the announced one. */
2127   if (chpk && type == 0x03 && channel->channel_pubkeys &&
2128       server->server_type != SILC_ROUTER) {
2129     SilcBuffer sidp;
2130     unsigned char mask[4], ulimit[4];
2131
2132     SILC_LOG_DEBUG(("Router enforces its list, remove old list"));
2133     silc_hash_table_free(channel->channel_pubkeys);
2134     channel->channel_pubkeys = NULL;
2135
2136     /* Send notify that removes the old list */
2137     sidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2138     SILC_PUT32_MSB((channel->mode & (~SILC_CHANNEL_MODE_CHANNEL_AUTH)), mask);
2139     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2140       SILC_PUT32_MSB(channel->user_limit, ulimit);
2141     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2142                                        SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
2143                                        sidp->data, silc_buffer_len(sidp),
2144                                        mask, 4,
2145                                        channel->cipher,
2146                                        channel->cipher ?
2147                                        strlen(channel->cipher) : 0,
2148                                        channel->hmac_name,
2149                                        channel->hmac_name ?
2150                                        strlen(channel->hmac_name) : 0,
2151                                        channel->passphrase,
2152                                        channel->passphrase ?
2153                                        strlen(channel->passphrase) : 0,
2154                                        NULL, 0, NULL, 0,
2155                                        (channel->mode &
2156                                         SILC_CHANNEL_MODE_ULIMIT ?
2157                                         ulimit : NULL),
2158                                        (channel->mode &
2159                                         SILC_CHANNEL_MODE_ULIMIT ?
2160                                         sizeof(ulimit) : 0));
2161     silc_buffer_free(sidp);
2162   }
2163
2164   while (chpk) {
2165     if (type == 0x03)
2166       type = 0x00;
2167     ret = silc_server_process_channel_pk(server, channel, type,
2168                                          chpk, chpklen);
2169     if (ret != SILC_STATUS_OK)
2170       break;
2171     chpk = silc_argument_get_next_arg(args, &type, &chpklen);
2172   }
2173
2174   silc_argument_payload_free(args);
2175   return ret;
2176 }
2177
2178 /* Verifies the Authentication Payload `auth' with one of the public keys
2179    on the `channel' public key list. */
2180
2181 SilcBool silc_server_verify_channel_auth(SilcServer server,
2182                                      SilcChannelEntry channel,
2183                                      SilcClientID *client_id,
2184                                      const unsigned char *auth,
2185                                      SilcUInt32 auth_len)
2186 {
2187   SilcAuthPayload ap;
2188   SilcPublicKey chpk;
2189   unsigned char *pkhash;
2190   SilcUInt32 pkhash_len;
2191   SilcBool ret = FALSE;
2192
2193   SILC_LOG_DEBUG(("Verifying channel authentication"));
2194
2195   if (!auth || !auth_len || !channel->channel_pubkeys)
2196     return FALSE;
2197
2198   /* Get the hash from the auth data which tells us what public key we
2199      must use in verification. */
2200
2201   ap = silc_auth_payload_parse(auth, auth_len);
2202   if (!ap)
2203     return FALSE;
2204
2205   pkhash = silc_auth_get_public_data(ap, &pkhash_len);
2206   if (pkhash_len < 128)
2207     goto out;
2208
2209   /* Find the public key with the hash */
2210   if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2211                             NULL, (void *)&chpk)) {
2212     SILC_LOG_DEBUG(("Public key not found in channel public key list"));
2213     goto out;
2214   }
2215
2216   /* Verify the signature */
2217   if (!silc_auth_verify(ap, SILC_AUTH_PUBLIC_KEY, (void *)chpk, 0,
2218                         server->sha1hash, client_id, SILC_ID_CLIENT)) {
2219     SILC_LOG_DEBUG(("Authentication failed"));
2220     goto out;
2221   }
2222
2223   ret = TRUE;
2224
2225  out:
2226   silc_auth_payload_free(ap);
2227   return ret;
2228 }