5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
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.
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.
21 #include "serverincludes.h"
22 #include "server_internal.h"
24 extern char *server_version;
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. */
32 silc_server_remove_clients_channels(SilcServer server,
33 SilcServerEntry server_entry,
34 SilcHashTable clients,
35 SilcClientEntry client,
36 SilcHashTable channels)
38 SilcChannelEntry channel;
39 SilcChannelClientEntry chl, chl2;
40 SilcHashTableList htl, htl2;
45 SILC_LOG_DEBUG(("Remove client %s from all channels",
46 client->nickname ? client->nickname :
47 (unsigned char *)""));
49 if (silc_hash_table_find(clients, client, NULL, NULL))
50 silc_hash_table_del(clients, client);
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;
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);
69 silc_hash_table_del(client->channels, channel);
70 silc_hash_table_del(channel->user_list, chl->client);
71 channel->user_count--;
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;
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--;
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);
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;
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);
114 silc_hash_table_list_reset(&htl2);
116 /* Add the channel to the the channels list to regenerate the
118 if (!silc_hash_table_find(channels, channel, NULL, NULL))
119 silc_hash_table_add(channels, channel, channel);
121 silc_hash_table_list_reset(&htl);
122 assert(!silc_hash_table_count(client->channels));
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. */
130 SilcBool silc_server_remove_clients_by_server(SilcServer server,
131 SilcServerEntry router,
132 SilcServerEntry entry,
133 SilcBool server_signoff)
136 SilcIDCacheEntry id_cache = NULL;
137 SilcClientEntry client = NULL;
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;
146 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
149 SILC_LOG_DEBUG(("Removing clients by %s",
150 entry->server_name ? entry->server_name : "server"));
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,
160 clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
163 if (server_signoff) {
164 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
166 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
167 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
168 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
169 argv[argc] = silc_calloc(silc_buffer_len(idp), sizeof(*argv[0]));
170 memcpy(argv[argc], idp->data, silc_buffer_len(idp));
171 argv_lens[argc] = silc_buffer_len(idp);
172 argv_types[argc] = argc + 1;
174 silc_buffer_free(idp);
178 if (silc_idcache_get_all(server->local_list->clients, &list)) {
179 silc_list_start(list);
180 while ((id_cache = silc_list_get(list))) {
181 client = (SilcClientEntry)id_cache->context;
183 /* If client is not registered, is not originated from `router'
184 and is not owned by `entry', skip it. */
185 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
186 client->router != router ||
187 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
188 client->id->ip.data_len))) {
192 if (server_signoff) {
193 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
195 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
196 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
198 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
200 argv[argc] = silc_calloc(silc_buffer_len(idp), sizeof(*argv[0]));
201 memcpy(argv[argc], idp->data, silc_buffer_len(idp));
202 argv_lens[argc] = silc_buffer_len(idp);
203 argv_types[argc] = argc + 1;
205 silc_buffer_free(idp);
209 /* Update statistics */
210 server->stat.clients--;
211 if (server->stat.cell_clients)
212 server->stat.cell_clients--;
213 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
214 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
216 /* Remove client's public key from repository, this will free it too. */
217 if (client->data.public_key) {
218 silc_skr_del_public_key(server->repository, client->data.public_key,
220 client->data.public_key = NULL;
223 silc_server_remove_clients_channels(server, entry, clients,
225 silc_server_del_from_watcher_list(server, client);
227 /* Remove the client entry */
228 if (!server_signoff) {
229 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
231 client->router = NULL;
232 client->connection = NULL;
233 silc_dlist_add(server->expired_clients, client);
235 silc_idlist_del_data(client);
236 silc_idlist_del_client(server->local_list, client);
241 if (silc_idcache_get_all(server->global_list->clients, &list)) {
242 silc_list_start(list);
243 while ((id_cache = silc_list_get(list))) {
244 client = (SilcClientEntry)id_cache->context;
246 /* If client is not registered, is not originated from `router'
247 and is not owned by `entry', skip it. */
248 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
249 client->router != router ||
250 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
251 client->id->ip.data_len))) {
255 if (server_signoff) {
256 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
257 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
258 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
260 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
262 argv[argc] = silc_calloc(silc_buffer_len(idp), sizeof(*argv[0]));
263 memcpy(argv[argc], idp->data, silc_buffer_len(idp));
264 argv_lens[argc] = silc_buffer_len(idp);
265 argv_types[argc] = argc + 1;
267 silc_buffer_free(idp);
270 /* Update statistics */
271 server->stat.clients--;
272 if (server->stat.cell_clients)
273 server->stat.cell_clients--;
274 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
275 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
277 /* Remove client's public key from repository, this will free it too. */
278 if (client->data.public_key) {
279 silc_skr_del_public_key(server->repository, client->data.public_key,
281 client->data.public_key = NULL;
284 silc_server_remove_clients_channels(server, entry, clients,
286 silc_server_del_from_watcher_list(server, client);
288 /* Remove the client entry */
289 if (!server_signoff) {
290 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
292 client->router = NULL;
293 client->connection = NULL;
294 silc_dlist_add(server->expired_clients, client);
296 silc_idlist_del_data(client);
297 silc_idlist_del_client(server->global_list, client);
302 /* Return now if we are shutting down */
303 if (server->server_shutdown) {
304 silc_hash_table_free(channels);
306 if (server_signoff) {
307 for (i = 0; i < argc; i++)
310 silc_free(argv_lens);
311 silc_free(argv_types);
312 silc_hash_table_free(clients);
317 /* Send the SERVER_SIGNOFF notify */
318 if (server_signoff) {
319 SilcBuffer args, not;
321 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
322 silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
324 /* Send SERVER_SIGNOFF notify to our primary router */
325 if (server->router != entry) {
326 args = silc_argument_payload_encode(1, argv, argv_lens,
328 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
329 SILC_BROADCAST(server),
330 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
332 silc_buffer_free(args);
335 /* Send to local clients. We also send the list of client ID's that
336 is to be removed for those servers that would like to use that list. */
337 args = silc_argument_payload_encode(argc, argv, argv_lens,
339 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
341 silc_server_packet_send_clients(server, clients,
342 SILC_PACKET_NOTIFY, 0, FALSE,
343 not->data, silc_buffer_len(not));
345 /* Send notify also to local backup routers */
346 silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
347 not->data, silc_buffer_len(not), FALSE, TRUE);
349 silc_buffer_free(args);
350 silc_buffer_free(not);
351 for (i = 0; i < argc; i++)
354 silc_free(argv_lens);
355 silc_free(argv_types);
356 silc_hash_table_free(clients);
359 /* We must now re-generate the channel key for all channels that had
360 this server's client(s) on the channel. As they left the channel we
361 must re-generate the channel key. */
362 silc_hash_table_list(channels, &htl);
363 while (silc_hash_table_get(&htl, NULL, (void *)&channel)) {
364 if (!silc_server_create_channel_key(server, channel, 0)) {
365 silc_hash_table_list_reset(&htl);
366 silc_hash_table_free(channels);
370 /* Do not send the channel key if private channel key mode is set */
371 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->send_key)
374 silc_server_send_channel_key(server, NULL, channel,
375 server->server_type == SILC_ROUTER ?
376 FALSE : !server->standalone);
378 silc_hash_table_list_reset(&htl);
379 silc_hash_table_free(channels);
384 static SilcServerEntry
385 silc_server_update_clients_by_real_server(SilcServer server,
386 SilcServerEntry from,
388 SilcClientEntry client,
390 SilcIDCacheEntry client_cache)
392 SilcServerEntry server_entry;
393 SilcIDCacheEntry id_cache = NULL;
395 SilcBool tolocal = (to == server->id_entry);
397 SILC_LOG_DEBUG(("Start"));
399 if (!silc_idcache_get_all(server->local_list->servers, &list))
402 silc_list_start(list);
403 while ((id_cache = silc_list_get(list))) {
404 server_entry = (SilcServerEntry)id_cache->context;
405 if (server_entry != from &&
406 (tolocal || server_entry != server->id_entry) &&
407 SILC_ID_COMPARE(server_entry->id, client->id,
408 client->id->ip.data_len)) {
409 SILC_LOG_DEBUG(("Found (local) %s",
410 silc_id_render(server_entry->id, SILC_ID_SERVER)));
412 if (!SILC_IS_LOCAL(server_entry) && server_entry->router) {
413 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
414 /* If the client is not marked as local then move it to local list
415 since the server is 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,
423 server_entry = server_entry->router;
425 SILC_LOG_DEBUG(("Server locally connected"));
426 /* If the client is not marked as local then move it to local list
427 since the server is local. */
428 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
429 SILC_LOG_DEBUG(("Moving client to local list"));
430 silc_idcache_add(server->local_list->clients, client_cache->name,
431 client_cache->id, client_cache->context);
432 silc_idcache_del_by_context(server->global_list->clients, client,
435 } else if (server->server_type == SILC_BACKUP_ROUTER && local) {
436 /* If we are backup router and this client is on local list, we
437 must move it to global list, as it is not currently local to
438 us (we are not primary). */
439 SILC_LOG_DEBUG(("Moving client to global list"));
440 silc_idcache_add(server->global_list->clients, client_cache->name,
441 client_cache->id, client_cache->context);
442 silc_idcache_del_by_context(server->local_list->clients, client,
451 if (!silc_idcache_get_all(server->global_list->servers, &list))
454 silc_list_start(list);
455 while ((id_cache = silc_list_get(list))) {
456 server_entry = (SilcServerEntry)id_cache->context;
457 if (server_entry != from && server_entry != server->id_entry &&
458 (tolocal || server_entry != server->id_entry) &&
459 SILC_ID_COMPARE(server_entry->id, client->id,
460 client->id->ip.data_len)) {
461 SILC_LOG_DEBUG(("Found (global) %s",
462 silc_id_render(server_entry->id, SILC_ID_SERVER)));
464 if (!SILC_IS_LOCAL(server_entry) && server_entry->router) {
465 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
466 /* If the client is marked as local then move it to global list
467 since the server is global. */
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,
475 server_entry = server_entry->router;
477 SILC_LOG_DEBUG(("Server locally connected"));
478 /* If the client is marked as local then move it to global list
479 since the server is global. */
480 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
481 SILC_LOG_DEBUG(("Moving client to global list"));
482 silc_idcache_add(server->global_list->clients, client_cache->name,
483 client_cache->id, client_cache->context);
484 silc_idcache_del_by_context(server->local_list->clients, client,
495 /* Updates the clients that are originated from the `from' to be originated
496 from the `to'. If the `resolve_real_server' is TRUE then this will
497 attempt to figure out which clients really are originated from the
498 `from' and which are originated from a server that we have connection
499 to, when we've acting as backup router. If it is FALSE the `to' will
500 be the new source. */
502 void silc_server_update_clients_by_server(SilcServer server,
503 SilcServerEntry from,
505 SilcBool resolve_real_server)
508 SilcIDCacheEntry id_cache = NULL;
509 SilcClientEntry client = NULL;
512 if (from && from->id) {
513 SILC_LOG_DEBUG(("Changing from server %s",
514 silc_id_render(from->id, SILC_ID_SERVER)));
517 SILC_LOG_DEBUG(("Changing to server %s",
518 silc_id_render(to->id, SILC_ID_SERVER)));
521 SILC_LOG_DEBUG(("global list"));
523 if (silc_idcache_get_all(server->global_list->clients, &list)) {
524 silc_list_start(list);
525 while ((id_cache = silc_list_get(list))) {
526 client = (SilcClientEntry)id_cache->context;
528 /* If entry is disabled skip it. If entry is local to us, do not
529 switch it to anyone else, it is ours so skip it. */
530 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
531 SILC_IS_LOCAL(client))
534 SILC_LOG_DEBUG(("Client %s",
535 silc_id_render(client->id, SILC_ID_CLIENT)));
536 if (client->router && client->router->id)
537 SILC_LOG_DEBUG(("Client->router %s",
538 silc_id_render(client->router->id, SILC_ID_SERVER)));
541 if (client->router == from) {
542 if (resolve_real_server) {
544 silc_server_update_clients_by_real_server(server, from, to,
547 if (!client->router) {
548 if (server->server_type == SILC_ROUTER)
549 client->router = from;
558 /* All are changed */
559 if (resolve_real_server)
560 /* Call this so that the entry is moved to correct list if
561 needed. No resolving by real server is actually done. */
562 silc_server_update_clients_by_real_server(server, NULL, to,
569 if (client->router && client->router->id)
570 SILC_LOG_DEBUG(("Client changed to %s",
571 silc_id_render(client->router->id, SILC_ID_SERVER)));
575 SILC_LOG_DEBUG(("local list"));
577 if (silc_idcache_get_all(server->local_list->clients, &list)) {
578 silc_list_start(list);
579 while ((id_cache = silc_list_get(list))) {
580 client = (SilcClientEntry)id_cache->context;
582 /* If entry is disabled skip it. If entry is local to us, do not
583 switch it to anyone else, it is ours so skip it. */
584 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
585 SILC_IS_LOCAL(client))
588 SILC_LOG_DEBUG(("Client %s",
589 silc_id_render(client->id, SILC_ID_CLIENT)));
590 if (client->router && client->router->id)
591 SILC_LOG_DEBUG(("Client->router %s",
592 silc_id_render(client->router->id, SILC_ID_SERVER)));
595 if (client->router == from) {
596 if (resolve_real_server) {
598 silc_server_update_clients_by_real_server(server, from, to,
602 client->router = from;
608 /* All are changed */
609 if (resolve_real_server)
610 /* Call this so that the entry is moved to correct list if
611 needed. No resolving by real server is actually done. */
612 silc_server_update_clients_by_real_server(server, NULL, to,
619 if (client->router && client->router->id)
620 SILC_LOG_DEBUG(("Client changed to %s",
621 silc_id_render(client->router->id, SILC_ID_SERVER)));
626 /* Updates servers that are from `from' to be originated from `to'. This
627 will also update the server's connection to `to's connection. */
629 void silc_server_update_servers_by_server(SilcServer server,
630 SilcServerEntry from,
634 SilcIDCacheEntry id_cache = NULL;
635 SilcServerEntry server_entry = NULL;
637 SILC_LOG_DEBUG(("Updating servers"));
639 if (silc_idcache_get_all(server->local_list->servers, &list)) {
640 silc_list_start(list);
641 while ((id_cache = silc_list_get(list))) {
642 server_entry = (SilcServerEntry)id_cache->context;
644 /* If entry is local to us, do not switch it to any anyone else,
646 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
647 server_entry == from)
650 /* If we are standalone router, any server that is not directly
651 connected to cannot exist anymore. If we are not standalone
652 we update it correctly. */
653 if (server->server_type == SILC_ROUTER && server->standalone) {
654 silc_server_backup_del(server, server_entry);
655 silc_server_backup_replaced_del(server, server_entry);
656 silc_idlist_del_data(server_entry);
657 silc_idlist_del_server(server->local_list, server_entry);
658 server->stat.servers--;
659 server->stat.cell_servers--;
661 /* XXX if we are not standalone, do a check from local config
662 whether this server is in our cell, but not connected to
663 us (in which case we must remove it). */
666 if (server_entry->router == from) {
667 SILC_LOG_DEBUG(("Updating server (local) %s",
668 server_entry->server_name ?
669 server_entry->server_name : ""));
670 server_entry->router = to;
671 server_entry->connection = to->connection;
675 SILC_LOG_DEBUG(("Updating server (local) %s",
676 server_entry->server_name ?
677 server_entry->server_name : ""));
678 server_entry->router = to;
679 server_entry->connection = to->connection;
685 if (silc_idcache_get_all(server->global_list->servers, &list)) {
686 silc_list_start(list);
687 while ((id_cache = silc_list_get(list))) {
688 server_entry = (SilcServerEntry)id_cache->context;
690 /* If entry is local to us, do not switch it to anyone else,
692 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
693 server_entry == from)
696 /* If we are standalone router, any server that is not directly
697 connected to cannot exist anymore. If we are not standalone
698 we update it correctly. */
699 if (server->server_type == SILC_ROUTER && server->standalone) {
700 silc_server_backup_del(server, server_entry);
701 silc_server_backup_replaced_del(server, server_entry);
702 silc_idlist_del_data(server_entry);
703 silc_idlist_del_server(server->global_list, server_entry);
704 server->stat.servers--;
705 server->stat.cell_servers--;
707 /* XXX if we are not standalone, do a check from local config
708 whether this server is in our cell, but not connected to
709 us (in which case we must remove it). */
712 if (server_entry->router == from) {
713 SILC_LOG_DEBUG(("Updating server (global) %s",
714 server_entry->server_name ?
715 server_entry->server_name : ""));
716 server_entry->router = to;
717 server_entry->connection = to->connection;
721 SILC_LOG_DEBUG(("Updating server (global) %s",
722 server_entry->server_name ?
723 server_entry->server_name : ""));
724 server_entry->router = to;
725 server_entry->connection = to->connection;
733 /* Toggles the enabled/disabled status of local server connections. Packets
734 can be sent to the servers when `toggle_enabled' is TRUE and will be
735 dropped if `toggle_enabled' is FALSE, after this function is called. */
737 void silc_server_local_servers_toggle_enabled(SilcServer server,
738 SilcBool toggle_enabled)
741 SilcIDCacheEntry id_cache = NULL;
742 SilcServerEntry server_entry = NULL;
744 if (silc_idcache_get_all(server->local_list->servers, &list)) {
745 silc_list_start(list);
746 while ((id_cache = silc_list_get(list))) {
747 server_entry = (SilcServerEntry)id_cache->context;
748 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry)
752 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
754 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
759 if (silc_idcache_get_all(server->global_list->servers, &list)) {
760 silc_list_start(list);
761 while ((id_cache = silc_list_get(list))) {
762 server_entry = (SilcServerEntry)id_cache->context;
763 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry)
767 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
769 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
775 /* Removes servers that are originated from the `from'. The server
776 entry is deleted in this function. If `remove_clients' is TRUE then
777 all clients originated from the server are removed too, and server
778 signoff is sent. Note that this does not remove the `from'. This
779 also does not remove locally connected servers. */
781 void silc_server_remove_servers_by_server(SilcServer server,
782 SilcServerEntry from,
783 SilcBool remove_clients)
786 SilcIDCacheEntry id_cache = NULL;
787 SilcServerEntry server_entry = NULL;
789 SILC_LOG_DEBUG(("Removing servers by %s",
790 from->server_name ? from->server_name : "server"));
792 if (silc_idcache_get_all(server->local_list->servers, &list)) {
793 silc_list_start(list);
794 while ((id_cache = silc_list_get(list))) {
795 server_entry = (SilcServerEntry)id_cache->context;
796 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
797 server_entry->router != from || server_entry == from)
800 /* Remove clients owned by this server */
802 silc_server_remove_clients_by_server(server, from, server_entry,
805 /* Remove the server */
806 silc_server_backup_del(server, server_entry);
807 silc_idlist_del_server(server->local_list, server_entry);
811 if (silc_idcache_get_all(server->global_list->servers, &list)) {
812 silc_list_start(list);
813 while ((id_cache = silc_list_get(list))) {
814 server_entry = (SilcServerEntry)id_cache->context;
815 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
816 server_entry->router != from || server_entry == from)
819 /* Remove clients owned by this server */
821 silc_server_remove_clients_by_server(server, from, server_entry,
824 /* Remove the server */
825 silc_server_backup_del(server, server_entry);
826 silc_idlist_del_server(server->global_list, server_entry);
831 /* Removes channels that are from `from. */
833 void silc_server_remove_channels_by_server(SilcServer server,
834 SilcServerEntry from)
837 SilcIDCacheEntry id_cache = NULL;
838 SilcChannelEntry channel = NULL;
840 SILC_LOG_DEBUG(("Removing channels by server"));
842 if (silc_idcache_get_all(server->global_list->channels, &list)) {
843 silc_list_start(list);
844 while ((id_cache = silc_list_get(list))) {
845 channel = (SilcChannelEntry)id_cache->context;
846 if (channel->router == from)
847 silc_idlist_del_channel(server->global_list, channel);
852 /* Updates channels that are from `from' to be originated from `to'. */
854 void silc_server_update_channels_by_server(SilcServer server,
855 SilcServerEntry from,
859 SilcIDCacheEntry id_cache = NULL;
860 SilcChannelEntry channel = NULL;
862 SILC_LOG_DEBUG(("Updating channels by server"));
864 if (silc_idcache_get_all(server->global_list->channels, &list)) {
865 silc_list_start(list);
866 while ((id_cache = silc_list_get(list))) {
867 channel = (SilcChannelEntry)id_cache->context;
869 if (channel->router == from)
870 channel->router = to;
873 channel->router = to;
879 /* Checks whether given channel has global users. If it does this returns
880 TRUE and FALSE if there is only locally connected clients on the channel. */
882 SilcBool silc_server_channel_has_global(SilcChannelEntry channel)
884 SilcChannelClientEntry chl;
885 SilcHashTableList htl;
887 silc_hash_table_list(channel->user_list, &htl);
888 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
889 if (chl->client->router) {
890 silc_hash_table_list_reset(&htl);
894 silc_hash_table_list_reset(&htl);
899 /* Checks whether given channel has locally connected users. If it does this
900 returns TRUE and FALSE if there is not one locally connected client. */
902 SilcBool silc_server_channel_has_local(SilcChannelEntry channel)
904 SilcChannelClientEntry chl;
905 SilcHashTableList htl;
907 silc_hash_table_list(channel->user_list, &htl);
908 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
909 if (SILC_IS_LOCAL(chl->client)) {
910 silc_hash_table_list_reset(&htl);
914 silc_hash_table_list_reset(&htl);
919 /* This function removes the channel and all users on the channel, unless
920 the channel is permanent. In this case the channel is disabled but all
921 users are removed from the channel. Returns TRUE if the channel is
922 destroyed totally, and FALSE if it is permanent and remains. */
924 SilcBool silc_server_channel_delete(SilcServer server,
925 SilcChannelEntry channel)
927 SilcChannelClientEntry chl;
928 SilcHashTableList htl;
929 SilcBool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
931 SILC_LOG_DEBUG(("Deleting channel %s", channel->channel_name));
934 /* Update statistics */
935 if (server->server_type == SILC_ROUTER)
936 server->stat.chanclients -= channel->user_count;
938 /* Totally delete the channel and all users on the channel. The
939 users are deleted automatically in silc_idlist_del_channel. */
940 channel->disabled = TRUE;
941 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
942 if (silc_idlist_del_channel(server->local_list, channel)) {
943 server->stat.my_channels--;
944 if (server->server_type == SILC_ROUTER) {
945 server->stat.channels--;
946 server->stat.cell_channels--;
949 if (silc_idlist_del_channel(server->global_list, channel))
950 if (server->server_type == SILC_ROUTER)
951 server->stat.channels--;
957 /* Channel is permanent, do not remove it, remove only users */
958 channel->disabled = TRUE;
959 silc_hash_table_list(channel->user_list, &htl);
960 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
961 silc_hash_table_del(chl->client->channels, channel);
962 silc_hash_table_del(channel->user_list, chl->client);
963 channel->user_count--;
965 /* Update statistics */
966 if (SILC_IS_LOCAL(chl->client))
967 server->stat.my_chanclients--;
968 if (server->server_type == SILC_ROUTER) {
969 server->stat.cell_chanclients--;
970 server->stat.chanclients--;
975 silc_hash_table_list_reset(&htl);
977 SILC_LOG_DEBUG(("Channel %s remains (permanent)", channel->channel_name));
982 /* Returns TRUE if the given client is on the channel. FALSE if not.
983 This works because we assure that the user list on the channel is
984 always in up to date thus we can only check the channel list from
985 `client' which is faster than checking the user list from `channel'. */
987 SilcBool silc_server_client_on_channel(SilcClientEntry client,
988 SilcChannelEntry channel,
989 SilcChannelClientEntry *chl)
991 if (!client || !channel)
994 return silc_hash_table_find(client->channels, channel, NULL,
998 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
999 socket connections with the IP address does not exist. Counts only
1000 fully established connections. */
1002 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1003 SilcConnectionType type)
1005 SilcServerConnection conn;
1006 SilcIDListData idata;
1010 silc_dlist_start(server->conns);
1011 while ((conn = silc_dlist_get(server->conns))) {
1014 silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->sock),
1015 NULL, NULL, &ipaddr, NULL);
1016 idata = silc_packet_get_context(conn->sock);
1017 if (!strcmp(ipaddr, ip) && idata && idata->conn_type == type)
1024 /* Find active socket connection by the IP address and port indicated by
1025 `ip' and `port', and socket connection type of `type'. */
1028 silc_server_find_socket_by_host(SilcServer server,
1029 SilcConnectionType type,
1030 const char *ip, SilcUInt16 port)
1032 SilcServerConnection conn;
1033 SilcIDListData idata;
1036 silc_dlist_start(server->conns);
1037 while ((conn = silc_dlist_get(server->conns))) {
1040 idata = silc_packet_get_context(conn->sock);
1041 silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->sock),
1042 NULL, NULL, &ipaddr, NULL);
1043 if (!strcmp(ipaddr, ip) &&
1044 (!port || conn->remote_port == port) &&
1045 idata->conn_type == type)
1052 /* Find number of sockets by IP address indicated by remote host, indicatd
1053 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1054 does not exist. If `ip' is provided then `hostname' is ignored. */
1056 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1058 const char *hostname,
1060 SilcConnectionType type)
1062 SilcServerConnection conn;
1063 SilcIDListData idata;
1064 SilcConnectionType t = SILC_CONN_UNKNOWN;
1067 if (!ip && !hostname)
1070 silc_dlist_start(server->conns);
1071 while ((conn = silc_dlist_get(server->conns))) {
1073 idata = silc_packet_get_context(conn->sock);
1075 t = idata->conn_type;
1077 if (((ip && !strcmp(conn->remote_host, ip)) ||
1078 (hostname && !strcmp(conn->remote_host, hostname))) &&
1079 conn->remote_port == port && t == type)
1086 /* SKR find callbcak */
1088 static void find_callback(SilcSKR skr, SilcSKRFind find,
1089 SilcSKRStatus status, SilcDList keys,
1092 SilcPublicKey *public_key = context;
1096 silc_dlist_start(keys);
1097 key = silc_dlist_get(keys);
1098 *public_key = key->key;
1099 silc_dlist_uninit(keys);
1102 silc_skr_find_free(find);
1105 /* Get public key by key usage and key context. */
1107 SilcPublicKey silc_server_get_public_key(SilcServer server,
1108 SilcSKRKeyUsage usage,
1112 SilcPublicKey public_key = NULL;
1114 SILC_LOG_DEBUG(("Start"));
1116 find = silc_skr_find_alloc();
1120 silc_skr_find_set_usage(find, usage);
1121 silc_skr_find_set_context(find, key_context);
1122 silc_skr_find(server->repository, server->schedule,
1123 find, find_callback, &public_key);
1128 /* Find public key by client for identification purposes. Finds keys
1129 with SILC_SKR_USAGE_IDENTIFICATION. */
1131 SilcBool silc_server_get_public_key_by_client(SilcServer server,
1132 SilcClientEntry client,
1133 SilcPublicKey *public_key)
1135 SilcPublicKey pubkey = NULL;
1136 SilcBool ret = FALSE;
1138 pubkey = silc_server_get_public_key(server, SILC_SKR_USAGE_IDENTIFICATION,
1144 *public_key = pubkey;
1149 /* Check whether the connection `sock' is allowed to connect to us. This
1150 checks for example whether there is too much connections for this host,
1151 and required version for the host etc. */
1153 SilcBool silc_server_connection_allowed(SilcServer server,
1154 SilcPacketStream sock,
1155 SilcConnectionType type,
1156 SilcServerConfigConnParams *global,
1157 SilcServerConfigConnParams *params,
1160 SilcUInt32 conn_number = (type == SILC_CONN_CLIENT ?
1161 server->stat.my_clients :
1162 type == SILC_CONN_SERVER ?
1163 server->stat.my_servers :
1164 server->stat.my_routers);
1165 SilcUInt32 num_sockets, max_hosts, max_per_host;
1166 SilcUInt32 r_protocol_version, l_protocol_version;
1167 SilcUInt32 r_software_version, l_software_version;
1168 char *r_vendor_version = NULL, *l_vendor_version;
1169 const char *hostname, *ip;
1171 silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
1172 NULL, &hostname, &ip, NULL);
1174 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1178 l_protocol_version =
1179 silc_version_to_num(params && params->version_protocol ?
1180 params->version_protocol :
1181 global->version_protocol);
1182 l_software_version =
1183 silc_version_to_num(params && params->version_software ?
1184 params->version_software :
1185 global->version_software);
1186 l_vendor_version = (params && params->version_software_vendor ?
1187 params->version_software_vendor :
1188 global->version_software_vendor);
1190 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1191 &r_software_version, NULL,
1192 &r_vendor_version)) {
1193 /* Match protocol version */
1194 if (l_protocol_version && r_protocol_version &&
1195 r_protocol_version < l_protocol_version) {
1196 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1198 silc_server_disconnect_remote(server, sock,
1199 SILC_STATUS_ERR_BAD_VERSION,
1200 "You support too old protocol version");
1204 /* Math software version */
1205 if (l_software_version && r_software_version &&
1206 r_software_version < l_software_version) {
1207 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1209 silc_server_disconnect_remote(server, sock,
1210 SILC_STATUS_ERR_BAD_VERSION,
1211 "You support too old software version");
1215 /* Regex match vendor version */
1216 if (l_vendor_version && r_vendor_version &&
1217 !silc_string_match(l_vendor_version, r_vendor_version)) {
1218 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1220 silc_server_disconnect_remote(server, sock,
1221 SILC_STATUS_ERR_BAD_VERSION,
1222 "Your software is not supported");
1226 silc_free(r_vendor_version);
1228 /* Check for maximum connections limit */
1230 num_sockets = silc_server_num_sockets_by_ip(server, ip, type);
1231 max_hosts = (params ? params->connections_max : global->connections_max);
1232 max_per_host = (params ? params->connections_max_per_host :
1233 global->connections_max_per_host);
1235 if (max_hosts && conn_number >= max_hosts) {
1236 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1238 silc_server_disconnect_remote(server, sock,
1239 SILC_STATUS_ERR_RESOURCE_LIMIT,
1240 "Server is full, try again later");
1244 if (num_sockets >= max_per_host) {
1245 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1247 silc_server_disconnect_remote(server, sock,
1248 SILC_STATUS_ERR_RESOURCE_LIMIT,
1249 "Too many connections from your host");
1256 /* Checks that client has rights to add or remove channel modes. If any
1257 of the checks fails FALSE is returned. */
1259 SilcBool silc_server_check_cmode_rights(SilcServer server,
1260 SilcChannelEntry channel,
1261 SilcChannelClientEntry client,
1264 SilcBool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1265 SilcBool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1267 /* Check whether has rights to change anything */
1268 if (!is_op && !is_fo)
1271 /* Check whether has rights to change everything */
1275 /* Founder implies operator */
1279 /* We know that client is channel operator, check that they are not
1280 changing anything that requires channel founder rights. Rest of the
1281 modes are available automatically for channel operator. */
1283 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1284 if (is_op && !is_fo)
1287 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1288 if (is_op && !is_fo)
1293 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1294 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1295 if (is_op && !is_fo)
1299 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1300 if (is_op && !is_fo)
1305 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1306 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1307 if (is_op && !is_fo)
1311 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1312 if (is_op && !is_fo)
1317 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1318 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1319 if (is_op && !is_fo)
1323 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1324 if (is_op && !is_fo)
1329 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1330 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1331 if (is_op && !is_fo)
1335 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1336 if (is_op && !is_fo)
1341 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1342 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1343 if (is_op && !is_fo)
1347 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1348 if (is_op && !is_fo)
1353 if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1354 if (!(channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)) {
1355 if (is_op && !is_fo)
1359 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1360 if (is_op && !is_fo)
1368 /* Check that the client has rights to change its user mode. Returns
1369 FALSE if setting some mode is not allowed. */
1371 SilcBool silc_server_check_umode_rights(SilcServer server,
1372 SilcClientEntry client,
1375 SilcBool server_op = FALSE, router_op = FALSE;
1377 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1378 /* Cannot set server operator mode (must use OPER command) */
1379 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1382 /* Remove the server operator rights */
1383 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1387 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1388 /* Cannot set router operator mode (must use SILCOPER command) */
1389 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1392 /* Remove the router operator rights */
1393 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1398 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1400 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1405 /* This function is used to send the notify packets and motd to the
1406 incoming client connection. */
1408 void silc_server_send_connect_notifys(SilcServer server,
1409 SilcPacketStream sock,
1410 SilcClientEntry client)
1414 SILC_LOG_DEBUG(("Send welcome notifys"));
1416 /* Send some nice info to the client */
1417 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1418 ("Welcome to the SILC Network %s",
1420 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1421 ("Your host is %s, running version %s",
1422 server->server_name, server_version));
1424 if (server->server_type == SILC_ROUTER) {
1425 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1426 ("There are %d clients, %d servers and %d "
1427 "routers in SILC Network",
1428 server->stat.clients, server->stat.servers,
1429 server->stat.routers));
1431 if (server->stat.clients && server->stat.servers + 1)
1432 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1433 ("There are %d clients, %d servers and %d "
1434 "routers in SILC Network",
1435 server->stat.clients, server->stat.servers,
1436 (server->standalone ? 0 :
1437 !server->stat.routers ? 1 :
1438 server->stat.routers)));
1441 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1442 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1443 ("There are %d clients on %d servers in our cell",
1444 server->stat.cell_clients,
1445 server->stat.cell_servers));
1446 if (server->server_type == SILC_ROUTER) {
1447 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1448 ("I have %d clients, %d channels, %d servers and "
1450 server->stat.my_clients,
1451 server->stat.my_channels,
1452 server->stat.my_servers,
1453 server->stat.my_routers));
1455 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1456 ("I have %d clients and %d channels formed",
1457 server->stat.my_clients,
1458 server->stat.my_channels));
1461 if (server->stat.server_ops || server->stat.router_ops)
1462 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1463 ("There are %d server operators and %d router "
1465 server->stat.server_ops,
1466 server->stat.router_ops));
1467 if (server->stat.my_router_ops + server->stat.my_server_ops)
1468 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1469 ("I have %d operators online",
1470 server->stat.my_router_ops +
1471 server->stat.my_server_ops));
1473 silc_packet_get_keys(sock, &key, NULL, NULL, NULL);
1474 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1475 ("Your connection is secured with %s cipher, "
1476 "key length %d bits",
1477 silc_cipher_get_name(key),
1478 silc_cipher_get_key_len(key)));
1479 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1480 ("Your current nickname is %s",
1484 silc_server_send_motd(server, sock);
1487 /* Kill the client indicated by `remote_client' sending KILLED notify
1488 to the client, to all channels client has joined and to primary
1489 router if needed. The killed client is also removed from all channels. */
1491 void silc_server_kill_client(SilcServer server,
1492 SilcClientEntry remote_client,
1493 const char *comment,
1495 SilcIdType killer_id_type)
1497 SilcBuffer killed, killer;
1499 SILC_LOG_DEBUG(("Killing client %s",
1500 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1502 /* Send the KILL notify packets. First send it to the channel, then
1503 to our primary router and then directly to the client who is being
1504 killed right now. */
1506 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1507 killer = silc_id_payload_encode(killer_id, killer_id_type);
1509 /* Send KILLED notify to the channels. It is not sent to the client
1510 as it will be sent differently destined directly to the client and not
1512 silc_server_send_notify_on_channels(server, remote_client,
1513 remote_client, SILC_NOTIFY_TYPE_KILLED,
1514 3, killed->data, silc_buffer_len(killed),
1515 comment, comment ? strlen(comment) : 0,
1516 killer->data, silc_buffer_len(killer));
1518 /* Send KILLED notify to primary route */
1519 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1520 SILC_BROADCAST(server), remote_client->id,
1521 comment, killer_id, killer_id_type);
1523 /* Send KILLED notify to the client directly */
1524 if (remote_client->connection || remote_client->router)
1525 silc_server_send_notify_killed(server, remote_client->connection ?
1526 remote_client->connection :
1527 remote_client->router->connection, FALSE,
1528 remote_client->id, comment,
1529 killer_id, killer_id_type);
1531 /* Remove the client from all channels. This generates new keys to the
1532 channels as well. */
1533 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1536 /* Remove the client entry, If it is locally connected then we will also
1537 disconnect the client here */
1538 if (remote_client->connection) {
1539 /* Remove locally conneted client */
1540 SilcPacketStream sock = remote_client->connection;
1541 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1542 silc_server_close_connection(server, sock);
1544 /* Update statistics */
1545 server->stat.clients--;
1546 if (server->stat.cell_clients)
1547 server->stat.cell_clients--;
1548 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1549 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1551 /* Remove client's public key from repository, this will free it too. */
1552 if (remote_client->data.public_key) {
1553 silc_skr_del_public_key(server->repository,
1554 remote_client->data.public_key, remote_client);
1555 remote_client->data.public_key = NULL;
1558 if (SILC_IS_LOCAL(remote_client)) {
1559 server->stat.my_clients--;
1560 silc_schedule_task_del_by_context(server->schedule, remote_client);
1563 /* Remove remote client */
1564 silc_idlist_del_data(remote_client);
1565 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1566 /* Remove this client from watcher list if it is */
1567 silc_server_del_from_watcher_list(server, remote_client);
1568 silc_idlist_del_client(server->local_list, remote_client);
1572 silc_buffer_free(killer);
1573 silc_buffer_free(killed);
1578 SilcClientEntry client;
1579 SilcNotifyType notify;
1580 const char *new_nick;
1581 } WatcherNotifyContext;
1584 silc_server_check_watcher_list_foreach(void *key, void *context,
1587 WatcherNotifyContext *notify = user_context;
1588 SilcClientEntry entry = context;
1589 SilcPacketStream sock;
1594 if (entry == notify->client)
1597 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1600 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1601 silc_id_render(entry->id, SILC_ID_CLIENT)));
1603 /* Send the WATCH notify */
1604 silc_server_send_notify_watch(notify->server, sock, entry,
1606 notify->new_nick ? notify->new_nick :
1607 (const char *)notify->client->nickname,
1609 notify->client->data.public_key);
1613 /* This function checks whether the `client' nickname and/or 'client'
1614 public key is being watched by someone, and notifies the watcher of the
1615 notify change of notify type indicated by `notify'. */
1617 SilcBool silc_server_check_watcher_list(SilcServer server,
1618 SilcClientEntry client,
1619 const char *new_nick,
1620 SilcNotifyType notify)
1622 unsigned char hash[16];
1623 WatcherNotifyContext n;
1625 SILC_LOG_DEBUG(("Checking watcher list %s",
1626 client->nickname ? client->nickname : (unsigned char *)""));
1628 /* If the watching is rejected by the client do nothing */
1629 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1632 /* Make hash from the nick, or take it from Client ID */
1633 if (client->nickname) {
1634 unsigned char *nickc;
1635 nickc = silc_identifier_check(client->nickname, strlen(client->nickname),
1636 SILC_STRING_UTF8, 128, NULL);
1639 silc_hash_make(server->md5hash, nickc, strlen(nickc), hash);
1642 memset(hash, 0, sizeof(hash));
1643 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1648 n.new_nick = new_nick;
1651 /* Send notify to all watchers watching this nickname */
1652 silc_hash_table_find_foreach(server->watcher_list, hash,
1653 silc_server_check_watcher_list_foreach, &n);
1655 /* Send notify to all watchers watching this public key */
1656 if (client->data.public_key)
1657 silc_hash_table_find_foreach(server->watcher_list_pk,
1658 client->data.public_key,
1659 silc_server_check_watcher_list_foreach,
1665 /* Remove the `client' from watcher list. After calling this the `client'
1666 is not watching any nicknames. */
1668 SilcBool silc_server_del_from_watcher_list(SilcServer server,
1669 SilcClientEntry client)
1671 SilcHashTableList htl;
1673 SilcClientEntry entry;
1674 SilcBool found = FALSE;
1676 silc_hash_table_list(server->watcher_list, &htl);
1677 while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1678 if (entry == client) {
1679 silc_hash_table_del_by_context(server->watcher_list, key, client);
1682 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1683 silc_id_render(client->id, SILC_ID_CLIENT)));
1685 /* Now check whether there still exists entries with this key, if not
1686 then free the key to not leak memory. */
1687 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1693 silc_hash_table_list_reset(&htl);
1695 silc_hash_table_list(server->watcher_list_pk, &htl);
1696 while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1697 if (entry == client) {
1698 silc_hash_table_del_by_context(server->watcher_list_pk, key, client);
1701 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1702 silc_id_render(client->id, SILC_ID_CLIENT)));
1704 /* Now check whether there still exists entries with this key, if not
1705 then free the key to not leak memory. */
1706 if (!silc_hash_table_find(server->watcher_list_pk, key, NULL, NULL))
1707 silc_pkcs_public_key_free(key);
1712 silc_hash_table_list_reset(&htl);
1717 /* Force the client indicated by `chl' to change the channel user mode
1718 on channel indicated by `channel' to `forced_mode'. */
1720 SilcBool silc_server_force_cumode_change(SilcServer server,
1721 SilcPacketStream sock,
1722 SilcChannelEntry channel,
1723 SilcChannelClientEntry chl,
1724 SilcUInt32 forced_mode)
1726 SilcBuffer idp1, idp2;
1727 unsigned char cumode[4];
1729 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1732 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1733 server->id, SILC_ID_SERVER,
1734 chl->client->id, NULL);
1736 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1737 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1738 SILC_PUT32_MSB(forced_mode, cumode);
1739 silc_server_send_notify_to_channel(server, sock, channel, FALSE, TRUE,
1740 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1741 3, idp1->data, silc_buffer_len(idp1),
1742 cumode, sizeof(cumode),
1743 idp2->data, silc_buffer_len(idp2));
1744 silc_buffer_free(idp1);
1745 silc_buffer_free(idp2);
1750 /* This function can be used to match the invite and ban lists. */
1752 SilcBool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1753 SilcUInt8 type, void *check)
1755 unsigned char *tmp = NULL;
1756 SilcUInt32 len = 0, t;
1757 SilcHashTableList htl;
1758 SilcBuffer entry, idp = NULL, pkp = NULL;
1759 SilcBool ret = FALSE;
1761 SILC_LOG_DEBUG(("Matching invite/ban"));
1763 if (type < 1 || type > 3 || !check)
1767 tmp = strdup((char *)check);
1772 pkp = silc_public_key_payload_encode(check);
1776 len = silc_buffer_len(pkp);
1779 idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
1783 len = silc_buffer_len(idp);
1786 /* Compare the list */
1787 silc_hash_table_list(list, &htl);
1788 while (silc_hash_table_get(&htl, (void *)&t, (void *)&entry)) {
1791 if (silc_string_match(entry->data, tmp)) {
1795 } else if (!memcmp(entry->data, tmp, len)) {
1801 silc_hash_table_list_reset(&htl);
1805 silc_buffer_free(idp);
1806 silc_buffer_free(pkp);
1810 /* Process invite or ban information */
1812 SilcBool silc_server_inviteban_process(SilcServer server,
1815 SilcArgumentPayload args)
1818 SilcUInt32 type, len;
1820 SilcHashTableList htl;
1822 SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1823 action == 0x01 ? "DEL" : "ADD"));
1825 /* Add the information to invite list */
1826 if (action == 0x00 || action == 0x03) {
1827 /* Traverse all arguments and add to the hash table according to
1829 tmp = silc_argument_get_first_arg(args, &type, &len);
1832 /* Check validity of the string. Actually we should parse the
1833 whole string and verify all components individually. */
1834 if (!silc_utf8_valid(tmp, len) || !len) {
1835 tmp = silc_argument_get_next_arg(args, &type, &len);
1838 if (strchr(tmp, ',')) {
1839 tmp = silc_argument_get_next_arg(args, &type, &len);
1843 /* Check if the string is added already */
1844 silc_hash_table_list(list, &htl);
1845 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1846 if (type == 1 && silc_string_match(tmp2->data, tmp)) {
1851 silc_hash_table_list_reset(&htl);
1854 /* Add the string to hash table */
1855 tmp2 = silc_buffer_alloc_size(len + 1);
1856 if (tmp[len - 1] == ',')
1857 tmp[len - 1] = '\0';
1858 silc_buffer_put(tmp2, tmp, len);
1859 silc_hash_table_add(list, (void *)1, tmp2);
1862 } else if (type == 2) {
1863 /* Public key. Check first if the public key is already on the
1864 list and ignore it if it is, otherwise, add it to hash table. */
1867 /* Verify validity of the public key */
1868 if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1869 tmp = silc_argument_get_next_arg(args, &type, &len);
1872 silc_pkcs_public_key_free(pk);
1874 /* Check if the public key is in the list already */
1875 silc_hash_table_list(list, &htl);
1876 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1877 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1882 silc_hash_table_list_reset(&htl);
1884 /* Add new public key to invite list */
1886 tmp2 = silc_buffer_alloc_size(len);
1887 silc_buffer_put(tmp2, tmp, len);
1888 silc_hash_table_add(list, (void *)2, tmp2);
1891 } else if (type == 3) {
1894 /* Check if the ID is in the list already */
1895 silc_hash_table_list(list, &htl);
1896 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1897 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1902 silc_hash_table_list_reset(&htl);
1904 /* Add new Client ID to invite list */
1906 tmp2 = silc_buffer_alloc_size(len);
1907 silc_buffer_put(tmp2, tmp, len);
1908 silc_hash_table_add(list, (void *)3, tmp2);
1912 tmp = silc_argument_get_next_arg(args, &type, &len);
1916 /* Delete information to invite list */
1917 if (action == 0x01 && list) {
1918 /* Now delete the arguments from invite list */
1919 tmp = silc_argument_get_first_arg(args, &type, &len);
1922 /* Check validity of the string. Actually we should parse the
1923 whole string and verify all components individually. */
1924 if (!silc_utf8_valid(tmp, len)) {
1925 tmp = silc_argument_get_next_arg(args, &type, &len);
1928 if (strchr(tmp, ',')) {
1929 tmp = silc_argument_get_next_arg(args, &type, &len);
1933 /* Delete from the list */
1934 silc_hash_table_list(list, &htl);
1935 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1936 if (type == 1 && silc_string_match(tmp2->data, tmp)) {
1937 silc_hash_table_del_by_context(list, (void *)1, tmp2);
1941 silc_hash_table_list_reset(&htl);
1943 } else if (type == 2) {
1947 /* Verify validity of the public key */
1948 if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1949 tmp = silc_argument_get_next_arg(args, &type, &len);
1952 silc_pkcs_public_key_free(pk);
1954 /* Delete from the invite list */
1955 silc_hash_table_list(list, &htl);
1956 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1957 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1958 silc_hash_table_del_by_context(list, (void *)2, tmp2);
1962 silc_hash_table_list_reset(&htl);
1964 } else if (type == 3) {
1967 /* Delete from the invite list */
1968 silc_hash_table_list(list, &htl);
1969 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1970 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1971 silc_hash_table_del_by_context(list, (void *)3, tmp2);
1975 silc_hash_table_list_reset(&htl);
1978 tmp = silc_argument_get_next_arg(args, &type, &len);
1985 /* Destructor for invite and ban list entrys */
1987 void silc_server_inviteban_destruct(void *key, void *context,
1990 silc_buffer_free(context);
1993 /* Creates connections accoring to configuration. */
1995 void silc_server_create_connections(SilcServer server)
1997 silc_schedule_task_del_by_callback(server->schedule,
1998 silc_server_connect_to_router);
1999 silc_schedule_task_add_timeout(server->schedule,
2000 silc_server_connect_to_router, server, 0, 1);
2004 silc_server_process_channel_pk_destruct(void *key, void *context,
2008 silc_pkcs_public_key_free(context);
2011 /* Processes a channel public key, either adds or removes it. */
2014 silc_server_process_channel_pk(SilcServer server,
2015 SilcChannelEntry channel,
2016 SilcUInt32 type, const unsigned char *pk,
2019 unsigned char pkhash[20];
2022 SILC_LOG_DEBUG(("Processing channel public key"));
2025 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2027 /* Decode the public key */
2028 if (!silc_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
2029 return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
2031 /* Create channel public key list (hash table) if needed */
2032 if (!channel->channel_pubkeys) {
2033 channel->channel_pubkeys =
2034 silc_hash_table_alloc(0, silc_hash_data, (void *)20,
2035 silc_hash_data_compare, (void *)20,
2036 silc_server_process_channel_pk_destruct, channel,
2040 /* Create SHA-1 digest of the public key data */
2041 silc_hash_make(server->sha1hash, pk + 4, pk_len - 4, pkhash);
2044 /* Add new public key to channel public key list */
2045 SILC_LOG_DEBUG(("Add new channel public key to channel %s",
2046 channel->channel_name));
2048 /* Check for resource limit */
2049 if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
2050 silc_pkcs_public_key_free(chpk);
2051 return SILC_STATUS_ERR_RESOURCE_LIMIT;
2054 /* Add if doesn't exist already */
2055 if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2057 silc_hash_table_add(channel->channel_pubkeys, silc_memdup(pkhash, 20),
2059 } else if (type == 0x01) {
2060 /* Delete public key from channel public key list */
2061 SILC_LOG_DEBUG(("Delete a channel public key from channel %s",
2062 channel->channel_name));
2063 if (!silc_hash_table_del(channel->channel_pubkeys, pkhash))
2064 silc_pkcs_public_key_free(chpk);
2066 silc_pkcs_public_key_free(chpk);
2067 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2070 return SILC_STATUS_OK;
2073 /* Returns the channel public keys as Argument List payload. */
2075 SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
2076 SilcChannelEntry channel,
2080 SilcHashTableList htl;
2081 SilcBuffer list, pkp;
2084 SILC_LOG_DEBUG(("Encoding channel public keys list"));
2086 if (!channel->channel_pubkeys ||
2087 !silc_hash_table_count(channel->channel_pubkeys))
2090 /* Encode the list */
2091 list = silc_buffer_alloc_size(2);
2092 silc_buffer_format(list,
2093 SILC_STR_UI_SHORT(silc_hash_table_count(
2094 channel->channel_pubkeys)),
2097 silc_hash_table_list(channel->channel_pubkeys, &htl);
2098 while (silc_hash_table_get(&htl, NULL, (void *)&pk)) {
2099 pkp = silc_public_key_payload_encode(pk);
2100 list = silc_argument_payload_encode_one(list, pkp->data,
2101 silc_buffer_len(pkp),
2103 delete ? 0x01 : 0x00);
2104 silc_buffer_free(pkp);
2106 silc_hash_table_list_reset(&htl);
2111 /* Sets the channel public keys into channel from the list of public keys. */
2113 SilcStatus silc_server_set_channel_pk_list(SilcServer server,
2114 SilcPacketStream sender,
2115 SilcChannelEntry channel,
2116 const unsigned char *pklist,
2117 SilcUInt32 pklist_len)
2120 SilcArgumentPayload args;
2121 unsigned char *chpk;
2122 SilcUInt32 chpklen, type;
2123 SilcStatus ret = SILC_STATUS_OK;
2125 SILC_LOG_DEBUG(("Setting channel public keys list"));
2127 if (!pklist || pklist_len < 2)
2128 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2130 /* Get the argument from the Argument List Payload */
2131 SILC_GET16_MSB(argc, pklist);
2132 args = silc_argument_payload_parse(pklist + 2, pklist_len - 2, argc);
2134 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2136 /* Process the public keys one by one */
2137 chpk = silc_argument_get_first_arg(args, &type, &chpklen);
2139 /* If announcing keys and we have them set already, do not allow this */
2140 if (chpk && type == 0x03 && channel->channel_pubkeys &&
2141 server->server_type == SILC_ROUTER &&
2142 sender != SILC_PRIMARY_ROUTE(server)) {
2143 SILC_LOG_DEBUG(("Channel public key list set already, enforce our list"));
2144 silc_argument_payload_free(args);
2145 return SILC_STATUS_ERR_OPERATION_ALLOWED;
2148 /* If we are normal server and receive announcement list and we already
2149 have keys set, we replace the old list with the announced one. */
2150 if (chpk && type == 0x03 && channel->channel_pubkeys &&
2151 server->server_type != SILC_ROUTER) {
2153 unsigned char mask[4], ulimit[4];
2155 SILC_LOG_DEBUG(("Router enforces its list, remove old list"));
2156 silc_hash_table_free(channel->channel_pubkeys);
2157 channel->channel_pubkeys = NULL;
2159 /* Send notify that removes the old list */
2160 sidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2161 SILC_PUT32_MSB((channel->mode & (~SILC_CHANNEL_MODE_CHANNEL_AUTH)), mask);
2162 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2163 SILC_PUT32_MSB(channel->user_limit, ulimit);
2164 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2165 SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
2166 sidp->data, silc_buffer_len(sidp),
2170 strlen(channel->cipher) : 0,
2172 channel->hmac_name ?
2173 strlen(channel->hmac_name) : 0,
2174 channel->passphrase,
2175 channel->passphrase ?
2176 strlen(channel->passphrase) : 0,
2179 SILC_CHANNEL_MODE_ULIMIT ?
2182 SILC_CHANNEL_MODE_ULIMIT ?
2183 sizeof(ulimit) : 0));
2184 silc_buffer_free(sidp);
2190 ret = silc_server_process_channel_pk(server, channel, type,
2192 if (ret != SILC_STATUS_OK)
2194 chpk = silc_argument_get_next_arg(args, &type, &chpklen);
2197 silc_argument_payload_free(args);
2201 /* Verifies the Authentication Payload `auth' with one of the public keys
2202 on the `channel' public key list. */
2204 SilcBool silc_server_verify_channel_auth(SilcServer server,
2205 SilcChannelEntry channel,
2206 SilcClientID *client_id,
2207 const unsigned char *auth,
2208 SilcUInt32 auth_len)
2212 unsigned char *pkhash;
2213 SilcUInt32 pkhash_len;
2214 SilcBool ret = FALSE;
2216 SILC_LOG_DEBUG(("Verifying channel authentication"));
2218 if (!auth || !auth_len || !channel->channel_pubkeys)
2221 /* Get the hash from the auth data which tells us what public key we
2222 must use in verification. */
2224 ap = silc_auth_payload_parse(auth, auth_len);
2228 pkhash = silc_auth_get_public_data(ap, &pkhash_len);
2229 if (pkhash_len < 128)
2232 /* Find the public key with the hash */
2233 if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2234 NULL, (void *)&chpk)) {
2235 SILC_LOG_DEBUG(("Public key not found in channel public key list"));
2239 /* Verify the signature */
2240 if (!silc_auth_verify(ap, SILC_AUTH_PUBLIC_KEY, (void *)chpk, 0,
2241 server->sha1hash, client_id, SILC_ID_CLIENT)) {
2242 SILC_LOG_DEBUG(("Authentication failed"));
2249 silc_auth_payload_free(ap);