`client' which is faster than checking the user list from `channel'. */
bool silc_server_client_on_channel(SilcClientEntry client,
- SilcChannelEntry channel)
+ SilcChannelEntry channel,
+ SilcChannelClientEntry *chl)
{
if (!client || !channel)
return FALSE;
- return silc_hash_table_find(client->channels, channel, NULL, NULL);
+ return silc_hash_table_find(client->channels, channel, NULL,
+ (void **)chl);
}
/* Checks string for bad characters and returns TRUE if they are found. */
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;
+}
+
+/* Checks that client has rights to add or remove channel modes. If any
+ of the checks fails FALSE is returned. */
+
+bool silc_server_check_cmode_rights(SilcServer server,
+ SilcChannelEntry channel,
+ SilcChannelClientEntry client,
+ SilcUInt32 mode)
+{
+ bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
+ bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
+
+ /* Check whether has rights to change anything */
+ if (!is_op && !is_fo)
+ return FALSE;
+
+ /* Check whether has rights to change everything */
+ if (is_op && is_fo)
+ return TRUE;
+
+ /* We know that client is channel operator, check that they are not
+ changing anything that requires channel founder rights. Rest of the
+ modes are available automatically for channel operator. */
+
+ if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
+ if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
+ if (is_op && !is_fo)
+ return FALSE;
+ } else {
+ if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
+ if (is_op && !is_fo)
+ return FALSE;
+ }
+ }
+
+ if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
+ if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
+ if (is_op && !is_fo)
+ return FALSE;
+ } else {
+ if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
+ if (is_op && !is_fo)
+ return FALSE;
+ }
+ }
+
+ if (mode & SILC_CHANNEL_MODE_CIPHER) {
+ if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
+ if (is_op && !is_fo)
+ return FALSE;
+ } else {
+ if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
+ if (is_op && !is_fo)
+ return FALSE;
+ }
+ }
+
+ if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
+ if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
+ if (is_op && !is_fo)
+ return FALSE;
+ } else {
+ if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
+ if (is_op && !is_fo)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* Check that the client has rights to change its user mode. Returns
+ FALSE if setting some mode is not allowed. */
+
+bool silc_server_check_umode_rights(SilcServer server,
+ SilcClientEntry client,
+ SilcUInt32 mode)
+{
+ bool server_op = FALSE, router_op = FALSE;
+
+ if (mode & SILC_UMODE_SERVER_OPERATOR) {
+ /* Cannot set server operator mode (must use OPER command) */
+ if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
+ return FALSE;
+ } else {
+ /* Remove the server operator rights */
+ if (client->mode & SILC_UMODE_SERVER_OPERATOR)
+ server_op = TRUE;
+ }
+
+ if (mode & SILC_UMODE_ROUTER_OPERATOR) {
+ /* Cannot set router operator mode (must use SILCOPER command) */
+ if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
+ return FALSE;
+ } else {
+ /* Remove the router operator rights */
+ if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
+ router_op = TRUE;
+ }
+
+ if (server_op)
+ SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
+ if (router_op)
+ SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
+
+ return TRUE;
+}