5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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;
43 SILC_LOG_DEBUG(("Start"));
45 if (!client || !client->id)
48 if (silc_hash_table_find(clients, client, NULL, NULL))
49 silc_hash_table_del(clients, client);
51 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
53 /* Remove the client from all channels. The client is removed from
54 the channels' user list. */
55 silc_hash_table_list(client->channels, &htl);
56 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
57 channel = chl->channel;
59 /* Remove channel if this is last client leaving the channel, unless
60 the channel is permanent. */
61 if (server->server_type == SILC_ROUTER &&
62 silc_hash_table_count(channel->user_list) < 2) {
63 if (silc_hash_table_find(channels, channel, NULL, NULL))
64 silc_hash_table_del(channels, channel);
65 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
66 silc_server_channel_delete(server, channel);
70 silc_hash_table_del(client->channels, channel);
71 silc_hash_table_del(channel->user_list, chl->client);
72 channel->user_count--;
74 /* If there is no global users on the channel anymore mark the channel
75 as local channel. Do not check if the removed client is local client. */
76 if (server->server_type != SILC_ROUTER && channel->global_users &&
77 chl->client->router && !silc_server_channel_has_global(channel))
78 channel->global_users = FALSE;
82 /* Update statistics */
83 if (client->connection)
84 server->stat.my_chanclients--;
85 if (server->server_type == SILC_ROUTER) {
86 server->stat.cell_chanclients--;
87 server->stat.chanclients--;
90 /* If there is not at least one local user on the channel then we don't
91 need the channel entry anymore, we can remove it safely, unless the
92 channel is permanent channel */
93 if (server->server_type != SILC_ROUTER &&
94 !silc_server_channel_has_local(channel)) {
95 if (silc_hash_table_find(channels, channel, NULL, NULL))
96 silc_hash_table_del(channels, channel);
97 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
98 silc_server_channel_delete(server, channel);
102 /* Mark other local clients to the table of clients whom will receive
103 the SERVER_SIGNOFF notify. */
104 silc_hash_table_list(channel->user_list, &htl2);
105 while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
106 SilcClientEntry c = chl2->client;
110 /* Add client to table, if it's not from the signoff server */
111 if (c->router != server_entry &&
112 !silc_hash_table_find(clients, c, NULL, NULL))
113 silc_hash_table_add(clients, c, c);
115 silc_hash_table_list_reset(&htl2);
117 /* Add the channel to the the channels list to regenerate the
119 if (!silc_hash_table_find(channels, channel, NULL, NULL))
120 silc_hash_table_add(channels, channel, channel);
122 silc_hash_table_list_reset(&htl);
123 silc_buffer_free(clidp);
126 /* This function is used to remove all client entries by the server `entry'.
127 This is called when the connection is lost to the server. In this case
128 we must invalidate all the client entries owned by the server `entry'.
129 If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
130 distributed to our local clients. */
132 bool silc_server_remove_clients_by_server(SilcServer server,
133 SilcServerEntry entry,
136 SilcIDCacheList list = NULL;
137 SilcIDCacheEntry id_cache = NULL;
138 SilcClientEntry client = NULL;
140 unsigned char **argv = NULL;
141 SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
142 SilcHashTableList htl;
143 SilcChannelEntry channel;
144 SilcHashTable channels, clients;
147 SILC_LOG_DEBUG(("Start"));
149 /* Allocate the hash table that holds the channels that require
150 channel key re-generation after we've removed this server's clients
151 from the channels. */
152 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
154 clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
157 if (server_signoff) {
158 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
159 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
160 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
161 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
162 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
163 memcpy(argv[argc], idp->data, idp->len);
164 argv_lens[argc] = idp->len;
165 argv_types[argc] = argc + 1;
167 silc_buffer_free(idp);
170 if (silc_idcache_get_all(server->local_list->clients, &list)) {
172 if (silc_idcache_list_first(list, &id_cache)) {
174 client = (SilcClientEntry)id_cache->context;
175 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
176 if (!silc_idcache_list_next(list, &id_cache))
182 if (client->router != entry) {
183 if (!silc_idcache_list_next(list, &id_cache))
189 if (server_signoff) {
190 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
191 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
192 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
194 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
196 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
197 memcpy(argv[argc], idp->data, idp->len);
198 argv_lens[argc] = idp->len;
199 argv_types[argc] = argc + 1;
201 silc_buffer_free(idp);
204 /* Update statistics */
205 server->stat.clients--;
206 if (server->stat.cell_clients)
207 server->stat.cell_clients--;
208 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
209 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
211 /* Remove the client entry */
212 silc_server_remove_clients_channels(server, entry, clients,
214 if (!server_signoff) {
215 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
216 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
218 /* Remove this client from watcher list if it is */
219 silc_server_del_from_watcher_list(server, client);
220 silc_idlist_del_client(server->local_list, client);
223 if (!silc_idcache_list_next(list, &id_cache))
227 silc_idcache_list_free(list);
230 if (silc_idcache_get_all(server->global_list->clients, &list)) {
232 if (silc_idcache_list_first(list, &id_cache)) {
234 client = (SilcClientEntry)id_cache->context;
235 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
236 if (!silc_idcache_list_next(list, &id_cache))
242 if (client->router != entry) {
243 if (!silc_idcache_list_next(list, &id_cache))
249 if (server_signoff) {
250 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
251 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
252 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
254 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
256 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
257 memcpy(argv[argc], idp->data, idp->len);
258 argv_lens[argc] = idp->len;
259 argv_types[argc] = argc + 1;
261 silc_buffer_free(idp);
264 /* Update statistics */
265 server->stat.clients--;
266 if (server->stat.cell_clients)
267 server->stat.cell_clients--;
268 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
269 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
271 /* Remove the client entry */
272 silc_server_remove_clients_channels(server, entry, clients,
274 if (!server_signoff) {
275 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
276 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
278 silc_idlist_del_client(server->global_list, client);
281 if (!silc_idcache_list_next(list, &id_cache))
285 silc_idcache_list_free(list);
288 /* Send the SERVER_SIGNOFF notify */
289 if (server_signoff) {
290 SilcBuffer args, not;
292 /* Send SERVER_SIGNOFF notify to our primary router */
293 if (!server->standalone && server->router &&
294 server->router != entry) {
295 args = silc_argument_payload_encode(1, argv, argv_lens,
297 silc_server_send_notify_args(server,
298 server->router->connection,
299 server->server_type == SILC_SERVER ?
301 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
303 silc_buffer_free(args);
308 /* Send to local clients. We also send the list of client ID's that
309 is to be removed for those servers that would like to use that list. */
310 args = silc_argument_payload_encode(argc, argv, argv_lens,
312 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
314 silc_server_packet_send_clients(server, clients,
315 SILC_PACKET_NOTIFY, 0, FALSE,
316 not->data, not->len, FALSE);
318 silc_buffer_free(args);
319 silc_buffer_free(not);
320 for (i = 0; i < argc; i++)
323 silc_free(argv_lens);
324 silc_free(argv_types);
325 silc_hash_table_free(clients);
328 /* We must now re-generate the channel key for all channels that had
329 this server's client(s) on the channel. As they left the channel we
330 must re-generate the channel key. */
331 silc_hash_table_list(channels, &htl);
332 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
333 if (!silc_server_create_channel_key(server, channel, 0)) {
334 silc_hash_table_list_reset(&htl);
335 silc_hash_table_free(channels);
339 /* Do not send the channel key if private channel key mode is set */
340 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
343 silc_server_send_channel_key(server, NULL, channel,
344 server->server_type == SILC_ROUTER ?
345 FALSE : !server->standalone);
347 silc_hash_table_list_reset(&htl);
348 silc_hash_table_free(channels);
353 static SilcServerEntry
354 silc_server_update_clients_by_real_server(SilcServer server,
355 SilcServerEntry from,
356 SilcClientEntry client,
358 SilcIDCacheEntry client_cache)
360 SilcServerEntry server_entry;
361 SilcIDCacheEntry id_cache = NULL;
362 SilcIDCacheList list;
364 if (!silc_idcache_get_all(server->local_list->servers, &list))
367 if (silc_idcache_list_first(list, &id_cache)) {
369 server_entry = (SilcServerEntry)id_cache->context;
370 if (server_entry != from &&
371 SILC_ID_COMPARE(server_entry->id, client->id,
372 client->id->ip.data_len)) {
373 SILC_LOG_DEBUG(("Found (local) %s",
374 silc_id_render(server_entry->id, SILC_ID_SERVER)));
376 if (!server_entry->data.send_key && server_entry->router) {
377 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
378 /* If the client is not marked as local then move it to local list
379 since the server is local. */
381 SILC_LOG_DEBUG(("Moving client to local list"));
382 silc_idcache_add(server->local_list->clients, client_cache->name,
383 client_cache->id, client_cache->context,
384 client_cache->expire, NULL);
385 silc_idcache_del_by_context(server->global_list->clients, client);
387 server_entry = server_entry->router;
389 /* If the client is not marked as local then move it to local list
390 since the server is local. */
391 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
392 SILC_LOG_DEBUG(("Moving client to local list"));
393 silc_idcache_add(server->local_list->clients, client_cache->name,
394 client_cache->id, client_cache->context,
395 client_cache->expire, NULL);
396 silc_idcache_del_by_context(server->global_list->clients, client);
400 silc_idcache_list_free(list);
404 if (!silc_idcache_list_next(list, &id_cache))
409 silc_idcache_list_free(list);
411 if (!silc_idcache_get_all(server->global_list->servers, &list))
414 if (silc_idcache_list_first(list, &id_cache)) {
416 server_entry = (SilcServerEntry)id_cache->context;
417 if (server_entry != from &&
418 SILC_ID_COMPARE(server_entry->id, client->id,
419 client->id->ip.data_len)) {
420 SILC_LOG_DEBUG(("Found (global) %s",
421 silc_id_render(server_entry->id, SILC_ID_SERVER)));
423 if (!server_entry->data.send_key && server_entry->router) {
424 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
425 /* If the client is marked as local then move it to global list
426 since the server is global. */
428 SILC_LOG_DEBUG(("Moving client to global list"));
429 silc_idcache_add(server->global_list->clients, client_cache->name,
430 client_cache->id, client_cache->context,
431 client_cache->expire, NULL);
432 silc_idcache_del_by_context(server->local_list->clients, client);
434 server_entry = server_entry->router;
436 /* If the client is marked as local then move it to global list
437 since the server is global. */
438 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
439 SILC_LOG_DEBUG(("Moving client to global list"));
440 silc_idcache_add(server->global_list->clients, client_cache->name,
441 client_cache->id, client_cache->context,
442 client_cache->expire, NULL);
443 silc_idcache_del_by_context(server->local_list->clients, client);
447 silc_idcache_list_free(list);
451 if (!silc_idcache_list_next(list, &id_cache))
456 silc_idcache_list_free(list);
461 /* Updates the clients that are originated from the `from' to be originated
462 from the `to'. If the `resolve_real_server' is TRUE then this will
463 attempt to figure out which clients really are originated from the
464 `from' and which are originated from a server that we have connection
465 to, when we've acting as backup router. If it is FALSE the `to' will
466 be the new source. This function also removes the clients that are
467 *really* originated from `from' if `remove_from' is TRUE. These are
468 clients that the `from' owns, and not just clients that are behind
471 void silc_server_update_clients_by_server(SilcServer server,
472 SilcServerEntry from,
474 bool resolve_real_server,
477 SilcIDCacheList list = NULL;
478 SilcIDCacheEntry id_cache = NULL;
479 SilcClientEntry client = NULL;
482 SILC_LOG_DEBUG(("Start"));
484 SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
486 SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
491 if (silc_idcache_get_all(server->global_list->clients, &list)) {
492 if (silc_idcache_list_first(list, &id_cache)) {
494 client = (SilcClientEntry)id_cache->context;
495 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
496 if (!silc_idcache_list_next(list, &id_cache))
502 SILC_LOG_DEBUG(("Client (global) %s",
503 silc_id_render(client->id, SILC_ID_CLIENT)));
505 SILC_LOG_DEBUG(("Client->router (global) %s",
506 silc_id_render(client->router->id, SILC_ID_SERVER)));
508 if (client->router == from) {
509 /* Skip clients that are *really* owned by the `from' */
510 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
511 client->id->ip.data_len)) {
512 SILC_LOG_DEBUG(("Found really owned client, skip it"));
513 if (!silc_idcache_list_next(list, &id_cache))
519 if (resolve_real_server) {
521 silc_server_update_clients_by_real_server(server, from, client,
530 if (!silc_idcache_list_next(list, &id_cache))
534 silc_idcache_list_free(list);
538 if (silc_idcache_get_all(server->local_list->clients, &list)) {
539 if (silc_idcache_list_first(list, &id_cache)) {
541 client = (SilcClientEntry)id_cache->context;
542 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
543 if (!silc_idcache_list_next(list, &id_cache))
549 SILC_LOG_DEBUG(("Client (local) %s",
550 silc_id_render(client->id, SILC_ID_CLIENT)));
552 SILC_LOG_DEBUG(("Client->router (local) %s",
553 silc_id_render(client->router->id, SILC_ID_SERVER)));
555 if (client->router == from) {
556 /* Skip clients that are *really* owned by the `from' */
557 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
558 client->id->ip.data_len)) {
559 SILC_LOG_DEBUG(("Found really owned client, skip it"));
560 if (!silc_idcache_list_next(list, &id_cache))
566 if (resolve_real_server) {
568 silc_server_update_clients_by_real_server(server, from, client,
571 client->router = from; /* on local list put old from */
577 if (!silc_idcache_list_next(list, &id_cache))
581 silc_idcache_list_free(list);
585 /* Now remove the clients that are still marked as orignated from the
586 `from'. These are the clients that really was owned by the `from' and
587 not just exist behind the `from'. */
588 silc_server_remove_clients_by_server(server, from, TRUE);
591 /* Updates servers that are from `from' to be originated from `to'. This
592 will also update the server's connection to `to's connection. */
594 void silc_server_update_servers_by_server(SilcServer server,
595 SilcServerEntry from,
598 SilcIDCacheList list = NULL;
599 SilcIDCacheEntry id_cache = NULL;
600 SilcServerEntry server_entry = NULL;
602 SILC_LOG_DEBUG(("Start"));
604 if (silc_idcache_get_all(server->local_list->servers, &list)) {
605 if (silc_idcache_list_first(list, &id_cache)) {
607 server_entry = (SilcServerEntry)id_cache->context;
608 if (server_entry->router == from) {
609 server_entry->router = to;
610 server_entry->connection = to->connection;
612 if (!silc_idcache_list_next(list, &id_cache))
616 silc_idcache_list_free(list);
619 if (silc_idcache_get_all(server->global_list->servers, &list)) {
620 if (silc_idcache_list_first(list, &id_cache)) {
622 server_entry = (SilcServerEntry)id_cache->context;
623 if (server_entry->router == from) {
624 server_entry->router = to;
625 server_entry->connection = to->connection;
627 if (!silc_idcache_list_next(list, &id_cache))
631 silc_idcache_list_free(list);
635 /* Removes channels that are from `from. */
637 void silc_server_remove_channels_by_server(SilcServer server,
638 SilcServerEntry from)
640 SilcIDCacheList list = NULL;
641 SilcIDCacheEntry id_cache = NULL;
642 SilcChannelEntry channel = NULL;
644 SILC_LOG_DEBUG(("Removing channels by server"));
646 if (silc_idcache_get_all(server->global_list->channels, &list)) {
647 if (silc_idcache_list_first(list, &id_cache)) {
649 channel = (SilcChannelEntry)id_cache->context;
650 if (channel->router == from)
651 silc_idlist_del_channel(server->global_list, channel);
652 if (!silc_idcache_list_next(list, &id_cache))
656 silc_idcache_list_free(list);
660 /* Updates channels that are from `from' to be originated from `to'. */
662 void silc_server_update_channels_by_server(SilcServer server,
663 SilcServerEntry from,
666 SilcIDCacheList list = NULL;
667 SilcIDCacheEntry id_cache = NULL;
668 SilcChannelEntry channel = NULL;
670 SILC_LOG_DEBUG(("Updating channels by server"));
672 if (silc_idcache_get_all(server->global_list->channels, &list)) {
673 if (silc_idcache_list_first(list, &id_cache)) {
675 channel = (SilcChannelEntry)id_cache->context;
676 if (channel->router == from)
677 channel->router = to;
678 if (!silc_idcache_list_next(list, &id_cache))
682 silc_idcache_list_free(list);
686 /* Checks whether given channel has global users. If it does this returns
687 TRUE and FALSE if there is only locally connected clients on the channel. */
689 bool silc_server_channel_has_global(SilcChannelEntry channel)
691 SilcChannelClientEntry chl;
692 SilcHashTableList htl;
694 silc_hash_table_list(channel->user_list, &htl);
695 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
696 if (chl->client->router) {
697 silc_hash_table_list_reset(&htl);
701 silc_hash_table_list_reset(&htl);
706 /* Checks whether given channel has locally connected users. If it does this
707 returns TRUE and FALSE if there is not one locally connected client. */
709 bool silc_server_channel_has_local(SilcChannelEntry channel)
711 SilcChannelClientEntry chl;
712 SilcHashTableList htl;
714 silc_hash_table_list(channel->user_list, &htl);
715 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
716 if (!chl->client->router) {
717 silc_hash_table_list_reset(&htl);
721 silc_hash_table_list_reset(&htl);
726 /* This function removes the channel and all users on the channel, unless
727 the channel is permanent. In this case the channel is disabled but all
728 users are removed from the channel. Returns TRUE if the channel is
729 destroyed totally, and FALSE if it is permanent and remains. */
731 bool silc_server_channel_delete(SilcServer server,
732 SilcChannelEntry channel)
734 SilcChannelClientEntry chl;
735 SilcHashTableList htl;
736 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
739 SILC_LOG_DEBUG(("Deleting %s channel", channel->channel_name));
741 /* Update statistics */
742 if (server->server_type == SILC_ROUTER)
743 server->stat.chanclients -= channel->user_count;
745 /* Totally delete the channel and all users on the channel. The
746 users are deleted automatically in silc_idlist_del_channel. */
747 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
748 if (silc_idlist_del_channel(server->local_list, channel)) {
749 server->stat.my_channels--;
750 if (server->server_type == SILC_ROUTER) {
751 server->stat.channels--;
752 server->stat.cell_channels--;
755 if (silc_idlist_del_channel(server->global_list, channel))
756 if (server->server_type == SILC_ROUTER)
757 server->stat.channels--;
763 /* Channel is permanent, do not remove it, remove only users */
764 channel->disabled = TRUE;
765 silc_hash_table_list(channel->user_list, &htl);
766 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
767 silc_hash_table_del(chl->client->channels, channel);
768 silc_hash_table_del(channel->user_list, chl->client);
769 channel->user_count--;
771 /* Update statistics */
772 if (chl->client->connection)
773 server->stat.my_chanclients--;
774 if (server->server_type == SILC_ROUTER) {
775 server->stat.cell_chanclients--;
776 server->stat.chanclients--;
781 silc_hash_table_list_reset(&htl);
783 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
788 /* Returns TRUE if the given client is on the channel. FALSE if not.
789 This works because we assure that the user list on the channel is
790 always in up to date thus we can only check the channel list from
791 `client' which is faster than checking the user list from `channel'. */
793 bool silc_server_client_on_channel(SilcClientEntry client,
794 SilcChannelEntry channel,
795 SilcChannelClientEntry *chl)
797 if (!client || !channel)
800 return silc_hash_table_find(client->channels, channel, NULL,
804 /* Checks string for bad characters and returns TRUE if they are found. */
806 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
810 for (i = 0; i < name_len; i++) {
811 if (!isascii(name[i]))
813 if (name[i] <= 32) return TRUE;
814 if (name[i] == ' ') return TRUE;
815 if (name[i] == '*') return TRUE;
816 if (name[i] == '?') return TRUE;
817 if (name[i] == ',') return TRUE;
823 /* Modifies the `name' if it includes bad characters and returns new
824 allocated name that does not include bad characters. */
826 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
829 char *newname = strdup(name);
831 for (i = 0; i < name_len; i++) {
832 if (!isascii(newname[i])) newname[i] = '_';
833 if (newname[i] <= 32) newname[i] = '_';
834 if (newname[i] == ' ') newname[i] = '_';
835 if (newname[i] == '*') newname[i] = '_';
836 if (newname[i] == '?') newname[i] = '_';
837 if (newname[i] == ',') newname[i] = '_';
843 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
844 socket connections with the IP address does not exist. */
846 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
851 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
852 if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
853 server->sockets[i]->type == type)
860 /* Find number of sockets by IP address indicated by remote host, indicatd
861 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
862 does not exist. If `ip' is provided then `hostname' is ignored. */
864 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
866 const char *hostname,
872 if (!ip && !hostname)
875 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
876 if (server->sockets[i] &&
877 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
878 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
879 server->sockets[i]->port == port &&
880 server->sockets[i]->type == type)
887 /* Finds locally cached public key by the public key received in the SKE.
888 If we have it locally cached then we trust it and will use it in the
889 authentication protocol. Returns the locally cached public key or NULL
890 if we do not find the public key. */
892 SilcPublicKey silc_server_find_public_key(SilcServer server,
893 SilcHashTable local_public_keys,
894 SilcPublicKey remote_public_key)
896 SilcPublicKey cached_key;
898 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
899 silc_hash_table_count(local_public_keys)));
901 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
902 (void **)&cached_key, NULL,
903 silc_hash_public_key, NULL,
904 silc_hash_public_key_compare, NULL)) {
905 SILC_LOG_ERROR(("Public key not found"));
909 SILC_LOG_DEBUG(("Found public key"));
914 /* This returns the first public key from the table of public keys. This
915 is used only in cases where single public key exists in the table and
916 we want to get a pointer to it. For public key tables that has multiple
917 keys in it the silc_server_find_public_key must be used. */
919 SilcPublicKey silc_server_get_public_key(SilcServer server,
920 SilcHashTable local_public_keys)
922 SilcPublicKey cached_key;
923 SilcHashTableList htl;
925 SILC_LOG_DEBUG(("Start"));
927 assert(silc_hash_table_count(local_public_keys) < 2);
929 silc_hash_table_list(local_public_keys, &htl);
930 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
932 silc_hash_table_list_reset(&htl);
937 /* Check whether the connection `sock' is allowed to connect to us. This
938 checks for example whether there is too much connections for this host,
939 and required version for the host etc. */
941 bool silc_server_connection_allowed(SilcServer server,
942 SilcSocketConnection sock,
944 SilcServerConfigConnParams *global,
945 SilcServerConfigConnParams *params,
948 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
949 server->stat.my_clients :
950 type == SILC_SOCKET_TYPE_SERVER ?
951 server->stat.my_servers :
952 server->stat.my_routers);
953 SilcUInt32 num_sockets, max_hosts, max_per_host;
954 SilcUInt32 r_protocol_version, l_protocol_version;
955 SilcUInt32 r_software_version, l_software_version;
956 char *r_vendor_version = NULL, *l_vendor_version;
961 silc_version_to_num(params && params->version_protocol ?
962 params->version_protocol :
963 global->version_protocol);
965 silc_version_to_num(params && params->version_software ?
966 params->version_software :
967 global->version_software);
968 l_vendor_version = (params && params->version_software_vendor ?
969 params->version_software_vendor :
970 global->version_software_vendor);
972 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
973 &r_software_version, NULL,
974 &r_vendor_version)) {
975 sock->version = r_protocol_version;
977 /* Match protocol version */
978 if (l_protocol_version && r_protocol_version &&
979 r_protocol_version < l_protocol_version) {
980 SILC_LOG_INFO(("Connection %s (%s) is too old version",
981 sock->hostname, sock->ip));
982 silc_server_disconnect_remote(server, sock,
983 SILC_STATUS_ERR_BAD_VERSION,
984 "You support too old protocol version");
988 /* Math software version */
989 if (l_software_version && r_software_version &&
990 r_software_version < l_software_version) {
991 SILC_LOG_INFO(("Connection %s (%s) is too old version",
992 sock->hostname, sock->ip));
993 silc_server_disconnect_remote(server, sock,
994 SILC_STATUS_ERR_BAD_VERSION,
995 "You support too old software version");
999 /* Regex match vendor version */
1000 if (l_vendor_version && r_vendor_version &&
1001 !silc_string_match(l_vendor_version, r_vendor_version)) {
1002 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1003 sock->hostname, sock->ip));
1004 silc_server_disconnect_remote(server, sock,
1005 SILC_STATUS_ERR_BAD_VERSION,
1006 "Your software is not supported");
1010 silc_free(r_vendor_version);
1012 /* Check for maximum connections limit */
1014 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1015 max_hosts = (params ? params->connections_max : global->connections_max);
1016 max_per_host = (params ? params->connections_max_per_host :
1017 global->connections_max_per_host);
1019 if (max_hosts && conn_number >= max_hosts) {
1020 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1021 sock->hostname, sock->ip));
1022 silc_server_disconnect_remote(server, sock,
1023 SILC_STATUS_ERR_RESOURCE_LIMIT,
1024 "Server is full, try again later");
1028 if (num_sockets >= max_per_host) {
1029 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1030 sock->hostname, sock->ip));
1031 silc_server_disconnect_remote(server, sock,
1032 SILC_STATUS_ERR_RESOURCE_LIMIT,
1033 "Too many connections from your host");
1040 /* Checks that client has rights to add or remove channel modes. If any
1041 of the checks fails FALSE is returned. */
1043 bool silc_server_check_cmode_rights(SilcServer server,
1044 SilcChannelEntry channel,
1045 SilcChannelClientEntry client,
1048 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1049 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1051 /* Check whether has rights to change anything */
1052 if (!is_op && !is_fo)
1055 /* Check whether has rights to change everything */
1059 /* Founder implies operator */
1063 /* We know that client is channel operator, check that they are not
1064 changing anything that requires channel founder rights. Rest of the
1065 modes are available automatically for channel operator. */
1067 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1068 if (is_op && !is_fo)
1071 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1072 if (is_op && !is_fo)
1077 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1078 if (is_op && !is_fo)
1081 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1082 if (is_op && !is_fo)
1087 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1088 if (is_op && !is_fo)
1091 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1092 if (is_op && !is_fo)
1097 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1098 if (is_op && !is_fo)
1101 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1102 if (is_op && !is_fo)
1107 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1108 if (is_op && !is_fo)
1111 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1112 if (is_op && !is_fo)
1117 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1118 if (is_op && !is_fo)
1121 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1122 if (is_op && !is_fo)
1130 /* Check that the client has rights to change its user mode. Returns
1131 FALSE if setting some mode is not allowed. */
1133 bool silc_server_check_umode_rights(SilcServer server,
1134 SilcClientEntry client,
1137 bool server_op = FALSE, router_op = FALSE;
1139 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1140 /* Cannot set server operator mode (must use OPER command) */
1141 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1144 /* Remove the server operator rights */
1145 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1149 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1150 /* Cannot set router operator mode (must use SILCOPER command) */
1151 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1154 /* Remove the router operator rights */
1155 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1160 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1162 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1167 /* This function is used to send the notify packets and motd to the
1168 incoming client connection. */
1170 void silc_server_send_connect_notifys(SilcServer server,
1171 SilcSocketConnection sock,
1172 SilcClientEntry client)
1174 SilcIDListData idata = (SilcIDListData)client;
1176 SILC_LOG_DEBUG(("Send welcome notifys"));
1178 /* Send some nice info to the client */
1179 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1180 ("Welcome to the SILC Network %s",
1182 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1183 ("Your host is %s, running version %s",
1184 server->server_name, server_version));
1186 if (server->server_type == SILC_ROUTER) {
1187 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1188 ("There are %d clients, %d servers and %d "
1189 "routers in SILC Network",
1190 server->stat.clients, server->stat.servers + 1,
1191 server->stat.routers));
1193 if (server->stat.clients && server->stat.servers + 1)
1194 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1195 ("There are %d clients, %d servers and %d "
1196 "routers in SILC Network",
1197 server->stat.clients, server->stat.servers + 1,
1198 (server->standalone ? 0 :
1199 !server->stat.routers ? 1 :
1200 server->stat.routers)));
1203 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1204 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1205 ("There are %d clients on %d server in our cell",
1206 server->stat.cell_clients,
1207 server->stat.cell_servers + 1));
1208 if (server->server_type == SILC_ROUTER) {
1209 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1210 ("I have %d clients, %d channels, %d servers and "
1212 server->stat.my_clients,
1213 server->stat.my_channels,
1214 server->stat.my_servers,
1215 server->stat.my_routers));
1217 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1218 ("I have %d clients and %d channels formed",
1219 server->stat.my_clients,
1220 server->stat.my_channels));
1223 if (server->stat.server_ops || server->stat.router_ops)
1224 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1225 ("There are %d server operators and %d router "
1227 server->stat.server_ops,
1228 server->stat.router_ops));
1229 if (server->stat.my_router_ops + server->stat.my_server_ops)
1230 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1231 ("I have %d operators online",
1232 server->stat.my_router_ops +
1233 server->stat.my_server_ops));
1235 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1236 ("Your connection is secured with %s cipher, "
1237 "key length %d bits",
1238 idata->send_key->cipher->name,
1239 idata->send_key->cipher->key_len));
1240 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1241 ("Your current nickname is %s",
1245 silc_server_send_motd(server, sock);
1248 /* Kill the client indicated by `remote_client' sending KILLED notify
1249 to the client, to all channels client has joined and to primary
1250 router if needed. The killed client is also removed from all channels. */
1252 void silc_server_kill_client(SilcServer server,
1253 SilcClientEntry remote_client,
1254 const char *comment,
1256 SilcIdType killer_id_type)
1258 SilcBuffer killed, killer;
1260 SILC_LOG_DEBUG(("Killing client %s",
1261 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1263 /* Send the KILL notify packets. First send it to the channel, then
1264 to our primary router and then directly to the client who is being
1265 killed right now. */
1267 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1268 killer = silc_id_payload_encode(killer_id, killer_id_type);
1270 /* Send KILLED notify to the channels. It is not sent to the client
1271 as it will be sent differently destined directly to the client and not
1273 silc_server_send_notify_on_channels(server, remote_client,
1274 remote_client, SILC_NOTIFY_TYPE_KILLED,
1275 3, killed->data, killed->len,
1276 comment, comment ? strlen(comment) : 0,
1277 killer->data, killer->len);
1279 /* Send KILLED notify to primary route */
1280 if (!server->standalone)
1281 silc_server_send_notify_killed(server, server->router->connection, TRUE,
1282 remote_client->id, comment,
1283 killer_id, killer_id_type);
1285 /* Send KILLED notify to the client directly */
1286 if (remote_client->connection || remote_client->router)
1287 silc_server_send_notify_killed(server, remote_client->connection ?
1288 remote_client->connection :
1289 remote_client->router->connection, FALSE,
1290 remote_client->id, comment,
1291 killer_id, killer_id_type);
1293 /* Remove the client from all channels. This generates new keys to the
1294 channels as well. */
1295 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1298 /* Remove the client entry, If it is locally connected then we will also
1299 disconnect the client here */
1300 if (remote_client->connection) {
1301 /* Remove locally conneted client */
1302 SilcSocketConnection sock = remote_client->connection;
1303 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1304 silc_server_close_connection(server, sock);
1306 /* Update statistics */
1307 server->stat.clients--;
1308 server->stat.my_clients--;
1309 if (server->stat.cell_clients)
1310 server->stat.cell_clients--;
1311 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1312 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1314 /* Remove remote client */
1315 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1316 /* Remove this client from watcher list if it is */
1317 silc_server_del_from_watcher_list(server, remote_client);
1318 silc_idlist_del_client(server->local_list, remote_client);
1322 silc_buffer_free(killer);
1323 silc_buffer_free(killed);
1328 SilcClientEntry client;
1329 SilcNotifyType notify;
1330 const char *new_nick;
1331 } WatcherNotifyContext;
1334 silc_server_check_watcher_list_foreach(void *key, void *context,
1337 WatcherNotifyContext *notify = user_context;
1338 SilcClientEntry entry = context;
1339 SilcSocketConnection sock;
1341 if (entry == notify->client)
1344 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1347 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1348 silc_id_render(entry->id, SILC_ID_CLIENT)));
1350 /* Send the WATCH notify */
1351 silc_server_send_notify_watch(notify->server, sock, entry,
1353 notify->new_nick ? notify->new_nick :
1354 (const char *)notify->client->nickname,
1359 /* This function checks whether the `client' nickname is being watched
1360 by someone, and notifies the watcher of the notify change of notify
1361 type indicated by `notify'. */
1363 bool silc_server_check_watcher_list(SilcServer server,
1364 SilcClientEntry client,
1365 const char *new_nick,
1366 SilcNotifyType notify)
1368 unsigned char hash[16];
1369 WatcherNotifyContext n;
1371 SILC_LOG_DEBUG(("Checking watcher list %s",
1372 client->nickname ? client->nickname : ""));
1374 /* If the watching is rejected by the client do nothing */
1375 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1378 /* Make hash from the nick, or take it from Client ID */
1379 if (client->nickname) {
1381 memset(nick, 0, sizeof(nick));
1382 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1383 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1385 memset(hash, 0, sizeof(hash));
1386 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1391 n.new_nick = new_nick;
1394 /* Send notify to all watchers */
1395 silc_hash_table_find_foreach(server->watcher_list, hash,
1396 silc_server_check_watcher_list_foreach, &n);
1401 /* Remove the `client' from watcher list. After calling this the `client'
1402 is not watching any nicknames. */
1404 bool silc_server_del_from_watcher_list(SilcServer server,
1405 SilcClientEntry client)
1407 SilcHashTableList htl;
1409 SilcClientEntry entry;
1412 silc_hash_table_list(server->watcher_list, &htl);
1413 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1414 if (entry == client) {
1415 silc_hash_table_del_by_context(server->watcher_list, key, client);
1417 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1418 silc_id_render(client->id, SILC_ID_CLIENT)));
1420 /* Now check whether there still exists entries with this key, if not
1421 then free the key to not leak memory. */
1422 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1428 silc_hash_table_list_reset(&htl);
1433 /* Force the client indicated by `chl' to change the channel user mode
1434 on channel indicated by `channel' to `forced_mode'. */
1436 bool silc_server_force_cumode_change(SilcServer server,
1437 SilcSocketConnection sock,
1438 SilcChannelEntry channel,
1439 SilcChannelClientEntry chl,
1440 SilcUInt32 forced_mode)
1442 SilcBuffer idp1, idp2;
1443 unsigned char cumode[4];
1445 SILC_LOG_DEBUG(("Start"));
1448 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1449 server->id, SILC_ID_SERVER,
1450 chl->client->id, NULL);
1452 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1453 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1454 SILC_PUT32_MSB(forced_mode, cumode);
1455 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1456 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1457 3, idp1->data, idp1->len,
1458 cumode, sizeof(cumode),
1459 idp2->data, idp2->len);
1460 silc_buffer_free(idp1);
1461 silc_buffer_free(idp2);