/* Remove the client from all channels. The client is removed from
the channels' user list. */
silc_hash_table_list(client->channels, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+ while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
channel = chl->channel;
/* Remove channel from client's channel list */
channel->disabled = TRUE;
silc_hash_table_list(channel->user_list, &htl2);
- while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
+ while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
silc_hash_table_del(chl2->client->channels, channel);
silc_hash_table_del(channel->user_list, chl2->client);
channel->user_count--;
this server's client(s) on the channel. As they left the channel we
must re-generate the channel key. */
silc_hash_table_list(channels, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&channel)) {
+ while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
if (!silc_server_create_channel_key(server, channel, 0)) {
silc_hash_table_list_reset(&htl);
silc_hash_table_free(channels);
SilcHashTableList htl;
silc_hash_table_list(channel->user_list, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+ while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
if (chl->client->router) {
silc_hash_table_list_reset(&htl);
return TRUE;
SilcHashTableList htl;
silc_hash_table_list(channel->user_list, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+ while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
if (!chl->client->router) {
silc_hash_table_list_reset(&htl);
return TRUE;
return count;
}
+
+/* Finds locally cached public key by the public key received in the SKE.
+ If we have it locally cached then we trust it and will use it in the
+ authentication protocol. Returns the locally cached public key or NULL
+ if we do not find the public key. */
+
+SilcPublicKey silc_server_find_public_key(SilcServer server,
+ SilcHashTable local_public_keys,
+ SilcPublicKey remote_public_key)
+{
+ SilcPublicKey cached_key;
+
+ SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
+ silc_hash_table_count(local_public_keys)));
+
+ if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
+ (void **)&cached_key, NULL,
+ silc_hash_public_key, NULL,
+ silc_hash_public_key_compare, NULL)) {
+ SILC_LOG_ERROR(("Public key not found"));
+ return NULL;
+ }
+
+ SILC_LOG_DEBUG(("Found public key"));
+
+ return cached_key;
+}
+
+/* This returns the first public key from the table of public keys. This
+ is used only in cases where single public key exists in the table and
+ we want to get a pointer to it. For public key tables that has multiple
+ keys in it the silc_server_find_public_key must be used. */
+
+SilcPublicKey silc_server_get_public_key(SilcServer server,
+ SilcHashTable local_public_keys)
+{
+ SilcPublicKey cached_key;
+ SilcHashTableList htl;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ assert(silc_hash_table_count(local_public_keys) < 2);
+
+ silc_hash_table_list(local_public_keys, &htl);
+ if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
+ return NULL;
+ silc_hash_table_list_reset(&htl);
+
+ 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;
+}