]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-11025 [core] allow/check ports in network lists
authorLuis Azedo <luis@2600hz.com>
Tue, 13 Mar 2018 19:41:45 +0000 (19:41 +0000)
committerlazedo <luis.azedo@factorlusitano.com>
Wed, 6 Mar 2019 11:56:03 +0000 (11:56 +0000)
src/include/switch_core.h
src/include/switch_utils.h
src/switch_core.c
src/switch_utils.c

index 526fe2632351aa7304bc93b77ae3b0f1eee6752e..7631fc287fe6006354b54bc5a6e07efabfacc3d8 100644 (file)
@@ -2427,6 +2427,7 @@ SWITCH_DECLARE(const char *) switch_lookup_timezone(const char *tz_name);
 SWITCH_DECLARE(switch_status_t) switch_strftime_tz(const char *tz, const char *format, char *date, size_t len, switch_time_t thetime);
 SWITCH_DECLARE(switch_status_t) switch_time_exp_tz_name(const char *tz, switch_time_exp_t *tm, switch_time_t thetime);
 SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload);
+SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_port_token(const char *ip_str, int port, const char *list_name, const char **token);
 SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token);
 #define switch_check_network_list_ip(_ip_str, _list_name) switch_check_network_list_ip_token(_ip_str, _list_name, NULL)
 SWITCH_DECLARE(void) switch_time_set_monotonic(switch_bool_t enable);
index 10242525f18d36ac1beea6fd79f014e6cc868743..62ec7c8d4134f297133ed6e8cc22ce28a3f12b82 100644 (file)
@@ -46,6 +46,16 @@ SWITCH_BEGIN_EXTERN_C
 
 #define SWITCH_URL_UNSAFE "\r\n #%&+:;<=>?@[\\]^`{|}\""
 
+#define MAX_NETWORK_PORTS 10
+
+struct switch_network_port_range {
+       int port;
+       int ports[MAX_NETWORK_PORTS];
+       int min_port;
+       int max_port;
+};
+typedef struct switch_network_port_range switch_network_port_range_t;
+typedef switch_network_port_range_t* switch_network_port_range_p;
 
 static inline char *switch_get_hex_bytes(switch_byte_t *buf, switch_size_t datalen, char *new_buf, switch_size_t new_datalen)
 {
@@ -1270,6 +1280,12 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_token(switch_networ
 
 SWITCH_DECLARE(char *) switch_network_ipv4_mapped_ipv6_addr(const char* ip_str);
 SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok);
+
+SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_port_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token, switch_network_port_range_p port);
+SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_port_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok, switch_network_port_range_p port);
+
+SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_port_token(switch_network_list_t *list, uint32_t ip, int port, const char **token);
+SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_port_token(switch_network_list_t *list, ip_t ip, int port, const char **token);
 SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_network_list_t *list, uint32_t ip, const char **token);
 SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_token(switch_network_list_t *list, ip_t ip, const char **token);
 #define switch_network_list_validate_ip(_list, _ip) switch_network_list_validate_ip_token(_list, _ip, NULL);
