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