5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2008 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);
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;
173 silc_buffer_free(idp);
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;
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))) {
190 if (server_signoff) {
191 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
193 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
194 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
196 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
198 argv[argc] = silc_calloc(silc_buffer_len(idp), sizeof(*argv[0]));
199 memcpy(argv[argc], idp->data, silc_buffer_len(idp));
200 argv_lens[argc] = silc_buffer_len(idp);
201 argv_types[argc] = argc + 1;
203 silc_buffer_free(idp);
207 /* Update statistics */
208 server->stat.clients--;
209 if (server->stat.cell_clients)
210 server->stat.cell_clients--;
211 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
212 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
214 /* Remove client's public key from repository, this will free it too. */
215 if (client->data.public_key) {
216 silc_skr_del_public_key(server->repository, client->data.public_key,
218 client->data.public_key = NULL;
221 silc_server_remove_clients_channels(server, entry, clients,
223 silc_server_del_from_watcher_list(server, client);
225 /* Remove the client entry */
226 if (!server_signoff) {
227 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
229 client->router = NULL;
230 client->connection = NULL;
231 client->data.created = silc_time();
232 silc_dlist_del(server->expired_clients, client);
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 client->data.created = silc_time();
295 silc_dlist_del(server->expired_clients, client);
296 silc_dlist_add(server->expired_clients, client);
298 silc_idlist_del_data(client);
299 silc_idlist_del_client(server->global_list, client);
304 /* Return now if we are shutting down */
305 if (server->server_shutdown) {
306 silc_hash_table_free(channels);
308 if (server_signoff) {
309 for (i = 0; i < argc; i++)
312 silc_free(argv_lens);
313 silc_free(argv_types);
314 silc_hash_table_free(clients);
319 /* Send the SERVER_SIGNOFF notify */
320 if (server_signoff) {
321 SilcBuffer args, not;
323 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
324 silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
326 /* Send SERVER_SIGNOFF notify to our primary router */
327 if (server->router != entry) {
328 args = silc_argument_payload_encode(1, argv, argv_lens,
330 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
331 SILC_BROADCAST(server),
332 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
334 silc_buffer_free(args);
337 /* Send to local clients. We also send the list of client ID's that
338 is to be removed for those servers that would like to use that list. */
339 args = silc_argument_payload_encode(argc, argv, argv_lens,
341 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
343 silc_server_packet_send_clients(server, clients,
344 SILC_PACKET_NOTIFY, 0, FALSE,
345 not->data, silc_buffer_len(not));
347 /* Send notify also to local backup routers */
348 silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
349 not->data, silc_buffer_len(not), FALSE, TRUE);
351 silc_buffer_free(args);
352 silc_buffer_free(not);
353 for (i = 0; i < argc; i++)
356 silc_free(argv_lens);
357 silc_free(argv_types);
358 silc_hash_table_free(clients);
361 /* We must now re-generate the channel key for all channels that had
362 this server's client(s) on the channel. As they left the channel we
363 must re-generate the channel key. */
364 silc_hash_table_list(channels, &htl);
365 while (silc_hash_table_get(&htl, NULL, (void *)&channel)) {
366 if (!silc_server_create_channel_key(server, channel, 0)) {
367 silc_hash_table_list_reset(&htl);
368 silc_hash_table_free(channels);
372 /* Do not send the channel key if private channel key mode is set */
373 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->send_key)
376 silc_server_send_channel_key(server, NULL, channel,
377 server->server_type == SILC_ROUTER ?
378 FALSE : !server->standalone);
380 silc_hash_table_list_reset(&htl);
381 silc_hash_table_free(channels);
386 static SilcServerEntry
387 silc_server_update_clients_by_real_server(SilcServer server,
388 SilcServerEntry from,
390 SilcClientEntry client,
392 SilcIDCacheEntry client_cache)
394 SilcServerEntry server_entry;
395 SilcIDCacheEntry id_cache = NULL;
397 SilcBool tolocal = (to == server->id_entry);
399 SILC_LOG_DEBUG(("Start"));
401 if (!silc_idcache_get_all(server->local_list->servers, &list))
404 silc_list_start(list);
405 while ((id_cache = silc_list_get(list))) {
406 server_entry = (SilcServerEntry)id_cache->context;
407 if (server_entry != from &&
408 (tolocal || server_entry != server->id_entry) &&
409 SILC_ID_COMPARE(server_entry->id, client->id,
410 client->id->ip.data_len)) {
411 SILC_LOG_DEBUG(("Found (local) %s",
412 silc_id_render(server_entry->id, SILC_ID_SERVER)));
414 if (!SILC_IS_LOCAL(server_entry) && server_entry->router) {
415 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
416 /* If the client is not marked as local then move it to local list
417 since the server is local. */
419 SILC_LOG_DEBUG(("Moving client to local list"));
420 silc_idcache_move(server->global_list->clients,
421 server->local_list->clients, client_cache);
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_move(server->global_list->clients,
431 server->local_list->clients, client_cache);
433 } else if (server->server_type == SILC_BACKUP_ROUTER && local) {
434 /* If we are backup router and this client is on local list, we
435 must move it to global list, as it is not currently local to
436 us (we are not primary). */
437 SILC_LOG_DEBUG(("Moving client to global list"));
438 silc_idcache_move(server->local_list->clients,
439 server->global_list->clients, client_cache);
447 if (!silc_idcache_get_all(server->global_list->servers, &list))
450 silc_list_start(list);
451 while ((id_cache = silc_list_get(list))) {
452 server_entry = (SilcServerEntry)id_cache->context;
453 if (server_entry != from && server_entry != server->id_entry &&
454 (tolocal || server_entry != server->id_entry) &&
455 SILC_ID_COMPARE(server_entry->id, client->id,
456 client->id->ip.data_len)) {
457 SILC_LOG_DEBUG(("Found (global) %s",
458 silc_id_render(server_entry->id, SILC_ID_SERVER)));
460 if (!SILC_IS_LOCAL(server_entry) && server_entry->router) {
461 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
462 /* If the client is marked as local then move it to global list
463 since the server is global. */
465 SILC_LOG_DEBUG(("Moving client to global list"));
466 silc_idcache_move(server->local_list->clients,
467 server->global_list->clients, client_cache);
469 server_entry = server_entry->router;
471 SILC_LOG_DEBUG(("Server locally connected"));
472 /* If the client is marked as local then move it to global list
473 since the server is global. */
474 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
475 SILC_LOG_DEBUG(("Moving client to global list"));
476 silc_idcache_move(server->local_list->clients,
477 server->global_list->clients, client_cache);
487 /* Updates the clients that are originated from the `from' to be originated
488 from the `to'. If the `resolve_real_server' is TRUE then this will
489 attempt to figure out which clients really are originated from the
490 `from' and which are originated from a server that we have connection
491 to, when we've acting as backup router. If it is FALSE the `to' will
492 be the new source. */
494 void silc_server_update_clients_by_server(SilcServer server,
495 SilcServerEntry from,
497 SilcBool resolve_real_server)
500 SilcIDCacheEntry id_cache = NULL;
501 SilcClientEntry client = NULL;
504 if (from && from->id) {
505 SILC_LOG_DEBUG(("Changing from server %s",
506 silc_id_render(from->id, SILC_ID_SERVER)));
509 SILC_LOG_DEBUG(("Changing to server %s",
510 silc_id_render(to->id, SILC_ID_SERVER)));
513 SILC_LOG_DEBUG(("global list"));
515 if (silc_idcache_get_all(server->global_list->clients, &list)) {
516 silc_list_start(list);
517 while ((id_cache = silc_list_get(list))) {
518 client = (SilcClientEntry)id_cache->context;
520 /* If entry is disabled skip it. If entry is local to us, do not
521 switch it to anyone else, it is ours so skip it. */
522 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
523 SILC_IS_LOCAL(client))
526 SILC_LOG_DEBUG(("Client %s",
527 silc_id_render(client->id, SILC_ID_CLIENT)));
528 if (client->router && client->router->id)
529 SILC_LOG_DEBUG(("Client->router %s",
530 silc_id_render(client->router->id, SILC_ID_SERVER)));
533 if (client->router == from) {
534 if (resolve_real_server) {
536 silc_server_update_clients_by_real_server(server, from, to,
539 if (!client->router) {
540 if (server->server_type == SILC_ROUTER)
541 client->router = from;
550 /* All are changed */
551 if (resolve_real_server)
552 /* Call this so that the entry is moved to correct list if
553 needed. No resolving by real server is actually done. */
554 silc_server_update_clients_by_real_server(server, NULL, to,
561 if (client->router && client->router->id)
562 SILC_LOG_DEBUG(("Client changed to %s",
563 silc_id_render(client->router->id, SILC_ID_SERVER)));
567 SILC_LOG_DEBUG(("local list"));
569 if (silc_idcache_get_all(server->local_list->clients, &list)) {
570 silc_list_start(list);
571 while ((id_cache = silc_list_get(list))) {
572 client = (SilcClientEntry)id_cache->context;
574 /* If entry is disabled skip it. If entry is local to us, do not
575 switch it to anyone else, it is ours so skip it. */
576 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
577 SILC_IS_LOCAL(client))
580 SILC_LOG_DEBUG(("Client %s",
581 silc_id_render(client->id, SILC_ID_CLIENT)));
582 if (client->router && client->router->id)
583 SILC_LOG_DEBUG(("Client->router %s",
584 silc_id_render(client->router->id, SILC_ID_SERVER)));
587 if (client->router == from) {
588 if (resolve_real_server) {
590 silc_server_update_clients_by_real_server(server, from, to,
594 client->router = from;
600 /* All are changed */
601 if (resolve_real_server)
602 /* Call this so that the entry is moved to correct list if
603 needed. No resolving by real server is actually done. */
604 silc_server_update_clients_by_real_server(server, NULL, to,
611 if (client->router && client->router->id)
612 SILC_LOG_DEBUG(("Client changed to %s",
613 silc_id_render(client->router->id, SILC_ID_SERVER)));
618 /* Updates servers that are from `from' to be originated from `to'. This
619 will also update the server's connection to `to's connection. */
621 void silc_server_update_servers_by_server(SilcServer server,
622 SilcServerEntry from,
626 SilcIDCacheEntry id_cache = NULL;
627 SilcServerEntry server_entry = NULL;
629 SILC_LOG_DEBUG(("Updating servers"));
631 if (silc_idcache_get_all(server->local_list->servers, &list)) {
632 silc_list_start(list);
633 while ((id_cache = silc_list_get(list))) {
634 server_entry = (SilcServerEntry)id_cache->context;
636 /* If entry is local to us, do not switch it to any anyone else,
638 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
639 server_entry == from)
642 /* If we are standalone router, any server that is not directly
643 connected to cannot exist anymore. If we are not standalone
644 we update it correctly. */
645 if (server->server_type == SILC_ROUTER && server->standalone) {
646 silc_server_backup_del(server, server_entry);
647 silc_server_backup_replaced_del(server, server_entry);
648 silc_idlist_del_data(server_entry);
649 silc_idlist_del_server(server->local_list, server_entry);
650 server->stat.servers--;
651 server->stat.cell_servers--;
653 /* XXX if we are not standalone, do a check from local config
654 whether this server is in our cell, but not connected to
655 us (in which case we must remove it). */
658 if (server_entry->router == from) {
659 SILC_LOG_DEBUG(("Updating server (local) %s",
660 server_entry->server_name ?
661 server_entry->server_name : ""));
662 server_entry->router = to;
663 server_entry->connection = to->connection;
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;
677 if (silc_idcache_get_all(server->global_list->servers, &list)) {
678 silc_list_start(list);
679 while ((id_cache = silc_list_get(list))) {
680 server_entry = (SilcServerEntry)id_cache->context;
682 /* If entry is local to us, do not switch it to anyone else,
684 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
685 server_entry == from)
688 /* If we are standalone router, any server that is not directly
689 connected to cannot exist anymore. If we are not standalone
690 we update it correctly. */
691 if (server->server_type == SILC_ROUTER && server->standalone) {
692 silc_server_backup_del(server, server_entry);
693 silc_server_backup_replaced_del(server, server_entry);
694 silc_idlist_del_data(server_entry);
695 silc_idlist_del_server(server->global_list, server_entry);
696 server->stat.servers--;
697 server->stat.cell_servers--;
699 /* XXX if we are not standalone, do a check from local config
700 whether this server is in our cell, but not connected to
701 us (in which case we must remove it). */
704 if (server_entry->router == from) {
705 SILC_LOG_DEBUG(("Updating server (global) %s",
706 server_entry->server_name ?
707 server_entry->server_name : ""));
708 server_entry->router = to;
709 server_entry->connection = to->connection;
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;
725 /* Toggles the enabled/disabled status of local server connections. Packets
726 can be sent to the servers when `toggle_enabled' is TRUE and will be
727 dropped if `toggle_enabled' is FALSE, after this function is called. */
729 void silc_server_local_servers_toggle_enabled(SilcServer server,
730 SilcBool toggle_enabled)
733 SilcIDCacheEntry id_cache = NULL;
734 SilcServerEntry server_entry = NULL;
736 if (silc_idcache_get_all(server->local_list->servers, &list)) {
737 silc_list_start(list);
738 while ((id_cache = silc_list_get(list))) {
739 server_entry = (SilcServerEntry)id_cache->context;
740 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry)
744 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
746 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
751 if (silc_idcache_get_all(server->global_list->servers, &list)) {
752 silc_list_start(list);
753 while ((id_cache = silc_list_get(list))) {
754 server_entry = (SilcServerEntry)id_cache->context;
755 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry)
759 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
761 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
767 /* Removes servers that are originated from the `from'. The server
768 entry is deleted in this function. If `remove_clients' is TRUE then
769 all clients originated from the server are removed too, and server
770 signoff is sent. Note that this does not remove the `from'. This
771 also does not remove locally connected servers. */
773 void silc_server_remove_servers_by_server(SilcServer server,
774 SilcServerEntry from,
775 SilcBool remove_clients)
778 SilcIDCacheEntry id_cache = NULL;
779 SilcServerEntry server_entry = NULL;
781 SILC_LOG_DEBUG(("Removing servers by %s",
782 from->server_name ? from->server_name : "server"));
784 if (silc_idcache_get_all(server->local_list->servers, &list)) {
785 silc_list_start(list);
786 while ((id_cache = silc_list_get(list))) {
787 server_entry = (SilcServerEntry)id_cache->context;
788 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
789 server_entry->router != from || server_entry == from)
792 /* Remove clients owned by this server */
794 silc_server_remove_clients_by_server(server, from, server_entry,
797 /* Remove the server */
798 silc_server_backup_del(server, server_entry);
799 silc_idlist_del_server(server->local_list, server_entry);
803 if (silc_idcache_get_all(server->global_list->servers, &list)) {
804 silc_list_start(list);
805 while ((id_cache = silc_list_get(list))) {
806 server_entry = (SilcServerEntry)id_cache->context;
807 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
808 server_entry->router != from || server_entry == from)
811 /* Remove clients owned by this server */
813 silc_server_remove_clients_by_server(server, from, server_entry,
816 /* Remove the server */
817 silc_server_backup_del(server, server_entry);
818 silc_idlist_del_server(server->global_list, server_entry);
823 /* Removes channels that are from `from. */
825 void silc_server_remove_channels_by_server(SilcServer server,
826 SilcServerEntry from)
829 SilcIDCacheEntry id_cache = NULL;
830 SilcChannelEntry channel = NULL;
832 SILC_LOG_DEBUG(("Removing channels by server"));
834 if (silc_idcache_get_all(server->global_list->channels, &list)) {
835 silc_list_start(list);
836 while ((id_cache = silc_list_get(list))) {
837 channel = (SilcChannelEntry)id_cache->context;
838 if (channel->router == from)
839 silc_idlist_del_channel(server->global_list, channel);
844 /* Updates channels that are from `from' to be originated from `to'. */
846 void silc_server_update_channels_by_server(SilcServer server,
847 SilcServerEntry from,
851 SilcIDCacheEntry id_cache = NULL;
852 SilcChannelEntry channel = NULL;
854 SILC_LOG_DEBUG(("Updating channels by server"));
856 if (silc_idcache_get_all(server->global_list->channels, &list)) {
857 silc_list_start(list);
858 while ((id_cache = silc_list_get(list))) {
859 channel = (SilcChannelEntry)id_cache->context;
861 if (channel->router == from)
862 channel->router = to;
865 channel->router = to;
871 /* Checks whether given channel has global users. If it does this returns
872 TRUE and FALSE if there is only locally connected clients on the channel. */
874 SilcBool silc_server_channel_has_global(SilcChannelEntry channel)
876 SilcChannelClientEntry chl;
877 SilcHashTableList htl;
879 silc_hash_table_list(channel->user_list, &htl);
880 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
881 if (chl->client->router) {
882 silc_hash_table_list_reset(&htl);
886 silc_hash_table_list_reset(&htl);
891 /* Checks whether given channel has locally connected users. If it does this
892 returns TRUE and FALSE if there is not one locally connected client. */
894 SilcBool silc_server_channel_has_local(SilcChannelEntry channel)
896 SilcChannelClientEntry chl;
897 SilcHashTableList htl;
899 silc_hash_table_list(channel->user_list, &htl);
900 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
901 if (SILC_IS_LOCAL(chl->client)) {
902 silc_hash_table_list_reset(&htl);
906 silc_hash_table_list_reset(&htl);
911 /* This function removes the channel and all users on the channel, unless
912 the channel is permanent. In this case the channel is disabled but all
913 users are removed from the channel. Returns TRUE if the channel is
914 destroyed totally, and FALSE if it is permanent and remains. */
916 SilcBool silc_server_channel_delete(SilcServer server,
917 SilcChannelEntry channel)
919 SilcChannelClientEntry chl;
920 SilcHashTableList htl;
921 SilcBool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
923 SILC_LOG_DEBUG(("Deleting channel %s", channel->channel_name));
926 /* Update statistics */
927 if (server->server_type == SILC_ROUTER)
928 server->stat.chanclients -= channel->user_count;
930 /* Totally delete the channel and all users on the channel. The
931 users are deleted automatically in silc_idlist_del_channel. */
932 channel->disabled = TRUE;
933 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
934 if (silc_idlist_del_channel(server->local_list, channel)) {
935 server->stat.my_channels--;
936 if (server->server_type == SILC_ROUTER) {
937 server->stat.channels--;
938 server->stat.cell_channels--;
941 if (silc_idlist_del_channel(server->global_list, channel))
942 if (server->server_type == SILC_ROUTER)
943 server->stat.channels--;
949 /* Channel is permanent, do not remove it, remove only users */
950 channel->disabled = TRUE;
951 silc_hash_table_list(channel->user_list, &htl);
952 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
953 silc_hash_table_del(chl->client->channels, channel);
954 silc_hash_table_del(channel->user_list, chl->client);
955 channel->user_count--;
957 /* Update statistics */
958 if (SILC_IS_LOCAL(chl->client))
959 server->stat.my_chanclients--;
960 if (server->server_type == SILC_ROUTER) {
961 server->stat.cell_chanclients--;
962 server->stat.chanclients--;
967 silc_hash_table_list_reset(&htl);
969 SILC_LOG_DEBUG(("Channel %s remains (permanent)", channel->channel_name));
974 /* Returns TRUE if the given client is on the channel. FALSE if not.
975 This works because we assure that the user list on the channel is
976 always in up to date thus we can only check the channel list from
977 `client' which is faster than checking the user list from `channel'. */
979 SilcBool silc_server_client_on_channel(SilcClientEntry client,
980 SilcChannelEntry channel,
981 SilcChannelClientEntry *chl)
983 if (!client || !channel)
986 return silc_hash_table_find(client->channels, channel, NULL,
990 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
991 socket connections with the IP address does not exist. Counts only
992 fully established connections. */
994 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
995 SilcConnectionType type)
997 SilcServerConnection conn;
998 SilcIDListData idata;
1002 silc_dlist_start(server->conns);
1003 while ((conn = silc_dlist_get(server->conns))) {
1004 if (!conn->sock || !silc_packet_stream_is_valid(conn->sock))
1006 silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->sock),
1007 NULL, NULL, &ipaddr, NULL);
1008 idata = silc_packet_get_context(conn->sock);
1009 if (!strcmp(ipaddr, ip) && idata && idata->conn_type == type)
1016 /* Find active socket connection by the IP address and port indicated by
1017 `ip' and `port', and socket connection type of `type'. */
1020 silc_server_find_socket_by_host(SilcServer server,
1021 SilcConnectionType type,
1022 const char *ip, SilcUInt16 port)
1024 SilcServerConnection conn;
1025 SilcIDListData idata;
1028 silc_dlist_start(server->conns);
1029 while ((conn = silc_dlist_get(server->conns))) {
1030 if (!conn->sock || !silc_packet_stream_is_valid(conn->sock))
1032 idata = silc_packet_get_context(conn->sock);
1033 silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->sock),
1034 NULL, NULL, &ipaddr, NULL);
1035 if (!strcmp(ipaddr, ip) &&
1036 (!port || conn->remote_port == port) &&
1037 idata->conn_type == type)
1044 /* Find number of sockets by IP address indicated by remote host, indicatd
1045 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1046 does not exist. If `ip' is provided then `hostname' is ignored. */
1048 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1050 const char *hostname,
1052 SilcConnectionType type)
1054 SilcServerConnection conn;
1055 SilcIDListData idata;
1056 SilcConnectionType t = SILC_CONN_UNKNOWN;
1059 if (!ip && !hostname)
1062 SILC_LOG_DEBUG(("Num connections %d", silc_dlist_count(server->conns)));
1064 silc_dlist_start(server->conns);
1065 while ((conn = silc_dlist_get(server->conns))) {
1067 idata = silc_packet_get_context(conn->sock);
1069 t = idata->conn_type;
1071 if (((ip && !strcmp(conn->remote_host, ip)) ||
1072 (hostname && !strcmp(conn->remote_host, hostname))) &&
1073 conn->remote_port == port && t == type)
1080 /* SKR find callbcak */
1082 static void find_callback(SilcSKR skr, SilcSKRFind find,
1083 SilcSKRStatus status, SilcDList keys,
1086 SilcPublicKey *public_key = context;
1090 silc_dlist_start(keys);
1091 key = silc_dlist_get(keys);
1092 *public_key = key->key;
1093 silc_dlist_uninit(keys);
1096 silc_skr_find_free(find);
1099 /* Get public key by key usage and key context. */
1101 SilcPublicKey silc_server_get_public_key(SilcServer server,
1102 SilcSKRKeyUsage usage,
1106 SilcPublicKey public_key = NULL;
1108 SILC_LOG_DEBUG(("Start"));
1110 find = silc_skr_find_alloc();
1114 silc_skr_find_set_usage(find, usage);
1115 silc_skr_find_set_context(find, key_context);
1116 silc_skr_find(server->repository, server->schedule,
1117 find, find_callback, &public_key);
1121 SILC_LOG_DEBUG(("Found public key"));
1123 SILC_LOG_DEBUG(("Public key not found"));
1124 #endif /* SILC_DEBUG */
1129 /* Find public key by client for identification purposes. Finds keys
1130 with SILC_SKR_USAGE_IDENTIFICATION. */
1132 SilcBool silc_server_get_public_key_by_client(SilcServer server,
1133 SilcClientEntry client,
1134 SilcPublicKey *public_key)
1136 SilcPublicKey pubkey = NULL;
1137 SilcBool ret = FALSE;
1139 pubkey = silc_server_get_public_key(server, SILC_SKR_USAGE_IDENTIFICATION,
1145 *public_key = pubkey;
1150 /* Check whether the connection `sock' is allowed to connect to us. This
1151 checks for example whether there is too much connections for this host,
1152 and required version for the host etc. */
1154 SilcBool silc_server_connection_allowed(SilcServer server,
1155 SilcPacketStream sock,
1156 SilcConnectionType type,
1157 SilcServerConfigConnParams *global,
1158 SilcServerConfigConnParams *params,
1161 SilcUInt32 conn_number = (type == SILC_CONN_CLIENT ?
1162 server->stat.my_clients :
1163 type == SILC_CONN_SERVER ?
1164 server->stat.my_servers :
1165 server->stat.my_routers);
1166 SilcUInt32 num_sockets, max_hosts, max_per_host;
1167 SilcUInt32 r_protocol_version, l_protocol_version;
1168 SilcUInt32 r_software_version, l_software_version;
1169 char *r_vendor_version = NULL, *l_vendor_version;
1170 const char *hostname, *ip;
1172 silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
1173 NULL, &hostname, &ip, NULL);
1175 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1179 l_protocol_version =
1180 silc_version_to_num(params && params->version_protocol ?
1181 params->version_protocol :
1182 global->version_protocol);
1183 l_software_version =
1184 silc_version_to_num(params && params->version_software ?
1185 params->version_software :
1186 global->version_software);
1187 l_vendor_version = (params && params->version_software_vendor ?
1188 params->version_software_vendor :
1189 global->version_software_vendor);
1191 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1192 &r_software_version, NULL,
1193 &r_vendor_version)) {
1194 /* Match protocol version */
1195 if (l_protocol_version && r_protocol_version &&
1196 r_protocol_version < l_protocol_version) {
1197 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1199 silc_server_disconnect_remote(server, sock,
1200 SILC_STATUS_ERR_BAD_VERSION,
1201 "You support too old protocol version");
1202 silc_server_free_sock_user_data(server, sock, NULL);
1206 /* Math software version */
1207 if (l_software_version && r_software_version &&
1208 r_software_version < l_software_version) {
1209 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1211 silc_server_disconnect_remote(server, sock,
1212 SILC_STATUS_ERR_BAD_VERSION,
1213 "You support too old software version");
1214 silc_server_free_sock_user_data(server, sock, NULL);
1218 /* Regex match vendor version */
1219 if (l_vendor_version && r_vendor_version &&
1220 !silc_string_match(l_vendor_version, r_vendor_version)) {
1221 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1223 silc_server_disconnect_remote(server, sock,
1224 SILC_STATUS_ERR_BAD_VERSION,
1225 "Your software is not supported");
1226 silc_server_free_sock_user_data(server, sock, NULL);
1230 silc_free(r_vendor_version);
1232 /* Check for maximum connections limit */
1234 num_sockets = silc_server_num_sockets_by_ip(server, ip, type);
1235 max_hosts = (params ? params->connections_max : global->connections_max);
1236 max_per_host = (params ? params->connections_max_per_host :
1237 global->connections_max_per_host);
1239 if (max_hosts && conn_number >= max_hosts) {
1240 SILC_LOG_DEBUG(("Server is full, %d >= %d", conn_number, max_hosts));
1241 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1243 silc_server_disconnect_remote(server, sock,
1244 SILC_STATUS_ERR_RESOURCE_LIMIT,
1245 "Server is full, try again later");
1246 silc_server_free_sock_user_data(server, sock, NULL);
1250 if (num_sockets >= max_per_host) {
1251 SILC_LOG_DEBUG(("Too many connections, %d >= %d", num_sockets,
1253 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1255 silc_server_disconnect_remote(server, sock,
1256 SILC_STATUS_ERR_RESOURCE_LIMIT,
1257 "Too many connections from your host");
1258 silc_server_free_sock_user_data(server, sock, NULL);
1265 /* Checks that client has rights to add or remove channel modes. If any
1266 of the checks fails FALSE is returned. */
1268 SilcBool silc_server_check_cmode_rights(SilcServer server,
1269 SilcChannelEntry channel,
1270 SilcChannelClientEntry client,
1273 SilcBool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1274 SilcBool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1276 /* Check whether has rights to change anything */
1277 if (!is_op && !is_fo)
1280 /* Check whether has rights to change everything */
1284 /* Founder implies operator */
1288 /* We know that client is channel operator, check that they are not
1289 changing anything that requires channel founder rights. Rest of the
1290 modes are available automatically for channel operator. */
1292 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1293 if (is_op && !is_fo)
1296 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1297 if (is_op && !is_fo)
1302 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1303 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1304 if (is_op && !is_fo)
1308 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1309 if (is_op && !is_fo)
1314 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1315 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1316 if (is_op && !is_fo)
1320 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1321 if (is_op && !is_fo)
1326 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1327 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1328 if (is_op && !is_fo)
1332 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1333 if (is_op && !is_fo)
1338 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1339 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1340 if (is_op && !is_fo)
1344 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1345 if (is_op && !is_fo)
1350 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1351 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1352 if (is_op && !is_fo)
1356 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1357 if (is_op && !is_fo)
1362 if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1363 if (!(channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)) {
1364 if (is_op && !is_fo)
1368 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1369 if (is_op && !is_fo)
1377 /* Check that the client has rights to change its user mode. Returns
1378 FALSE if setting some mode is not allowed. */
1380 SilcBool silc_server_check_umode_rights(SilcServer server,
1381 SilcClientEntry client,
1384 SilcBool server_op = FALSE, router_op = FALSE;
1386 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1387 /* Cannot set server operator mode (must use OPER command) */
1388 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1391 /* Remove the server operator rights */
1392 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1396 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1397 /* Cannot set router operator mode (must use SILCOPER command) */
1398 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1401 /* Remove the router operator rights */
1402 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1407 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1409 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1414 /* This function is used to send the notify packets and motd to the
1415 incoming client connection. */
1417 void silc_server_send_connect_notifys(SilcServer server,
1418 SilcPacketStream sock,
1419 SilcClientEntry client)
1423 SILC_LOG_DEBUG(("Send welcome notifys"));
1425 /* Send some nice info to the client */
1426 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1427 ("Welcome to the SILC Network %s",
1429 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1430 ("Your host is %s, running version %s",
1431 server->server_name, server_version));
1433 if (server->server_type == SILC_ROUTER) {
1434 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1435 ("There are %d clients, %d servers and %d "
1436 "routers in SILC Network",
1437 server->stat.clients, server->stat.servers,
1438 server->stat.routers));
1440 if (server->stat.clients && server->stat.servers + 1)
1441 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1442 ("There are %d clients, %d servers and %d "
1443 "routers in SILC Network",
1444 server->stat.clients, server->stat.servers,
1445 (server->standalone ? 0 :
1446 !server->stat.routers ? 1 :
1447 server->stat.routers)));
1450 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1451 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1452 ("There are %d clients on %d servers in our cell",
1453 server->stat.cell_clients,
1454 server->stat.cell_servers));
1455 if (server->server_type == SILC_ROUTER) {
1456 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1457 ("I have %d clients, %d channels, %d servers and "
1459 server->stat.my_clients,
1460 server->stat.my_channels,
1461 server->stat.my_servers,
1462 server->stat.my_routers));
1464 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1465 ("I have %d clients and %d channels formed",
1466 server->stat.my_clients,
1467 server->stat.my_channels));
1470 if (server->stat.server_ops || server->stat.router_ops)
1471 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1472 ("There are %d server operators and %d router "
1474 server->stat.server_ops,
1475 server->stat.router_ops));
1476 if (server->stat.my_router_ops + server->stat.my_server_ops)
1477 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1478 ("I have %d operators online",
1479 server->stat.my_router_ops +
1480 server->stat.my_server_ops));
1482 silc_packet_get_keys(sock, &key, NULL, NULL, NULL);
1483 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1484 ("Your connection is secured with %s cipher, "
1485 "key length %d bits",
1486 silc_cipher_get_name(key),
1487 silc_cipher_get_key_len(key)));
1488 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1489 ("Your current nickname is %s",
1493 silc_server_send_motd(server, sock);
1496 /* Kill the client indicated by `remote_client' sending KILLED notify
1497 to the client, to all channels client has joined and to primary
1498 router if needed. The killed client is also removed from all channels. */
1500 void silc_server_kill_client(SilcServer server,
1501 SilcClientEntry remote_client,
1502 const char *comment,
1504 SilcIdType killer_id_type)
1506 SilcBuffer killed, killer;
1508 SILC_LOG_DEBUG(("Killing client %s",
1509 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1511 /* Send the KILL notify packets. First send it to the channel, then
1512 to our primary router and then directly to the client who is being
1513 killed right now. */
1515 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1516 killer = silc_id_payload_encode(killer_id, killer_id_type);
1518 /* Send KILLED notify to the channels. It is not sent to the client
1519 as it will be sent differently destined directly to the client and not
1521 silc_server_send_notify_on_channels(server, remote_client,
1522 remote_client, SILC_NOTIFY_TYPE_KILLED,
1523 3, killed->data, silc_buffer_len(killed),
1524 comment, comment ? strlen(comment) : 0,
1525 killer->data, silc_buffer_len(killer));
1527 /* Send KILLED notify to primary route */
1528 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1529 SILC_BROADCAST(server), remote_client->id,
1530 comment, killer_id, killer_id_type);
1532 /* Send KILLED notify to the client directly */
1533 if (remote_client->connection || remote_client->router)
1534 silc_server_send_notify_killed(server, remote_client->connection ?
1535 remote_client->connection :
1536 remote_client->router->connection, FALSE,
1537 remote_client->id, comment,
1538 killer_id, killer_id_type);
1540 /* Remove the client from all channels. This generates new keys to the
1541 channels as well. */
1542 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1545 /* Remove the client entry, If it is locally connected then we will also
1546 disconnect the client here */
1547 if (remote_client->connection) {
1548 /* Remove locally conneted client */
1549 SilcPacketStream sock = remote_client->connection;
1550 silc_server_free_sock_user_data(server, sock, NULL);
1551 silc_server_close_connection(server, sock);
1553 /* Update statistics */
1554 server->stat.clients--;
1555 if (server->stat.cell_clients)
1556 server->stat.cell_clients--;
1557 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1558 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1560 /* Remove client's public key from repository, this will free it too. */
1561 if (remote_client->data.public_key) {
1562 silc_skr_del_public_key(server->repository,
1563 remote_client->data.public_key, remote_client);
1564 remote_client->data.public_key = NULL;
1567 if (SILC_IS_LOCAL(remote_client)) {
1568 server->stat.my_clients--;
1569 silc_schedule_task_del_by_context(server->schedule, remote_client);
1572 /* Remove remote client */
1573 silc_dlist_del(server->expired_clients, remote_client);
1574 silc_idlist_del_data(remote_client);
1575 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1576 /* Remove this client from watcher list if it is */
1577 silc_server_del_from_watcher_list(server, remote_client);
1578 silc_idlist_del_client(server->local_list, remote_client);
1582 silc_buffer_free(killer);
1583 silc_buffer_free(killed);
1588 SilcClientEntry client;
1589 SilcNotifyType notify;
1590 const char *new_nick;
1591 } WatcherNotifyContext;
1594 silc_server_check_watcher_list_foreach(void *key, void *context,
1597 WatcherNotifyContext *notify = user_context;
1598 SilcClientEntry entry = context;
1599 SilcPacketStream sock;
1604 if (entry == notify->client)
1607 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1610 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1611 silc_id_render(entry->id, SILC_ID_CLIENT)));
1613 /* Send the WATCH notify */
1614 silc_server_send_notify_watch(notify->server, sock, entry,
1616 notify->new_nick ? notify->new_nick :
1617 (const char *)notify->client->nickname,
1619 notify->client->data.public_key);
1623 /* This function checks whether the `client' nickname and/or 'client'
1624 public key is being watched by someone, and notifies the watcher of the
1625 notify change of notify type indicated by `notify'. */
1627 SilcBool silc_server_check_watcher_list(SilcServer server,
1628 SilcClientEntry client,
1629 const char *new_nick,
1630 SilcNotifyType notify)
1632 unsigned char hash[16];
1633 WatcherNotifyContext n;
1635 SILC_LOG_DEBUG(("Checking watcher list %s",
1636 client->nickname ? client->nickname : (unsigned char *)""));
1638 /* If the watching is rejected by the client do nothing */
1639 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1642 /* Make hash from the nick, or take it from Client ID */
1643 if (client->nickname) {
1644 unsigned char *nickc;
1645 nickc = silc_identifier_check(client->nickname, strlen(client->nickname),
1646 SILC_STRING_UTF8, 128, NULL);
1649 silc_hash_make(server->md5hash, nickc, strlen(nickc), hash);
1652 memset(hash, 0, sizeof(hash));
1653 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1658 n.new_nick = new_nick;
1661 /* Send notify to all watchers watching this nickname */
1662 silc_hash_table_find_foreach(server->watcher_list, hash,
1663 silc_server_check_watcher_list_foreach, &n);
1665 /* Send notify to all watchers watching this public key */
1666 if (client->data.public_key)
1667 silc_hash_table_find_foreach(server->watcher_list_pk,
1668 client->data.public_key,
1669 silc_server_check_watcher_list_foreach,
1675 /* Remove the `client' from watcher list. After calling this the `client'
1676 is not watching any nicknames. */
1678 SilcBool silc_server_del_from_watcher_list(SilcServer server,
1679 SilcClientEntry client)
1681 SilcHashTableList htl;
1683 SilcClientEntry entry;
1684 SilcBool found = FALSE;
1686 silc_hash_table_list(server->watcher_list, &htl);
1687 while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1688 if (entry == client) {
1689 silc_hash_table_del_by_context(server->watcher_list, key, client);
1692 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1693 silc_id_render(client->id, SILC_ID_CLIENT)));
1695 /* Now check whether there still exists entries with this key, if not
1696 then free the key to not leak memory. */
1697 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1703 silc_hash_table_list_reset(&htl);
1705 silc_hash_table_list(server->watcher_list_pk, &htl);
1706 while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1707 if (entry == client) {
1708 silc_hash_table_del_by_context(server->watcher_list_pk, key, client);
1711 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1712 silc_id_render(client->id, SILC_ID_CLIENT)));
1714 /* Now check whether there still exists entries with this key, if not
1715 then free the key to not leak memory. */
1716 if (!silc_hash_table_find(server->watcher_list_pk, key, NULL, NULL))
1717 silc_pkcs_public_key_free(key);
1722 silc_hash_table_list_reset(&htl);
1727 /* Force the client indicated by `chl' to change the channel user mode
1728 on channel indicated by `channel' to `forced_mode'. */
1730 SilcBool silc_server_force_cumode_change(SilcServer server,
1731 SilcPacketStream sock,
1732 SilcChannelEntry channel,
1733 SilcChannelClientEntry chl,
1734 SilcUInt32 forced_mode)
1736 SilcBuffer idp1, idp2;
1737 unsigned char cumode[4];
1739 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1742 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1743 server->id, SILC_ID_SERVER,
1744 chl->client->id, NULL);
1746 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1747 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1748 SILC_PUT32_MSB(forced_mode, cumode);
1749 silc_server_send_notify_to_channel(server, sock, channel, FALSE, TRUE,
1750 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1751 3, idp1->data, silc_buffer_len(idp1),
1752 cumode, sizeof(cumode),
1753 idp2->data, silc_buffer_len(idp2));
1754 silc_buffer_free(idp1);
1755 silc_buffer_free(idp2);
1760 /* This function can be used to match the invite and ban lists. */
1762 SilcBool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1763 SilcUInt8 type, void *check)
1765 unsigned char *tmp = NULL;
1767 SilcHashTableList htl;
1768 SilcBuffer entry, idp = NULL, pkp = NULL;
1769 SilcBool ret = FALSE;
1772 SILC_LOG_DEBUG(("Matching invite/ban"));
1774 if (type < 1 || type > 3 || !check)
1778 tmp = strdup((char *)check);
1783 pkp = silc_public_key_payload_encode(check);
1787 len = silc_buffer_len(pkp);
1790 idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
1794 len = silc_buffer_len(idp);
1797 /* Compare the list */
1798 silc_hash_table_list(list, &htl);
1799 while (silc_hash_table_get(&htl, (void *)&t, (void *)&entry)) {
1800 if (type == SILC_PTR_TO_32(t)) {
1802 if (silc_string_match(entry->data, tmp)) {
1806 } else if (silc_buffer_len(entry) == len &&
1807 !memcmp(entry->data, tmp, len)) {
1813 silc_hash_table_list_reset(&htl);
1817 silc_buffer_free(idp);
1818 silc_buffer_free(pkp);
1822 /* Process invite or ban information */
1824 SilcBool silc_server_inviteban_process(SilcServer server,
1827 SilcArgumentPayload args)
1830 SilcUInt32 type, len;
1833 SilcHashTableList htl;
1835 SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1836 action == 0x01 ? "DEL" : "ADD"));
1838 /* Add the information to invite list */
1839 if (action == 0x00 || action == 0x03) {
1840 /* Traverse all arguments and add to the hash table according to
1842 tmp = silc_argument_get_first_arg(args, &type, &len);
1845 /* Check validity of the string. Actually we should parse the
1846 whole string and verify all components individually. */
1847 if (!silc_utf8_valid(tmp, len) || !len) {
1848 tmp = silc_argument_get_next_arg(args, &type, &len);
1851 if (strchr(tmp, ',')) {
1852 tmp = silc_argument_get_next_arg(args, &type, &len);
1856 /* Check if the string is added already */
1857 silc_hash_table_list(list, &htl);
1858 while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1859 if (SILC_PTR_TO_32(ptype) == 1 &&
1860 silc_string_match(tmp2->data, tmp)) {
1865 silc_hash_table_list_reset(&htl);
1868 /* Add the string to hash table */
1869 tmp2 = silc_buffer_alloc_size(len + 1);
1870 if (tmp[len - 1] == ',')
1871 tmp[len - 1] = '\0';
1872 silc_buffer_put(tmp2, tmp, len);
1873 silc_hash_table_add(list, (void *)1, tmp2);
1876 } else if (type == 2) {
1877 /* Public key. Check first if the public key is already on the
1878 list and ignore it if it is, otherwise, add it to hash table. */
1881 /* Verify validity of the public key */
1882 if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1883 tmp = silc_argument_get_next_arg(args, &type, &len);
1886 silc_pkcs_public_key_free(pk);
1888 /* Check if the public key is in the list already */
1889 silc_hash_table_list(list, &htl);
1890 while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1891 if (SILC_PTR_TO_32(ptype) == 2 && !memcmp(tmp2->data, tmp, len)) {
1896 silc_hash_table_list_reset(&htl);
1898 /* Add new public key to invite list */
1900 tmp2 = silc_buffer_alloc_size(len);
1901 silc_buffer_put(tmp2, tmp, len);
1902 silc_hash_table_add(list, (void *)2, tmp2);
1905 } else if (type == 3) {
1908 /* Check if the ID is in the list already */
1909 silc_hash_table_list(list, &htl);
1910 while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1911 if (SILC_PTR_TO_32(ptype) == 3 && !memcmp(tmp2->data, tmp, len)) {
1916 silc_hash_table_list_reset(&htl);
1918 /* Add new Client ID to invite list */
1920 tmp2 = silc_buffer_alloc_size(len);
1921 silc_buffer_put(tmp2, tmp, len);
1922 silc_hash_table_add(list, (void *)3, tmp2);
1926 tmp = silc_argument_get_next_arg(args, &type, &len);
1930 /* Delete information to invite list */
1931 if (action == 0x01 && list) {
1932 /* Now delete the arguments from invite list */
1933 tmp = silc_argument_get_first_arg(args, &type, &len);
1936 /* Check validity of the string. Actually we should parse the
1937 whole string and verify all components individually. */
1938 if (!silc_utf8_valid(tmp, len)) {
1939 tmp = silc_argument_get_next_arg(args, &type, &len);
1942 if (strchr(tmp, ',')) {
1943 tmp = silc_argument_get_next_arg(args, &type, &len);
1947 /* Delete from the list */
1948 silc_hash_table_list(list, &htl);
1949 while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1950 if (SILC_PTR_TO_32(ptype) == 1 &&
1951 silc_string_match(tmp2->data, tmp)) {
1952 silc_hash_table_del_by_context(list, (void *)1, tmp2);
1956 silc_hash_table_list_reset(&htl);
1958 } else if (type == 2) {
1962 /* Verify validity of the public key */
1963 if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1964 tmp = silc_argument_get_next_arg(args, &type, &len);
1967 silc_pkcs_public_key_free(pk);
1969 /* Delete from the invite list */
1970 silc_hash_table_list(list, &htl);
1971 while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1972 if (SILC_PTR_TO_32(ptype) == 2 && !memcmp(tmp2->data, tmp, len)) {
1973 silc_hash_table_del_by_context(list, (void *)2, tmp2);
1977 silc_hash_table_list_reset(&htl);
1979 } else if (type == 3) {
1982 /* Delete from the invite list */
1983 silc_hash_table_list(list, &htl);
1984 while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
1985 if (SILC_PTR_TO_32(ptype) == 3 && !memcmp(tmp2->data, tmp, len)) {
1986 silc_hash_table_del_by_context(list, (void *)3, tmp2);
1990 silc_hash_table_list_reset(&htl);
1993 tmp = silc_argument_get_next_arg(args, &type, &len);
2000 /* Destructor for invite and ban list entrys */
2002 void silc_server_inviteban_destruct(void *key, void *context,
2005 silc_buffer_free(context);
2008 /* Creates connections accoring to configuration. */
2010 void silc_server_create_connections(SilcServer server)
2012 silc_schedule_task_del_by_callback(server->schedule,
2013 silc_server_connect_to_router);
2014 silc_schedule_task_add_timeout(server->schedule,
2015 silc_server_connect_to_router, server, 1, 0);
2019 silc_server_process_channel_pk_destruct(void *key, void *context,
2023 silc_pkcs_public_key_free(context);
2026 /* Processes a channel public key, either adds or removes it. */
2029 silc_server_process_channel_pk(SilcServer server,
2030 SilcChannelEntry channel,
2031 SilcUInt32 type, const unsigned char *pk,
2034 unsigned char pkhash[20];
2037 SILC_LOG_DEBUG(("Processing channel public key"));
2040 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2042 /* Decode the public key */
2043 if (!silc_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
2044 return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
2046 /* Create channel public key list (hash table) if needed */
2047 if (!channel->channel_pubkeys) {
2048 channel->channel_pubkeys =
2049 silc_hash_table_alloc(0, silc_hash_data, (void *)20,
2050 silc_hash_data_compare, (void *)20,
2051 silc_server_process_channel_pk_destruct, channel,
2055 /* Create SHA-1 digest of the public key data */
2056 silc_hash_make(server->sha1hash, pk + 4, pk_len - 4, pkhash);
2059 /* Add new public key to channel public key list */
2060 SILC_LOG_DEBUG(("Add new channel public key to channel %s",
2061 channel->channel_name));
2063 /* Check for resource limit */
2064 if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
2065 silc_pkcs_public_key_free(chpk);
2066 return SILC_STATUS_ERR_RESOURCE_LIMIT;
2069 /* Add if doesn't exist already */
2070 if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2072 silc_hash_table_add(channel->channel_pubkeys, silc_memdup(pkhash, 20),
2074 } else if (type == 0x01) {
2075 /* Delete public key from channel public key list */
2076 SILC_LOG_DEBUG(("Delete a channel public key from channel %s",
2077 channel->channel_name));
2078 if (!silc_hash_table_del(channel->channel_pubkeys, pkhash))
2079 silc_pkcs_public_key_free(chpk);
2081 silc_pkcs_public_key_free(chpk);
2082 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2085 return SILC_STATUS_OK;
2088 /* Returns the channel public keys as Argument List payload. */
2090 SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
2091 SilcChannelEntry channel,
2095 SilcHashTableList htl;
2096 SilcBuffer list, pkp;
2099 SILC_LOG_DEBUG(("Encoding channel public keys list"));
2101 if (!channel->channel_pubkeys ||
2102 !silc_hash_table_count(channel->channel_pubkeys))
2105 /* Encode the list */
2106 list = silc_buffer_alloc_size(2);
2107 silc_buffer_format(list,
2108 SILC_STR_UI_SHORT(silc_hash_table_count(
2109 channel->channel_pubkeys)),
2112 silc_hash_table_list(channel->channel_pubkeys, &htl);
2113 while (silc_hash_table_get(&htl, NULL, (void *)&pk)) {
2114 pkp = silc_public_key_payload_encode(pk);
2117 list = silc_argument_payload_encode_one(list, pkp->data,
2118 silc_buffer_len(pkp),
2120 delete ? 0x01 : 0x00);
2121 silc_buffer_free(pkp);
2123 silc_hash_table_list_reset(&htl);
2128 /* Sets the channel public keys into channel from the list of public keys. */
2130 SilcStatus silc_server_set_channel_pk_list(SilcServer server,
2131 SilcPacketStream sender,
2132 SilcChannelEntry channel,
2133 const unsigned char *pklist,
2134 SilcUInt32 pklist_len)
2137 SilcArgumentPayload args;
2138 unsigned char *chpk;
2139 SilcUInt32 chpklen, type;
2140 SilcStatus ret = SILC_STATUS_OK;
2142 SILC_LOG_DEBUG(("Setting channel public keys list"));
2144 if (!pklist || pklist_len < 2)
2145 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2147 /* Get the argument from the Argument List Payload */
2148 SILC_GET16_MSB(argc, pklist);
2149 args = silc_argument_payload_parse(pklist + 2, pklist_len - 2, argc);
2151 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2153 /* Process the public keys one by one */
2154 chpk = silc_argument_get_first_arg(args, &type, &chpklen);
2156 /* If announcing keys and we have them set already, do not allow this */
2157 if (chpk && type == 0x03 && channel->channel_pubkeys &&
2158 server->server_type == SILC_ROUTER &&
2159 sender != SILC_PRIMARY_ROUTE(server)) {
2160 SILC_LOG_DEBUG(("Channel public key list set already, enforce our list"));
2161 silc_argument_payload_free(args);
2162 return SILC_STATUS_ERR_OPERATION_ALLOWED;
2165 /* If we are normal server and receive announcement list and we already
2166 have keys set, we replace the old list with the announced one. */
2167 if (chpk && type == 0x03 && channel->channel_pubkeys &&
2168 server->server_type != SILC_ROUTER) {
2170 unsigned char mask[4], ulimit[4];
2172 SILC_LOG_DEBUG(("Router enforces its list, remove old list"));
2173 silc_hash_table_free(channel->channel_pubkeys);
2174 channel->channel_pubkeys = NULL;
2176 /* Send notify that removes the old list */
2177 sidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2178 SILC_PUT32_MSB((channel->mode & (~SILC_CHANNEL_MODE_CHANNEL_AUTH)), mask);
2179 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2180 SILC_PUT32_MSB(channel->user_limit, ulimit);
2181 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2182 SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
2183 sidp->data, silc_buffer_len(sidp),
2187 strlen(channel->cipher) : 0,
2189 channel->hmac_name ?
2190 strlen(channel->hmac_name) : 0,
2191 channel->passphrase,
2192 channel->passphrase ?
2193 strlen(channel->passphrase) : 0,
2196 SILC_CHANNEL_MODE_ULIMIT ?
2199 SILC_CHANNEL_MODE_ULIMIT ?
2200 sizeof(ulimit) : 0));
2201 silc_buffer_free(sidp);
2207 ret = silc_server_process_channel_pk(server, channel, type,
2209 if (ret != SILC_STATUS_OK)
2211 chpk = silc_argument_get_next_arg(args, &type, &chpklen);
2214 silc_argument_payload_free(args);
2218 /* Verifies the Authentication Payload `auth' with one of the public keys
2219 on the `channel' public key list. */
2221 SilcBool silc_server_verify_channel_auth(SilcServer server,
2222 SilcChannelEntry channel,
2223 SilcClientID *client_id,
2224 const unsigned char *auth,
2225 SilcUInt32 auth_len)
2229 unsigned char *pkhash;
2230 SilcUInt32 pkhash_len;
2231 SilcBool ret = FALSE;
2233 SILC_LOG_DEBUG(("Verifying channel authentication"));
2235 if (!auth || !auth_len || !channel->channel_pubkeys)
2238 /* Get the hash from the auth data which tells us what public key we
2239 must use in verification. */
2241 ap = silc_auth_payload_parse(auth, auth_len);
2245 pkhash = silc_auth_get_public_data(ap, &pkhash_len);
2246 if (pkhash_len < 128)
2249 /* Find the public key with the hash */
2250 if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2251 NULL, (void *)&chpk)) {
2252 SILC_LOG_DEBUG(("Public key not found in channel public key list"));
2256 /* Verify the signature */
2257 if (!silc_auth_verify(ap, SILC_AUTH_PUBLIC_KEY, (void *)chpk, 0,
2258 server->sha1hash, client_id, SILC_ID_CLIENT)) {
2259 SILC_LOG_DEBUG(("Authentication failed"));
2266 silc_auth_payload_free(ap);