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 from client's channel list */
55 silc_hash_table_del(client->channels, channel);
57 /* Remove channel if there is no users anymore */
58 if (server->server_type == SILC_ROUTER &&
59 silc_hash_table_count(channel->user_list) < 2) {
61 if (silc_hash_table_find(channels, channel, NULL, NULL))
62 silc_hash_table_del(channels, channel);
65 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
67 if (silc_idlist_del_channel(server->local_list, channel))
68 server->stat.my_channels--;
70 silc_idlist_del_channel(server->global_list, channel);
74 /* Remove client from channel's client list */
75 silc_hash_table_del(channel->user_list, chl->client);
76 channel->user_count--;
78 /* If there is no global users on the channel anymore mark the channel
79 as local channel. Do not check if the removed client is local client. */
80 if (server->server_type != SILC_ROUTER && channel->global_users &&
81 chl->client->router && !silc_server_channel_has_global(channel))
82 channel->global_users = FALSE;
85 server->stat.my_chanclients--;
87 /* If there is not at least one local user on the channel then we don't
88 need the channel entry anymore, we can remove it safely. */
89 if (server->server_type != SILC_ROUTER &&
90 !silc_server_channel_has_local(channel)) {
92 if (silc_hash_table_find(channels, channel, NULL, NULL))
93 silc_hash_table_del(channels, channel);
96 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
98 if (channel->founder_key) {
99 /* The founder auth data exists, do not remove the channel entry */
100 SilcChannelClientEntry chl2;
101 SilcHashTableList htl2;
103 channel->disabled = TRUE;
105 silc_hash_table_list(channel->user_list, &htl2);
106 while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
107 silc_hash_table_del(chl2->client->channels, channel);
108 silc_hash_table_del(channel->user_list, chl2->client);
109 channel->user_count--;
112 silc_hash_table_list_reset(&htl2);
116 /* Remove the channel entry */
117 if (silc_idlist_del_channel(server->local_list, channel))
118 server->stat.my_channels--;
120 silc_idlist_del_channel(server->global_list, channel);
124 /* Add the channel to the the channels list to regenerate the
126 if (!silc_hash_table_find(channels, channel, NULL, NULL))
127 silc_hash_table_add(channels, channel, channel);
129 silc_hash_table_list_reset(&htl);
131 silc_buffer_free(clidp);
134 /* This function is used to remove all client entries by the server `entry'.
135 This is called when the connection is lost to the server. In this case
136 we must invalidate all the client entries owned by the server `entry'.
137 If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
138 distributed to our local clients. */
140 bool silc_server_remove_clients_by_server(SilcServer server,
141 SilcServerEntry entry,
144 SilcIDCacheList list = NULL;
145 SilcIDCacheEntry id_cache = NULL;
146 SilcClientEntry client = NULL;
148 SilcClientEntry *clients = NULL;
149 SilcUInt32 clients_c = 0;
150 unsigned char **argv = NULL;
151 SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
152 SilcHashTableList htl;
153 SilcChannelEntry channel;
154 SilcHashTable channels;
157 SILC_LOG_DEBUG(("Start"));
159 /* Allocate the hash table that holds the channels that require
160 channel key re-generation after we've removed this server's clients
161 from the channels. */
162 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
165 if (server_signoff) {
166 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
167 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
168 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
169 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
170 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
171 memcpy(argv[argc], idp->data, idp->len);
172 argv_lens[argc] = idp->len;
173 argv_types[argc] = argc + 1;
175 silc_buffer_free(idp);
178 if (silc_idcache_get_all(server->local_list->clients, &list)) {
180 if (silc_idcache_list_first(list, &id_cache)) {
182 client = (SilcClientEntry)id_cache->context;
183 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
184 if (!silc_idcache_list_next(list, &id_cache))
190 if (client->router != entry) {
191 if (server_signoff) {
192 clients = silc_realloc(clients,
193 sizeof(*clients) * (clients_c + 1));
194 clients[clients_c] = client;
198 if (!silc_idcache_list_next(list, &id_cache))
204 if (server_signoff) {
205 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
206 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
207 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
209 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
211 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
212 memcpy(argv[argc], idp->data, idp->len);
213 argv_lens[argc] = idp->len;
214 argv_types[argc] = argc + 1;
216 silc_buffer_free(idp);
219 /* Update statistics */
220 server->stat.clients--;
221 if (server->stat.cell_clients)
222 server->stat.cell_clients--;
223 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
224 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
226 /* Remove the client entry */
227 silc_server_remove_clients_channels(server, NULL, client, channels);
228 if (!server_signoff) {
229 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
230 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
232 silc_idlist_del_client(server->local_list, client);
234 /* Remove this client from watcher list if it is */
235 silc_server_del_from_watcher_list(server, client);
238 if (!silc_idcache_list_next(list, &id_cache))
242 silc_idcache_list_free(list);
245 if (silc_idcache_get_all(server->global_list->clients, &list)) {
247 if (silc_idcache_list_first(list, &id_cache)) {
249 client = (SilcClientEntry)id_cache->context;
250 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
251 if (!silc_idcache_list_next(list, &id_cache))
257 if (client->router != entry) {
258 if (server_signoff && client->connection) {
259 clients = silc_realloc(clients,
260 sizeof(*clients) * (clients_c + 1));
261 clients[clients_c] = client;
265 if (!silc_idcache_list_next(list, &id_cache))
271 if (server_signoff) {
272 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
273 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
274 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
276 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
278 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
279 memcpy(argv[argc], idp->data, idp->len);
280 argv_lens[argc] = idp->len;
281 argv_types[argc] = argc + 1;
283 silc_buffer_free(idp);
286 /* Update statistics */
287 server->stat.clients--;
288 if (server->stat.cell_clients)
289 server->stat.cell_clients--;
290 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
291 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
293 /* Remove the client entry */
294 silc_server_remove_clients_channels(server, NULL, client, channels);
295 if (!server_signoff) {
296 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
297 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
299 silc_idlist_del_client(server->global_list, client);
302 if (!silc_idcache_list_next(list, &id_cache))
306 silc_idcache_list_free(list);
309 /* Send the SERVER_SIGNOFF notify */
310 if (server_signoff) {
311 SilcBuffer args, not;
313 /* Send SERVER_SIGNOFF notify to our primary router */
314 if (!server->standalone && server->router &&
315 server->router != entry) {
316 args = silc_argument_payload_encode(1, argv, argv_lens,
318 silc_server_send_notify_args(server,
319 server->router->connection,
320 server->server_type == SILC_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, clients_c,
334 SILC_PACKET_NOTIFY, 0, FALSE,
335 not->data, not->len, FALSE);
338 silc_buffer_free(args);
339 silc_buffer_free(not);
340 for (i = 0; i < argc; i++)
343 silc_free(argv_lens);
344 silc_free(argv_types);
347 /* We must now re-generate the channel key for all channels that had
348 this server's client(s) on the channel. As they left the channel we
349 must re-generate the channel key. */
350 silc_hash_table_list(channels, &htl);
351 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
352 if (!silc_server_create_channel_key(server, channel, 0)) {
353 silc_hash_table_list_reset(&htl);
354 silc_hash_table_free(channels);
358 /* Do not send the channel key if private channel key mode is set */
359 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
362 silc_server_send_channel_key(server, NULL, channel,
363 server->server_type == SILC_ROUTER ?
364 FALSE : !server->standalone);
366 silc_hash_table_list_reset(&htl);
367 silc_hash_table_free(channels);
372 static SilcServerEntry
373 silc_server_update_clients_by_real_server(SilcServer server,
374 SilcServerEntry from,
375 SilcClientEntry client,
377 SilcIDCacheEntry client_cache)
379 SilcServerEntry server_entry;
380 SilcIDCacheEntry id_cache = NULL;
381 SilcIDCacheList list;
383 if (!silc_idcache_get_all(server->local_list->servers, &list))
386 if (silc_idcache_list_first(list, &id_cache)) {
388 server_entry = (SilcServerEntry)id_cache->context;
389 if (server_entry != from &&
390 SILC_ID_COMPARE(server_entry->id, client->id,
391 client->id->ip.data_len)) {
392 SILC_LOG_DEBUG(("Found (local) %s",
393 silc_id_render(server_entry->id, SILC_ID_SERVER)));
395 if (!server_entry->data.send_key && server_entry->router) {
396 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
397 /* If the client is not marked as local then move it to local list
398 since the server is local. */
400 SILC_LOG_DEBUG(("Moving client to local list"));
401 silc_idcache_add(server->local_list->clients, client_cache->name,
402 client_cache->id, client_cache->context,
403 client_cache->expire, NULL);
404 silc_idcache_del_by_context(server->global_list->clients, client);
406 server_entry = server_entry->router;
408 /* If the client is not marked as local then move it to local list
409 since the server is local. */
410 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
411 SILC_LOG_DEBUG(("Moving client to local list"));
412 silc_idcache_add(server->local_list->clients, client_cache->name,
413 client_cache->id, client_cache->context,
414 client_cache->expire, NULL);
415 silc_idcache_del_by_context(server->global_list->clients, client);
419 silc_idcache_list_free(list);
423 if (!silc_idcache_list_next(list, &id_cache))
428 silc_idcache_list_free(list);
430 if (!silc_idcache_get_all(server->global_list->servers, &list))
433 if (silc_idcache_list_first(list, &id_cache)) {
435 server_entry = (SilcServerEntry)id_cache->context;
436 if (server_entry != from &&
437 SILC_ID_COMPARE(server_entry->id, client->id,
438 client->id->ip.data_len)) {
439 SILC_LOG_DEBUG(("Found (global) %s",
440 silc_id_render(server_entry->id, SILC_ID_SERVER)));
442 if (!server_entry->data.send_key && server_entry->router) {
443 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
444 /* If the client is marked as local then move it to global list
445 since the server is global. */
447 SILC_LOG_DEBUG(("Moving client to global list"));
448 silc_idcache_add(server->global_list->clients, client_cache->name,
449 client_cache->id, client_cache->context,
450 client_cache->expire, NULL);
451 silc_idcache_del_by_context(server->local_list->clients, client);
453 server_entry = server_entry->router;
455 /* If the client is marked as local then move it to global list
456 since the server is global. */
457 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
458 SILC_LOG_DEBUG(("Moving client to global list"));
459 silc_idcache_add(server->global_list->clients, client_cache->name,
460 client_cache->id, client_cache->context,
461 client_cache->expire, NULL);
462 silc_idcache_del_by_context(server->local_list->clients, client);
466 silc_idcache_list_free(list);
470 if (!silc_idcache_list_next(list, &id_cache))
475 silc_idcache_list_free(list);
480 /* Updates the clients that are originated from the `from' to be originated
481 from the `to'. If the `resolve_real_server' is TRUE then this will
482 attempt to figure out which clients really are originated from the
483 `from' and which are originated from a server that we have connection
484 to, when we've acting as backup router. If it is FALSE the `to' will
485 be the new source. This function also removes the clients that are
486 *really* originated from `from' if `remove_from' is TRUE. These are
487 clients that the `from' owns, and not just clients that are behind
490 void silc_server_update_clients_by_server(SilcServer server,
491 SilcServerEntry from,
493 bool resolve_real_server,
496 SilcIDCacheList list = NULL;
497 SilcIDCacheEntry id_cache = NULL;
498 SilcClientEntry client = NULL;
501 SILC_LOG_DEBUG(("Start"));
503 SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
505 SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
510 if (silc_idcache_get_all(server->global_list->clients, &list)) {
511 if (silc_idcache_list_first(list, &id_cache)) {
513 client = (SilcClientEntry)id_cache->context;
514 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
515 if (!silc_idcache_list_next(list, &id_cache))
521 SILC_LOG_DEBUG(("Client (global) %s",
522 silc_id_render(client->id, SILC_ID_CLIENT)));
524 SILC_LOG_DEBUG(("Client->router (global) %s",
525 silc_id_render(client->router->id, SILC_ID_SERVER)));
527 if (client->router == from) {
528 /* Skip clients that are *really* owned by the `from' */
529 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
530 client->id->ip.data_len)) {
531 SILC_LOG_DEBUG(("Found really owned client, skip it"));
532 if (!silc_idcache_list_next(list, &id_cache))
538 if (resolve_real_server) {
540 silc_server_update_clients_by_real_server(server, from, client,
549 if (!silc_idcache_list_next(list, &id_cache))
553 silc_idcache_list_free(list);
557 if (silc_idcache_get_all(server->local_list->clients, &list)) {
558 if (silc_idcache_list_first(list, &id_cache)) {
560 client = (SilcClientEntry)id_cache->context;
561 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
562 if (!silc_idcache_list_next(list, &id_cache))
568 SILC_LOG_DEBUG(("Client (local) %s",
569 silc_id_render(client->id, SILC_ID_CLIENT)));
571 SILC_LOG_DEBUG(("Client->router (local) %s",
572 silc_id_render(client->router->id, SILC_ID_SERVER)));
574 if (client->router == from) {
575 /* Skip clients that are *really* owned by the `from' */
576 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
577 client->id->ip.data_len)) {
578 SILC_LOG_DEBUG(("Found really owned client, skip it"));
579 if (!silc_idcache_list_next(list, &id_cache))
585 if (resolve_real_server) {
587 silc_server_update_clients_by_real_server(server, from, client,
590 client->router = from; /* on local list put old from */
596 if (!silc_idcache_list_next(list, &id_cache))
600 silc_idcache_list_free(list);
604 /* Now remove the clients that are still marked as orignated from the
605 `from'. These are the clients that really was owned by the `from' and
606 not just exist behind the `from'. */
607 silc_server_remove_clients_by_server(server, from, TRUE);
610 /* Updates servers that are from `from' to be originated from `to'. This
611 will also update the server's connection to `to's connection. */
613 void silc_server_update_servers_by_server(SilcServer server,
614 SilcServerEntry from,
617 SilcIDCacheList list = NULL;
618 SilcIDCacheEntry id_cache = NULL;
619 SilcServerEntry server_entry = NULL;
621 SILC_LOG_DEBUG(("Start"));
623 if (silc_idcache_get_all(server->local_list->servers, &list)) {
624 if (silc_idcache_list_first(list, &id_cache)) {
626 server_entry = (SilcServerEntry)id_cache->context;
627 if (server_entry->router == from) {
628 server_entry->router = to;
629 server_entry->connection = to->connection;
631 if (!silc_idcache_list_next(list, &id_cache))
635 silc_idcache_list_free(list);
638 if (silc_idcache_get_all(server->global_list->servers, &list)) {
639 if (silc_idcache_list_first(list, &id_cache)) {
641 server_entry = (SilcServerEntry)id_cache->context;
642 if (server_entry->router == from) {
643 server_entry->router = to;
644 server_entry->connection = to->connection;
646 if (!silc_idcache_list_next(list, &id_cache))
650 silc_idcache_list_free(list);
654 /* Removes channels that are from `from. */
656 void silc_server_remove_channels_by_server(SilcServer server,
657 SilcServerEntry from)
659 SilcIDCacheList list = NULL;
660 SilcIDCacheEntry id_cache = NULL;
661 SilcChannelEntry channel = NULL;
663 SILC_LOG_DEBUG(("Start"));
665 if (silc_idcache_get_all(server->global_list->channels, &list)) {
666 if (silc_idcache_list_first(list, &id_cache)) {
668 channel = (SilcChannelEntry)id_cache->context;
669 if (channel->router == from)
670 silc_idlist_del_channel(server->global_list, channel);
671 if (!silc_idcache_list_next(list, &id_cache))
675 silc_idcache_list_free(list);
679 /* Updates channels that are from `from' to be originated from `to'. */
681 void silc_server_update_channels_by_server(SilcServer server,
682 SilcServerEntry from,
685 SilcIDCacheList list = NULL;
686 SilcIDCacheEntry id_cache = NULL;
687 SilcChannelEntry channel = NULL;
689 SILC_LOG_DEBUG(("Start"));
691 if (silc_idcache_get_all(server->global_list->channels, &list)) {
692 if (silc_idcache_list_first(list, &id_cache)) {
694 channel = (SilcChannelEntry)id_cache->context;
695 if (channel->router == from)
696 channel->router = to;
697 if (!silc_idcache_list_next(list, &id_cache))
701 silc_idcache_list_free(list);
705 /* Checks whether given channel has global users. If it does this returns
706 TRUE and FALSE if there is only locally connected clients on the channel. */
708 bool silc_server_channel_has_global(SilcChannelEntry channel)
710 SilcChannelClientEntry chl;
711 SilcHashTableList htl;
713 silc_hash_table_list(channel->user_list, &htl);
714 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
715 if (chl->client->router) {
716 silc_hash_table_list_reset(&htl);
720 silc_hash_table_list_reset(&htl);
725 /* Checks whether given channel has locally connected users. If it does this
726 returns TRUE and FALSE if there is not one locally connected client. */
728 bool silc_server_channel_has_local(SilcChannelEntry channel)
730 SilcChannelClientEntry chl;
731 SilcHashTableList htl;
733 silc_hash_table_list(channel->user_list, &htl);
734 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
735 if (!chl->client->router) {
736 silc_hash_table_list_reset(&htl);
740 silc_hash_table_list_reset(&htl);
745 /* Returns TRUE if the given client is on the channel. FALSE if not.
746 This works because we assure that the user list on the channel is
747 always in up to date thus we can only check the channel list from
748 `client' which is faster than checking the user list from `channel'. */
750 bool silc_server_client_on_channel(SilcClientEntry client,
751 SilcChannelEntry channel,
752 SilcChannelClientEntry *chl)
754 if (!client || !channel)
757 return silc_hash_table_find(client->channels, channel, NULL,
761 /* Checks string for bad characters and returns TRUE if they are found. */
763 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
767 for (i = 0; i < name_len; i++) {
768 if (!isascii(name[i]))
770 if (name[i] <= 32) return TRUE;
771 if (name[i] == ' ') return TRUE;
772 if (name[i] == '*') return TRUE;
773 if (name[i] == '?') return TRUE;
774 if (name[i] == ',') return TRUE;
780 /* Modifies the `name' if it includes bad characters and returns new
781 allocated name that does not include bad characters. */
783 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
786 char *newname = strdup(name);
788 for (i = 0; i < name_len; i++) {
789 if (!isascii(newname[i])) newname[i] = '_';
790 if (newname[i] <= 32) newname[i] = '_';
791 if (newname[i] == ' ') newname[i] = '_';
792 if (newname[i] == '*') newname[i] = '_';
793 if (newname[i] == '?') newname[i] = '_';
794 if (newname[i] == ',') newname[i] = '_';
800 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
801 socket connections with the IP address does not exist. */
803 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
808 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
809 if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
810 server->sockets[i]->type == type)
817 /* Find number of sockets by IP address indicated by remote host, indicatd
818 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
819 does not exist. If `ip' is provided then `hostname' is ignored. */
821 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
823 const char *hostname,
829 if (!ip && !hostname)
832 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
833 if (server->sockets[i] &&
834 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
835 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
836 server->sockets[i]->port == port &&
837 server->sockets[i]->type == type)
844 /* Finds locally cached public key by the public key received in the SKE.
845 If we have it locally cached then we trust it and will use it in the
846 authentication protocol. Returns the locally cached public key or NULL
847 if we do not find the public key. */
849 SilcPublicKey silc_server_find_public_key(SilcServer server,
850 SilcHashTable local_public_keys,
851 SilcPublicKey remote_public_key)
853 SilcPublicKey cached_key;
855 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
856 silc_hash_table_count(local_public_keys)));
858 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
859 (void **)&cached_key, NULL,
860 silc_hash_public_key, NULL,
861 silc_hash_public_key_compare, NULL)) {
862 SILC_LOG_ERROR(("Public key not found"));
866 SILC_LOG_DEBUG(("Found public key"));
871 /* This returns the first public key from the table of public keys. This
872 is used only in cases where single public key exists in the table and
873 we want to get a pointer to it. For public key tables that has multiple
874 keys in it the silc_server_find_public_key must be used. */
876 SilcPublicKey silc_server_get_public_key(SilcServer server,
877 SilcHashTable local_public_keys)
879 SilcPublicKey cached_key;
880 SilcHashTableList htl;
882 SILC_LOG_DEBUG(("Start"));
884 assert(silc_hash_table_count(local_public_keys) < 2);
886 silc_hash_table_list(local_public_keys, &htl);
887 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
889 silc_hash_table_list_reset(&htl);
894 /* Check whether the connection `sock' is allowed to connect to us. This
895 checks for example whether there is too much connections for this host,
896 and required version for the host etc. */
898 bool silc_server_connection_allowed(SilcServer server,
899 SilcSocketConnection sock,
901 SilcServerConfigConnParams *global,
902 SilcServerConfigConnParams *params,
905 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
906 server->stat.my_clients :
907 type == SILC_SOCKET_TYPE_SERVER ?
908 server->stat.my_servers :
909 server->stat.my_routers);
910 SilcUInt32 num_sockets, max_hosts, max_per_host;
911 SilcUInt32 r_protocol_version, l_protocol_version;
912 SilcUInt32 r_software_version, l_software_version;
913 char *r_vendor_version = NULL, *l_vendor_version;
918 silc_version_to_num(params && params->version_protocol ?
919 params->version_protocol :
920 global->version_protocol);
922 silc_version_to_num(params && params->version_software ?
923 params->version_software :
924 global->version_software);
925 l_vendor_version = (params && params->version_software_vendor ?
926 params->version_software_vendor :
927 global->version_software_vendor);
929 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
930 &r_software_version, NULL,
931 &r_vendor_version)) {
932 sock->version = r_protocol_version;
934 /* Match protocol version */
935 if (l_protocol_version && r_protocol_version &&
936 r_protocol_version < l_protocol_version) {
937 SILC_LOG_INFO(("Connection %s (%s) is too old version",
938 sock->hostname, sock->ip));
939 silc_server_disconnect_remote(server, sock,
940 SILC_STATUS_ERR_BAD_VERSION,
941 "You support too old protocol version");
945 /* Math software version */
946 if (l_software_version && r_software_version &&
947 r_software_version < l_software_version) {
948 SILC_LOG_INFO(("Connection %s (%s) is too old version",
949 sock->hostname, sock->ip));
950 silc_server_disconnect_remote(server, sock,
951 SILC_STATUS_ERR_BAD_VERSION,
952 "You support too old software version");
956 /* Regex match vendor version */
957 if (l_vendor_version && r_vendor_version &&
958 !silc_string_match(l_vendor_version, r_vendor_version)) {
959 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
960 sock->hostname, sock->ip));
961 silc_server_disconnect_remote(server, sock,
962 SILC_STATUS_ERR_BAD_VERSION,
963 "Your software is not supported");
967 silc_free(r_vendor_version);
969 /* Check for maximum connections limit */
971 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
972 max_hosts = (params ? params->connections_max : global->connections_max);
973 max_per_host = (params ? params->connections_max_per_host :
974 global->connections_max_per_host);
976 if (max_hosts && conn_number >= max_hosts) {
977 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
978 sock->hostname, sock->ip));
979 silc_server_disconnect_remote(server, sock,
980 SILC_STATUS_ERR_RESOURCE_LIMIT,
981 "Server is full, try again later");
985 if (num_sockets >= max_per_host) {
986 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
987 sock->hostname, sock->ip));
988 silc_server_disconnect_remote(server, sock,
989 SILC_STATUS_ERR_RESOURCE_LIMIT,
990 "Too many connections from your host");
997 /* Checks that client has rights to add or remove channel modes. If any
998 of the checks fails FALSE is returned. */
1000 bool silc_server_check_cmode_rights(SilcServer server,
1001 SilcChannelEntry channel,
1002 SilcChannelClientEntry client,
1005 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1006 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1008 /* Check whether has rights to change anything */
1009 if (!is_op && !is_fo)
1012 /* Check whether has rights to change everything */
1016 /* We know that client is channel operator, check that they are not
1017 changing anything that requires channel founder rights. Rest of the
1018 modes are available automatically for channel operator. */
1020 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1021 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
1022 if (is_op && !is_fo)
1025 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1026 if (is_op && !is_fo)
1031 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1032 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
1033 if (is_op && !is_fo)
1036 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1037 if (is_op && !is_fo)
1042 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1043 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
1044 if (is_op && !is_fo)
1047 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1048 if (is_op && !is_fo)
1053 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1054 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
1055 if (is_op && !is_fo)
1058 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1059 if (is_op && !is_fo)
1064 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1065 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS))
1066 if (is_op && !is_fo)
1069 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1070 if (is_op && !is_fo)
1075 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1076 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS))
1077 if (is_op && !is_fo)
1080 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1081 if (is_op && !is_fo)
1089 /* Check that the client has rights to change its user mode. Returns
1090 FALSE if setting some mode is not allowed. */
1092 bool silc_server_check_umode_rights(SilcServer server,
1093 SilcClientEntry client,
1096 bool server_op = FALSE, router_op = FALSE;
1098 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1099 /* Cannot set server operator mode (must use OPER command) */
1100 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1103 /* Remove the server operator rights */
1104 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1108 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1109 /* Cannot set router operator mode (must use SILCOPER command) */
1110 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1113 /* Remove the router operator rights */
1114 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1119 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1121 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1126 /* This function is used to send the notify packets and motd to the
1127 incoming client connection. */
1129 void silc_server_send_connect_notifys(SilcServer server,
1130 SilcSocketConnection sock,
1131 SilcClientEntry client)
1133 SilcIDListData idata = (SilcIDListData)client;
1135 /* Send some nice info to the client */
1136 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1137 ("Welcome to the SILC Network %s",
1139 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1140 ("Your host is %s, running version %s",
1141 server->server_name, server_version));
1143 if (server->stat.clients && server->stat.servers + 1)
1144 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1145 ("There are %d clients on %d servers in SILC "
1146 "Network", server->stat.clients,
1147 server->stat.servers + 1));
1148 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1149 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1150 ("There are %d clients on %d server in our cell",
1151 server->stat.cell_clients,
1152 server->stat.cell_servers + 1));
1153 if (server->server_type == SILC_ROUTER) {
1154 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1155 ("I have %d clients, %d channels, %d servers and "
1157 server->stat.my_clients,
1158 server->stat.my_channels,
1159 server->stat.my_servers,
1160 server->stat.my_routers));
1162 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1163 ("I have %d clients and %d channels formed",
1164 server->stat.my_clients,
1165 server->stat.my_channels));
1168 if (server->stat.server_ops || server->stat.router_ops)
1169 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1170 ("There are %d server operators and %d router "
1172 server->stat.server_ops,
1173 server->stat.router_ops));
1174 if (server->stat.my_router_ops + server->stat.my_server_ops)
1175 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1176 ("I have %d operators online",
1177 server->stat.my_router_ops +
1178 server->stat.my_server_ops));
1180 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1181 ("Your connection is secured with %s cipher, "
1182 "key length %d bits",
1183 idata->send_key->cipher->name,
1184 idata->send_key->cipher->key_len));
1185 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1186 ("Your current nickname is %s",
1190 silc_server_send_motd(server, sock);
1193 /* Kill the client indicated by `remote_client' sending KILLED notify
1194 to the client, to all channels client has joined and to primary
1195 router if needed. The killed client is also removed from all channels. */
1197 void silc_server_kill_client(SilcServer server,
1198 SilcClientEntry remote_client,
1199 const char *comment,
1201 SilcIdType killer_id_type)
1203 SilcBuffer killed, killer;
1205 /* Send the KILL notify packets. First send it to the channel, then
1206 to our primary router and then directly to the client who is being
1207 killed right now. */
1209 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1210 killer = silc_id_payload_encode(killer_id, killer_id_type);
1212 /* Send KILLED notify to the channels. It is not sent to the client
1213 as it will be sent differently destined directly to the client and not
1215 silc_server_send_notify_on_channels(server, remote_client,
1216 remote_client, SILC_NOTIFY_TYPE_KILLED,
1217 3, killed->data, killed->len,
1218 comment, comment ? strlen(comment) : 0,
1219 killer->data, killer->len);
1221 /* Send KILLED notify to primary route */
1222 if (!server->standalone)
1223 silc_server_send_notify_killed(server, server->router->connection, TRUE,
1224 remote_client->id, comment,
1225 killer_id, killer_id_type);
1227 /* Send KILLED notify to the client directly */
1228 if (remote_client->connection || remote_client->router)
1229 silc_server_send_notify_killed(server, remote_client->connection ?
1230 remote_client->connection :
1231 remote_client->router->connection, FALSE,
1232 remote_client->id, comment,
1233 killer_id, killer_id_type);
1235 /* Remove the client from all channels. This generates new keys to the
1236 channels as well. */
1237 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1240 /* Remove the client entry, If it is locally connected then we will also
1241 disconnect the client here */
1242 if (remote_client->connection) {
1243 /* Remove locally conneted client */
1244 SilcSocketConnection sock = remote_client->connection;
1245 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1246 silc_server_close_connection(server, sock);
1248 /* Update statistics */
1249 server->stat.clients--;
1250 server->stat.my_clients--;
1251 if (server->stat.cell_clients)
1252 server->stat.cell_clients--;
1253 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1254 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1256 /* Remove remote client */
1257 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1258 /* Remove this client from watcher list if it is */
1259 silc_server_del_from_watcher_list(server, remote_client);
1261 silc_idlist_del_client(server->local_list, remote_client);
1265 silc_buffer_free(killer);
1266 silc_buffer_free(killed);
1271 SilcClientEntry client;
1272 SilcNotifyType notify;
1273 const char *new_nick;
1274 } WatcherNotifyContext;
1277 silc_server_check_watcher_list_foreach(void *key, void *context,
1280 WatcherNotifyContext *notify = user_context;
1281 SilcClientEntry entry = context;
1282 SilcSocketConnection sock;
1284 if (entry == notify->client)
1287 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1290 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1291 silc_id_render(entry->id, SILC_ID_CLIENT)));
1293 /* Send the WATCH notify */
1294 silc_server_send_notify_watch(notify->server, sock, entry,
1296 notify->new_nick ? notify->new_nick :
1297 (const char *)notify->client->nickname,
1302 /* This function checks whether the `client' nickname is being watched
1303 by someone, and notifies the watcher of the notify change of notify
1304 type indicated by `notify'. */
1306 bool silc_server_check_watcher_list(SilcServer server,
1307 SilcClientEntry client,
1308 const char *new_nick,
1309 SilcNotifyType notify)
1311 unsigned char hash[16];
1312 WatcherNotifyContext n;
1314 SILC_LOG_DEBUG(("Start"));
1316 /* If the watching is rejected by the client do nothing */
1317 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1320 /* Make hash from the nick, or take it from Client ID */
1321 if (client->nickname) {
1323 memset(nick, 0, sizeof(nick));
1324 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1325 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1327 memset(hash, 0, sizeof(hash));
1328 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1333 n.new_nick = new_nick;
1336 /* Send notify to all watchers */
1337 silc_hash_table_find_foreach(server->watcher_list, hash,
1338 silc_server_check_watcher_list_foreach, &n);
1343 /* Remove the `client' from watcher list. After calling this the `client'
1344 is not watching any nicknames. */
1346 bool silc_server_del_from_watcher_list(SilcServer server,
1347 SilcClientEntry client)
1349 SilcHashTableList htl;
1351 SilcClientEntry entry;
1354 silc_hash_table_list(server->watcher_list, &htl);
1355 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1356 if (entry == client) {
1357 silc_hash_table_del_by_context(server->watcher_list, key, client);
1359 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1360 silc_id_render(client->id, SILC_ID_CLIENT)));
1362 /* Now check whether there still exists entries with this key, if not
1363 then free the key to not leak memory. */
1364 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1370 silc_hash_table_list_reset(&htl);