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. */
31 static void silc_server_remove_clients_channels(SilcServer server,
32 SilcSocketConnection sock,
33 SilcClientEntry client,
34 SilcHashTable channels)
36 SilcChannelEntry channel;
37 SilcChannelClientEntry chl;
38 SilcHashTableList htl;
41 SILC_LOG_DEBUG(("Start"));
43 if (!client || !client->id)
46 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
48 /* Remove the client from all channels. The client is removed from
49 the channels' user list. */
50 silc_hash_table_list(client->channels, &htl);
51 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
52 channel = chl->channel;
54 /* Remove channel if this is last client leaving the channel, unless
55 the channel is permanent. */
56 if (server->server_type == SILC_ROUTER &&
57 silc_hash_table_count(channel->user_list) < 2) {
58 if (silc_hash_table_find(channels, channel, NULL, NULL))
59 silc_hash_table_del(channels, channel);
60 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
61 silc_server_channel_delete(server, channel);
65 silc_hash_table_del(client->channels, channel);
66 silc_hash_table_del(channel->user_list, chl->client);
67 channel->user_count--;
69 /* If there is no global users on the channel anymore mark the channel
70 as local channel. Do not check if the removed client is local client. */
71 if (server->server_type != SILC_ROUTER && channel->global_users &&
72 chl->client->router && !silc_server_channel_has_global(channel))
73 channel->global_users = FALSE;
77 /* Update statistics */
78 if (client->connection)
79 server->stat.my_chanclients--;
80 if (server->server_type == SILC_ROUTER) {
81 server->stat.cell_chanclients--;
82 server->stat.chanclients--;
85 /* If there is not at least one local user on the channel then we don't
86 need the channel entry anymore, we can remove it safely, unless the
87 channel is permanent channel */
88 if (server->server_type != SILC_ROUTER &&
89 !silc_server_channel_has_local(channel)) {
90 if (silc_hash_table_find(channels, channel, NULL, NULL))
91 silc_hash_table_del(channels, channel);
92 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
93 silc_server_channel_delete(server, channel);
97 /* Add the channel to the the channels list to regenerate the
99 if (!silc_hash_table_find(channels, channel, NULL, NULL))
100 silc_hash_table_add(channels, channel, channel);
102 silc_hash_table_list_reset(&htl);
103 silc_buffer_free(clidp);
106 /* This function is used to remove all client entries by the server `entry'.
107 This is called when the connection is lost to the server. In this case
108 we must invalidate all the client entries owned by the server `entry'.
109 If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
110 distributed to our local clients. */
112 bool silc_server_remove_clients_by_server(SilcServer server,
113 SilcServerEntry entry,
116 SilcIDCacheList list = NULL;
117 SilcIDCacheEntry id_cache = NULL;
118 SilcClientEntry client = NULL;
120 SilcClientEntry *clients = NULL;
121 SilcUInt32 clients_c = 0;
122 unsigned char **argv = NULL;
123 SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
124 SilcHashTableList htl;
125 SilcChannelEntry channel;
126 SilcHashTable channels;
129 SILC_LOG_DEBUG(("Start"));
131 /* Allocate the hash table that holds the channels that require
132 channel key re-generation after we've removed this server's clients
133 from the channels. */
134 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
137 if (server_signoff) {
138 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
139 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
140 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
141 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
142 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
143 memcpy(argv[argc], idp->data, idp->len);
144 argv_lens[argc] = idp->len;
145 argv_types[argc] = argc + 1;
147 silc_buffer_free(idp);
150 if (silc_idcache_get_all(server->local_list->clients, &list)) {
152 if (silc_idcache_list_first(list, &id_cache)) {
154 client = (SilcClientEntry)id_cache->context;
155 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
156 if (!silc_idcache_list_next(list, &id_cache))
162 if (client->router != entry) {
163 if (server_signoff) {
164 clients = silc_realloc(clients,
165 sizeof(*clients) * (clients_c + 1));
166 clients[clients_c] = client;
170 if (!silc_idcache_list_next(list, &id_cache))
176 if (server_signoff) {
177 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
178 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
179 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
181 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
183 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
184 memcpy(argv[argc], idp->data, idp->len);
185 argv_lens[argc] = idp->len;
186 argv_types[argc] = argc + 1;
188 silc_buffer_free(idp);
191 /* Update statistics */
192 server->stat.clients--;
193 if (server->stat.cell_clients)
194 server->stat.cell_clients--;
195 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
196 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
198 /* Remove the client entry */
199 silc_server_remove_clients_channels(server, NULL, client, channels);
200 if (!server_signoff) {
201 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
202 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
204 /* Remove this client from watcher list if it is */
205 silc_server_del_from_watcher_list(server, client);
206 silc_idlist_del_client(server->local_list, client);
209 if (!silc_idcache_list_next(list, &id_cache))
213 silc_idcache_list_free(list);
216 if (silc_idcache_get_all(server->global_list->clients, &list)) {
218 if (silc_idcache_list_first(list, &id_cache)) {
220 client = (SilcClientEntry)id_cache->context;
221 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
222 if (!silc_idcache_list_next(list, &id_cache))
228 if (client->router != entry) {
229 if (server_signoff && client->connection) {
230 clients = silc_realloc(clients,
231 sizeof(*clients) * (clients_c + 1));
232 clients[clients_c] = client;
236 if (!silc_idcache_list_next(list, &id_cache))
242 if (server_signoff) {
243 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
244 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
245 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
247 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
249 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
250 memcpy(argv[argc], idp->data, idp->len);
251 argv_lens[argc] = idp->len;
252 argv_types[argc] = argc + 1;
254 silc_buffer_free(idp);
257 /* Update statistics */
258 server->stat.clients--;
259 if (server->stat.cell_clients)
260 server->stat.cell_clients--;
261 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
262 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
264 /* Remove the client entry */
265 silc_server_remove_clients_channels(server, NULL, client, channels);
266 if (!server_signoff) {
267 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
268 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
270 silc_idlist_del_client(server->global_list, client);
273 if (!silc_idcache_list_next(list, &id_cache))
277 silc_idcache_list_free(list);
280 /* Send the SERVER_SIGNOFF notify */
281 if (server_signoff) {
282 SilcBuffer args, not;
284 /* Send SERVER_SIGNOFF notify to our primary router */
285 if (!server->standalone && server->router &&
286 server->router != entry) {
287 args = silc_argument_payload_encode(1, argv, argv_lens,
289 silc_server_send_notify_args(server,
290 server->router->connection,
291 server->server_type == SILC_SERVER ?
293 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
295 silc_buffer_free(args);
298 /* Send to local clients. We also send the list of client ID's that
299 is to be removed for those servers that would like to use that list. */
300 args = silc_argument_payload_encode(argc, argv, argv_lens,
302 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
304 silc_server_packet_send_clients(server, clients, clients_c,
305 SILC_PACKET_NOTIFY, 0, FALSE,
306 not->data, not->len, FALSE);
309 silc_buffer_free(args);
310 silc_buffer_free(not);
311 for (i = 0; i < argc; i++)
314 silc_free(argv_lens);
315 silc_free(argv_types);
318 /* We must now re-generate the channel key for all channels that had
319 this server's client(s) on the channel. As they left the channel we
320 must re-generate the channel key. */
321 silc_hash_table_list(channels, &htl);
322 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
323 if (!silc_server_create_channel_key(server, channel, 0)) {
324 silc_hash_table_list_reset(&htl);
325 silc_hash_table_free(channels);
329 /* Do not send the channel key if private channel key mode is set */
330 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
333 silc_server_send_channel_key(server, NULL, channel,
334 server->server_type == SILC_ROUTER ?
335 FALSE : !server->standalone);
337 silc_hash_table_list_reset(&htl);
338 silc_hash_table_free(channels);
343 static SilcServerEntry
344 silc_server_update_clients_by_real_server(SilcServer server,
345 SilcServerEntry from,
346 SilcClientEntry client,
348 SilcIDCacheEntry client_cache)
350 SilcServerEntry server_entry;
351 SilcIDCacheEntry id_cache = NULL;
352 SilcIDCacheList list;
354 if (!silc_idcache_get_all(server->local_list->servers, &list))
357 if (silc_idcache_list_first(list, &id_cache)) {
359 server_entry = (SilcServerEntry)id_cache->context;
360 if (server_entry != from &&
361 SILC_ID_COMPARE(server_entry->id, client->id,
362 client->id->ip.data_len)) {
363 SILC_LOG_DEBUG(("Found (local) %s",
364 silc_id_render(server_entry->id, SILC_ID_SERVER)));
366 if (!server_entry->data.send_key && server_entry->router) {
367 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
368 /* If the client is not marked as local then move it to local list
369 since the server is local. */
371 SILC_LOG_DEBUG(("Moving client to local list"));
372 silc_idcache_add(server->local_list->clients, client_cache->name,
373 client_cache->id, client_cache->context,
374 client_cache->expire, NULL);
375 silc_idcache_del_by_context(server->global_list->clients, client);
377 server_entry = server_entry->router;
379 /* If the client is not marked as local then move it to local list
380 since the server is local. */
381 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
382 SILC_LOG_DEBUG(("Moving client to local list"));
383 silc_idcache_add(server->local_list->clients, client_cache->name,
384 client_cache->id, client_cache->context,
385 client_cache->expire, NULL);
386 silc_idcache_del_by_context(server->global_list->clients, client);
390 silc_idcache_list_free(list);
394 if (!silc_idcache_list_next(list, &id_cache))
399 silc_idcache_list_free(list);
401 if (!silc_idcache_get_all(server->global_list->servers, &list))
404 if (silc_idcache_list_first(list, &id_cache)) {
406 server_entry = (SilcServerEntry)id_cache->context;
407 if (server_entry != from &&
408 SILC_ID_COMPARE(server_entry->id, client->id,
409 client->id->ip.data_len)) {
410 SILC_LOG_DEBUG(("Found (global) %s",
411 silc_id_render(server_entry->id, SILC_ID_SERVER)));
413 if (!server_entry->data.send_key && server_entry->router) {
414 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
415 /* If the client is marked as local then move it to global list
416 since the server is global. */
418 SILC_LOG_DEBUG(("Moving client to global list"));
419 silc_idcache_add(server->global_list->clients, client_cache->name,
420 client_cache->id, client_cache->context,
421 client_cache->expire, NULL);
422 silc_idcache_del_by_context(server->local_list->clients, client);
424 server_entry = server_entry->router;
426 /* If the client is marked as local then move it to global list
427 since the server is global. */
428 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
429 SILC_LOG_DEBUG(("Moving client to global list"));
430 silc_idcache_add(server->global_list->clients, client_cache->name,
431 client_cache->id, client_cache->context,
432 client_cache->expire, NULL);
433 silc_idcache_del_by_context(server->local_list->clients, client);
437 silc_idcache_list_free(list);
441 if (!silc_idcache_list_next(list, &id_cache))
446 silc_idcache_list_free(list);
451 /* Updates the clients that are originated from the `from' to be originated
452 from the `to'. If the `resolve_real_server' is TRUE then this will
453 attempt to figure out which clients really are originated from the
454 `from' and which are originated from a server that we have connection
455 to, when we've acting as backup router. If it is FALSE the `to' will
456 be the new source. This function also removes the clients that are
457 *really* originated from `from' if `remove_from' is TRUE. These are
458 clients that the `from' owns, and not just clients that are behind
461 void silc_server_update_clients_by_server(SilcServer server,
462 SilcServerEntry from,
464 bool resolve_real_server,
467 SilcIDCacheList list = NULL;
468 SilcIDCacheEntry id_cache = NULL;
469 SilcClientEntry client = NULL;
472 SILC_LOG_DEBUG(("Start"));
474 SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
476 SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
481 if (silc_idcache_get_all(server->global_list->clients, &list)) {
482 if (silc_idcache_list_first(list, &id_cache)) {
484 client = (SilcClientEntry)id_cache->context;
485 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
486 if (!silc_idcache_list_next(list, &id_cache))
492 SILC_LOG_DEBUG(("Client (global) %s",
493 silc_id_render(client->id, SILC_ID_CLIENT)));
495 SILC_LOG_DEBUG(("Client->router (global) %s",
496 silc_id_render(client->router->id, SILC_ID_SERVER)));
498 if (client->router == from) {
499 /* Skip clients that are *really* owned by the `from' */
500 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
501 client->id->ip.data_len)) {
502 SILC_LOG_DEBUG(("Found really owned client, skip it"));
503 if (!silc_idcache_list_next(list, &id_cache))
509 if (resolve_real_server) {
511 silc_server_update_clients_by_real_server(server, from, client,
520 if (!silc_idcache_list_next(list, &id_cache))
524 silc_idcache_list_free(list);
528 if (silc_idcache_get_all(server->local_list->clients, &list)) {
529 if (silc_idcache_list_first(list, &id_cache)) {
531 client = (SilcClientEntry)id_cache->context;
532 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
533 if (!silc_idcache_list_next(list, &id_cache))
539 SILC_LOG_DEBUG(("Client (local) %s",
540 silc_id_render(client->id, SILC_ID_CLIENT)));
542 SILC_LOG_DEBUG(("Client->router (local) %s",
543 silc_id_render(client->router->id, SILC_ID_SERVER)));
545 if (client->router == from) {
546 /* Skip clients that are *really* owned by the `from' */
547 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
548 client->id->ip.data_len)) {
549 SILC_LOG_DEBUG(("Found really owned client, skip it"));
550 if (!silc_idcache_list_next(list, &id_cache))
556 if (resolve_real_server) {
558 silc_server_update_clients_by_real_server(server, from, client,
561 client->router = from; /* on local list put old from */
567 if (!silc_idcache_list_next(list, &id_cache))
571 silc_idcache_list_free(list);
575 /* Now remove the clients that are still marked as orignated from the
576 `from'. These are the clients that really was owned by the `from' and
577 not just exist behind the `from'. */
578 silc_server_remove_clients_by_server(server, from, TRUE);
581 /* Updates servers that are from `from' to be originated from `to'. This
582 will also update the server's connection to `to's connection. */
584 void silc_server_update_servers_by_server(SilcServer server,
585 SilcServerEntry from,
588 SilcIDCacheList list = NULL;
589 SilcIDCacheEntry id_cache = NULL;
590 SilcServerEntry server_entry = NULL;
592 SILC_LOG_DEBUG(("Start"));
594 if (silc_idcache_get_all(server->local_list->servers, &list)) {
595 if (silc_idcache_list_first(list, &id_cache)) {
597 server_entry = (SilcServerEntry)id_cache->context;
598 if (server_entry->router == from) {
599 server_entry->router = to;
600 server_entry->connection = to->connection;
602 if (!silc_idcache_list_next(list, &id_cache))
606 silc_idcache_list_free(list);
609 if (silc_idcache_get_all(server->global_list->servers, &list)) {
610 if (silc_idcache_list_first(list, &id_cache)) {
612 server_entry = (SilcServerEntry)id_cache->context;
613 if (server_entry->router == from) {
614 server_entry->router = to;
615 server_entry->connection = to->connection;
617 if (!silc_idcache_list_next(list, &id_cache))
621 silc_idcache_list_free(list);
625 /* Removes channels that are from `from. */
627 void silc_server_remove_channels_by_server(SilcServer server,
628 SilcServerEntry from)
630 SilcIDCacheList list = NULL;
631 SilcIDCacheEntry id_cache = NULL;
632 SilcChannelEntry channel = NULL;
634 SILC_LOG_DEBUG(("Removing channels by server"));
636 if (silc_idcache_get_all(server->global_list->channels, &list)) {
637 if (silc_idcache_list_first(list, &id_cache)) {
639 channel = (SilcChannelEntry)id_cache->context;
640 if (channel->router == from)
641 silc_idlist_del_channel(server->global_list, channel);
642 if (!silc_idcache_list_next(list, &id_cache))
646 silc_idcache_list_free(list);
650 /* Updates channels that are from `from' to be originated from `to'. */
652 void silc_server_update_channels_by_server(SilcServer server,
653 SilcServerEntry from,
656 SilcIDCacheList list = NULL;
657 SilcIDCacheEntry id_cache = NULL;
658 SilcChannelEntry channel = NULL;
660 SILC_LOG_DEBUG(("Updating channels by server"));
662 if (silc_idcache_get_all(server->global_list->channels, &list)) {
663 if (silc_idcache_list_first(list, &id_cache)) {
665 channel = (SilcChannelEntry)id_cache->context;
666 if (channel->router == from)
667 channel->router = to;
668 if (!silc_idcache_list_next(list, &id_cache))
672 silc_idcache_list_free(list);
676 /* Checks whether given channel has global users. If it does this returns
677 TRUE and FALSE if there is only locally connected clients on the channel. */
679 bool silc_server_channel_has_global(SilcChannelEntry channel)
681 SilcChannelClientEntry chl;
682 SilcHashTableList htl;
684 silc_hash_table_list(channel->user_list, &htl);
685 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
686 if (chl->client->router) {
687 silc_hash_table_list_reset(&htl);
691 silc_hash_table_list_reset(&htl);
696 /* Checks whether given channel has locally connected users. If it does this
697 returns TRUE and FALSE if there is not one locally connected client. */
699 bool silc_server_channel_has_local(SilcChannelEntry channel)
701 SilcChannelClientEntry chl;
702 SilcHashTableList htl;
704 silc_hash_table_list(channel->user_list, &htl);
705 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
706 if (!chl->client->router) {
707 silc_hash_table_list_reset(&htl);
711 silc_hash_table_list_reset(&htl);
716 /* This function removes the channel and all users on the channel, unless
717 the channel is permanent. In this case the channel is disabled but all
718 users are removed from the channel. Returns TRUE if the channel is
719 destroyed totally, and FALSE if it is permanent and remains. */
721 bool silc_server_channel_delete(SilcServer server,
722 SilcChannelEntry channel)
724 SilcChannelClientEntry chl;
725 SilcHashTableList htl;
726 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
729 SILC_LOG_DEBUG(("Deleting %s channel", channel->channel_name));
731 /* Update statistics */
732 if (server->server_type == SILC_ROUTER)
733 server->stat.chanclients -= channel->user_count;
735 /* Totally delete the channel and all users on the channel. The
736 users are deleted automatically in silc_idlist_del_channel. */
737 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
738 if (silc_idlist_del_channel(server->local_list, channel)) {
739 server->stat.my_channels--;
740 if (server->server_type == SILC_ROUTER) {
741 server->stat.channels--;
742 server->stat.cell_channels--;
745 if (silc_idlist_del_channel(server->global_list, channel))
746 if (server->server_type == SILC_ROUTER)
747 server->stat.channels--;
753 /* Channel is permanent, do not remove it, remove only users */
754 channel->disabled = TRUE;
755 silc_hash_table_list(channel->user_list, &htl);
756 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
757 silc_hash_table_del(chl->client->channels, channel);
758 silc_hash_table_del(channel->user_list, chl->client);
759 channel->user_count--;
761 /* Update statistics */
762 if (chl->client->connection)
763 server->stat.my_chanclients--;
764 if (server->server_type == SILC_ROUTER) {
765 server->stat.cell_chanclients--;
766 server->stat.chanclients--;
771 silc_hash_table_list_reset(&htl);
773 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
778 /* Returns TRUE if the given client is on the channel. FALSE if not.
779 This works because we assure that the user list on the channel is
780 always in up to date thus we can only check the channel list from
781 `client' which is faster than checking the user list from `channel'. */
783 bool silc_server_client_on_channel(SilcClientEntry client,
784 SilcChannelEntry channel,
785 SilcChannelClientEntry *chl)
787 if (!client || !channel)
790 return silc_hash_table_find(client->channels, channel, NULL,
794 /* Checks string for bad characters and returns TRUE if they are found. */
796 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
800 for (i = 0; i < name_len; i++) {
801 if (!isascii(name[i]))
803 if (name[i] <= 32) return TRUE;
804 if (name[i] == ' ') return TRUE;
805 if (name[i] == '*') return TRUE;
806 if (name[i] == '?') return TRUE;
807 if (name[i] == ',') return TRUE;
813 /* Modifies the `name' if it includes bad characters and returns new
814 allocated name that does not include bad characters. */
816 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
819 char *newname = strdup(name);
821 for (i = 0; i < name_len; i++) {
822 if (!isascii(newname[i])) newname[i] = '_';
823 if (newname[i] <= 32) newname[i] = '_';
824 if (newname[i] == ' ') newname[i] = '_';
825 if (newname[i] == '*') newname[i] = '_';
826 if (newname[i] == '?') newname[i] = '_';
827 if (newname[i] == ',') newname[i] = '_';
833 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
834 socket connections with the IP address does not exist. */
836 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
841 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
842 if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
843 server->sockets[i]->type == type)
850 /* Find number of sockets by IP address indicated by remote host, indicatd
851 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
852 does not exist. If `ip' is provided then `hostname' is ignored. */
854 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
856 const char *hostname,
862 if (!ip && !hostname)
865 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
866 if (server->sockets[i] &&
867 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
868 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
869 server->sockets[i]->port == port &&
870 server->sockets[i]->type == type)
877 /* Finds locally cached public key by the public key received in the SKE.
878 If we have it locally cached then we trust it and will use it in the
879 authentication protocol. Returns the locally cached public key or NULL
880 if we do not find the public key. */
882 SilcPublicKey silc_server_find_public_key(SilcServer server,
883 SilcHashTable local_public_keys,
884 SilcPublicKey remote_public_key)
886 SilcPublicKey cached_key;
888 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
889 silc_hash_table_count(local_public_keys)));
891 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
892 (void **)&cached_key, NULL,
893 silc_hash_public_key, NULL,
894 silc_hash_public_key_compare, NULL)) {
895 SILC_LOG_ERROR(("Public key not found"));
899 SILC_LOG_DEBUG(("Found public key"));
904 /* This returns the first public key from the table of public keys. This
905 is used only in cases where single public key exists in the table and
906 we want to get a pointer to it. For public key tables that has multiple
907 keys in it the silc_server_find_public_key must be used. */
909 SilcPublicKey silc_server_get_public_key(SilcServer server,
910 SilcHashTable local_public_keys)
912 SilcPublicKey cached_key;
913 SilcHashTableList htl;
915 SILC_LOG_DEBUG(("Start"));
917 assert(silc_hash_table_count(local_public_keys) < 2);
919 silc_hash_table_list(local_public_keys, &htl);
920 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
922 silc_hash_table_list_reset(&htl);
927 /* Check whether the connection `sock' is allowed to connect to us. This
928 checks for example whether there is too much connections for this host,
929 and required version for the host etc. */
931 bool silc_server_connection_allowed(SilcServer server,
932 SilcSocketConnection sock,
934 SilcServerConfigConnParams *global,
935 SilcServerConfigConnParams *params,
938 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
939 server->stat.my_clients :
940 type == SILC_SOCKET_TYPE_SERVER ?
941 server->stat.my_servers :
942 server->stat.my_routers);
943 SilcUInt32 num_sockets, max_hosts, max_per_host;
944 SilcUInt32 r_protocol_version, l_protocol_version;
945 SilcUInt32 r_software_version, l_software_version;
946 char *r_vendor_version = NULL, *l_vendor_version;
951 silc_version_to_num(params && params->version_protocol ?
952 params->version_protocol :
953 global->version_protocol);
955 silc_version_to_num(params && params->version_software ?
956 params->version_software :
957 global->version_software);
958 l_vendor_version = (params && params->version_software_vendor ?
959 params->version_software_vendor :
960 global->version_software_vendor);
962 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
963 &r_software_version, NULL,
964 &r_vendor_version)) {
965 sock->version = r_protocol_version;
967 /* Match protocol version */
968 if (l_protocol_version && r_protocol_version &&
969 r_protocol_version < l_protocol_version) {
970 SILC_LOG_INFO(("Connection %s (%s) is too old version",
971 sock->hostname, sock->ip));
972 silc_server_disconnect_remote(server, sock,
973 SILC_STATUS_ERR_BAD_VERSION,
974 "You support too old protocol version");
978 /* Math software version */
979 if (l_software_version && r_software_version &&
980 r_software_version < l_software_version) {
981 SILC_LOG_INFO(("Connection %s (%s) is too old version",
982 sock->hostname, sock->ip));
983 silc_server_disconnect_remote(server, sock,
984 SILC_STATUS_ERR_BAD_VERSION,
985 "You support too old software version");
989 /* Regex match vendor version */
990 if (l_vendor_version && r_vendor_version &&
991 !silc_string_match(l_vendor_version, r_vendor_version)) {
992 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
993 sock->hostname, sock->ip));
994 silc_server_disconnect_remote(server, sock,
995 SILC_STATUS_ERR_BAD_VERSION,
996 "Your software is not supported");
1000 silc_free(r_vendor_version);
1002 /* Check for maximum connections limit */
1004 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1005 max_hosts = (params ? params->connections_max : global->connections_max);
1006 max_per_host = (params ? params->connections_max_per_host :
1007 global->connections_max_per_host);
1009 if (max_hosts && conn_number >= max_hosts) {
1010 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1011 sock->hostname, sock->ip));
1012 silc_server_disconnect_remote(server, sock,
1013 SILC_STATUS_ERR_RESOURCE_LIMIT,
1014 "Server is full, try again later");
1018 if (num_sockets >= max_per_host) {
1019 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1020 sock->hostname, sock->ip));
1021 silc_server_disconnect_remote(server, sock,
1022 SILC_STATUS_ERR_RESOURCE_LIMIT,
1023 "Too many connections from your host");
1030 /* Checks that client has rights to add or remove channel modes. If any
1031 of the checks fails FALSE is returned. */
1033 bool silc_server_check_cmode_rights(SilcServer server,
1034 SilcChannelEntry channel,
1035 SilcChannelClientEntry client,
1038 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1039 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1041 /* Check whether has rights to change anything */
1042 if (!is_op && !is_fo)
1045 /* Check whether has rights to change everything */
1049 /* Founder implies operator */
1053 /* We know that client is channel operator, check that they are not
1054 changing anything that requires channel founder rights. Rest of the
1055 modes are available automatically for channel operator. */
1057 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1058 if (is_op && !is_fo)
1061 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1062 if (is_op && !is_fo)
1067 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1068 if (is_op && !is_fo)
1071 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1072 if (is_op && !is_fo)
1077 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1078 if (is_op && !is_fo)
1081 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1082 if (is_op && !is_fo)
1087 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1088 if (is_op && !is_fo)
1091 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1092 if (is_op && !is_fo)
1097 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1098 if (is_op && !is_fo)
1101 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1102 if (is_op && !is_fo)
1107 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1108 if (is_op && !is_fo)
1111 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1112 if (is_op && !is_fo)
1120 /* Check that the client has rights to change its user mode. Returns
1121 FALSE if setting some mode is not allowed. */
1123 bool silc_server_check_umode_rights(SilcServer server,
1124 SilcClientEntry client,
1127 bool server_op = FALSE, router_op = FALSE;
1129 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1130 /* Cannot set server operator mode (must use OPER command) */
1131 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1134 /* Remove the server operator rights */
1135 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1139 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1140 /* Cannot set router operator mode (must use SILCOPER command) */
1141 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1144 /* Remove the router operator rights */
1145 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1150 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1152 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1157 /* This function is used to send the notify packets and motd to the
1158 incoming client connection. */
1160 void silc_server_send_connect_notifys(SilcServer server,
1161 SilcSocketConnection sock,
1162 SilcClientEntry client)
1164 SilcIDListData idata = (SilcIDListData)client;
1166 /* Send some nice info to the client */
1167 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1168 ("Welcome to the SILC Network %s",
1170 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1171 ("Your host is %s, running version %s",
1172 server->server_name, server_version));
1174 if (server->server_type == SILC_ROUTER) {
1175 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1176 ("There are %d clients, %d servers and %d "
1177 "routers in SILC Network",
1178 server->stat.clients, server->stat.servers + 1,
1179 server->stat.routers));
1181 if (server->stat.clients && server->stat.servers + 1)
1182 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1183 ("There are %d clients, %d servers and %d "
1184 "routers in SILC Network",
1185 server->stat.clients, server->stat.servers + 1,
1186 (server->standalone ? 0 :
1187 !server->stat.routers ? 1 :
1188 server->stat.routers)));
1191 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1192 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1193 ("There are %d clients on %d server in our cell",
1194 server->stat.cell_clients,
1195 server->stat.cell_servers + 1));
1196 if (server->server_type == SILC_ROUTER) {
1197 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1198 ("I have %d clients, %d channels, %d servers and "
1200 server->stat.my_clients,
1201 server->stat.my_channels,
1202 server->stat.my_servers,
1203 server->stat.my_routers));
1205 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1206 ("I have %d clients and %d channels formed",
1207 server->stat.my_clients,
1208 server->stat.my_channels));
1211 if (server->stat.server_ops || server->stat.router_ops)
1212 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1213 ("There are %d server operators and %d router "
1215 server->stat.server_ops,
1216 server->stat.router_ops));
1217 if (server->stat.my_router_ops + server->stat.my_server_ops)
1218 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1219 ("I have %d operators online",
1220 server->stat.my_router_ops +
1221 server->stat.my_server_ops));
1223 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1224 ("Your connection is secured with %s cipher, "
1225 "key length %d bits",
1226 idata->send_key->cipher->name,
1227 idata->send_key->cipher->key_len));
1228 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1229 ("Your current nickname is %s",
1233 silc_server_send_motd(server, sock);
1236 /* Kill the client indicated by `remote_client' sending KILLED notify
1237 to the client, to all channels client has joined and to primary
1238 router if needed. The killed client is also removed from all channels. */
1240 void silc_server_kill_client(SilcServer server,
1241 SilcClientEntry remote_client,
1242 const char *comment,
1244 SilcIdType killer_id_type)
1246 SilcBuffer killed, killer;
1248 SILC_LOG_DEBUG(("Killing client %s",
1249 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1251 /* Send the KILL notify packets. First send it to the channel, then
1252 to our primary router and then directly to the client who is being
1253 killed right now. */
1255 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1256 killer = silc_id_payload_encode(killer_id, killer_id_type);
1258 /* Send KILLED notify to the channels. It is not sent to the client
1259 as it will be sent differently destined directly to the client and not
1261 silc_server_send_notify_on_channels(server, remote_client,
1262 remote_client, SILC_NOTIFY_TYPE_KILLED,
1263 3, killed->data, killed->len,
1264 comment, comment ? strlen(comment) : 0,
1265 killer->data, killer->len);
1267 /* Send KILLED notify to primary route */
1268 if (!server->standalone)
1269 silc_server_send_notify_killed(server, server->router->connection, TRUE,
1270 remote_client->id, comment,
1271 killer_id, killer_id_type);
1273 /* Send KILLED notify to the client directly */
1274 if (remote_client->connection || remote_client->router)
1275 silc_server_send_notify_killed(server, remote_client->connection ?
1276 remote_client->connection :
1277 remote_client->router->connection, FALSE,
1278 remote_client->id, comment,
1279 killer_id, killer_id_type);
1281 /* Remove the client from all channels. This generates new keys to the
1282 channels as well. */
1283 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1286 /* Remove the client entry, If it is locally connected then we will also
1287 disconnect the client here */
1288 if (remote_client->connection) {
1289 /* Remove locally conneted client */
1290 SilcSocketConnection sock = remote_client->connection;
1291 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1292 silc_server_close_connection(server, sock);
1294 /* Update statistics */
1295 server->stat.clients--;
1296 server->stat.my_clients--;
1297 if (server->stat.cell_clients)
1298 server->stat.cell_clients--;
1299 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1300 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1302 /* Remove remote client */
1303 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1304 /* Remove this client from watcher list if it is */
1305 silc_server_del_from_watcher_list(server, remote_client);
1306 silc_idlist_del_client(server->local_list, remote_client);
1310 silc_buffer_free(killer);
1311 silc_buffer_free(killed);
1316 SilcClientEntry client;
1317 SilcNotifyType notify;
1318 const char *new_nick;
1319 } WatcherNotifyContext;
1322 silc_server_check_watcher_list_foreach(void *key, void *context,
1325 WatcherNotifyContext *notify = user_context;
1326 SilcClientEntry entry = context;
1327 SilcSocketConnection sock;
1329 if (entry == notify->client)
1332 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1335 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1336 silc_id_render(entry->id, SILC_ID_CLIENT)));
1338 /* Send the WATCH notify */
1339 silc_server_send_notify_watch(notify->server, sock, entry,
1341 notify->new_nick ? notify->new_nick :
1342 (const char *)notify->client->nickname,
1347 /* This function checks whether the `client' nickname is being watched
1348 by someone, and notifies the watcher of the notify change of notify
1349 type indicated by `notify'. */
1351 bool silc_server_check_watcher_list(SilcServer server,
1352 SilcClientEntry client,
1353 const char *new_nick,
1354 SilcNotifyType notify)
1356 unsigned char hash[16];
1357 WatcherNotifyContext n;
1359 SILC_LOG_DEBUG(("Start"));
1361 /* If the watching is rejected by the client do nothing */
1362 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1365 /* Make hash from the nick, or take it from Client ID */
1366 if (client->nickname) {
1368 memset(nick, 0, sizeof(nick));
1369 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1370 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1372 memset(hash, 0, sizeof(hash));
1373 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1378 n.new_nick = new_nick;
1381 /* Send notify to all watchers */
1382 silc_hash_table_find_foreach(server->watcher_list, hash,
1383 silc_server_check_watcher_list_foreach, &n);
1388 /* Remove the `client' from watcher list. After calling this the `client'
1389 is not watching any nicknames. */
1391 bool silc_server_del_from_watcher_list(SilcServer server,
1392 SilcClientEntry client)
1394 SilcHashTableList htl;
1396 SilcClientEntry entry;
1399 silc_hash_table_list(server->watcher_list, &htl);
1400 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1401 if (entry == client) {
1402 silc_hash_table_del_by_context(server->watcher_list, key, client);
1404 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1405 silc_id_render(client->id, SILC_ID_CLIENT)));
1407 /* Now check whether there still exists entries with this key, if not
1408 then free the key to not leak memory. */
1409 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1415 silc_hash_table_list_reset(&htl);
1420 /* Force the client indicated by `chl' to change the channel user mode
1421 on channel indicated by `channel' to `forced_mode'. */
1423 bool silc_server_force_cumode_change(SilcServer server,
1424 SilcSocketConnection sock,
1425 SilcChannelEntry channel,
1426 SilcChannelClientEntry chl,
1427 SilcUInt32 forced_mode)
1429 SilcBuffer idp1, idp2;
1430 unsigned char cumode[4];
1432 SILC_LOG_DEBUG(("Start"));
1435 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1436 server->id, SILC_ID_SERVER,
1437 chl->client->id, NULL);
1439 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1440 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1441 SILC_PUT32_MSB(forced_mode, cumode);
1442 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1443 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1444 3, idp1->data, idp1->len,
1445 cumode, sizeof(cumode),
1446 idp2->data, idp2->len);
1447 silc_buffer_free(idp1);
1448 silc_buffer_free(idp2);