From 4722de507b3490497866b68199bb3a5c1b53edc5 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 16 Jul 2008 17:44:54 +0000 Subject: [PATCH] add domain-based acl auth thingy git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9056 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_core.h | 3 +- src/include/switch_ivr.h | 2 +- src/include/switch_utils.h | 11 ++- .../applications/mod_dptools/mod_dptools.c | 49 +------------ src/mod/endpoints/mod_sofia/sofia.c | 26 +++++-- src/switch_core.c | 70 ++++++++++++------- src/switch_ivr.c | 58 +++++++++++++++ src/switch_utils.c | 18 +++-- 8 files changed, 150 insertions(+), 87 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 89e4741c62..8bfdfcf038 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1642,7 +1642,8 @@ SWITCH_DECLARE(void) switch_core_setrlimits(void); SWITCH_DECLARE(void) switch_time_sync(void); SWITCH_DECLARE(time_t) switch_timestamp(time_t *t); SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload); -SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip(const char *ip_str, const char *list_name); +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); SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration); SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration); diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 52e60dd7ad..56a0a0f48b 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -783,7 +783,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_digit_stream_parser_set_terminator(sw SWITCH_DECLARE(switch_say_method_t) switch_ivr_get_say_method_by_name(const char *name); SWITCH_DECLARE(switch_say_type_t) switch_ivr_get_say_type_by_name(const char *name); - + SWITCH_DECLARE(switch_status_t) switch_ivr_set_user(switch_core_session_t *session, const char *data); /** @} */ SWITCH_END_EXTERN_C diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 0acc2ad2b0..1572548149 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -413,12 +413,17 @@ SWITCH_DECLARE(char *) switch_find_end_paren(const char *s, char open, char clos SWITCH_DECLARE(int) switch_parse_cidr(const char *string, uint32_t *ip, uint32_t *mask, uint32_t *bitp); SWITCH_DECLARE(switch_status_t) switch_network_list_create(switch_network_list_t **list, switch_bool_t default_type, switch_memory_pool_t *pool); -SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr(switch_network_list_t *list, const char *cidr_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); +#define switch_network_list_add_cidr(_list, _cidr_str, _ok) switch_network_list_add_cidr_token(_list, _cidr_str, _ok, NULL) + + 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_bool_t) switch_network_list_validate_ip(switch_network_list_t *list, uint32_t ip); +SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_network_list_t *list, uint32_t ip, const char **token); +#define switch_network_list_validate_ip(_list, _ip) switch_network_list_validate_ip_token(_list, _ip, NULL); + #define switch_test_subnet(_ip, _net, _mask) (_mask ? ((_net & _mask) == (_ip & _mask)) : _net ? _net == _ip : 1) - int switch_inet_pton(int af, const char *src, void *dst); +int switch_inet_pton(int af, const char *src, void *dst); /* malloc or DIE macros */ #ifdef NDEBUG diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 77dda42332..98d8296d2a 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -365,54 +365,7 @@ SWITCH_STANDARD_APP(three_way_function) #define SET_USER_SYNTAX "@" SWITCH_STANDARD_APP(set_user_function) { - switch_xml_t x_domain, xml = NULL, x_user, x_param, x_params; - char *user, *mailbox, *domain; - switch_channel_t *channel = switch_core_session_get_channel(session); - - if (switch_strlen_zero(data)) { - goto error; - } - - user = switch_core_session_strdup(session, data); - - if (!(domain = strchr(user, '@'))) { - goto error; - } - - *domain++ = '\0'; - - if (switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, NULL) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain); - goto done; - } - - if ((mailbox = (char *) switch_xml_attr(x_user, "mailbox"))) { - switch_channel_set_variable(channel, "mailbox", mailbox); - } - - if ((x_params = switch_xml_child(x_user, "variables"))) { - for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { - const char *var = switch_xml_attr(x_param, "name"); - const char *val = switch_xml_attr(x_param, "value"); - - if (var && val) { - switch_channel_set_variable(channel, var, val); - } - } - } - - switch_channel_set_variable(channel, "user_name", user); - switch_channel_set_variable(channel, "domain_name", domain); - - goto done; - - error: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No user@domain specified.\n"); - - done: - if (xml) { - switch_xml_free(xml); - } + switch_ivr_set_user(session, data); } SWITCH_STANDARD_APP(ring_ready_function) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 9f22dcd08a..801474707d 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2965,6 +2965,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua)); int network_port = 0; char *is_nat = NULL; + char *acl_token = NULL; if (sess_count >= sess_max || !(profile->pflags & PFLAG_RUNNING)) { nua_respond(nh, 503, "Maximum Calls In Progress", SIPTAG_RETRY_AFTER_STR("300"), TAG_END()); @@ -3018,23 +3019,27 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ } } } - + if (profile->acl_count) { uint32_t x = 0; int ok = 1; char *last_acl = NULL; + const char *token; for (x = 0; x < profile->acl_count; x++) { last_acl = profile->acl[x]; - if (!(ok = switch_check_network_list_ip(network_ip, last_acl))) { + if (!(ok = switch_check_network_list_ip_token(network_ip, last_acl, &token))) { break; } } if (ok) { + if (token) { + acl_token = strdup(token); + } if ((profile->pflags & PFLAG_AUTH_CALLS)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s Approved by acl %s. Access Granted.\n", - network_ip, switch_str_nil(last_acl)); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s Approved by acl %s[%s]. Access Granted.\n", + network_ip, switch_str_nil(last_acl), switch_str_nil(acl_token)); is_auth = 1; } } else { @@ -3090,6 +3095,19 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ channel = tech_pvt->channel = switch_core_session_get_channel(session); + if (acl_token) { + switch_channel_set_variable(channel, "acl_token", acl_token); + if (strchr(acl_token, '@')) { + if (switch_ivr_set_user(session, acl_token) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Authenticating user %s\n", acl_token); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error Authenticating user %s\n", acl_token); + } + } + free(acl_token); + acl_token = NULL; + } + if (sip->sip_contact && sip->sip_contact->m_url) { char tmp[35] = ""; sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url); diff --git a/src/switch_core.c b/src/switch_core.c index 411616e23d..d86af82b3f 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -691,7 +691,7 @@ typedef struct { static switch_ip_list_t IP_LIST = { 0 }; -SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip(const char *ip_str, const char *list_name) +SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token) { switch_network_list_t *list; uint32_t ip, net, mask, bits; @@ -703,7 +703,7 @@ SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip(const char *ip_str, c ip = htonl(ip); if ((list = switch_core_hash_find(IP_LIST.hash, list_name))) { - ok = switch_network_list_validate_ip(list, ip); + ok = switch_network_list_validate_ip_token(list, ip, token); } else if (strchr(list_name, '/')) { switch_parse_cidr(list_name, &net, &mask, &bits); ok = switch_test_subnet(ip, net, mask); @@ -761,7 +761,7 @@ 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; + const char *cidr = NULL, *host = NULL, *mask = NULL, *domain = NULL; switch_bool_t ok = default_type; const char *type = switch_xml_attr(x_node, "type"); @@ -772,35 +772,55 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload) cidr = switch_xml_attr(x_node, "cidr"); host = switch_xml_attr(x_node, "host"); mask = switch_xml_attr(x_node, "mask"); + domain = switch_xml_attr(x_node, "domain"); - if (cidr) { + if (domain) { + switch_event_t *my_params = NULL; + switch_xml_t x_domain, xml_root; + switch_xml_t ut; + + switch_event_create(&my_params, SWITCH_EVENT_MESSAGE); + switch_assert(my_params); + switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "domain", domain); + switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "purpose", "network-list"); + + if (switch_xml_locate_domain(domain, my_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain); + continue; + } + + for (ut = switch_xml_child(x_domain, "user"); ut; ut = ut->next) { + const char *user_cidr = switch_xml_attr(ut, "cidr"); + const char *id = switch_xml_attr(ut, "id"); + + if (id && user_cidr) { + char *token = switch_mprintf("%s@%s", id, domain); + switch_assert(token); + + if (switch_network_list_add_cidr_token(list, user_cidr, ok, token) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s (%s) [%s] to list %s\n", + user_cidr, ok ? "allow" : "deny", switch_str_nil(token), name); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Adding %s (%s) [%s] to list %s\n", + user_cidr, ok ? "allow" : "deny", switch_str_nil(token), name); + } + free(token); + } + } + switch_xml_free(xml_root); + } else if (cidr) { if (switch_network_list_add_cidr(list, cidr, ok) == SWITCH_STATUS_SUCCESS) { - if (reload) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", - name); - } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); } else { - if (reload) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "Error Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, - "Error Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); - } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Error Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); } } else if (host && mask) { if (switch_network_list_add_host_mask(list, host, mask, ok) == SWITCH_STATUS_SUCCESS) { - if (reload) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, - "Adding %s/%s (%s) to list %s\n", host, mask, ok ? "allow" : "deny", name); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, - "Adding %s/%s (%s) to list %s\n", host, mask, ok ? "allow" : "deny", name); - } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, + "Adding %s/%s (%s) to list %s\n", host, mask, ok ? "allow" : "deny", name); } - } + } switch_core_hash_insert(IP_LIST.hash, name, list); } diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 7ebb131a64..b0c76dbd93 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -1760,6 +1760,64 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session, c } +SWITCH_DECLARE(switch_status_t) switch_ivr_set_user(switch_core_session_t *session, const char *data) +{ + switch_xml_t x_domain, xml = NULL, x_user, x_param, x_params; + char *user, *mailbox, *domain; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_status_t status = SWITCH_STATUS_FALSE; + + if (switch_strlen_zero(data)) { + goto error; + } + + user = switch_core_session_strdup(session, data); + + if (!(domain = strchr(user, '@'))) { + goto error; + } + + *domain++ = '\0'; + + if (switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain); + goto done; + } + + status = SWITCH_STATUS_SUCCESS; + + if ((mailbox = (char *) switch_xml_attr(x_user, "mailbox"))) { + switch_channel_set_variable(channel, "mailbox", mailbox); + } + + if ((x_params = switch_xml_child(x_user, "variables"))) { + for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { + const char *var = switch_xml_attr(x_param, "name"); + const char *val = switch_xml_attr(x_param, "value"); + + if (var && val) { + switch_channel_set_variable(channel, var, val); + } + } + } + + switch_channel_set_variable(channel, "user_name", user); + switch_channel_set_variable(channel, "domain_name", domain); + + goto done; + + error: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No user@domain specified.\n"); + + done: + if (xml) { + switch_xml_free(xml); + } + + return status; +} + + /* For Emacs: * Local Variables: * mode:c diff --git a/src/switch_utils.c b/src/switch_utils.c index fb371517ce..04c66d2c7a 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -43,6 +43,7 @@ struct switch_network_node { uint32_t mask; uint32_t bits; switch_bool_t ok; + char *token; struct switch_network_node *next; }; typedef struct switch_network_node switch_network_node_t; @@ -77,7 +78,7 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_create(switch_network_list_t return SWITCH_STATUS_SUCCESS; } -SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip(switch_network_list_t *list, uint32_t ip) +SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_network_list_t *list, uint32_t ip, const char **token) { switch_network_node_t *node; switch_bool_t ok = list->default_type; @@ -90,15 +91,19 @@ SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip(switch_network_lis } else { ok = SWITCH_FALSE; } + bits = node->bits; + + if (token) { + *token = node->token; + } } } return ok; } - -SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr(switch_network_list_t *list, const char *cidr_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) { uint32_t ip, mask, bits; switch_network_node_t *node; @@ -114,13 +119,16 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr(switch_network_list node->ok = ok; node->bits = bits; + if (!switch_strlen_zero(token)) { + node->token = switch_core_strdup(list->pool, token); + } + node->next = list->node_head; list->node_head = node; - return SWITCH_STATUS_SUCCESS; + 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) { int ip, mask;