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);
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);
192 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
193 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
195 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
197 argv[argc] = silc_calloc(silc_buffer_len(idp), sizeof(*argv[0]));
198 memcpy(argv[argc], idp->data, silc_buffer_len(idp));
199 argv_lens[argc] = silc_buffer_len(idp);
200 argv_types[argc] = argc + 1;
202 silc_buffer_free(idp);
205 /* Update statistics */
206 server->stat.clients--;
207 if (server->stat.cell_clients)
208 server->stat.cell_clients--;
209 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
210 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
212 /* Remove client's public key from repository, this will free it too. */
213 if (client->data.public_key) {
214 silc_skr_del_public_key(server->repository, client->data.public_key,
216 client->data.public_key = NULL;
219 silc_server_remove_clients_channels(server, entry, clients,
221 silc_server_del_from_watcher_list(server, client);
223 /* Remove the client entry */
224 if (!server_signoff) {
225 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
227 client->router = NULL;
228 client->connection = NULL;
229 silc_dlist_add(server->expired_clients, client);
231 silc_idlist_del_data(client);
232 silc_idlist_del_client(server->local_list, client);
237 if (silc_idcache_get_all(server->global_list->clients, &list)) {
238 silc_list_start(list);
239 while ((id_cache = silc_list_get(list))) {
240 client = (SilcClientEntry)id_cache->context;
242 /* If client is not registered, is not originated from `router'
243 and is not owned by `entry', skip it. */
244 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
245 client->router != router ||
246 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
247 client->id->ip.data_len))) {
251 if (server_signoff) {
252 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
253 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
254 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
256 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
258 argv[argc] = silc_calloc(silc_buffer_len(idp), sizeof(*argv[0]));
259 memcpy(argv[argc], idp->data, silc_buffer_len(idp));
260 argv_lens[argc] = silc_buffer_len(idp);
261 argv_types[argc] = argc + 1;
263 silc_buffer_free(idp);
266 /* Update statistics */
267 server->stat.clients--;
268 if (server->stat.cell_clients)
269 server->stat.cell_clients--;
270 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
271 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
273 /* Remove client's public key from repository, this will free it too. */
274 if (client->data.public_key) {
275 silc_skr_del_public_key(server->repository, client->data.public_key,
277 client->data.public_key = NULL;
280 silc_server_remove_clients_channels(server, entry, clients,
282 silc_server_del_from_watcher_list(server, client);
284 /* Remove the client entry */
285 if (!server_signoff) {
286 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
288 client->router = NULL;
289 client->connection = NULL;
290 silc_dlist_add(server->expired_clients, client);
292 silc_idlist_del_data(client);
293 silc_idlist_del_client(server->global_list, client);
298 /* Return now if we are shutting down */
299 if (server->server_shutdown) {
300 silc_hash_table_free(channels);
302 if (server_signoff) {
303 for (i = 0; i < argc; i++)
306 silc_free(argv_lens);
307 silc_free(argv_types);
308 silc_hash_table_free(clients);
313 /* Send the SERVER_SIGNOFF notify */
314 if (server_signoff) {
315 SilcBuffer args, not;
317 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
318 silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
320 /* Send SERVER_SIGNOFF notify to our primary router */
321 if (server->router != entry) {
322 args = silc_argument_payload_encode(1, argv, argv_lens,
324 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
325 SILC_BROADCAST(server),
326 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
328 silc_buffer_free(args);
331 /* Send to local clients. We also send the list of client ID's that
332 is to be removed for those servers that would like to use that list. */
333 args = silc_argument_payload_encode(argc, argv, argv_lens,
335 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
337 silc_server_packet_send_clients(server, clients,
338 SILC_PACKET_NOTIFY, 0, FALSE,
339 not->data, silc_buffer_len(not));
341 /* Send notify also to local backup routers */
342 silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
343 not->data, silc_buffer_len(not), FALSE, TRUE);
345 silc_buffer_free(args);
346 silc_buffer_free(not);
347 for (i = 0; i < argc; i++)
350 silc_free(argv_lens);
351 silc_free(argv_types);
352 silc_hash_table_free(clients);
355 /* We must now re-generate the channel key for all channels that had
356 this server's client(s) on the channel. As they left the channel we
357 must re-generate the channel key. */
358 silc_hash_table_list(channels, &htl);
359 while (silc_hash_table_get(&htl, NULL, (void *)&channel)) {
360 if (!silc_server_create_channel_key(server, channel, 0)) {
361 silc_hash_table_list_reset(&htl);
362 silc_hash_table_free(channels);
366 /* Do not send the channel key if private channel key mode is set */
367 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->send_key)
370 silc_server_send_channel_key(server, NULL, channel,
371 server->server_type == SILC_ROUTER ?
372 FALSE : !server->standalone);
374 silc_hash_table_list_reset(&htl);
375 silc_hash_table_free(channels);
380 static SilcServerEntry
381 silc_server_update_clients_by_real_server(SilcServer server,
382 SilcServerEntry from,
384 SilcClientEntry client,
386 SilcIDCacheEntry client_cache)
388 SilcServerEntry server_entry;
389 SilcIDCacheEntry id_cache = NULL;
391 SilcBool tolocal = (to == server->id_entry);
393 SILC_LOG_DEBUG(("Start"));
395 if (!silc_idcache_get_all(server->local_list->servers, &list))
398 silc_list_start(list);
399 while ((id_cache = silc_list_get(list))) {
400 server_entry = (SilcServerEntry)id_cache->context;
401 if (server_entry != from &&
402 (tolocal || server_entry != server->id_entry) &&
403 SILC_ID_COMPARE(server_entry->id, client->id,
404 client->id->ip.data_len)) {
405 SILC_LOG_DEBUG(("Found (local) %s",
406 silc_id_render(server_entry->id, SILC_ID_SERVER)));
408 if (!SILC_IS_LOCAL(server_entry) && server_entry->router) {
409 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
410 /* If the client is not marked as local then move it to local list
411 since the server is local. */
413 SILC_LOG_DEBUG(("Moving client to local list"));
414 silc_idcache_add(server->local_list->clients, client_cache->name,
415 client_cache->id, client_cache->context);
416 silc_idcache_del_by_context(server->global_list->clients, client,
419 server_entry = server_entry->router;
421 SILC_LOG_DEBUG(("Server locally connected"));
422 /* If the client is not marked as local then move it to local list
423 since the server is local. */
424 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
425 SILC_LOG_DEBUG(("Moving client to local list"));
426 silc_idcache_add(server->local_list->clients, client_cache->name,
427 client_cache->id, client_cache->context);
428 silc_idcache_del_by_context(server->global_list->clients, client,
431 } else if (server->server_type == SILC_BACKUP_ROUTER && local) {
432 /* If we are backup router and this client is on local list, we
433 must move it to global list, as it is not currently local to
434 us (we are not primary). */
435 SILC_LOG_DEBUG(("Moving client to global list"));
436 silc_idcache_add(server->global_list->clients, client_cache->name,
437 client_cache->id, client_cache->context);
438 silc_idcache_del_by_context(server->local_list->clients, client,
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_add(server->global_list->clients, client_cache->name,
467 client_cache->id, client_cache->context);
468 silc_idcache_del_by_context(server->local_list->clients, client,
471 server_entry = server_entry->router;
473 SILC_LOG_DEBUG(("Server locally connected"));
474 /* If the client is marked as local then move it to global list
475 since the server is global. */
476 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
477 SILC_LOG_DEBUG(("Moving client to global list"));
478 silc_idcache_add(server->global_list->clients, client_cache->name,
479 client_cache->id, client_cache->context);
480 silc_idcache_del_by_context(server->local_list->clients, client,
491 /* Updates the clients that are originated from the `from' to be originated
492 from the `to'. If the `resolve_real_server' is TRUE then this will
493 attempt to figure out which clients really are originated from the
494 `from' and which are originated from a server that we have connection
495 to, when we've acting as backup router. If it is FALSE the `to' will
496 be the new source. */
498 void silc_server_update_clients_by_server(SilcServer server,
499 SilcServerEntry from,
501 SilcBool resolve_real_server)
504 SilcIDCacheEntry id_cache = NULL;
505 SilcClientEntry client = NULL;
508 if (from && from->id) {
509 SILC_LOG_DEBUG(("Changing from server %s",
510 silc_id_render(from->id, SILC_ID_SERVER)));
513 SILC_LOG_DEBUG(("Changing to server %s",
514 silc_id_render(to->id, SILC_ID_SERVER)));
517 SILC_LOG_DEBUG(("global list"));
519 if (silc_idcache_get_all(server->global_list->clients, &list)) {
520 silc_list_start(list);
521 while ((id_cache = silc_list_get(list))) {
522 client = (SilcClientEntry)id_cache->context;
524 /* If entry is disabled skip it. If entry is local to us, do not
525 switch it to anyone else, it is ours so skip it. */
526 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
527 SILC_IS_LOCAL(client))
530 SILC_LOG_DEBUG(("Client %s",
531 silc_id_render(client->id, SILC_ID_CLIENT)));
532 if (client->router && client->router->id)
533 SILC_LOG_DEBUG(("Client->router %s",
534 silc_id_render(client->router->id, SILC_ID_SERVER)));
537 if (client->router == from) {
538 if (resolve_real_server) {
540 silc_server_update_clients_by_real_server(server, from, to,
543 if (!client->router) {
544 if (server->server_type == SILC_ROUTER)
545 client->router = from;
554 /* All are changed */
555 if (resolve_real_server)
556 /* Call this so that the entry is moved to correct list if
557 needed. No resolving by real server is actually done. */
558 silc_server_update_clients_by_real_server(server, NULL, to,
565 if (client->router && client->router->id)
566 SILC_LOG_DEBUG(("Client changed to %s",
567 silc_id_render(client->router->id, SILC_ID_SERVER)));
571 SILC_LOG_DEBUG(("local list"));
573 if (silc_idcache_get_all(server->local_list->clients, &list)) {
574 silc_list_start(list);
575 while ((id_cache = silc_list_get(list))) {
576 client = (SilcClientEntry)id_cache->context;
578 /* If entry is disabled skip it. If entry is local to us, do not
579 switch it to anyone else, it is ours so skip it. */
580 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
581 SILC_IS_LOCAL(client))
584 SILC_LOG_DEBUG(("Client %s",
585 silc_id_render(client->id, SILC_ID_CLIENT)));
586 if (client->router && client->router->id)
587 SILC_LOG_DEBUG(("Client->router %s",
588 silc_id_render(client->router->id, SILC_ID_SERVER)));
591 if (client->router == from) {
592 if (resolve_real_server) {
594 silc_server_update_clients_by_real_server(server, from, to,
598 client->router = from;
604 /* All are changed */
605 if (resolve_real_server)
606 /* Call this so that the entry is moved to correct list if
607 needed. No resolving by real server is actually done. */
608 silc_server_update_clients_by_real_server(server, NULL, to,
615 if (client->router && client->router->id)
616 SILC_LOG_DEBUG(("Client changed to %s",
617 silc_id_render(client->router->id, SILC_ID_SERVER)));
622 /* Updates servers that are from `from' to be originated from `to'. This
623 will also update the server's connection to `to's connection. */
625 void silc_server_update_servers_by_server(SilcServer server,
626 SilcServerEntry from,
630 SilcIDCacheEntry id_cache = NULL;
631 SilcServerEntry server_entry = NULL;
633 SILC_LOG_DEBUG(("Updating servers"));
635 if (silc_idcache_get_all(server->local_list->servers, &list)) {
636 silc_list_start(list);
637 while ((id_cache = silc_list_get(list))) {
638 server_entry = (SilcServerEntry)id_cache->context;
640 /* If entry is local to us, do not switch it to any anyone else,
642 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
643 server_entry == from)
646 /* If we are standalone router, any server that is not directly
647 connected to cannot exist anymore. If we are not standalone
648 we update it correctly. */
649 if (server->server_type == SILC_ROUTER && server->standalone) {
650 silc_server_backup_del(server, server_entry);
651 silc_server_backup_replaced_del(server, server_entry);
652 silc_idlist_del_data(server_entry);
653 silc_idlist_del_server(server->local_list, server_entry);
654 server->stat.servers--;
655 server->stat.cell_servers--;
657 /* XXX if we are not standalone, do a check from local config
658 whether this server is in our cell, but not connected to
659 us (in which case we must remove it). */
662 if (server_entry->router == from) {
663 SILC_LOG_DEBUG(("Updating server (local) %s",
664 server_entry->server_name ?
665 server_entry->server_name : ""));
666 server_entry->router = to;
667 server_entry->connection = to->connection;
671 SILC_LOG_DEBUG(("Updating server (local) %s",
672 server_entry->server_name ?
673 server_entry->server_name : ""));
674 server_entry->router = to;
675 server_entry->connection = to->connection;
681 if (silc_idcache_get_all(server->global_list->servers, &list)) {
682 silc_list_start(list);
683 while ((id_cache = silc_list_get(list))) {
684 server_entry = (SilcServerEntry)id_cache->context;
686 /* If entry is local to us, do not switch it to anyone else,
688 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
689 server_entry == from)
692 /* If we are standalone router, any server that is not directly
693 connected to cannot exist anymore. If we are not standalone
694 we update it correctly. */
695 if (server->server_type == SILC_ROUTER && server->standalone) {
696 silc_server_backup_del(server, server_entry);
697 silc_server_backup_replaced_del(server, server_entry);
698 silc_idlist_del_data(server_entry);
699 silc_idlist_del_server(server->global_list, server_entry);
700 server->stat.servers--;
701 server->stat.cell_servers--;
703 /* XXX if we are not standalone, do a check from local config
704 whether this server is in our cell, but not connected to
705 us (in which case we must remove it). */
708 if (server_entry->router == from) {
709 SILC_LOG_DEBUG(("Updating server (global) %s",
710 server_entry->server_name ?
711 server_entry->server_name : ""));
712 server_entry->router = to;
713 server_entry->connection = to->connection;
717 SILC_LOG_DEBUG(("Updating server (global) %s",
718 server_entry->server_name ?
719 server_entry->server_name : ""));
720 server_entry->router = to;
721 server_entry->connection = to->connection;
729 /* Toggles the enabled/disabled status of local server connections. Packets
730 can be sent to the servers when `toggle_enabled' is TRUE and will be
731 dropped if `toggle_enabled' is FALSE, after this function is called. */
733 void silc_server_local_servers_toggle_enabled(SilcServer server,
734 SilcBool toggle_enabled)
737 SilcIDCacheEntry id_cache = NULL;
738 SilcServerEntry server_entry = NULL;
740 if (silc_idcache_get_all(server->local_list->servers, &list)) {
741 silc_list_start(list);
742 while ((id_cache = silc_list_get(list))) {
743 server_entry = (SilcServerEntry)id_cache->context;
744 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry)
748 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
750 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
755 if (silc_idcache_get_all(server->global_list->servers, &list)) {
756 silc_list_start(list);
757 while ((id_cache = silc_list_get(list))) {
758 server_entry = (SilcServerEntry)id_cache->context;
759 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry)
763 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
765 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
771 /* Removes servers that are originated from the `from'. The server
772 entry is deleted in this function. If `remove_clients' is TRUE then
773 all clients originated from the server are removed too, and server
774 signoff is sent. Note that this does not remove the `from'. This
775 also does not remove locally connected servers. */
777 void silc_server_remove_servers_by_server(SilcServer server,
778 SilcServerEntry from,
779 SilcBool remove_clients)
782 SilcIDCacheEntry id_cache = NULL;
783 SilcServerEntry server_entry = NULL;
785 SILC_LOG_DEBUG(("Removing servers by %s",
786 from->server_name ? from->server_name : "server"));
788 if (silc_idcache_get_all(server->local_list->servers, &list)) {
789 silc_list_start(list);
790 while ((id_cache = silc_list_get(list))) {
791 server_entry = (SilcServerEntry)id_cache->context;
792 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
793 server_entry->router != from || server_entry == from)
796 /* Remove clients owned by this server */
798 silc_server_remove_clients_by_server(server, from, server_entry,
801 /* Remove the server */
802 silc_server_backup_del(server, server_entry);
803 silc_idlist_del_server(server->local_list, server_entry);
807 if (silc_idcache_get_all(server->global_list->servers, &list)) {
808 silc_list_start(list);
809 while ((id_cache = silc_list_get(list))) {
810 server_entry = (SilcServerEntry)id_cache->context;
811 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
812 server_entry->router != from || server_entry == from)
815 /* Remove clients owned by this server */
817 silc_server_remove_clients_by_server(server, from, server_entry,
820 /* Remove the server */
821 silc_server_backup_del(server, server_entry);
822 silc_idlist_del_server(server->global_list, server_entry);
827 /* Removes channels that are from `from. */
829 void silc_server_remove_channels_by_server(SilcServer server,
830 SilcServerEntry from)
833 SilcIDCacheEntry id_cache = NULL;
834 SilcChannelEntry channel = NULL;
836 SILC_LOG_DEBUG(("Removing channels by server"));
838 if (silc_idcache_get_all(server->global_list->channels, &list)) {
839 silc_list_start(list);
840 while ((id_cache = silc_list_get(list))) {
841 channel = (SilcChannelEntry)id_cache->context;
842 if (channel->router == from)
843 silc_idlist_del_channel(server->global_list, channel);
848 /* Updates channels that are from `from' to be originated from `to'. */
850 void silc_server_update_channels_by_server(SilcServer server,
851 SilcServerEntry from,
855 SilcIDCacheEntry id_cache = NULL;
856 SilcChannelEntry channel = NULL;
858 SILC_LOG_DEBUG(("Updating channels by server"));
860 if (silc_idcache_get_all(server->global_list->channels, &list)) {
861 silc_list_start(list);
862 while ((id_cache = silc_list_get(list))) {
863 channel = (SilcChannelEntry)id_cache->context;
865 if (channel->router == from)
866 channel->router = to;
869 channel->router = to;
875 /* Checks whether given channel has global users. If it does this returns
876 TRUE and FALSE if there is only locally connected clients on the channel. */
878 SilcBool silc_server_channel_has_global(SilcChannelEntry channel)
880 SilcChannelClientEntry chl;
881 SilcHashTableList htl;
883 silc_hash_table_list(channel->user_list, &htl);
884 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
885 if (chl->client->router) {
886 silc_hash_table_list_reset(&htl);
890 silc_hash_table_list_reset(&htl);
895 /* Checks whether given channel has locally connected users. If it does this
896 returns TRUE and FALSE if there is not one locally connected client. */
898 SilcBool silc_server_channel_has_local(SilcChannelEntry channel)
900 SilcChannelClientEntry chl;
901 SilcHashTableList htl;
903 silc_hash_table_list(channel->user_list, &htl);
904 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
905 if (SILC_IS_LOCAL(chl->client)) {
906 silc_hash_table_list_reset(&htl);
910 silc_hash_table_list_reset(&htl);
915 /* This function removes the channel and all users on the channel, unless
916 the channel is permanent. In this case the channel is disabled but all
917 users are removed from the channel. Returns TRUE if the channel is
918 destroyed totally, and FALSE if it is permanent and remains. */
920 SilcBool silc_server_channel_delete(SilcServer server,
921 SilcChannelEntry channel)
923 SilcChannelClientEntry chl;
924 SilcHashTableList htl;
925 SilcBool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
927 SILC_LOG_DEBUG(("Deleting channel %s", channel->channel_name));
930 /* Update statistics */
931 if (server->server_type == SILC_ROUTER)
932 server->stat.chanclients -= channel->user_count;
934 /* Totally delete the channel and all users on the channel. The
935 users are deleted automatically in silc_idlist_del_channel. */
936 channel->disabled = TRUE;
937 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
938 if (silc_idlist_del_channel(server->local_list, channel)) {
939 server->stat.my_channels--;
940 if (server->server_type == SILC_ROUTER) {
941 server->stat.channels--;
942 server->stat.cell_channels--;
945 if (silc_idlist_del_channel(server->global_list, channel))
946 if (server->server_type == SILC_ROUTER)
947 server->stat.channels--;
953 /* Channel is permanent, do not remove it, remove only users */
954 channel->disabled = TRUE;
955 silc_hash_table_list(channel->user_list, &htl);
956 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
957 silc_hash_table_del(chl->client->channels, channel);
958 silc_hash_table_del(channel->user_list, chl->client);
959 channel->user_count--;
961 /* Update statistics */
962 if (SILC_IS_LOCAL(chl->client))
963 server->stat.my_chanclients--;
964 if (server->server_type == SILC_ROUTER) {
965 server->stat.cell_chanclients--;
966 server->stat.chanclients--;
971 silc_hash_table_list_reset(&htl);
973 SILC_LOG_DEBUG(("Channel %s remains (permanent)", channel->channel_name));
978 /* Returns TRUE if the given client is on the channel. FALSE if not.
979 This works because we assure that the user list on the channel is
980 always in up to date thus we can only check the channel list from
981 `client' which is faster than checking the user list from `channel'. */
983 SilcBool silc_server_client_on_channel(SilcClientEntry client,
984 SilcChannelEntry channel,
985 SilcChannelClientEntry *chl)
987 if (!client || !channel)
990 return silc_hash_table_find(client->channels, channel, NULL,
994 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
995 socket connections with the IP address does not exist. Counts only
996 fully established connections. */
998 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
999 SilcConnectionType type)
1001 SilcServerConnection conn;
1002 SilcIDListData idata;
1006 silc_dlist_start(server->conns);
1007 while ((conn = silc_dlist_get(server->conns))) {
1010 silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->sock),
1011 NULL, NULL, &ipaddr, NULL);
1012 idata = silc_packet_get_context(conn->sock);
1013 if (!strcmp(ipaddr, ip) && idata && idata->conn_type == type)
1020 /* Find active socket connection by the IP address and port indicated by
1021 `ip' and `port', and socket connection type of `type'. */
1024 silc_server_find_socket_by_host(SilcServer server,
1025 SilcConnectionType type,
1026 const char *ip, SilcUInt16 port)
1028 SilcServerConnection conn;
1029 SilcIDListData idata;
1032 silc_dlist_start(server->conns);
1033 while ((conn = silc_dlist_get(server->conns))) {
1036 idata = silc_packet_get_context(conn->sock);
1037 silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->sock),
1038 NULL, NULL, &ipaddr, NULL);
1039 if (!strcmp(ipaddr, ip) &&
1040 (!port || conn->remote_port == port) &&
1041 idata->conn_type == type)
1048 /* Find number of sockets by IP address indicated by remote host, indicatd
1049 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1050 does not exist. If `ip' is provided then `hostname' is ignored. */
1052 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1054 const char *hostname,
1057 SilcServerConnection conn;
1060 if (!ip && !hostname)
1063 silc_dlist_start(server->conns);
1064 while ((conn = silc_dlist_get(server->conns))) {
1065 if (((ip && !strcmp(conn->remote_host, ip)) ||
1066 (hostname && !strcmp(conn->remote_host, hostname))) &&
1067 conn->remote_port == port)
1074 /* SKR find callbcak */
1076 static void find_callback(SilcSKR skr, SilcSKRFind find,
1077 SilcSKRStatus status, SilcDList keys,
1080 SilcPublicKey *public_key = context;
1084 silc_dlist_start(keys);
1085 key = silc_dlist_get(keys);
1086 *public_key = key->key;
1087 silc_dlist_uninit(keys);
1090 silc_skr_find_free(find);
1093 /* Get public key by key usage and key context. */
1095 SilcPublicKey silc_server_get_public_key(SilcServer server,
1096 SilcSKRKeyUsage usage,
1100 SilcPublicKey public_key = NULL;
1102 SILC_LOG_DEBUG(("Start"));
1104 find = silc_skr_find_alloc();
1108 silc_skr_find_set_usage(find, usage);
1109 silc_skr_find_set_context(find, key_context);
1110 silc_skr_find(server->repository, server->schedule,
1111 find, find_callback, &public_key);
1116 /* Find public key by client for identification purposes. Finds keys
1117 with SILC_SKR_USAGE_IDENTIFICATION. */
1119 SilcBool silc_server_get_public_key_by_client(SilcServer server,
1120 SilcClientEntry client,
1121 SilcPublicKey *public_key)
1123 SilcPublicKey pubkey = NULL;
1124 SilcBool ret = FALSE;
1126 pubkey = silc_server_get_public_key(server, SILC_SKR_USAGE_IDENTIFICATION,
1132 *public_key = pubkey;
1137 /* Check whether the connection `sock' is allowed to connect to us. This
1138 checks for example whether there is too much connections for this host,
1139 and required version for the host etc. */
1141 SilcBool silc_server_connection_allowed(SilcServer server,
1142 SilcPacketStream sock,
1143 SilcConnectionType type,
1144 SilcServerConfigConnParams *global,
1145 SilcServerConfigConnParams *params,
1148 SilcUInt32 conn_number = (type == SILC_CONN_CLIENT ?
1149 server->stat.my_clients :
1150 type == SILC_CONN_SERVER ?
1151 server->stat.my_servers :
1152 server->stat.my_routers);
1153 SilcUInt32 num_sockets, max_hosts, max_per_host;
1154 SilcUInt32 r_protocol_version, l_protocol_version;
1155 SilcUInt32 r_software_version, l_software_version;
1156 char *r_vendor_version = NULL, *l_vendor_version;
1157 const char *hostname, *ip;
1159 silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
1160 NULL, &hostname, &ip, NULL);
1162 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1166 l_protocol_version =
1167 silc_version_to_num(params && params->version_protocol ?
1168 params->version_protocol :
1169 global->version_protocol);
1170 l_software_version =
1171 silc_version_to_num(params && params->version_software ?
1172 params->version_software :
1173 global->version_software);
1174 l_vendor_version = (params && params->version_software_vendor ?
1175 params->version_software_vendor :
1176 global->version_software_vendor);
1178 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1179 &r_software_version, NULL,
1180 &r_vendor_version)) {
1181 /* Match protocol version */
1182 if (l_protocol_version && r_protocol_version &&
1183 r_protocol_version < l_protocol_version) {
1184 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1186 silc_server_disconnect_remote(server, sock,
1187 SILC_STATUS_ERR_BAD_VERSION,
1188 "You support too old protocol version");
1192 /* Math software version */
1193 if (l_software_version && r_software_version &&
1194 r_software_version < l_software_version) {
1195 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1197 silc_server_disconnect_remote(server, sock,
1198 SILC_STATUS_ERR_BAD_VERSION,
1199 "You support too old software version");
1203 /* Regex match vendor version */
1204 if (l_vendor_version && r_vendor_version &&
1205 !silc_string_match(l_vendor_version, r_vendor_version)) {
1206 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1208 silc_server_disconnect_remote(server, sock,
1209 SILC_STATUS_ERR_BAD_VERSION,
1210 "Your software is not supported");
1214 silc_free(r_vendor_version);
1216 /* Check for maximum connections limit */
1218 num_sockets = silc_server_num_sockets_by_ip(server, ip, type);
1219 max_hosts = (params ? params->connections_max : global->connections_max);
1220 max_per_host = (params ? params->connections_max_per_host :
1221 global->connections_max_per_host);
1223 if (max_hosts && conn_number >= max_hosts) {
1224 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1226 silc_server_disconnect_remote(server, sock,
1227 SILC_STATUS_ERR_RESOURCE_LIMIT,
1228 "Server is full, try again later");
1232 if (num_sockets >= max_per_host) {
1233 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1235 silc_server_disconnect_remote(server, sock,
1236 SILC_STATUS_ERR_RESOURCE_LIMIT,
1237 "Too many connections from your host");
1244 /* Checks that client has rights to add or remove channel modes. If any
1245 of the checks fails FALSE is returned. */
1247 SilcBool silc_server_check_cmode_rights(SilcServer server,
1248 SilcChannelEntry channel,
1249 SilcChannelClientEntry client,
1252 SilcBool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1253 SilcBool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1255 /* Check whether has rights to change anything */
1256 if (!is_op && !is_fo)
1259 /* Check whether has rights to change everything */
1263 /* Founder implies operator */
1267 /* We know that client is channel operator, check that they are not
1268 changing anything that requires channel founder rights. Rest of the
1269 modes are available automatically for channel operator. */
1271 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1272 if (is_op && !is_fo)
1275 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1276 if (is_op && !is_fo)
1281 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1282 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1283 if (is_op && !is_fo)
1287 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1288 if (is_op && !is_fo)
1293 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1294 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1295 if (is_op && !is_fo)
1299 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1300 if (is_op && !is_fo)
1305 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1306 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1307 if (is_op && !is_fo)
1311 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1312 if (is_op && !is_fo)
1317 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1318 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1319 if (is_op && !is_fo)
1323 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1324 if (is_op && !is_fo)
1329 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1330 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1331 if (is_op && !is_fo)
1335 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1336 if (is_op && !is_fo)
1341 if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1342 if (!(channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)) {
1343 if (is_op && !is_fo)
1347 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1348 if (is_op && !is_fo)
1356 /* Check that the client has rights to change its user mode. Returns
1357 FALSE if setting some mode is not allowed. */
1359 SilcBool silc_server_check_umode_rights(SilcServer server,
1360 SilcClientEntry client,
1363 SilcBool server_op = FALSE, router_op = FALSE;
1365 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1366 /* Cannot set server operator mode (must use OPER command) */
1367 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1370 /* Remove the server operator rights */
1371 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1375 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1376 /* Cannot set router operator mode (must use SILCOPER command) */
1377 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1380 /* Remove the router operator rights */
1381 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1386 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1388 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1393 /* This function is used to send the notify packets and motd to the
1394 incoming client connection. */
1396 void silc_server_send_connect_notifys(SilcServer server,
1397 SilcPacketStream sock,
1398 SilcClientEntry client)
1402 SILC_LOG_DEBUG(("Send welcome notifys"));
1404 /* Send some nice info to the client */
1405 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1406 ("Welcome to the SILC Network %s",
1408 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1409 ("Your host is %s, running version %s",
1410 server->server_name, server_version));
1412 if (server->server_type == SILC_ROUTER) {
1413 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1414 ("There are %d clients, %d servers and %d "
1415 "routers in SILC Network",
1416 server->stat.clients, server->stat.servers,
1417 server->stat.routers));
1419 if (server->stat.clients && server->stat.servers + 1)
1420 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1421 ("There are %d clients, %d servers and %d "
1422 "routers in SILC Network",
1423 server->stat.clients, server->stat.servers,
1424 (server->standalone ? 0 :
1425 !server->stat.routers ? 1 :
1426 server->stat.routers)));
1429 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1430 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1431 ("There are %d clients on %d servers in our cell",
1432 server->stat.cell_clients,
1433 server->stat.cell_servers));
1434 if (server->server_type == SILC_ROUTER) {
1435 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1436 ("I have %d clients, %d channels, %d servers and "
1438 server->stat.my_clients,
1439 server->stat.my_channels,
1440 server->stat.my_servers,
1441 server->stat.my_routers));
1443 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1444 ("I have %d clients and %d channels formed",
1445 server->stat.my_clients,
1446 server->stat.my_channels));
1449 if (server->stat.server_ops || server->stat.router_ops)
1450 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1451 ("There are %d server operators and %d router "
1453 server->stat.server_ops,
1454 server->stat.router_ops));
1455 if (server->stat.my_router_ops + server->stat.my_server_ops)
1456 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1457 ("I have %d operators online",
1458 server->stat.my_router_ops +
1459 server->stat.my_server_ops));
1461 silc_packet_get_keys(sock, &key, NULL, NULL, NULL);
1462 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1463 ("Your connection is secured with %s cipher, "
1464 "key length %d bits",
1465 silc_cipher_get_name(key),
1466 silc_cipher_get_key_len(key)));
1467 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1468 ("Your current nickname is %s",
1472 silc_server_send_motd(server, sock);
1475 /* Kill the client indicated by `remote_client' sending KILLED notify
1476 to the client, to all channels client has joined and to primary
1477 router if needed. The killed client is also removed from all channels. */
1479 void silc_server_kill_client(SilcServer server,
1480 SilcClientEntry remote_client,
1481 const char *comment,
1483 SilcIdType killer_id_type)
1485 SilcBuffer killed, killer;
1487 SILC_LOG_DEBUG(("Killing client %s",
1488 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1490 /* Send the KILL notify packets. First send it to the channel, then
1491 to our primary router and then directly to the client who is being
1492 killed right now. */
1494 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1495 killer = silc_id_payload_encode(killer_id, killer_id_type);
1497 /* Send KILLED notify to the channels. It is not sent to the client
1498 as it will be sent differently destined directly to the client and not
1500 silc_server_send_notify_on_channels(server, remote_client,
1501 remote_client, SILC_NOTIFY_TYPE_KILLED,
1502 3, killed->data, silc_buffer_len(killed),
1503 comment, comment ? strlen(comment) : 0,
1504 killer->data, silc_buffer_len(killer));
1506 /* Send KILLED notify to primary route */
1507 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1508 SILC_BROADCAST(server), remote_client->id,
1509 comment, killer_id, killer_id_type);
1511 /* Send KILLED notify to the client directly */
1512 if (remote_client->connection || remote_client->router)
1513 silc_server_send_notify_killed(server, remote_client->connection ?
1514 remote_client->connection :
1515 remote_client->router->connection, FALSE,
1516 remote_client->id, comment,
1517 killer_id, killer_id_type);
1519 /* Remove the client from all channels. This generates new keys to the
1520 channels as well. */
1521 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1524 /* Remove the client entry, If it is locally connected then we will also
1525 disconnect the client here */
1526 if (remote_client->connection) {
1527 /* Remove locally conneted client */
1528 SilcPacketStream sock = remote_client->connection;
1529 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1530 silc_server_close_connection(server, sock);
1532 /* Update statistics */
1533 server->stat.clients--;
1534 if (server->stat.cell_clients)
1535 server->stat.cell_clients--;
1536 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1537 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1539 /* Remove client's public key from repository, this will free it too. */
1540 if (remote_client->data.public_key) {
1541 silc_skr_del_public_key(server->repository,
1542 remote_client->data.public_key, remote_client);
1543 remote_client->data.public_key = NULL;
1546 if (SILC_IS_LOCAL(remote_client)) {
1547 server->stat.my_clients--;
1548 silc_schedule_task_del_by_context(server->schedule, remote_client);
1551 /* Remove remote client */
1552 silc_idlist_del_data(remote_client);
1553 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1554 /* Remove this client from watcher list if it is */
1555 silc_server_del_from_watcher_list(server, remote_client);
1556 silc_idlist_del_client(server->local_list, remote_client);
1560 silc_buffer_free(killer);
1561 silc_buffer_free(killed);
1566 SilcClientEntry client;
1567 SilcNotifyType notify;
1568 const char *new_nick;
1569 } WatcherNotifyContext;
1572 silc_server_check_watcher_list_foreach(void *key, void *context,
1575 WatcherNotifyContext *notify = user_context;
1576 SilcClientEntry entry = context;
1577 SilcPacketStream sock;
1582 if (entry == notify->client)
1585 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1588 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1589 silc_id_render(entry->id, SILC_ID_CLIENT)));
1591 /* Send the WATCH notify */
1592 silc_server_send_notify_watch(notify->server, sock, entry,
1594 notify->new_nick ? notify->new_nick :
1595 (const char *)notify->client->nickname,
1597 notify->client->data.public_key);
1601 /* This function checks whether the `client' nickname and/or 'client'
1602 public key is being watched by someone, and notifies the watcher of the
1603 notify change of notify type indicated by `notify'. */
1605 SilcBool silc_server_check_watcher_list(SilcServer server,
1606 SilcClientEntry client,
1607 const char *new_nick,
1608 SilcNotifyType notify)
1610 unsigned char hash[16];
1611 WatcherNotifyContext n;
1613 SILC_LOG_DEBUG(("Checking watcher list %s",
1614 client->nickname ? client->nickname : (unsigned char *)""));
1616 /* If the watching is rejected by the client do nothing */
1617 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1620 /* Make hash from the nick, or take it from Client ID */
1621 if (client->nickname) {
1622 unsigned char *nickc;
1623 nickc = silc_identifier_check(client->nickname, strlen(client->nickname),
1624 SILC_STRING_UTF8, 128, NULL);
1627 silc_hash_make(server->md5hash, nickc, strlen(nickc), hash);
1630 memset(hash, 0, sizeof(hash));
1631 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1636 n.new_nick = new_nick;
1639 /* Send notify to all watchers watching this nickname */
1640 silc_hash_table_find_foreach(server->watcher_list, hash,
1641 silc_server_check_watcher_list_foreach, &n);
1643 /* Send notify to all watchers watching this public key */
1644 if (client->data.public_key)
1645 silc_hash_table_find_foreach(server->watcher_list_pk,
1646 client->data.public_key,
1647 silc_server_check_watcher_list_foreach,
1653 /* Remove the `client' from watcher list. After calling this the `client'
1654 is not watching any nicknames. */
1656 SilcBool silc_server_del_from_watcher_list(SilcServer server,
1657 SilcClientEntry client)
1659 SilcHashTableList htl;
1661 SilcClientEntry entry;
1662 SilcBool found = FALSE;
1664 silc_hash_table_list(server->watcher_list, &htl);
1665 while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1666 if (entry == client) {
1667 silc_hash_table_del_by_context(server->watcher_list, key, client);
1670 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1671 silc_id_render(client->id, SILC_ID_CLIENT)));
1673 /* Now check whether there still exists entries with this key, if not
1674 then free the key to not leak memory. */
1675 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1681 silc_hash_table_list_reset(&htl);
1683 silc_hash_table_list(server->watcher_list_pk, &htl);
1684 while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
1685 if (entry == client) {
1686 silc_hash_table_del_by_context(server->watcher_list_pk, key, client);
1689 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1690 silc_id_render(client->id, SILC_ID_CLIENT)));
1692 /* Now check whether there still exists entries with this key, if not
1693 then free the key to not leak memory. */
1694 if (!silc_hash_table_find(server->watcher_list_pk, key, NULL, NULL))
1695 silc_pkcs_public_key_free(key);
1700 silc_hash_table_list_reset(&htl);
1705 /* Force the client indicated by `chl' to change the channel user mode
1706 on channel indicated by `channel' to `forced_mode'. */
1708 SilcBool silc_server_force_cumode_change(SilcServer server,
1709 SilcPacketStream sock,
1710 SilcChannelEntry channel,
1711 SilcChannelClientEntry chl,
1712 SilcUInt32 forced_mode)
1714 SilcBuffer idp1, idp2;
1715 unsigned char cumode[4];
1717 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1720 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1721 server->id, SILC_ID_SERVER,
1722 chl->client->id, NULL);
1724 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1725 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1726 SILC_PUT32_MSB(forced_mode, cumode);
1727 silc_server_send_notify_to_channel(server, sock, channel, FALSE, TRUE,
1728 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1729 3, idp1->data, silc_buffer_len(idp1),
1730 cumode, sizeof(cumode),
1731 idp2->data, silc_buffer_len(idp2));
1732 silc_buffer_free(idp1);
1733 silc_buffer_free(idp2);
1738 /* This function can be used to match the invite and ban lists. */
1740 SilcBool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1741 SilcUInt8 type, void *check)
1743 unsigned char *tmp = NULL;
1744 SilcUInt32 len = 0, t;
1745 SilcHashTableList htl;
1746 SilcBuffer entry, idp = NULL, pkp = NULL;
1747 SilcBool ret = FALSE;
1749 SILC_LOG_DEBUG(("Matching invite/ban"));
1751 if (type < 1 || type > 3 || !check)
1755 tmp = strdup((char *)check);
1760 pkp = silc_public_key_payload_encode(check);
1764 len = silc_buffer_len(pkp);
1767 idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
1771 len = silc_buffer_len(idp);
1774 /* Compare the list */
1775 silc_hash_table_list(list, &htl);
1776 while (silc_hash_table_get(&htl, (void *)&t, (void *)&entry)) {
1779 if (silc_string_match(entry->data, tmp)) {
1783 } else if (!memcmp(entry->data, tmp, len)) {
1789 silc_hash_table_list_reset(&htl);
1793 silc_buffer_free(idp);
1794 silc_buffer_free(pkp);
1798 /* Process invite or ban information */
1800 SilcBool silc_server_inviteban_process(SilcServer server,
1803 SilcArgumentPayload args)
1806 SilcUInt32 type, len;
1808 SilcHashTableList htl;
1810 SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1811 action == 0x01 ? "DEL" : "ADD"));
1813 /* Add the information to invite list */
1814 if (action == 0x00 || action == 0x03) {
1815 /* Traverse all arguments and add to the hash table according to
1817 tmp = silc_argument_get_first_arg(args, &type, &len);
1820 /* Check validity of the string. Actually we should parse the
1821 whole string and verify all components individually. */
1822 if (!silc_utf8_valid(tmp, len) || !len) {
1823 tmp = silc_argument_get_next_arg(args, &type, &len);
1826 if (strchr(tmp, ',')) {
1827 tmp = silc_argument_get_next_arg(args, &type, &len);
1831 /* Check if the string is added already */
1832 silc_hash_table_list(list, &htl);
1833 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1834 if (type == 1 && silc_string_match(tmp2->data, tmp)) {
1839 silc_hash_table_list_reset(&htl);
1842 /* Add the string to hash table */
1843 tmp2 = silc_buffer_alloc_size(len + 1);
1844 if (tmp[len - 1] == ',')
1845 tmp[len - 1] = '\0';
1846 silc_buffer_put(tmp2, tmp, len);
1847 silc_hash_table_add(list, (void *)1, tmp2);
1850 } else if (type == 2) {
1851 /* Public key. Check first if the public key is already on the
1852 list and ignore it if it is, otherwise, add it to hash table. */
1855 /* Verify validity of the public key */
1856 if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1857 tmp = silc_argument_get_next_arg(args, &type, &len);
1860 silc_pkcs_public_key_free(pk);
1862 /* Check if the public key is in the list already */
1863 silc_hash_table_list(list, &htl);
1864 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1865 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1870 silc_hash_table_list_reset(&htl);
1872 /* Add new public key to invite list */
1874 tmp2 = silc_buffer_alloc_size(len);
1875 silc_buffer_put(tmp2, tmp, len);
1876 silc_hash_table_add(list, (void *)2, tmp2);
1879 } else if (type == 3) {
1882 /* Check if the ID is in the list already */
1883 silc_hash_table_list(list, &htl);
1884 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1885 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1890 silc_hash_table_list_reset(&htl);
1892 /* Add new Client ID to invite list */
1894 tmp2 = silc_buffer_alloc_size(len);
1895 silc_buffer_put(tmp2, tmp, len);
1896 silc_hash_table_add(list, (void *)3, tmp2);
1900 tmp = silc_argument_get_next_arg(args, &type, &len);
1904 /* Delete information to invite list */
1905 if (action == 0x01 && list) {
1906 /* Now delete the arguments from invite list */
1907 tmp = silc_argument_get_first_arg(args, &type, &len);
1910 /* Check validity of the string. Actually we should parse the
1911 whole string and verify all components individually. */
1912 if (!silc_utf8_valid(tmp, len)) {
1913 tmp = silc_argument_get_next_arg(args, &type, &len);
1916 if (strchr(tmp, ',')) {
1917 tmp = silc_argument_get_next_arg(args, &type, &len);
1921 /* Delete from the list */
1922 silc_hash_table_list(list, &htl);
1923 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1924 if (type == 1 && silc_string_match(tmp2->data, tmp)) {
1925 silc_hash_table_del_by_context(list, (void *)1, tmp2);
1929 silc_hash_table_list_reset(&htl);
1931 } else if (type == 2) {
1935 /* Verify validity of the public key */
1936 if (!silc_public_key_payload_decode(tmp, len, &pk)) {
1937 tmp = silc_argument_get_next_arg(args, &type, &len);
1940 silc_pkcs_public_key_free(pk);
1942 /* Delete from the invite list */
1943 silc_hash_table_list(list, &htl);
1944 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1945 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1946 silc_hash_table_del_by_context(list, (void *)2, tmp2);
1950 silc_hash_table_list_reset(&htl);
1952 } else if (type == 3) {
1955 /* Delete from the invite list */
1956 silc_hash_table_list(list, &htl);
1957 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1958 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1959 silc_hash_table_del_by_context(list, (void *)3, tmp2);
1963 silc_hash_table_list_reset(&htl);
1966 tmp = silc_argument_get_next_arg(args, &type, &len);
1973 /* Destructor for invite and ban list entrys */
1975 void silc_server_inviteban_destruct(void *key, void *context,
1978 silc_buffer_free(context);
1981 /* Creates connections accoring to configuration. */
1983 void silc_server_create_connections(SilcServer server)
1985 silc_schedule_task_del_by_callback(server->schedule,
1986 silc_server_connect_to_router);
1987 silc_schedule_task_add_timeout(server->schedule,
1988 silc_server_connect_to_router, server, 0, 1);
1992 silc_server_process_channel_pk_destruct(void *key, void *context,
1996 silc_pkcs_public_key_free(context);
1999 /* Processes a channel public key, either adds or removes it. */
2002 silc_server_process_channel_pk(SilcServer server,
2003 SilcChannelEntry channel,
2004 SilcUInt32 type, const unsigned char *pk,
2007 unsigned char pkhash[20];
2010 SILC_LOG_DEBUG(("Processing channel public key"));
2013 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2015 /* Decode the public key */
2016 if (!silc_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
2017 return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
2019 /* Create channel public key list (hash table) if needed */
2020 if (!channel->channel_pubkeys) {
2021 channel->channel_pubkeys =
2022 silc_hash_table_alloc(0, silc_hash_data, (void *)20,
2023 silc_hash_data_compare, (void *)20,
2024 silc_server_process_channel_pk_destruct, channel,
2028 /* Create SHA-1 digest of the public key data */
2029 silc_hash_make(server->sha1hash, pk + 4, pk_len - 4, pkhash);
2032 /* Add new public key to channel public key list */
2033 SILC_LOG_DEBUG(("Add new channel public key to channel %s",
2034 channel->channel_name));
2036 /* Check for resource limit */
2037 if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
2038 silc_pkcs_public_key_free(chpk);
2039 return SILC_STATUS_ERR_RESOURCE_LIMIT;
2042 /* Add if doesn't exist already */
2043 if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2045 silc_hash_table_add(channel->channel_pubkeys, silc_memdup(pkhash, 20),
2047 } else if (type == 0x01) {
2048 /* Delete public key from channel public key list */
2049 SILC_LOG_DEBUG(("Delete a channel public key from channel %s",
2050 channel->channel_name));
2051 if (!silc_hash_table_del(channel->channel_pubkeys, pkhash))
2052 silc_pkcs_public_key_free(chpk);
2054 silc_pkcs_public_key_free(chpk);
2055 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2058 return SILC_STATUS_OK;
2061 /* Returns the channel public keys as Argument List payload. */
2063 SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
2064 SilcChannelEntry channel,
2068 SilcHashTableList htl;
2069 SilcBuffer list, pkp;
2072 SILC_LOG_DEBUG(("Encoding channel public keys list"));
2074 if (!channel->channel_pubkeys ||
2075 !silc_hash_table_count(channel->channel_pubkeys))
2078 /* Encode the list */
2079 list = silc_buffer_alloc_size(2);
2080 silc_buffer_format(list,
2081 SILC_STR_UI_SHORT(silc_hash_table_count(
2082 channel->channel_pubkeys)),
2085 silc_hash_table_list(channel->channel_pubkeys, &htl);
2086 while (silc_hash_table_get(&htl, NULL, (void *)&pk)) {
2087 pkp = silc_public_key_payload_encode(pk);
2088 list = silc_argument_payload_encode_one(list, pkp->data,
2089 silc_buffer_len(pkp),
2091 delete ? 0x01 : 0x00);
2092 silc_buffer_free(pkp);
2094 silc_hash_table_list_reset(&htl);
2099 /* Sets the channel public keys into channel from the list of public keys. */
2101 SilcStatus silc_server_set_channel_pk_list(SilcServer server,
2102 SilcPacketStream sender,
2103 SilcChannelEntry channel,
2104 const unsigned char *pklist,
2105 SilcUInt32 pklist_len)
2108 SilcArgumentPayload args;
2109 unsigned char *chpk;
2110 SilcUInt32 chpklen, type;
2111 SilcStatus ret = SILC_STATUS_OK;
2113 SILC_LOG_DEBUG(("Setting channel public keys list"));
2115 if (!pklist || pklist_len < 2)
2116 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2118 /* Get the argument from the Argument List Payload */
2119 SILC_GET16_MSB(argc, pklist);
2120 args = silc_argument_payload_parse(pklist + 2, pklist_len - 2, argc);
2122 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2124 /* Process the public keys one by one */
2125 chpk = silc_argument_get_first_arg(args, &type, &chpklen);
2127 /* If announcing keys and we have them set already, do not allow this */
2128 if (chpk && type == 0x03 && channel->channel_pubkeys &&
2129 server->server_type == SILC_ROUTER &&
2130 sender != SILC_PRIMARY_ROUTE(server)) {
2131 SILC_LOG_DEBUG(("Channel public key list set already, enforce our list"));
2132 silc_argument_payload_free(args);
2133 return SILC_STATUS_ERR_OPERATION_ALLOWED;
2136 /* If we are normal server and receive announcement list and we already
2137 have keys set, we replace the old list with the announced one. */
2138 if (chpk && type == 0x03 && channel->channel_pubkeys &&
2139 server->server_type != SILC_ROUTER) {
2141 unsigned char mask[4], ulimit[4];
2143 SILC_LOG_DEBUG(("Router enforces its list, remove old list"));
2144 silc_hash_table_free(channel->channel_pubkeys);
2145 channel->channel_pubkeys = NULL;
2147 /* Send notify that removes the old list */
2148 sidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2149 SILC_PUT32_MSB((channel->mode & (~SILC_CHANNEL_MODE_CHANNEL_AUTH)), mask);
2150 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2151 SILC_PUT32_MSB(channel->user_limit, ulimit);
2152 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2153 SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
2154 sidp->data, silc_buffer_len(sidp),
2158 strlen(channel->cipher) : 0,
2160 channel->hmac_name ?
2161 strlen(channel->hmac_name) : 0,
2162 channel->passphrase,
2163 channel->passphrase ?
2164 strlen(channel->passphrase) : 0,
2167 SILC_CHANNEL_MODE_ULIMIT ?
2170 SILC_CHANNEL_MODE_ULIMIT ?
2171 sizeof(ulimit) : 0));
2172 silc_buffer_free(sidp);
2178 ret = silc_server_process_channel_pk(server, channel, type,
2180 if (ret != SILC_STATUS_OK)
2182 chpk = silc_argument_get_next_arg(args, &type, &chpklen);
2185 silc_argument_payload_free(args);
2189 /* Verifies the Authentication Payload `auth' with one of the public keys
2190 on the `channel' public key list. */
2192 SilcBool silc_server_verify_channel_auth(SilcServer server,
2193 SilcChannelEntry channel,
2194 SilcClientID *client_id,
2195 const unsigned char *auth,
2196 SilcUInt32 auth_len)
2200 unsigned char *pkhash;
2201 SilcUInt32 pkhash_len;
2202 SilcBool ret = FALSE;
2204 SILC_LOG_DEBUG(("Verifying channel authentication"));
2206 if (!auth || !auth_len || !channel->channel_pubkeys)
2209 /* Get the hash from the auth data which tells us what public key we
2210 must use in verification. */
2212 ap = silc_auth_payload_parse(auth, auth_len);
2216 pkhash = silc_auth_get_public_data(ap, &pkhash_len);
2217 if (pkhash_len < 128)
2220 /* Find the public key with the hash */
2221 if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2222 NULL, (void *)&chpk)) {
2223 SILC_LOG_DEBUG(("Public key not found in channel public key list"));
2227 /* Verify the signature */
2228 if (!silc_auth_verify(ap, SILC_AUTH_PUBLIC_KEY, (void *)chpk, 0,
2229 server->sha1hash, client_id, SILC_ID_CLIENT)) {
2230 SILC_LOG_DEBUG(("Authentication failed"));
2237 silc_auth_payload_free(ap);