X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fserver_util.c;h=529b75de5fdcca6999210533542f7fa7350b9944;hb=a4bca275d651ca750224149945bc8fca5c80de77;hp=dc76c48161f642ac13932a06fc0148f71bbe463e;hpb=f50fab3886a56151079728daa678fed3b882b433;p=silc.git diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index dc76c481..529b75de 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -856,3 +856,104 @@ SilcPublicKey silc_server_get_public_key(SilcServer server, return cached_key; } + +/* Check whether the connection `sock' is allowed to connect to us. This + checks for example whether there is too much connections for this host, + and required version for the host etc. */ + +bool silc_server_connection_allowed(SilcServer server, + SilcSocketConnection sock, + SilcSocketType type, + SilcServerConfigConnParams *global, + SilcServerConfigConnParams *params, + SilcSKE ske) +{ + SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ? + server->stat.my_clients : + type == SILC_SOCKET_TYPE_SERVER ? + server->stat.my_servers : + server->stat.my_routers); + SilcUInt32 num_sockets, max_hosts, max_per_host; + SilcUInt32 r_protocol_version, l_protocol_version; + SilcUInt32 r_software_version, l_software_version; + char *r_vendor_version = NULL, *l_vendor_version; + + /* Check version */ + + l_protocol_version = + silc_version_to_num(params && params->version_protocol ? + params->version_protocol : + global->version_protocol); + l_software_version = + silc_version_to_num(params && params->version_software ? + params->version_software : + global->version_software); + l_vendor_version = (params && params->version_software_vendor ? + params->version_software_vendor : + global->version_software_vendor); + + if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL, + &r_software_version, NULL, + &r_vendor_version)) { + /* Match protocol version */ + if (l_protocol_version && r_protocol_version && + r_protocol_version < l_protocol_version) { + SILC_LOG_INFO(("Connection %s (%s) is too old version", + sock->hostname, sock->ip)); + silc_server_disconnect_remote(server, sock, + "Server closed connection: " + "You support too old protocol version"); + return FALSE; + } + + /* Math software version */ + if (l_software_version && r_software_version && + r_software_version < l_software_version) { + SILC_LOG_INFO(("Connection %s (%s) is too old version", + sock->hostname, sock->ip)); + silc_server_disconnect_remote(server, sock, + "Server closed connection: " + "You support too old software version"); + return FALSE; + } + + /* Regex match vendor version */ + if (l_vendor_version && r_vendor_version && + !silc_string_match(l_vendor_version, r_vendor_version)) { + SILC_LOG_INFO(("Connection %s (%s) is unsupported version", + sock->hostname, sock->ip)); + silc_server_disconnect_remote(server, sock, + "Server closed connection: " + "Your software is not supported"); + return FALSE; + } + } + silc_free(r_vendor_version); + + /* Check for maximum connections limit */ + + num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type); + max_hosts = (params ? params->connections_max : global->connections_max); + max_per_host = (params ? params->connections_max_per_host : + global->connections_max_per_host); + + if (max_hosts && conn_number >= max_hosts) { + SILC_LOG_INFO(("Server is full, closing %s (%s) connection", + sock->hostname, sock->ip)); + silc_server_disconnect_remote(server, sock, + "Server closed connection: " + "Server is full, try again later"); + return FALSE; + } + + if (num_sockets >= max_per_host) { + SILC_LOG_INFO(("Too many connections from %s (%s), closing connection", + sock->hostname, sock->ip)); + silc_server_disconnect_remote(server, sock, + "Server closed connection: " + "Too many connections from your host"); + return FALSE; + } + + return TRUE; +}