index 596ef2bbe4fef5cfab9280fb0c1c95119248c02b..0fb040fbbd5c4ce0fb12618e82a27d09c1ac8541 100644 (file)
@@ -1370,7 +1370,7 @@ typedef struct {
 
 static switch_ip_list_t IP_LIST = { 0 };
 
-SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token)
+SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_port_token(const char *ip_str, int port, const char *list_name, const char **token)
 {
        switch_network_list_t *list;
        ip_t  ip, mask, net;
@@ -1398,9 +1398,9 @@ SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_
 
        if ((list = switch_core_hash_find(IP_LIST.hash, list_name))) {
                if (ipv6) {
-                       ok = switch_network_list_validate_ip6_token(list, ip, token);
+                       ok = switch_network_list_validate_ip6_port_token(list, ip, port, token);
                } else {
-                       ok = switch_network_list_validate_ip_token(list, ip.v4, token);
+                       ok = switch_network_list_validate_ip_port_token(list, ip.v4, port, token);
                }
        } else if (strchr(list_name, '/')) {
                if (strchr(list_name, ',')) {
@@ -1443,6 +1443,10 @@ SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_
        return ok;
 }
 
+SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token)
+{
+       return switch_check_network_list_ip_port_token(ip_str, 0, list_name, token);
+}
 
 SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
 {
@@ -1589,9 +1593,12 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
 
 
                                for (x_node = switch_xml_child(x_list, "node"); x_node; x_node = x_node->next) {
-                                       const char *cidr = NULL, *host = NULL, *mask = NULL, *domain = NULL;
+                                       const char *cidr = NULL, *host = NULL, *mask = NULL, *domain = NULL, *port = NULL;
                                        switch_bool_t ok = default_type;
                                        const char *type = switch_xml_attr(x_node, "type");
+                                       switch_network_port_range_t port_range;
+                                       char *argv[MAX_NETWORK_PORTS] = { 0 };
+                                       int argc = 0, i;
 
                                        if (type) {
                                                ok = switch_true(type);
@@ -1602,6 +1609,25 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
                                        mask = switch_xml_attr(x_node, "mask");
                                        domain = switch_xml_attr(x_node, "domain");
 
+                                       memset(&port_range, 0, sizeof(switch_network_port_range_t));
+
+                                       if( (port = switch_xml_attr(x_node, "port")) != NULL) {
+                                               port_range.port = atoi(port);
+                                       }
+
+                                       if( (port = switch_xml_attr(x_node, "ports")) != NULL) {
+                                               argc = switch_separate_string((char*)port, ',', argv, (sizeof(argv) / sizeof(argv[0])));
+                                               for(i=0; i < argc; i++) {
+                                                       port_range.ports[i] = atoi(argv[i]);
+                                               }
+                                       }
+                                       if( (port = switch_xml_attr(x_node, "port-min")) != NULL) {
+                                               port_range.min_port = atoi(port);
+                                       }
+                                       if( (port = switch_xml_attr(x_node, "port-max")) != NULL) {
+                                               port_range.max_port = atoi(port);
+                                       }
+
                                        if (domain) {
                                                switch_event_t *my_params = NULL;
                                                switch_xml_t x_domain, xml_root;
@@ -1646,7 +1672,7 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
                                                                                if (id && user_cidr) {
                                                                                        char *token = switch_mprintf("%s@%s", id, domain);
                                                                                        switch_assert(token);
-                                                                                       switch_network_list_add_cidr_token(list, user_cidr, ok, token);
+                                                                                       switch_network_list_add_cidr_port_token(list, user_cidr, ok, token, &port_range);
                                                                                        free(token);
                                                                                }
                                                                        }
@@ -1656,13 +1682,13 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
 
                                                switch_xml_free(xml_root);
                                        } else if (cidr) {
-                                               switch_network_list_add_cidr(list, cidr, ok);
+                                               switch_network_list_add_cidr_port_token(list, cidr, ok, NULL, &port_range);
                                        } else if (host && mask) {
-                                               switch_network_list_add_host_mask(list, host, mask, ok);
+                                               switch_network_list_add_host_port_mask(list, host, mask, ok, &port_range);
                                        }
-
-                                       switch_core_hash_insert(IP_LIST.hash, name, list);
                                }
+
+                               switch_core_hash_insert(IP_LIST.hash, name, list);
                        }
                }
 
index 52ec8f6327029f285fe61995d0243d10b9da5c7d..2ac0a0e4152611cc7c6e13d65200aeeffdee14b2 100644 (file)
@@ -54,6 +54,7 @@ struct switch_network_node {
        switch_bool_t ok;
        char *token;
        char *str;
+       switch_network_port_range_t port_range;
        struct switch_network_node *next;
 };
 typedef struct switch_network_node switch_network_node_t;
@@ -467,7 +468,8 @@ SWITCH_DECLARE(switch_bool_t) switch_testv6_subnet(ip_t _ip, ip_t _net, ip_t _ma
                        else return SWITCH_TRUE;
                }
 }
-SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_token(switch_network_list_t *list, ip_t ip, const char **token)
+
+SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_port_token(switch_network_list_t *list, ip_t ip, int port, const char **token)
 {
        switch_network_node_t *node;
        switch_bool_t ok = list->default_type;
@@ -494,7 +496,29 @@ SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_token(switch_netw
        return ok;
 }
 
-SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_network_list_t *list, uint32_t ip, const char **token)
+SWITCH_DECLARE(switch_bool_t) is_port_in_node(int port, switch_network_node_t *node)
+{
+       if(port == 0)
+               return SWITCH_TRUE;
+       if(node->port_range.port != 0 && node->port_range.port != port)
+               return SWITCH_FALSE;
+       if(node->port_range.ports[0] != 0) {
+               int i;
+               for(i=0; i < MAX_NETWORK_PORTS && node->port_range.ports[i] != 0; i++) {
+                       if(port == node->port_range.ports[i])
+                               return SWITCH_TRUE;
+               }
+               return SWITCH_FALSE;
+       }
+       if(node->port_range.min_port != 0 || node->port_range.max_port != 0) {
+               if(port >= node->port_range.min_port && port <= node->port_range.max_port)
+                       return SWITCH_TRUE;
+               return SWITCH_FALSE;
+       }
+       return SWITCH_TRUE;
+}
+
+SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_port_token(switch_network_list_t *list, uint32_t ip, int port, const char **token)
 {
        switch_network_node_t *node;
        switch_bool_t ok = list->default_type;
@@ -502,7 +526,7 @@ SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_netwo
 
        for (node = list->node_head; node; node = node->next) {
                if (node->family == AF_INET6) continue; /* want AF_INET */
-               if (node->bits >= bits && switch_test_subnet(ip, node->ip.v4, node->mask.v4)) {
+               if (node->bits >= bits && switch_test_subnet(ip, node->ip.v4, node->mask.v4) && is_port_in_node(port, node)) {
                        if (node->ok) {
                                ok = SWITCH_TRUE;
                        } else {
@@ -520,6 +544,16 @@ SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_netwo
        return ok;
 }
 
+SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_token(switch_network_list_t *list, ip_t ip, const char **token)
+{
+       return switch_network_list_validate_ip6_port_token(list, ip, 0, token);
+}
+
+SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_network_list_t *list, uint32_t ip, const char **token)
+{
+       return switch_network_list_validate_ip_port_token(list, ip, 0, token);
+}
+
 SWITCH_DECLARE(char *) switch_network_ipv4_mapped_ipv6_addr(const char* ip_str)
 {
        /* ipv4 mapped ipv6 address */
@@ -531,22 +565,52 @@ SWITCH_DECLARE(char *) switch_network_ipv4_mapped_ipv6_addr(const char* ip_str)
        return strdup(ip_str + 7);
 }
 
+SWITCH_DECLARE(char*) switch_network_port_range_to_string(switch_network_port_range_p port)
+{
+       if (!port) {
+               return NULL;
+       }
+
+       if (port->port != 0) {
+               return switch_mprintf("port: %i ", port->port);
+       }
+
+       if (port->ports[0] != 0) {
+               int i, written = 0;
+               char buf[MAX_NETWORK_PORTS * 6];
+           for (i = 0; i < MAX_NETWORK_PORTS && port->ports[i] != 0; i++) {
+               written += snprintf(buf + written, sizeof(buf) - written, (i != 0 ? ", %u" : "%u"), port->ports[i]);
+           }
+               return switch_mprintf("ports: [%s] ", buf);
+       }
+
+       if (port->min_port != 0 || port->max_port != 0) {
+               return switch_mprintf("port range: [%i-%i] ", port->min_port, port->max_port);
+       }
+
+       return NULL;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_network_list_perform_add_cidr_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok,
-                                                                                                                                                  const char *token)
+                                                                                                                                                  const char *token, switch_network_port_range_p port)
 {
        ip_t ip, mask;
        uint32_t bits;
        switch_network_node_t *node;
        char *ipv4 = NULL;
+       char *ports = NULL;
 
        if ((ipv4 = switch_network_ipv4_mapped_ipv6_addr(cidr_str))) {
                cidr_str = ipv4;
        }
 
+       ports = switch_network_port_range_to_string(port);
+
        if (switch_parse_cidr(cidr_str, &ip, &mask, &bits)) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Adding %s (%s) [%s] to list %s\n",
-                                                 cidr_str, ok ? "allow" : "deny", switch_str_nil(token), list->name);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Adding %s %s(%s) [%s] to list %s\n",
+                                                 cidr_str, ports ? ports : "", ok ? "allow" : "deny", switch_str_nil(token), list->name);
                switch_safe_free(ipv4);
+               switch_safe_free(ports);
                return SWITCH_STATUS_GENERR;
        }
 
