5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2001 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 /* Removes the client from channels and possibly removes the channels
25 as well. After removing those channels that exist, their channel
26 keys are regnerated. This is called only by the function
27 silc_server_remove_clients_by_server. */
29 static void silc_server_remove_clients_channels(SilcServer server,
30 SilcSocketConnection sock,
31 SilcClientEntry client,
32 SilcHashTable channels)
34 SilcChannelEntry channel;
35 SilcChannelClientEntry chl;
36 SilcHashTableList htl;
39 SILC_LOG_DEBUG(("Start"));
41 if (!client || !client->id)
44 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
46 /* Remove the client from all channels. The client is removed from
47 the channels' user list. */
48 silc_hash_table_list(client->channels, &htl);
49 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
50 channel = chl->channel;
52 /* Remove channel from client's channel list */
53 silc_hash_table_del(client->channels, channel);
55 /* Remove channel if there is no users anymore */
56 if (server->server_type == SILC_ROUTER &&
57 silc_hash_table_count(channel->user_list) < 2) {
59 if (silc_hash_table_find(channels, channel, NULL, NULL))
60 silc_hash_table_del(channels, channel);
63 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
65 if (silc_idlist_del_channel(server->local_list, channel))
66 server->stat.my_channels--;
68 silc_idlist_del_channel(server->global_list, channel);
72 /* Remove client from channel's client list */
73 silc_hash_table_del(channel->user_list, chl->client);
74 channel->user_count--;
76 /* If there is no global users on the channel anymore mark the channel
77 as local channel. Do not check if the removed client is local client. */
78 if (server->server_type != SILC_ROUTER && channel->global_users &&
79 chl->client->router && !silc_server_channel_has_global(channel))
80 channel->global_users = FALSE;
83 server->stat.my_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. */
87 if (server->server_type != SILC_ROUTER &&
88 !silc_server_channel_has_local(channel)) {
90 if (silc_hash_table_find(channels, channel, NULL, NULL))
91 silc_hash_table_del(channels, channel);
94 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
96 if (channel->founder_key) {
97 /* The founder auth data exists, do not remove the channel entry */
98 SilcChannelClientEntry chl2;
99 SilcHashTableList htl2;
101 channel->disabled = TRUE;
103 silc_hash_table_list(channel->user_list, &htl2);
104 while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
105 silc_hash_table_del(chl2->client->channels, channel);
106 silc_hash_table_del(channel->user_list, chl2->client);
107 channel->user_count--;
110 silc_hash_table_list_reset(&htl2);
114 /* Remove the channel entry */
115 if (silc_idlist_del_channel(server->local_list, channel))
116 server->stat.my_channels--;
118 silc_idlist_del_channel(server->global_list, channel);
122 /* Add the channel to the the channels list to regenerate the
124 if (!silc_hash_table_find(channels, channel, NULL, NULL))
125 silc_hash_table_add(channels, channel, channel);
127 silc_hash_table_list_reset(&htl);
129 silc_buffer_free(clidp);
132 /* This function is used to remove all client entries by the server `entry'.
133 This is called when the connection is lost to the server. In this case
134 we must invalidate all the client entries owned by the server `entry'.
135 If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
136 distributed to our local clients. */
138 bool silc_server_remove_clients_by_server(SilcServer server,
139 SilcServerEntry entry,
142 SilcIDCacheList list = NULL;
143 SilcIDCacheEntry id_cache = NULL;
144 SilcClientEntry client = NULL;
146 SilcClientEntry *clients = NULL;
147 SilcUInt32 clients_c = 0;
148 unsigned char **argv = NULL;
149 SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
150 SilcHashTableList htl;
151 SilcChannelEntry channel;
152 SilcHashTable channels;
155 SILC_LOG_DEBUG(("Start"));
157 /* Allocate the hash table that holds the channels that require
158 channel key re-generation after we've removed this server's clients
159 from the channels. */
160 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
163 if (server_signoff) {
164 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
165 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
166 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
167 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
168 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
169 memcpy(argv[argc], idp->data, idp->len);
170 argv_lens[argc] = idp->len;
171 argv_types[argc] = argc + 1;
173 silc_buffer_free(idp);
176 if (silc_idcache_get_all(server->local_list->clients, &list)) {
178 if (silc_idcache_list_first(list, &id_cache)) {
180 client = (SilcClientEntry)id_cache->context;
181 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
182 if (!silc_idcache_list_next(list, &id_cache))
188 if (client->router != entry) {
189 if (server_signoff) {
190 clients = silc_realloc(clients,
191 sizeof(*clients) * (clients_c + 1));
192 clients[clients_c] = client;
196 if (!silc_idcache_list_next(list, &id_cache))
202 if (server_signoff) {
203 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
204 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
205 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
207 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
209 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
210 memcpy(argv[argc], idp->data, idp->len);
211 argv_lens[argc] = idp->len;
212 argv_types[argc] = argc + 1;
214 silc_buffer_free(idp);
217 /* Update statistics */
218 server->stat.clients--;
219 if (server->server_type == SILC_ROUTER)
220 server->stat.cell_clients--;
221 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
222 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
224 /* Remove the client entry */
225 silc_server_remove_clients_channels(server, NULL, client, channels);
226 if (!server_signoff) {
227 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
228 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
230 silc_idlist_del_client(server->local_list, client);
233 if (!silc_idcache_list_next(list, &id_cache))
237 silc_idcache_list_free(list);
240 if (silc_idcache_get_all(server->global_list->clients, &list)) {
242 if (silc_idcache_list_first(list, &id_cache)) {
244 client = (SilcClientEntry)id_cache->context;
245 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
246 if (!silc_idcache_list_next(list, &id_cache))
252 if (client->router != entry) {
253 if (server_signoff && client->connection) {
254 clients = silc_realloc(clients,
255 sizeof(*clients) * (clients_c + 1));
256 clients[clients_c] = client;
260 if (!silc_idcache_list_next(list, &id_cache))
266 if (server_signoff) {
267 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
268 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
269 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
271 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
273 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
274 memcpy(argv[argc], idp->data, idp->len);
275 argv_lens[argc] = idp->len;
276 argv_types[argc] = argc + 1;
278 silc_buffer_free(idp);
281 /* Update statistics */
282 server->stat.clients--;
283 if (server->server_type == SILC_ROUTER)
284 server->stat.cell_clients--;
285 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
286 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
288 /* Remove the client entry */
289 silc_server_remove_clients_channels(server, NULL, client, channels);
290 if (!server_signoff) {
291 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
292 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
294 silc_idlist_del_client(server->global_list, client);
297 if (!silc_idcache_list_next(list, &id_cache))
301 silc_idcache_list_free(list);
304 /* Send the SERVER_SIGNOFF notify */
305 if (server_signoff) {
306 SilcBuffer args, not;
308 /* Send SERVER_SIGNOFF notify to our primary router */
309 if (!server->standalone && server->router &&
310 server->router != entry) {
311 args = silc_argument_payload_encode(1, argv, argv_lens,
313 silc_server_send_notify_args(server,
314 server->router->connection,
315 server->server_type == SILC_SERVER ?
317 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
319 silc_buffer_free(args);
322 /* Send to local clients. We also send the list of client ID's that
323 is to be removed for those servers that would like to use that list. */
324 args = silc_argument_payload_encode(argc, argv, argv_lens,
326 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
328 silc_server_packet_send_clients(server, clients, clients_c,
329 SILC_PACKET_NOTIFY, 0, FALSE,
330 not->data, not->len, FALSE);
333 silc_buffer_free(args);
334 silc_buffer_free(not);
335 for (i = 0; i < argc; i++)
338 silc_free(argv_lens);
339 silc_free(argv_types);
342 /* We must now re-generate the channel key for all channels that had
343 this server's client(s) on the channel. As they left the channel we
344 must re-generate the channel key. */
345 silc_hash_table_list(channels, &htl);
346 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
347 if (!silc_server_create_channel_key(server, channel, 0)) {
348 silc_hash_table_list_reset(&htl);
349 silc_hash_table_free(channels);
353 /* Do not send the channel key if private channel key mode is set */
354 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
357 silc_server_send_channel_key(server, NULL, channel,
358 server->server_type == SILC_ROUTER ?
359 FALSE : !server->standalone);
361 silc_hash_table_list_reset(&htl);
362 silc_hash_table_free(channels);
367 static SilcServerEntry
368 silc_server_update_clients_by_real_server(SilcServer server,
369 SilcServerEntry from,
370 SilcClientEntry client,
372 SilcIDCacheEntry client_cache)
374 SilcServerEntry server_entry;
375 SilcIDCacheEntry id_cache = NULL;
376 SilcIDCacheList list;
378 if (!silc_idcache_get_all(server->local_list->servers, &list))
381 if (silc_idcache_list_first(list, &id_cache)) {
383 server_entry = (SilcServerEntry)id_cache->context;
384 if (server_entry != from &&
385 SILC_ID_COMPARE(server_entry->id, client->id,
386 client->id->ip.data_len)) {
387 SILC_LOG_DEBUG(("Found (local) %s",
388 silc_id_render(server_entry->id, SILC_ID_SERVER)));
390 if (!server_entry->data.send_key && server_entry->router) {
391 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
392 /* If the client is not marked as local then move it to local list
393 since the server is local. */
395 SILC_LOG_DEBUG(("Moving client to local list"));
396 silc_idcache_add(server->local_list->clients, client_cache->name,
397 client_cache->id, client_cache->context,
398 client_cache->expire, NULL);
399 silc_idcache_del_by_context(server->global_list->clients, client);
401 server_entry = server_entry->router;
403 /* If the client is not marked as local then move it to local list
404 since the server is local. */
405 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
406 SILC_LOG_DEBUG(("Moving client to local list"));
407 silc_idcache_add(server->local_list->clients, client_cache->name,
408 client_cache->id, client_cache->context,
409 client_cache->expire, NULL);
410 silc_idcache_del_by_context(server->global_list->clients, client);
414 silc_idcache_list_free(list);
418 if (!silc_idcache_list_next(list, &id_cache))
423 silc_idcache_list_free(list);
425 if (!silc_idcache_get_all(server->global_list->servers, &list))
428 if (silc_idcache_list_first(list, &id_cache)) {
430 server_entry = (SilcServerEntry)id_cache->context;
431 if (server_entry != from &&
432 SILC_ID_COMPARE(server_entry->id, client->id,
433 client->id->ip.data_len)) {
434 SILC_LOG_DEBUG(("Found (global) %s",
435 silc_id_render(server_entry->id, SILC_ID_SERVER)));
437 if (!server_entry->data.send_key && server_entry->router) {
438 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
439 /* If the client is marked as local then move it to global list
440 since the server is global. */
442 SILC_LOG_DEBUG(("Moving client to global list"));
443 silc_idcache_add(server->global_list->clients, client_cache->name,
444 client_cache->id, client_cache->context,
445 client_cache->expire, NULL);
446 silc_idcache_del_by_context(server->local_list->clients, client);
448 server_entry = server_entry->router;
450 /* If the client is marked as local then move it to global list
451 since the server is global. */
452 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
453 SILC_LOG_DEBUG(("Moving client to global list"));
454 silc_idcache_add(server->global_list->clients, client_cache->name,
455 client_cache->id, client_cache->context,
456 client_cache->expire, NULL);
457 silc_idcache_del_by_context(server->local_list->clients, client);
461 silc_idcache_list_free(list);
465 if (!silc_idcache_list_next(list, &id_cache))
470 silc_idcache_list_free(list);
475 /* Updates the clients that are originated from the `from' to be originated
476 from the `to'. If the `resolve_real_server' is TRUE then this will
477 attempt to figure out which clients really are originated from the
478 `from' and which are originated from a server that we have connection
479 to, when we've acting as backup router. If it is FALSE the `to' will
480 be the new source. This function also removes the clients that are
481 *really* originated from `from' if `remove_from' is TRUE. These are
482 clients that the `from' owns, and not just clients that are behind
485 void silc_server_update_clients_by_server(SilcServer server,
486 SilcServerEntry from,
488 bool resolve_real_server,
491 SilcIDCacheList list = NULL;
492 SilcIDCacheEntry id_cache = NULL;
493 SilcClientEntry client = NULL;
496 SILC_LOG_DEBUG(("Start"));
498 SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
500 SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
505 if (silc_idcache_get_all(server->global_list->clients, &list)) {
506 if (silc_idcache_list_first(list, &id_cache)) {
508 client = (SilcClientEntry)id_cache->context;
509 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
510 if (!silc_idcache_list_next(list, &id_cache))
516 SILC_LOG_DEBUG(("Client (global) %s",
517 silc_id_render(client->id, SILC_ID_CLIENT)));
519 SILC_LOG_DEBUG(("Client->router (global) %s",
520 silc_id_render(client->router->id, SILC_ID_SERVER)));
522 if (client->router == from) {
523 /* Skip clients that are *really* owned by the `from' */
524 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
525 client->id->ip.data_len)) {
526 SILC_LOG_DEBUG(("Found really owned client, skip it"));
527 if (!silc_idcache_list_next(list, &id_cache))
533 if (resolve_real_server) {
535 silc_server_update_clients_by_real_server(server, from, client,
544 if (!silc_idcache_list_next(list, &id_cache))
548 silc_idcache_list_free(list);
552 if (silc_idcache_get_all(server->local_list->clients, &list)) {
553 if (silc_idcache_list_first(list, &id_cache)) {
555 client = (SilcClientEntry)id_cache->context;
556 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
557 if (!silc_idcache_list_next(list, &id_cache))
563 SILC_LOG_DEBUG(("Client (local) %s",
564 silc_id_render(client->id, SILC_ID_CLIENT)));
566 SILC_LOG_DEBUG(("Client->router (local) %s",
567 silc_id_render(client->router->id, SILC_ID_SERVER)));
569 if (client->router == from) {
570 /* Skip clients that are *really* owned by the `from' */
571 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
572 client->id->ip.data_len)) {
573 SILC_LOG_DEBUG(("Found really owned client, skip it"));
574 if (!silc_idcache_list_next(list, &id_cache))
580 if (resolve_real_server) {
582 silc_server_update_clients_by_real_server(server, from, client,
585 client->router = from; /* on local list put old from */
591 if (!silc_idcache_list_next(list, &id_cache))
595 silc_idcache_list_free(list);
599 /* Now remove the clients that are still marked as orignated from the
600 `from'. These are the clients that really was owned by the `from' and
601 not just exist behind the `from'. */
602 silc_server_remove_clients_by_server(server, from, TRUE);
605 /* Updates servers that are from `from' to be originated from `to'. This
606 will also update the server's connection to `to's connection. */
608 void silc_server_update_servers_by_server(SilcServer server,
609 SilcServerEntry from,
612 SilcIDCacheList list = NULL;
613 SilcIDCacheEntry id_cache = NULL;
614 SilcServerEntry server_entry = NULL;
616 SILC_LOG_DEBUG(("Start"));
618 if (silc_idcache_get_all(server->local_list->servers, &list)) {
619 if (silc_idcache_list_first(list, &id_cache)) {
621 server_entry = (SilcServerEntry)id_cache->context;
622 if (server_entry->router == from) {
623 server_entry->router = to;
624 server_entry->connection = to->connection;
626 if (!silc_idcache_list_next(list, &id_cache))
630 silc_idcache_list_free(list);
633 if (silc_idcache_get_all(server->global_list->servers, &list)) {
634 if (silc_idcache_list_first(list, &id_cache)) {
636 server_entry = (SilcServerEntry)id_cache->context;
637 if (server_entry->router == from) {
638 server_entry->router = to;
639 server_entry->connection = to->connection;
641 if (!silc_idcache_list_next(list, &id_cache))
645 silc_idcache_list_free(list);
649 /* Removes channels that are from `from. */
651 void silc_server_remove_channels_by_server(SilcServer server,
652 SilcServerEntry from)
654 SilcIDCacheList list = NULL;
655 SilcIDCacheEntry id_cache = NULL;
656 SilcChannelEntry channel = NULL;
658 SILC_LOG_DEBUG(("Start"));
660 if (silc_idcache_get_all(server->global_list->channels, &list)) {
661 if (silc_idcache_list_first(list, &id_cache)) {
663 channel = (SilcChannelEntry)id_cache->context;
664 if (channel->router == from)
665 silc_idlist_del_channel(server->global_list, channel);
666 if (!silc_idcache_list_next(list, &id_cache))
670 silc_idcache_list_free(list);
674 /* Updates channels that are from `from' to be originated from `to'. */
676 void silc_server_update_channels_by_server(SilcServer server,
677 SilcServerEntry from,
680 SilcIDCacheList list = NULL;
681 SilcIDCacheEntry id_cache = NULL;
682 SilcChannelEntry channel = NULL;
684 SILC_LOG_DEBUG(("Start"));
686 if (silc_idcache_get_all(server->global_list->channels, &list)) {
687 if (silc_idcache_list_first(list, &id_cache)) {
689 channel = (SilcChannelEntry)id_cache->context;
690 if (channel->router == from)
691 channel->router = to;
692 if (!silc_idcache_list_next(list, &id_cache))
696 silc_idcache_list_free(list);
700 /* Checks whether given channel has global users. If it does this returns
701 TRUE and FALSE if there is only locally connected clients on the channel. */
703 bool silc_server_channel_has_global(SilcChannelEntry channel)
705 SilcChannelClientEntry chl;
706 SilcHashTableList htl;
708 silc_hash_table_list(channel->user_list, &htl);
709 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
710 if (chl->client->router) {
711 silc_hash_table_list_reset(&htl);
715 silc_hash_table_list_reset(&htl);
720 /* Checks whether given channel has locally connected users. If it does this
721 returns TRUE and FALSE if there is not one locally connected client. */
723 bool silc_server_channel_has_local(SilcChannelEntry channel)
725 SilcChannelClientEntry chl;
726 SilcHashTableList htl;
728 silc_hash_table_list(channel->user_list, &htl);
729 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
730 if (!chl->client->router) {
731 silc_hash_table_list_reset(&htl);
735 silc_hash_table_list_reset(&htl);
740 /* Returns TRUE if the given client is on the channel. FALSE if not.
741 This works because we assure that the user list on the channel is
742 always in up to date thus we can only check the channel list from
743 `client' which is faster than checking the user list from `channel'. */
745 bool silc_server_client_on_channel(SilcClientEntry client,
746 SilcChannelEntry channel)
748 if (!client || !channel)
751 return silc_hash_table_find(client->channels, channel, NULL, NULL);
754 /* Checks string for bad characters and returns TRUE if they are found. */
756 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
760 for (i = 0; i < name_len; i++) {
761 if (!isascii(name[i]))
763 if (name[i] <= 32) return TRUE;
764 if (name[i] == ' ') return TRUE;
765 if (name[i] == '*') return TRUE;
766 if (name[i] == '?') return TRUE;
767 if (name[i] == ',') return TRUE;
773 /* Modifies the `name' if it includes bad characters and returns new
774 allocated name that does not include bad characters. */
776 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
779 char *newname = strdup(name);
781 for (i = 0; i < name_len; i++) {
782 if (!isascii(newname[i])) newname[i] = '_';
783 if (newname[i] <= 32) newname[i] = '_';
784 if (newname[i] == ' ') newname[i] = '_';
785 if (newname[i] == '*') newname[i] = '_';
786 if (newname[i] == '?') newname[i] = '_';
787 if (newname[i] == ',') newname[i] = '_';
793 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
794 socket connections with the IP address does not exist. */
796 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
801 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
802 if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
803 server->sockets[i]->type == type)
810 /* Finds locally cached public key by the public key received in the SKE.
811 If we have it locally cached then we trust it and will use it in the
812 authentication protocol. Returns the locally cached public key or NULL
813 if we do not find the public key. */
815 SilcPublicKey silc_server_find_public_key(SilcServer server,
816 SilcHashTable local_public_keys,
817 SilcPublicKey remote_public_key)
819 SilcPublicKey cached_key;
821 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
822 silc_hash_table_count(local_public_keys)));
824 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
825 (void **)&cached_key, NULL,
826 silc_hash_public_key, NULL,
827 silc_hash_public_key_compare, NULL)) {
828 SILC_LOG_ERROR(("Public key not found"));
832 SILC_LOG_DEBUG(("Found public key"));
837 /* This returns the first public key from the table of public keys. This
838 is used only in cases where single public key exists in the table and
839 we want to get a pointer to it. For public key tables that has multiple
840 keys in it the silc_server_find_public_key must be used. */
842 SilcPublicKey silc_server_get_public_key(SilcServer server,
843 SilcHashTable local_public_keys)
845 SilcPublicKey cached_key;
846 SilcHashTableList htl;
848 SILC_LOG_DEBUG(("Start"));
850 assert(silc_hash_table_count(local_public_keys) < 2);
852 silc_hash_table_list(local_public_keys, &htl);
853 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
855 silc_hash_table_list_reset(&htl);
860 /* Check whether the connection `sock' is allowed to connect to us. This
861 checks for example whether there is too much connections for this host,
862 and required version for the host etc. */
864 bool silc_server_connection_allowed(SilcServer server,
865 SilcSocketConnection sock,
867 SilcServerConfigConnParams *global,
868 SilcServerConfigConnParams *params,
871 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
872 server->stat.my_clients :
873 type == SILC_SOCKET_TYPE_SERVER ?
874 server->stat.my_servers :
875 server->stat.my_routers);
876 SilcUInt32 num_sockets, max_hosts, max_per_host;
877 SilcUInt32 r_protocol_version, l_protocol_version;
878 SilcUInt32 r_software_version, l_software_version;
879 char *r_vendor_version = NULL, *l_vendor_version;
884 silc_version_to_num(params && params->version_protocol ?
885 params->version_protocol :
886 global->version_protocol);
888 silc_version_to_num(params && params->version_software ?
889 params->version_software :
890 global->version_software);
891 l_vendor_version = (params && params->version_software_vendor ?
892 params->version_software_vendor :
893 global->version_software_vendor);
895 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
896 &r_software_version, NULL,
897 &r_vendor_version)) {
898 /* Match protocol version */
899 if (l_protocol_version && r_protocol_version &&
900 r_protocol_version < l_protocol_version) {
901 SILC_LOG_INFO(("Connection %s (%s) is too old version",
902 sock->hostname, sock->ip));
903 silc_server_disconnect_remote(server, sock,
904 "Server closed connection: "
905 "You support too old protocol version");
909 /* Math software version */
910 if (l_software_version && r_software_version &&
911 r_software_version < l_software_version) {
912 SILC_LOG_INFO(("Connection %s (%s) is too old version",
913 sock->hostname, sock->ip));
914 silc_server_disconnect_remote(server, sock,
915 "Server closed connection: "
916 "You support too old software version");
920 /* Regex match vendor version */
921 if (l_vendor_version && r_vendor_version &&
922 !silc_string_match(l_vendor_version, r_vendor_version)) {
923 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
924 sock->hostname, sock->ip));
925 silc_server_disconnect_remote(server, sock,
926 "Server closed connection: "
927 "Your software is not supported");
931 silc_free(r_vendor_version);
933 /* Check for maximum connections limit */
935 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
936 max_hosts = (params ? params->connections_max : global->connections_max);
937 max_per_host = (params ? params->connections_max_per_host :
938 global->connections_max_per_host);
940 if (max_hosts && conn_number >= max_hosts) {
941 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
942 sock->hostname, sock->ip));
943 silc_server_disconnect_remote(server, sock,
944 "Server closed connection: "
945 "Server is full, try again later");
949 if (num_sockets >= max_per_host) {
950 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
951 sock->hostname, sock->ip));
952 silc_server_disconnect_remote(server, sock,
953 "Server closed connection: "
954 "Too many connections from your host");