5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2003 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);
124 /* This function removes all client entries that are originated from
125 `router' and are owned by `entry'. `router' and `entry' can be same
126 too. If `server_signoff' is TRUE then SERVER_SIGNOFF notify is
127 distributed to our local clients. */
129 bool silc_server_remove_clients_by_server(SilcServer server,
130 SilcServerEntry router,
131 SilcServerEntry entry,
134 SilcIDCacheList list = NULL;
135 SilcIDCacheEntry id_cache = NULL;
136 SilcClientEntry client = NULL;
138 unsigned char **argv = NULL;
139 SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
140 SilcHashTableList htl;
141 SilcChannelEntry channel;
142 SilcHashTable channels, clients;
145 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
148 SILC_LOG_DEBUG(("Removing clients by %s",
149 entry->server_name ? entry->server_name : "server"));
154 /* Allocate the hash table that holds the channels that require
155 channel key re-generation after we've removed this server's clients
156 from the channels. */
157 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
159 clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
162 if (server_signoff) {
163 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
164 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
165 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
166 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
167 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
168 memcpy(argv[argc], idp->data, idp->len);
169 argv_lens[argc] = idp->len;
170 argv_types[argc] = argc + 1;
172 silc_buffer_free(idp);
175 if (silc_idcache_get_all(server->local_list->clients, &list)) {
176 if (silc_idcache_list_first(list, &id_cache)) {
178 client = (SilcClientEntry)id_cache->context;
180 /* If client is not registered, is not originated from `router'
181 and is not owned by `entry', skip it. */
182 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
183 client->router != router ||
184 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
185 client->id->ip.data_len))) {
186 if (!silc_idcache_list_next(list, &id_cache))
192 if (server_signoff) {
193 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
194 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
195 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
197 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
199 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
200 memcpy(argv[argc], idp->data, idp->len);
201 argv_lens[argc] = idp->len;
202 argv_types[argc] = argc + 1;
204 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 silc_server_remove_clients_channels(server, entry, clients,
216 silc_server_del_from_watcher_list(server, client);
218 /* Remove the client entry */
219 if (!server_signoff) {
220 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
221 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
223 silc_idlist_del_data(client);
224 silc_idlist_del_client(server->local_list, client);
227 if (!silc_idcache_list_next(list, &id_cache))
231 silc_idcache_list_free(list);
234 if (silc_idcache_get_all(server->global_list->clients, &list)) {
236 if (silc_idcache_list_first(list, &id_cache)) {
238 client = (SilcClientEntry)id_cache->context;
240 /* If client is not registered, is not originated from `router'
241 and is not owned by `entry', skip it. */
242 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
243 client->router != router ||
244 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
245 client->id->ip.data_len))) {
246 if (!silc_idcache_list_next(list, &id_cache))
252 if (server_signoff) {
253 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
254 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
255 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
257 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
259 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
260 memcpy(argv[argc], idp->data, idp->len);
261 argv_lens[argc] = idp->len;
262 argv_types[argc] = argc + 1;
264 silc_buffer_free(idp);
267 /* Update statistics */
268 server->stat.clients--;
269 if (server->stat.cell_clients)
270 server->stat.cell_clients--;
271 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
272 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
274 silc_server_remove_clients_channels(server, entry, clients,
276 silc_server_del_from_watcher_list(server, client);
278 /* Remove the client entry */
279 if (!server_signoff) {
280 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
281 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
283 silc_idlist_del_data(client);
284 silc_idlist_del_client(server->global_list, client);
287 if (!silc_idcache_list_next(list, &id_cache))
291 silc_idcache_list_free(list);
294 /* Return now if we are shutting down */
295 if (server->server_shutdown) {
296 silc_hash_table_free(channels);
298 if (server_signoff) {
299 for (i = 0; i < argc; i++)
302 silc_free(argv_lens);
303 silc_free(argv_types);
304 silc_hash_table_free(clients);
309 /* Send the SERVER_SIGNOFF notify */
310 if (server_signoff) {
311 SilcBuffer args, not;
313 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
314 silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
316 /* Send SERVER_SIGNOFF notify to our primary router */
317 if (server->router != entry) {
318 args = silc_argument_payload_encode(1, argv, argv_lens,
320 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
321 SILC_BROADCAST(server),
322 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
324 silc_buffer_free(args);
327 /* Send to local clients. We also send the list of client ID's that
328 is to be removed for those servers that would like to use that list. */
329 args = silc_argument_payload_encode(argc, argv, argv_lens,
331 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
333 silc_server_packet_send_clients(server, clients,
334 SILC_PACKET_NOTIFY, 0, FALSE,
335 not->data, not->len, FALSE);
337 /* Send notify also to local backup routers */
338 silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
339 not->data, not->len, FALSE, TRUE);
341 silc_buffer_free(args);
342 silc_buffer_free(not);
343 for (i = 0; i < argc; i++)
346 silc_free(argv_lens);
347 silc_free(argv_types);
348 silc_hash_table_free(clients);
351 /* We must now re-generate the channel key for all channels that had
352 this server's client(s) on the channel. As they left the channel we
353 must re-generate the channel key. */
354 silc_hash_table_list(channels, &htl);
355 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
356 if (!silc_server_create_channel_key(server, channel, 0)) {
357 silc_hash_table_list_reset(&htl);
358 silc_hash_table_free(channels);
362 /* Do not send the channel key if private channel key mode is set */
363 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->channel_key)
366 silc_server_send_channel_key(server, NULL, channel,
367 server->server_type == SILC_ROUTER ?
368 FALSE : !server->standalone);
370 silc_hash_table_list_reset(&htl);
371 silc_hash_table_free(channels);
376 static SilcServerEntry
377 silc_server_update_clients_by_real_server(SilcServer server,
378 SilcServerEntry from,
380 SilcClientEntry client,
382 SilcIDCacheEntry client_cache)
384 SilcServerEntry server_entry;
385 SilcIDCacheEntry id_cache = NULL;
386 SilcIDCacheList list;
387 bool tolocal = (to == server->id_entry);
389 SILC_LOG_DEBUG(("Start"));
391 if (!silc_idcache_get_all(server->local_list->servers, &list))
394 if (silc_idcache_list_first(list, &id_cache)) {
396 server_entry = (SilcServerEntry)id_cache->context;
397 if (server_entry != from &&
398 (tolocal || server_entry != server->id_entry) &&
399 SILC_ID_COMPARE(server_entry->id, client->id,
400 client->id->ip.data_len)) {
401 SILC_LOG_DEBUG(("Found (local) %s",
402 silc_id_render(server_entry->id, SILC_ID_SERVER)));
404 if (!server_entry->data.send_key && server_entry->router) {
405 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
406 /* If the client is not marked as local then move it to local list
407 since the server is local. */
409 SILC_LOG_DEBUG(("Moving client to local list"));
410 silc_idcache_add(server->local_list->clients, client_cache->name,
411 client_cache->id, client_cache->context,
412 client_cache->expire, NULL);
413 silc_idcache_del_by_context(server->global_list->clients, client);
415 server_entry = server_entry->router;
417 SILC_LOG_DEBUG(("Server locally connected"));
418 /* If the client is not marked as local then move it to local list
419 since the server is local. */
420 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
421 SILC_LOG_DEBUG(("Moving client to local list"));
422 silc_idcache_add(server->local_list->clients, client_cache->name,
423 client_cache->id, client_cache->context,
424 client_cache->expire, NULL);
425 silc_idcache_del_by_context(server->global_list->clients, client);
427 } else if (server->server_type == SILC_BACKUP_ROUTER && local) {
428 /* If we are backup router and this client is on local list, we
429 must move it to global list, as it is not currently local to
430 us (we are not primary). */
431 SILC_LOG_DEBUG(("Moving client to global list"));
432 silc_idcache_add(server->global_list->clients, client_cache->name,
433 client_cache->id, client_cache->context,
434 client_cache->expire, NULL);
435 silc_idcache_del_by_context(server->local_list->clients, client);
439 silc_idcache_list_free(list);
443 if (!silc_idcache_list_next(list, &id_cache))
448 silc_idcache_list_free(list);
450 if (!silc_idcache_get_all(server->global_list->servers, &list))
453 if (silc_idcache_list_first(list, &id_cache)) {
455 server_entry = (SilcServerEntry)id_cache->context;
456 if (server_entry != from && server_entry != server->id_entry &&
457 (tolocal || server_entry != server->id_entry) &&
458 SILC_ID_COMPARE(server_entry->id, client->id,
459 client->id->ip.data_len)) {
460 SILC_LOG_DEBUG(("Found (global) %s",
461 silc_id_render(server_entry->id, SILC_ID_SERVER)));
463 if (!server_entry->data.send_key && server_entry->router) {
464 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
465 /* If the client is marked as local then move it to global list
466 since the server is global. */
468 SILC_LOG_DEBUG(("Moving client to global list"));
469 silc_idcache_add(server->global_list->clients, client_cache->name,
470 client_cache->id, client_cache->context, 0, NULL);
471 silc_idcache_del_by_context(server->local_list->clients, client);
473 server_entry = server_entry->router;
475 SILC_LOG_DEBUG(("Server locally connected"));
476 /* If the client is marked as local then move it to global list
477 since the server is global. */
478 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
479 SILC_LOG_DEBUG(("Moving client to global list"));
480 silc_idcache_add(server->global_list->clients, client_cache->name,
481 client_cache->id, client_cache->context, 0, NULL);
482 silc_idcache_del_by_context(server->local_list->clients, client);
486 silc_idcache_list_free(list);
490 if (!silc_idcache_list_next(list, &id_cache))
495 silc_idcache_list_free(list);
500 /* Updates the clients that are originated from the `from' to be originated
501 from the `to'. If the `resolve_real_server' is TRUE then this will
502 attempt to figure out which clients really are originated from the
503 `from' and which are originated from a server that we have connection
504 to, when we've acting as backup router. If it is FALSE the `to' will
505 be the new source. */
507 void silc_server_update_clients_by_server(SilcServer server,
508 SilcServerEntry from,
510 bool resolve_real_server)
512 SilcIDCacheList list = NULL;
513 SilcIDCacheEntry id_cache = NULL;
514 SilcClientEntry client = NULL;
517 if (from && from->id) {
518 SILC_LOG_DEBUG(("Changing from server %s",
519 silc_id_render(from->id, SILC_ID_SERVER)));
522 SILC_LOG_DEBUG(("Changing to server %s",
523 silc_id_render(to->id, SILC_ID_SERVER)));
526 SILC_LOG_DEBUG(("global list"));
528 if (silc_idcache_get_all(server->global_list->clients, &list)) {
529 if (silc_idcache_list_first(list, &id_cache)) {
531 client = (SilcClientEntry)id_cache->context;
533 /* If entry is disabled skip it. If entry is local to us, do not
534 switch it to anyone else, it is ours so skip it. */
535 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
536 SILC_IS_LOCAL(client)) {
537 if (!silc_idcache_list_next(list, &id_cache))
543 SILC_LOG_DEBUG(("Client %s",
544 silc_id_render(client->id, SILC_ID_CLIENT)));
546 SILC_LOG_DEBUG(("Client->router %s",
547 silc_id_render(client->router->id, SILC_ID_SERVER)));
550 if (client->router == from) {
551 if (resolve_real_server) {
553 silc_server_update_clients_by_real_server(server, from, to,
556 if (!client->router) {
557 if (server->server_type == SILC_ROUTER)
558 client->router = from;
567 /* All are changed */
568 if (resolve_real_server)
569 /* Call this so that the entry is moved to correct list if
570 needed. No resolving by real server is actually done. */
571 silc_server_update_clients_by_real_server(server, NULL, to,
579 SILC_LOG_DEBUG(("Client changed to %s",
580 silc_id_render(client->router->id, SILC_ID_SERVER)));
582 if (!silc_idcache_list_next(list, &id_cache))
586 silc_idcache_list_free(list);
589 SILC_LOG_DEBUG(("local list"));
591 if (silc_idcache_get_all(server->local_list->clients, &list)) {
592 if (silc_idcache_list_first(list, &id_cache)) {
594 client = (SilcClientEntry)id_cache->context;
596 /* If entry is disabled skip it. If entry is local to us, do not
597 switch it to anyone else, it is ours so skip it. */
598 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
599 SILC_IS_LOCAL(client)) {
600 if (!silc_idcache_list_next(list, &id_cache))
606 SILC_LOG_DEBUG(("Client %s",
607 silc_id_render(client->id, SILC_ID_CLIENT)));
609 SILC_LOG_DEBUG(("Client->router %s",
610 silc_id_render(client->router->id, SILC_ID_SERVER)));
613 if (client->router == from) {
614 if (resolve_real_server) {
616 silc_server_update_clients_by_real_server(server, from, to,
620 client->router = from;
626 /* All are changed */
627 if (resolve_real_server)
628 /* Call this so that the entry is moved to correct list if
629 needed. No resolving by real server is actually done. */
630 silc_server_update_clients_by_real_server(server, NULL, to,
638 SILC_LOG_DEBUG(("Client changed to %s",
639 silc_id_render(client->router->id, SILC_ID_SERVER)));
641 if (!silc_idcache_list_next(list, &id_cache))
645 silc_idcache_list_free(list);
649 /* Updates servers that are from `from' to be originated from `to'. This
650 will also update the server's connection to `to's connection. */
652 void silc_server_update_servers_by_server(SilcServer server,
653 SilcServerEntry from,
656 SilcIDCacheList list = NULL;
657 SilcIDCacheEntry id_cache = NULL;
658 SilcServerEntry server_entry = NULL;
660 SILC_LOG_DEBUG(("Updating servers"));
662 if (silc_idcache_get_all(server->local_list->servers, &list)) {
663 if (silc_idcache_list_first(list, &id_cache)) {
665 server_entry = (SilcServerEntry)id_cache->context;
667 /* If entry is local to us, do not switch it to any anyone else,
669 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
670 server_entry == from) {
671 if (!silc_idcache_list_next(list, &id_cache))
677 /* If we are standalone router, any server that is not directly
678 connected to cannot exist anymore. If we are not standalone
679 we update it correctly. */
680 if (server->server_type == SILC_ROUTER && server->standalone) {
681 silc_server_backup_del(server, server_entry);
682 silc_server_backup_replaced_del(server, server_entry);
683 silc_idlist_del_data(server_entry);
684 silc_idlist_del_server(server->local_list, server_entry);
685 server->stat.servers--;
686 server->stat.cell_servers--;
688 /* XXX if we are not standalone, do a check from local config
689 whether this server is in our cell, but not connected to
690 us (in which case we must remove it). */
693 if (server_entry->router == from) {
694 SILC_LOG_DEBUG(("Updating server (local) %s",
695 server_entry->server_name ?
696 server_entry->server_name : ""));
697 server_entry->router = to;
698 server_entry->connection = to->connection;
702 SILC_LOG_DEBUG(("Updating server (local) %s",
703 server_entry->server_name ?
704 server_entry->server_name : ""));
705 server_entry->router = to;
706 server_entry->connection = to->connection;
710 if (!silc_idcache_list_next(list, &id_cache))
714 silc_idcache_list_free(list);
717 if (silc_idcache_get_all(server->global_list->servers, &list)) {
718 if (silc_idcache_list_first(list, &id_cache)) {
720 server_entry = (SilcServerEntry)id_cache->context;
722 /* If entry is local to us, do not switch it to anyone else,
724 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
725 server_entry == from) {
726 if (!silc_idcache_list_next(list, &id_cache))
732 /* If we are standalone router, any server that is not directly
733 connected to cannot exist anymore. If we are not standalone
734 we update it correctly. */
735 if (server->server_type == SILC_ROUTER && server->standalone) {
736 silc_server_backup_del(server, server_entry);
737 silc_server_backup_replaced_del(server, server_entry);
738 silc_idlist_del_data(server_entry);
739 silc_idlist_del_server(server->global_list, server_entry);
740 server->stat.servers--;
741 server->stat.cell_servers--;
743 /* XXX if we are not standalone, do a check from local config
744 whether this server is in our cell, but not connected to
745 us (in which case we must remove it). */
748 if (server_entry->router == from) {
749 SILC_LOG_DEBUG(("Updating server (global) %s",
750 server_entry->server_name ?
751 server_entry->server_name : ""));
752 server_entry->router = to;
753 server_entry->connection = to->connection;
757 SILC_LOG_DEBUG(("Updating server (global) %s",
758 server_entry->server_name ?
759 server_entry->server_name : ""));
760 server_entry->router = to;
761 server_entry->connection = to->connection;
765 if (!silc_idcache_list_next(list, &id_cache))
769 silc_idcache_list_free(list);
774 /* Toggles the enabled/disabled status of local server connections. Packets
775 can be sent to the servers when `toggle_enabled' is TRUE and will be
776 dropped if `toggle_enabled' is FALSE, after this function is called. */
778 void silc_server_local_servers_toggle_enabled(SilcServer server,
781 SilcIDCacheList list = NULL;
782 SilcIDCacheEntry id_cache = NULL;
783 SilcServerEntry server_entry = NULL;
785 if (silc_idcache_get_all(server->local_list->servers, &list)) {
786 if (silc_idcache_list_first(list, &id_cache)) {
788 server_entry = (SilcServerEntry)id_cache->context;
789 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
790 if (!silc_idcache_list_next(list, &id_cache))
797 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
799 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
801 if (!silc_idcache_list_next(list, &id_cache))
805 silc_idcache_list_free(list);
808 if (silc_idcache_get_all(server->global_list->servers, &list)) {
809 if (silc_idcache_list_first(list, &id_cache)) {
811 server_entry = (SilcServerEntry)id_cache->context;
812 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
813 if (!silc_idcache_list_next(list, &id_cache))
820 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
822 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
824 if (!silc_idcache_list_next(list, &id_cache))
828 silc_idcache_list_free(list);
832 /* Removes servers that are originated from the `from'. The server
833 entry is deleted in this function. If `remove_clients' is TRUE then
834 all clients originated from the server are removed too, and server
835 signoff is sent. Note that this does not remove the `from'. This
836 also does not remove locally connected servers. */
838 void silc_server_remove_servers_by_server(SilcServer server,
839 SilcServerEntry from,
842 SilcIDCacheList list = NULL;
843 SilcIDCacheEntry id_cache = NULL;
844 SilcServerEntry server_entry = NULL;
846 SILC_LOG_DEBUG(("Removing servers by %s",
847 from->server_name ? from->server_name : "server"));
849 if (silc_idcache_get_all(server->local_list->servers, &list)) {
850 if (silc_idcache_list_first(list, &id_cache)) {
852 server_entry = (SilcServerEntry)id_cache->context;
853 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
854 server_entry->router != from || server_entry == from) {
855 if (!silc_idcache_list_next(list, &id_cache))
861 /* Remove clients owned by this server */
863 silc_server_remove_clients_by_server(server, from, server_entry,
866 /* Remove the server */
867 silc_idlist_del_server(server->local_list, server_entry);
869 if (!silc_idcache_list_next(list, &id_cache))
873 silc_idcache_list_free(list);
876 if (silc_idcache_get_all(server->global_list->servers, &list)) {
877 if (silc_idcache_list_first(list, &id_cache)) {
879 server_entry = (SilcServerEntry)id_cache->context;
880 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
881 server_entry->router != from || server_entry == from) {
882 if (!silc_idcache_list_next(list, &id_cache))
888 /* Remove clients owned by this server */
890 silc_server_remove_clients_by_server(server, from, server_entry,
893 /* Remove the server */
894 silc_idlist_del_server(server->global_list, server_entry);
896 if (!silc_idcache_list_next(list, &id_cache))
900 silc_idcache_list_free(list);
904 /* Removes channels that are from `from. */
906 void silc_server_remove_channels_by_server(SilcServer server,
907 SilcServerEntry from)
909 SilcIDCacheList list = NULL;
910 SilcIDCacheEntry id_cache = NULL;
911 SilcChannelEntry channel = NULL;
913 SILC_LOG_DEBUG(("Removing channels by server"));
915 if (silc_idcache_get_all(server->global_list->channels, &list)) {
916 if (silc_idcache_list_first(list, &id_cache)) {
918 channel = (SilcChannelEntry)id_cache->context;
919 if (channel->router == from)
920 silc_idlist_del_channel(server->global_list, channel);
921 if (!silc_idcache_list_next(list, &id_cache))
925 silc_idcache_list_free(list);
929 /* Updates channels that are from `from' to be originated from `to'. */
931 void silc_server_update_channels_by_server(SilcServer server,
932 SilcServerEntry from,
935 SilcIDCacheList list = NULL;
936 SilcIDCacheEntry id_cache = NULL;
937 SilcChannelEntry channel = NULL;
939 SILC_LOG_DEBUG(("Updating channels by server"));
941 if (silc_idcache_get_all(server->global_list->channels, &list)) {
942 if (silc_idcache_list_first(list, &id_cache)) {
944 channel = (SilcChannelEntry)id_cache->context;
946 if (channel->router == from)
947 channel->router = to;
950 channel->router = to;
952 if (!silc_idcache_list_next(list, &id_cache))
956 silc_idcache_list_free(list);
960 /* Checks whether given channel has global users. If it does this returns
961 TRUE and FALSE if there is only locally connected clients on the channel. */
963 bool silc_server_channel_has_global(SilcChannelEntry channel)
965 SilcChannelClientEntry chl;
966 SilcHashTableList htl;
968 silc_hash_table_list(channel->user_list, &htl);
969 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
970 if (chl->client->router) {
971 silc_hash_table_list_reset(&htl);
975 silc_hash_table_list_reset(&htl);
980 /* Checks whether given channel has locally connected users. If it does this
981 returns TRUE and FALSE if there is not one locally connected client. */
983 bool silc_server_channel_has_local(SilcChannelEntry channel)
985 SilcChannelClientEntry chl;
986 SilcHashTableList htl;
988 silc_hash_table_list(channel->user_list, &htl);
989 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
990 if (SILC_IS_LOCAL(chl->client)) {
991 silc_hash_table_list_reset(&htl);
995 silc_hash_table_list_reset(&htl);
1000 /* This function removes the channel and all users on the channel, unless
1001 the channel is permanent. In this case the channel is disabled but all
1002 users are removed from the channel. Returns TRUE if the channel is
1003 destroyed totally, and FALSE if it is permanent and remains. */
1005 bool silc_server_channel_delete(SilcServer server,
1006 SilcChannelEntry channel)
1008 SilcChannelClientEntry chl;
1009 SilcHashTableList htl;
1010 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
1013 /* Update statistics */
1014 if (server->server_type == SILC_ROUTER)
1015 server->stat.chanclients -= channel->user_count;
1017 /* Totally delete the channel and all users on the channel. The
1018 users are deleted automatically in silc_idlist_del_channel. */
1019 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
1020 if (silc_idlist_del_channel(server->local_list, channel)) {
1021 server->stat.my_channels--;
1022 if (server->server_type == SILC_ROUTER) {
1023 server->stat.channels--;
1024 server->stat.cell_channels--;
1027 if (silc_idlist_del_channel(server->global_list, channel))
1028 if (server->server_type == SILC_ROUTER)
1029 server->stat.channels--;
1035 /* Channel is permanent, do not remove it, remove only users */
1036 channel->disabled = TRUE;
1037 silc_hash_table_list(channel->user_list, &htl);
1038 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
1039 silc_hash_table_del(chl->client->channels, channel);
1040 silc_hash_table_del(channel->user_list, chl->client);
1041 channel->user_count--;
1043 /* Update statistics */
1044 if (SILC_IS_LOCAL(chl->client))
1045 server->stat.my_chanclients--;
1046 if (server->server_type == SILC_ROUTER) {
1047 server->stat.cell_chanclients--;
1048 server->stat.chanclients--;
1053 silc_hash_table_list_reset(&htl);
1055 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
1060 /* Returns TRUE if the given client is on the channel. FALSE if not.
1061 This works because we assure that the user list on the channel is
1062 always in up to date thus we can only check the channel list from
1063 `client' which is faster than checking the user list from `channel'. */
1065 bool silc_server_client_on_channel(SilcClientEntry client,
1066 SilcChannelEntry channel,
1067 SilcChannelClientEntry *chl)
1069 if (!client || !channel)
1072 return silc_hash_table_find(client->channels, channel, NULL,
1076 /* Checks string for bad characters and returns TRUE if they are found. */
1078 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
1082 for (i = 0; i < name_len; i++) {
1083 if (!isascii(name[i]))
1085 if (name[i] <= 32) return TRUE;
1086 if (name[i] == ' ') return TRUE;
1087 if (name[i] == '*') return TRUE;
1088 if (name[i] == '?') return TRUE;
1089 if (name[i] == ',') return TRUE;
1090 if (name[i] == '@') return TRUE;
1091 if (name[i] == '!') return TRUE;
1097 /* Same as silc_server_name_bad_chars but check for channel names. */
1099 bool silc_server_name_bad_chchars(const char *name, SilcUInt32 name_len)
1103 for (i = 0; i < name_len; i++) {
1104 if (!isascii(name[i]))
1106 if (name[i] <= 32) return TRUE;
1107 if (name[i] == ' ') return TRUE;
1108 if (name[i] == '*') return TRUE;
1109 if (name[i] == '?') return TRUE;
1110 if (name[i] == ',') return TRUE;
1116 /* Modifies the `name' if it includes bad characters and returns new
1117 allocated name that does not include bad characters. */
1119 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
1122 char *newname = strdup(name);
1124 for (i = 0; i < name_len; i++) {
1125 if (!isascii(newname[i])) newname[i] = '_';
1126 if (newname[i] <= 32) newname[i] = '_';
1127 if (newname[i] == ' ') newname[i] = '_';
1128 if (newname[i] == '*') newname[i] = '_';
1129 if (newname[i] == '?') newname[i] = '_';
1130 if (newname[i] == ',') newname[i] = '_';
1136 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
1137 socket connections with the IP address does not exist. */
1139 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1140 SilcSocketType type)
1144 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1145 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1146 !strcmp(server->sockets[i]->ip, ip) &&
1147 server->sockets[i]->type == type)
1154 /* Find number of sockets by IP address indicated by remote host, indicatd
1155 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1156 does not exist. If `ip' is provided then `hostname' is ignored. */
1158 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1160 const char *hostname,
1162 SilcSocketType type)
1166 if (!ip && !hostname)
1169 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1170 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1171 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
1172 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
1173 server->sockets[i]->port == port &&
1174 server->sockets[i]->type == type)
1181 /* Finds locally cached public key by the public key received in the SKE.
1182 If we have it locally cached then we trust it and will use it in the
1183 authentication protocol. Returns the locally cached public key or NULL
1184 if we do not find the public key. */
1186 SilcPublicKey silc_server_find_public_key(SilcServer server,
1187 SilcHashTable local_public_keys,
1188 SilcPublicKey remote_public_key)
1190 SilcPublicKey cached_key;
1192 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
1193 silc_hash_table_count(local_public_keys)));
1195 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
1196 (void **)&cached_key, NULL,
1197 silc_hash_public_key, NULL,
1198 silc_hash_public_key_compare, NULL)) {
1199 SILC_LOG_ERROR(("Public key not found"));
1203 SILC_LOG_DEBUG(("Found public key"));
1208 /* This returns the first public key from the table of public keys. This
1209 is used only in cases where single public key exists in the table and
1210 we want to get a pointer to it. For public key tables that has multiple
1211 keys in it the silc_server_find_public_key must be used. */
1213 SilcPublicKey silc_server_get_public_key(SilcServer server,
1214 SilcHashTable local_public_keys)
1216 SilcPublicKey cached_key;
1217 SilcHashTableList htl;
1219 SILC_LOG_DEBUG(("Start"));
1221 assert(silc_hash_table_count(local_public_keys) < 2);
1223 silc_hash_table_list(local_public_keys, &htl);
1224 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key)) {
1225 silc_hash_table_list_reset(&htl);
1228 silc_hash_table_list_reset(&htl);
1233 /* Check whether the connection `sock' is allowed to connect to us. This
1234 checks for example whether there is too much connections for this host,
1235 and required version for the host etc. */
1237 bool silc_server_connection_allowed(SilcServer server,
1238 SilcSocketConnection sock,
1239 SilcSocketType type,
1240 SilcServerConfigConnParams *global,
1241 SilcServerConfigConnParams *params,
1244 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1245 server->stat.my_clients :
1246 type == SILC_SOCKET_TYPE_SERVER ?
1247 server->stat.my_servers :
1248 server->stat.my_routers);
1249 SilcUInt32 num_sockets, max_hosts, max_per_host;
1250 SilcUInt32 r_protocol_version, l_protocol_version;
1251 SilcUInt32 r_software_version, l_software_version;
1252 char *r_vendor_version = NULL, *l_vendor_version;
1254 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1258 l_protocol_version =
1259 silc_version_to_num(params && params->version_protocol ?
1260 params->version_protocol :
1261 global->version_protocol);
1262 l_software_version =
1263 silc_version_to_num(params && params->version_software ?
1264 params->version_software :
1265 global->version_software);
1266 l_vendor_version = (params && params->version_software_vendor ?
1267 params->version_software_vendor :
1268 global->version_software_vendor);
1270 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1271 &r_software_version, NULL,
1272 &r_vendor_version)) {
1273 sock->version = r_protocol_version;
1275 /* Match protocol version */
1276 if (l_protocol_version && r_protocol_version &&
1277 r_protocol_version < l_protocol_version) {
1278 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1279 sock->hostname, sock->ip));
1280 sock->protocol = NULL;
1281 silc_server_disconnect_remote(server, sock,
1282 SILC_STATUS_ERR_BAD_VERSION,
1283 "You support too old protocol version");
1287 /* Math software version */
1288 if (l_software_version && r_software_version &&
1289 r_software_version < l_software_version) {
1290 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1291 sock->hostname, sock->ip));
1292 sock->protocol = NULL;
1293 silc_server_disconnect_remote(server, sock,
1294 SILC_STATUS_ERR_BAD_VERSION,
1295 "You support too old software version");
1299 /* Regex match vendor version */
1300 if (l_vendor_version && r_vendor_version &&
1301 !silc_string_match(l_vendor_version, r_vendor_version)) {
1302 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1303 sock->hostname, sock->ip));
1304 sock->protocol = NULL;
1305 silc_server_disconnect_remote(server, sock,
1306 SILC_STATUS_ERR_BAD_VERSION,
1307 "Your software is not supported");
1311 silc_free(r_vendor_version);
1313 /* Check for maximum connections limit */
1315 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1316 max_hosts = (params ? params->connections_max : global->connections_max);
1317 max_per_host = (params ? params->connections_max_per_host :
1318 global->connections_max_per_host);
1320 if (max_hosts && conn_number >= max_hosts) {
1321 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1322 sock->hostname, sock->ip));
1323 sock->protocol = NULL;
1324 silc_server_disconnect_remote(server, sock,
1325 SILC_STATUS_ERR_RESOURCE_LIMIT,
1326 "Server is full, try again later");
1330 if (num_sockets >= max_per_host) {
1331 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1332 sock->hostname, sock->ip));
1333 sock->protocol = NULL;
1334 silc_server_disconnect_remote(server, sock,
1335 SILC_STATUS_ERR_RESOURCE_LIMIT,
1336 "Too many connections from your host");
1343 /* Checks that client has rights to add or remove channel modes. If any
1344 of the checks fails FALSE is returned. */
1346 bool silc_server_check_cmode_rights(SilcServer server,
1347 SilcChannelEntry channel,
1348 SilcChannelClientEntry client,
1351 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1352 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1354 /* Check whether has rights to change anything */
1355 if (!is_op && !is_fo)
1358 /* Check whether has rights to change everything */
1362 /* Founder implies operator */
1366 /* We know that client is channel operator, check that they are not
1367 changing anything that requires channel founder rights. Rest of the
1368 modes are available automatically for channel operator. */
1370 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1371 if (is_op && !is_fo)
1374 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1375 if (is_op && !is_fo)
1380 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1381 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1382 if (is_op && !is_fo)
1386 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1387 if (is_op && !is_fo)
1392 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1393 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1394 if (is_op && !is_fo)
1398 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1399 if (is_op && !is_fo)
1404 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1405 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1406 if (is_op && !is_fo)
1410 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1411 if (is_op && !is_fo)
1416 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1417 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1418 if (is_op && !is_fo)
1422 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1423 if (is_op && !is_fo)
1428 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1429 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1430 if (is_op && !is_fo)
1434 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1435 if (is_op && !is_fo)
1440 if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1441 if (!(channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)) {
1442 if (is_op && !is_fo)
1446 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
1447 if (is_op && !is_fo)
1455 /* Check that the client has rights to change its user mode. Returns
1456 FALSE if setting some mode is not allowed. */
1458 bool silc_server_check_umode_rights(SilcServer server,
1459 SilcClientEntry client,
1462 bool server_op = FALSE, router_op = FALSE;
1464 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1465 /* Cannot set server operator mode (must use OPER command) */
1466 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1469 /* Remove the server operator rights */
1470 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1474 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1475 /* Cannot set router operator mode (must use SILCOPER command) */
1476 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1479 /* Remove the router operator rights */
1480 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1485 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1487 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1492 /* This function is used to send the notify packets and motd to the
1493 incoming client connection. */
1495 void silc_server_send_connect_notifys(SilcServer server,
1496 SilcSocketConnection sock,
1497 SilcClientEntry client)
1499 SilcIDListData idata = (SilcIDListData)client;
1501 SILC_LOG_DEBUG(("Send welcome notifys"));
1503 /* Send some nice info to the client */
1504 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1505 ("Welcome to the SILC Network %s",
1507 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1508 ("Your host is %s, running version %s",
1509 server->server_name, server_version));
1511 if (server->server_type == SILC_ROUTER) {
1512 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1513 ("There are %d clients, %d servers and %d "
1514 "routers in SILC Network",
1515 server->stat.clients, server->stat.servers,
1516 server->stat.routers));
1518 if (server->stat.clients && server->stat.servers + 1)
1519 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1520 ("There are %d clients, %d servers and %d "
1521 "routers in SILC Network",
1522 server->stat.clients, server->stat.servers,
1523 (server->standalone ? 0 :
1524 !server->stat.routers ? 1 :
1525 server->stat.routers)));
1528 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1529 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1530 ("There are %d clients on %d server in our cell",
1531 server->stat.cell_clients,
1532 server->stat.cell_servers));
1533 if (server->server_type == SILC_ROUTER) {
1534 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1535 ("I have %d clients, %d channels, %d servers and "
1537 server->stat.my_clients,
1538 server->stat.my_channels,
1539 server->stat.my_servers,
1540 server->stat.my_routers));
1542 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1543 ("I have %d clients and %d channels formed",
1544 server->stat.my_clients,
1545 server->stat.my_channels));
1548 if (server->stat.server_ops || server->stat.router_ops)
1549 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1550 ("There are %d server operators and %d router "
1552 server->stat.server_ops,
1553 server->stat.router_ops));
1554 if (server->stat.my_router_ops + server->stat.my_server_ops)
1555 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1556 ("I have %d operators online",
1557 server->stat.my_router_ops +
1558 server->stat.my_server_ops));
1560 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1561 ("Your connection is secured with %s cipher, "
1562 "key length %d bits",
1563 silc_cipher_get_name(idata->send_key),
1564 silc_cipher_get_key_len(idata->send_key)));
1565 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1566 ("Your current nickname is %s",
1570 silc_server_send_motd(server, sock);
1573 /* Kill the client indicated by `remote_client' sending KILLED notify
1574 to the client, to all channels client has joined and to primary
1575 router if needed. The killed client is also removed from all channels. */
1577 void silc_server_kill_client(SilcServer server,
1578 SilcClientEntry remote_client,
1579 const char *comment,
1581 SilcIdType killer_id_type)
1583 SilcBuffer killed, killer;
1585 SILC_LOG_DEBUG(("Killing client %s",
1586 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1588 /* Send the KILL notify packets. First send it to the channel, then
1589 to our primary router and then directly to the client who is being
1590 killed right now. */
1592 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1593 killer = silc_id_payload_encode(killer_id, killer_id_type);
1595 /* Send KILLED notify to the channels. It is not sent to the client
1596 as it will be sent differently destined directly to the client and not
1598 silc_server_send_notify_on_channels(server, remote_client,
1599 remote_client, SILC_NOTIFY_TYPE_KILLED,
1600 3, killed->data, killed->len,
1601 comment, comment ? strlen(comment) : 0,
1602 killer->data, killer->len);
1604 /* Send KILLED notify to primary route */
1605 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1606 SILC_BROADCAST(server), remote_client->id,
1607 comment, killer_id, killer_id_type);
1609 /* Send KILLED notify to the client directly */
1610 if (remote_client->connection || remote_client->router)
1611 silc_server_send_notify_killed(server, remote_client->connection ?
1612 remote_client->connection :
1613 remote_client->router->connection, FALSE,
1614 remote_client->id, comment,
1615 killer_id, killer_id_type);
1617 /* Remove the client from all channels. This generates new keys to the
1618 channels as well. */
1619 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1622 /* Remove the client entry, If it is locally connected then we will also
1623 disconnect the client here */
1624 if (remote_client->connection) {
1625 /* Remove locally conneted client */
1626 SilcSocketConnection sock = remote_client->connection;
1627 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1628 silc_server_close_connection(server, sock);
1630 /* Update statistics */
1631 server->stat.clients--;
1632 if (server->stat.cell_clients)
1633 server->stat.cell_clients--;
1634 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1635 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1637 if (SILC_IS_LOCAL(remote_client)) {
1638 server->stat.my_clients--;
1639 silc_schedule_task_del_by_context(server->schedule, remote_client);
1640 silc_idlist_del_data(remote_client);
1643 /* Remove remote client */
1644 silc_idlist_del_data(remote_client);
1645 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1646 /* Remove this client from watcher list if it is */
1647 silc_server_del_from_watcher_list(server, remote_client);
1648 silc_idlist_del_client(server->local_list, remote_client);
1652 silc_buffer_free(killer);
1653 silc_buffer_free(killed);
1658 SilcClientEntry client;
1659 SilcNotifyType notify;
1660 const char *new_nick;
1661 } WatcherNotifyContext;
1664 silc_server_check_watcher_list_foreach(void *key, void *context,
1667 WatcherNotifyContext *notify = user_context;
1668 SilcClientEntry entry = context;
1669 SilcSocketConnection sock;
1674 if (entry == notify->client)
1677 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1680 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1681 silc_id_render(entry->id, SILC_ID_CLIENT)));
1683 /* Send the WATCH notify */
1684 silc_server_send_notify_watch(notify->server, sock, entry,
1686 notify->new_nick ? notify->new_nick :
1687 (const char *)notify->client->nickname,
1692 /* This function checks whether the `client' nickname is being watched
1693 by someone, and notifies the watcher of the notify change of notify
1694 type indicated by `notify'. */
1696 bool silc_server_check_watcher_list(SilcServer server,
1697 SilcClientEntry client,
1698 const char *new_nick,
1699 SilcNotifyType notify)
1701 unsigned char hash[16];
1702 WatcherNotifyContext n;
1704 SILC_LOG_DEBUG(("Checking watcher list %s",
1705 client->nickname ? client->nickname : (unsigned char *)""));
1707 /* If the watching is rejected by the client do nothing */
1708 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1711 /* Make hash from the nick, or take it from Client ID */
1712 if (client->nickname) {
1714 memset(nick, 0, sizeof(nick));
1715 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1716 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1718 memset(hash, 0, sizeof(hash));
1719 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1724 n.new_nick = new_nick;
1727 /* Send notify to all watchers */
1728 silc_hash_table_find_foreach(server->watcher_list, hash,
1729 silc_server_check_watcher_list_foreach, &n);
1734 /* Remove the `client' from watcher list. After calling this the `client'
1735 is not watching any nicknames. */
1737 bool silc_server_del_from_watcher_list(SilcServer server,
1738 SilcClientEntry client)
1740 SilcHashTableList htl;
1742 SilcClientEntry entry;
1745 silc_hash_table_list(server->watcher_list, &htl);
1746 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1747 if (entry == client) {
1748 silc_hash_table_del_by_context(server->watcher_list, key, client);
1751 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1752 silc_id_render(client->id, SILC_ID_CLIENT)));
1754 /* Now check whether there still exists entries with this key, if not
1755 then free the key to not leak memory. */
1756 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1762 silc_hash_table_list_reset(&htl);
1767 /* Force the client indicated by `chl' to change the channel user mode
1768 on channel indicated by `channel' to `forced_mode'. */
1770 bool silc_server_force_cumode_change(SilcServer server,
1771 SilcSocketConnection sock,
1772 SilcChannelEntry channel,
1773 SilcChannelClientEntry chl,
1774 SilcUInt32 forced_mode)
1776 SilcBuffer idp1, idp2;
1777 unsigned char cumode[4];
1779 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1782 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1783 server->id, SILC_ID_SERVER,
1784 chl->client->id, NULL);
1786 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1787 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1788 SILC_PUT32_MSB(forced_mode, cumode);
1789 silc_server_send_notify_to_channel(server, sock, channel, FALSE, TRUE,
1790 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1791 3, idp1->data, idp1->len,
1792 cumode, sizeof(cumode),
1793 idp2->data, idp2->len);
1794 silc_buffer_free(idp1);
1795 silc_buffer_free(idp2);
1800 /* Find active socket connection by the IP address and port indicated by
1801 `ip' and `port', and socket connection type of `type'. */
1803 SilcSocketConnection
1804 silc_server_find_socket_by_host(SilcServer server,
1805 SilcSocketType type,
1806 const char *ip, SilcUInt16 port)
1810 for (i = 0; i < server->config->param.connections_max; i++) {
1811 if (!server->sockets[i])
1813 if (!strcmp(server->sockets[i]->ip, ip) &&
1814 (!port || server->sockets[i]->port == port) &&
1815 server->sockets[i]->type == type)
1816 return server->sockets[i];
1822 /* This function can be used to match the invite and ban lists. */
1824 bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1825 SilcUInt8 type, void *check)
1827 unsigned char *tmp = NULL;
1828 SilcUInt32 len = 0, t;
1829 SilcHashTableList htl;
1830 SilcBuffer entry, idp = NULL, pkp = NULL;
1833 if (type < 1 || type > 3 || !check)
1837 tmp = strdup((char *)check);
1842 pkp = silc_pkcs_public_key_payload_encode(check);
1849 idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
1856 /* Compare the list */
1857 silc_hash_table_list(list, &htl);
1858 while (silc_hash_table_get(&htl, (void **)&t, (void **)&entry)) {
1861 if (silc_string_match(entry->data, tmp)) {
1865 } else if (!memcmp(entry->data, tmp, len)) {
1871 silc_hash_table_list_reset(&htl);
1875 silc_buffer_free(idp);
1876 silc_buffer_free(pkp);
1880 /* Process invite or ban information */
1882 void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
1883 SilcUInt8 action, SilcArgumentPayload args)
1886 SilcUInt32 type, len;
1888 SilcHashTableList htl;
1890 SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1891 action == 0x01 ? "DEL" : "ADD"));
1893 /* Add the information to invite list */
1894 if (action == 0x00 || action == 0x03) {
1895 /* Traverse all arguments and add to the hash table according to
1897 tmp = silc_argument_get_first_arg(args, &type, &len);
1900 /* Invite string. Get the old invite string from hash table
1901 and append this at the end of the existing one. */
1902 if (!silc_hash_table_find(list, (void *)1, NULL, (void *)&tmp2)) {
1903 tmp2 = silc_calloc(1, sizeof(*tmp2));
1904 silc_hash_table_add(list, (void *)1, tmp2);
1907 /* Check that the string is not part of invite string already */
1908 if (action == 0x00) {
1909 if (silc_string_match(tmp2->data, tmp))
1913 if (tmp[len - 1] == ',')
1914 tmp[len - 1] = '\0';
1915 silc_buffer_strformat(tmp2, tmp, SILC_STR_END);
1916 silc_buffer_strformat(tmp2, ",", SILC_STR_END);
1919 /* Announced list. Check each entry in the list */
1920 unsigned char e[256];
1921 char *start, *end, *n, *rtmp;
1924 rtmp = silc_memdup(tmp, len);
1925 for (i = 0, k = 0; i < len; i++) {
1929 memset(e, 0, sizeof(e));
1930 silc_strncat(e, sizeof(e), tmp + k, i - k);
1931 if (!silc_string_match(tmp2->data, e)) {
1936 /* Matches. Delete it since we have it already */
1937 start = strstr(rtmp, e);
1938 if (start && strlen(start) >= (i - k)) {
1939 end = start + (i - k);
1940 n = silc_calloc(strlen(rtmp) - (i - k), sizeof(*n));
1941 strncat(n, rtmp, start - rtmp);
1942 if (strlen(end) > 1)
1943 strncat(n, end + 1, ((rtmp + strlen(rtmp)) - end) - 1);
1951 /* Save the part that we didn't already have. */
1952 if (strlen(rtmp) > 1) {
1953 silc_buffer_strformat(tmp2, rtmp, SILC_STR_END);
1954 silc_buffer_strformat(tmp2, ",", SILC_STR_END);
1959 } else if (type == 2) {
1960 /* Public key. Check first if the public key is already on the
1961 list and ignore it if it is, otherwise, add it to hash table. */
1963 /* Check if the public key is in the list already */
1964 silc_hash_table_list(list, &htl);
1965 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1966 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1971 silc_hash_table_list_reset(&htl);
1973 /* Add new public key to invite list */
1975 tmp2 = silc_buffer_alloc_size(len);
1976 silc_buffer_put(tmp2, tmp, len);
1977 silc_hash_table_add(list, (void *)2, tmp2);
1980 } else if (type == 3) {
1983 /* Check if the ID is in the list already */
1984 silc_hash_table_list(list, &htl);
1985 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1986 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1991 silc_hash_table_list_reset(&htl);
1993 /* Add new Client ID to invite list */
1995 tmp2 = silc_buffer_alloc_size(len);
1996 silc_buffer_put(tmp2, tmp, len);
1997 silc_hash_table_add(list, (void *)3, tmp2);
2001 tmp = silc_argument_get_next_arg(args, &type, &len);
2005 /* Delete information to invite list */
2006 if (action == 0x01 && list) {
2007 /* Now delete the arguments from invite list */
2008 tmp = silc_argument_get_first_arg(args, &type, &len);
2011 /* Invite string. Get the old string from hash table and delete
2012 the requested string. */
2013 char *string = NULL, *start, *end, *n;
2015 if (silc_hash_table_find(list, (void *)1, NULL, (void **)&tmp2)) {
2016 string = tmp2->head;
2017 if (tmp2->truelen && !strncmp(string, tmp, tmp2->truelen - 1)) {
2018 /* Delete entire string */
2019 silc_hash_table_del(list, (void *)1);
2020 } else if (tmp2->truelen) {
2021 /* Delete part of the string */
2022 start = strstr(string, tmp);
2023 if (start && strlen(start) >= len) {
2025 n = silc_calloc(strlen(string) - len, sizeof(*n));
2026 strncat(n, string, start - string);
2027 if (strlen(end) > 1)
2028 strncat(n, end + 1, ((string + strlen(string)) - end) - 1);
2029 silc_free(tmp2->head);
2030 silc_buffer_set(tmp2, n, strlen(n));
2035 } else if (type == 2) {
2038 /* Delete from the invite list */
2039 silc_hash_table_list(list, &htl);
2040 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
2041 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
2042 silc_hash_table_del_by_context(list, (void *)2, tmp2);
2046 silc_hash_table_list_reset(&htl);
2048 } else if (type == 3) {
2051 /* Delete from the invite list */
2052 silc_hash_table_list(list, &htl);
2053 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
2054 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
2055 silc_hash_table_del_by_context(list, (void *)3, tmp2);
2059 silc_hash_table_list_reset(&htl);
2062 tmp = silc_argument_get_next_arg(args, &type, &len);
2067 /* Destructor for invite and ban list entrys */
2069 void silc_server_inviteban_destruct(void *key, void *context,
2072 silc_buffer_free(context);
2075 /* Creates connections accoring to configuration. */
2077 void silc_server_create_connections(SilcServer server)
2079 silc_schedule_task_del_by_callback(server->schedule,
2080 silc_server_connect_to_router);
2081 silc_schedule_task_add(server->schedule, 0,
2082 silc_server_connect_to_router, server, 0, 1,
2083 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
2087 silc_server_process_channel_pk_destruct(void *key, void *context,
2091 silc_pkcs_public_key_free(context);
2094 /* Processes a channel public key, either adds or removes it. */
2097 silc_server_process_channel_pk(SilcServer server,
2098 SilcChannelEntry channel,
2099 SilcUInt32 type, const unsigned char *pk,
2102 unsigned char pkhash[20];
2105 SILC_LOG_DEBUG(("Processing channel public key"));
2108 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2110 /* Decode the public key */
2111 if (!silc_pkcs_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
2112 return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
2114 /* Create channel public key list (hash table) if needed */
2115 if (!channel->channel_pubkeys) {
2116 channel->channel_pubkeys =
2117 silc_hash_table_alloc(0, silc_hash_data, (void *)20,
2118 silc_hash_data_compare, (void *)20,
2119 silc_server_process_channel_pk_destruct, channel,
2123 /* Create SHA-1 digest of the public key data */
2124 silc_hash_make(server->sha1hash, pk + 4, pk_len - 4, pkhash);
2127 /* Add new public key to channel public key list */
2128 SILC_LOG_DEBUG(("Add new channel public key to channel %s",
2129 channel->channel_name));
2131 /* Check for resource limit */
2132 if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
2133 silc_pkcs_public_key_free(chpk);
2134 return SILC_STATUS_ERR_RESOURCE_LIMIT;
2137 /* Add if doesn't exist already */
2138 if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2140 silc_hash_table_add(channel->channel_pubkeys, silc_memdup(pkhash, 20),
2142 } else if (type == 0x01) {
2143 /* Delete public key from channel public key list */
2144 SILC_LOG_DEBUG(("Delete a channel public key from channel %s",
2145 channel->channel_name));
2146 if (!silc_hash_table_del(channel->channel_pubkeys, pkhash))
2147 silc_pkcs_public_key_free(chpk);
2149 silc_pkcs_public_key_free(chpk);
2150 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2153 return SILC_STATUS_OK;
2156 /* Returns the channel public keys as Argument List payload. */
2158 SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
2159 SilcChannelEntry channel,
2163 SilcHashTableList htl;
2164 SilcBuffer list, pkp;
2167 SILC_LOG_DEBUG(("Encoding channel public keys list"));
2169 if (!channel->channel_pubkeys ||
2170 !silc_hash_table_count(channel->channel_pubkeys))
2173 /* Encode the list */
2174 list = silc_buffer_alloc_size(2);
2175 silc_buffer_format(list,
2176 SILC_STR_UI_SHORT(silc_hash_table_count(
2177 channel->channel_pubkeys)),
2180 silc_hash_table_list(channel->channel_pubkeys, &htl);
2181 while (silc_hash_table_get(&htl, NULL, (void **)&pk)) {
2182 pkp = silc_pkcs_public_key_payload_encode(pk);
2183 list = silc_argument_payload_encode_one(list, pkp->data, pkp->len,
2185 delete ? 0x01 : 0x00);
2186 silc_buffer_free(pkp);
2188 silc_hash_table_list_reset(&htl);
2193 /* Sets the channel public keys into channel from the list of public keys. */
2195 SilcStatus silc_server_set_channel_pk_list(SilcServer server,
2196 SilcSocketConnection sender,
2197 SilcChannelEntry channel,
2198 const unsigned char *pklist,
2199 SilcUInt32 pklist_len)
2202 SilcArgumentPayload args;
2203 unsigned char *chpk;
2204 SilcUInt32 chpklen, type;
2205 SilcStatus ret = SILC_STATUS_OK;
2207 SILC_LOG_DEBUG(("Setting channel public keys list"));
2209 if (!pklist || pklist_len < 2)
2210 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2212 /* Get the argument from the Argument List Payload */
2213 SILC_GET16_MSB(argc, pklist);
2214 args = silc_argument_payload_parse(pklist + 2, pklist_len - 2, argc);
2216 return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
2218 /* Process the public keys one by one */
2219 chpk = silc_argument_get_first_arg(args, &type, &chpklen);
2221 /* If announcing keys and we have them set already, do not allow this */
2222 if (chpk && type == 0x03 && channel->channel_pubkeys &&
2223 server->server_type == SILC_ROUTER &&
2224 sender != SILC_PRIMARY_ROUTE(server)) {
2225 SILC_LOG_DEBUG(("Channel public key list set already, enforce our list"));
2226 silc_argument_payload_free(args);
2227 return SILC_STATUS_ERR_OPERATION_ALLOWED;
2230 /* If we are normal server and receive announcement list and we already
2231 have keys set, we replace the old list with the announced one. */
2232 if (chpk && type == 0x03 && channel->channel_pubkeys &&
2233 server->server_type != SILC_ROUTER) {
2235 unsigned char mask[4];
2237 SILC_LOG_DEBUG(("Router enforces its list, remove old list"));
2238 silc_hash_table_free(channel->channel_pubkeys);
2239 channel->channel_pubkeys = NULL;
2241 /* Send notify that removes the old list */
2242 sidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2243 SILC_PUT32_MSB((channel->mode & (~SILC_CHANNEL_MODE_CHANNEL_AUTH)), mask);
2244 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2245 SILC_NOTIFY_TYPE_CMODE_CHANGE, 7,
2246 sidp->data, sidp->len,
2250 strlen(channel->cipher) : 0,
2252 channel->hmac_name ?
2253 strlen(channel->hmac_name) : 0,
2254 channel->passphrase,
2255 channel->passphrase ?
2256 strlen(channel->passphrase) : 0,
2258 silc_buffer_free(sidp);
2264 ret = silc_server_process_channel_pk(server, channel, type,
2266 if (ret != SILC_STATUS_OK)
2268 chpk = silc_argument_get_next_arg(args, &type, &chpklen);
2271 silc_argument_payload_free(args);
2275 /* Verifies the Authentication Payload `auth' with one of the public keys
2276 on the `channel' public key list. */
2278 bool silc_server_verify_channel_auth(SilcServer server,
2279 SilcChannelEntry channel,
2280 SilcClientID *client_id,
2281 const unsigned char *auth,
2282 SilcUInt32 auth_len)
2286 unsigned char *pkhash;
2287 SilcUInt32 pkhash_len;
2290 SILC_LOG_DEBUG(("Verifying channel authentication"));
2292 if (!auth || !auth_len || !channel->channel_pubkeys)
2295 /* Get the hash from the auth data which tells us what public key we
2296 must use in verification. */
2298 ap = silc_auth_payload_parse(auth, auth_len);
2302 pkhash = silc_auth_get_public_data(ap, &pkhash_len);
2303 if (pkhash_len < 128)
2306 /* Find the public key with the hash */
2307 if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
2308 NULL, (void **)&chpk)) {
2309 SILC_LOG_DEBUG(("Public key not found in channel public key list"));
2313 /* Verify the signature */
2314 if (!silc_auth_verify(ap, SILC_AUTH_PUBLIC_KEY, (void *)chpk, 0,
2315 server->sha1hash, client_id, SILC_ID_CLIENT)) {
2316 SILC_LOG_DEBUG(("Authentication failed"));
2323 silc_auth_payload_free(ap);