@@ -557,6 +621,10 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_perform_add_cidr_token(switc
        node->ok = ok;
        node->bits = bits;
        node->str = switch_core_strdup(list->pool, cidr_str);
+       if(port) {
+               memcpy(&node->port_range, port, sizeof(switch_network_port_range_t));
+       }
+
 
        if (strchr(cidr_str,':')) {
                node->family = AF_INET6;
@@ -571,14 +639,15 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_perform_add_cidr_token(switc
        node->next = list->node_head;
        list->node_head = node;
 
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s (%s) [%s] to list %s\n",
-                                         cidr_str, ok ? "allow" : "deny", switch_str_nil(token), list->name);
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s %s(%s) [%s] to list %s\n",
+                                         cidr_str, ports ? ports : "", ok ? "allow" : "deny", switch_str_nil(token), list->name);
 
        switch_safe_free(ipv4);
+       switch_safe_free(ports);
        return SWITCH_STATUS_SUCCESS;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token)
+SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_port_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token, switch_network_port_range_p port)
 {
        char *cidr_str_dup = NULL;
        switch_status_t status = SWITCH_STATUS_SUCCESS;
@@ -592,20 +661,25 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_token(switch_networ
                if ((argc = switch_separate_string(cidr_str_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
                        for (i = 0; i < argc; i++) {
                                switch_status_t this_status;
-                               if ((this_status = switch_network_list_perform_add_cidr_token(list, argv[i], ok, token)) != SWITCH_STATUS_SUCCESS) {
+                               if ((this_status = switch_network_list_perform_add_cidr_token(list, argv[i], ok, token, port)) != SWITCH_STATUS_SUCCESS) {
                                        status = this_status;
                                }
                        }
                }
        } else {
-               status = switch_network_list_perform_add_cidr_token(list, cidr_str, ok, token);
+               status = switch_network_list_perform_add_cidr_token(list, cidr_str, ok, token, port);
        }
 
        switch_safe_free(cidr_str_dup);
        return status;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok)
+SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token)
+{
+       return switch_network_list_add_cidr_port_token(list, cidr_str, ok, token, NULL);
+}
+
+SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_port_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok, switch_network_port_range_p port)
 {
        ip_t ip, mask;
        switch_network_node_t *node;
@@ -618,6 +692,9 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_mask(switch_network
        node->ip.v4 = ntohl(ip.v4);
        node->mask.v4 = ntohl(mask.v4);
        node->ok = ok;
+       if(port) {
+               memcpy(&node->port_range, port, sizeof(switch_network_port_range_t));
+       }
 
        /* http://graphics.stanford.edu/~seander/bithacks.html */
        mask.v4 = mask.v4 - ((mask.v4 >> 1) & 0x55555555);
@@ -632,6 +709,11 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_mask(switch_network
        return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok)
+{
+       return switch_network_list_add_host_port_mask(list, host, mask_str, ok, NULL);
+}
+
 
 SWITCH_DECLARE(int) switch_parse_cidr(const char *string, ip_t *ip, ip_t *mask, uint32_t *bitp)
 {