]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
BOUNTY-15 - add user-agent-filter and max-registrations-per-extension
authorRupa Schomaker <rupa@rupa.com>
Tue, 2 Feb 2010 21:04:41 +0000 (21:04 +0000)
committerRupa Schomaker <rupa@rupa.com>
Tue, 2 Feb 2010 21:04:41 +0000 (21:04 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16557 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_reg.c

index d9730a723ca544ebdde887ac677c18cdaa0d1e42..676eeb7747e7869c1e14a0ad1156854028530b94 100644 (file)
@@ -2161,6 +2161,12 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
                                        stream->write_function(stream, "AGGRESSIVENAT    \t%s\n", sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION) ? "true" : "false");
                                        stream->write_function(stream, "STUN-ENABLED     \t%s\n", sofia_test_pflag(profile, PFLAG_STUN_ENABLED) ? "true" : "false");
                                        stream->write_function(stream, "STUN-AUTO-DISABLE\t%s\n", sofia_test_pflag(profile, PFLAG_STUN_AUTO_DISABLE) ? "true" : "false");
+                                       if (profile->user_agent_filter) {
+                                       stream->write_function(stream, "USER-AGENT-FILTER\t%s\n", switch_str_nil(profile->user_agent_filter));
+                                       }
+                                       if (profile->max_registrations_perext > 0) {
+                                       stream->write_function(stream, "MAX-REG-PEREXT   \t%d\n", profile->max_registrations_perext);
+                                       }
                                        stream->write_function(stream, "CALLS-IN         \t%d\n", profile->ib_calls);
                                        stream->write_function(stream, "FAILED-CALLS-IN  \t%d\n", profile->ib_failed_calls);
                                        stream->write_function(stream, "CALLS-OUT        \t%d\n", profile->ob_calls);
@@ -2382,6 +2388,8 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
                                        stream->write_function(stream, "    <stun-enabled>%s</stun-enabled>\n", sofia_test_pflag(profile, PFLAG_STUN_ENABLED) ? "true" : "false");
                                        stream->write_function(stream, "    <stun-auto-disable>%s</stun-auto-disable>\n", 
                                                                                   sofia_test_pflag(profile, PFLAG_STUN_AUTO_DISABLE) ? "true" : "false");
+                                       stream->write_function(stream, "    <user-agent-filter>%s</user-agent-filter>\n", switch_str_nil(profile->user_agent_filter));
+                                       stream->write_function(stream, "    <max-registrations-per-extension>%d</max-registrations-per-extension>\n", profile->max_registrations_perext);
                                        stream->write_function(stream, "    <calls-in>%d</calls-in>\n", profile->ib_calls);
                                        stream->write_function(stream, "    <calls-out>%d</calls-out>\n", profile->ob_calls);
                                        stream->write_function(stream, "    <failed-calls-in>%d</failed-calls-in>\n", profile->ib_failed_calls);
index 1c743db4d716c187b89d3d85f6263dfd97c37b55..3fd797c746aecd700b034552c3329395d2b3dbfd 100644 (file)
@@ -515,6 +515,8 @@ struct sofia_profile {
        sofia_presence_type_t pres_type;
        sofia_media_options_t media_options;
        uint32_t force_subscription_expires;
+       char *user_agent_filter;
+       uint32_t max_registrations_perext;
        switch_rtp_bug_flag_t auto_rtp_bugs;
        uint32_t ib_calls;
        uint32_t ob_calls;
index fe321a8faaf9e8e7baf07e836df0f6dadc97f0a9..31739d4cccebca683c2d6a925a0f2a862615b4bd 100644 (file)
@@ -2191,6 +2191,10 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
                                                } else {
                                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SOFIA_MAX_ACL);
                                                }
+                                       } else if (!strcasecmp(var, "user-agent-filter")) {
+                                               profile->user_agent_filter = switch_core_strdup(profile->pool, val);
+                                       } else if (!strcasecmp(var, "max-registrations-per-extension")) {
+                                               profile->max_registrations_perext = atoi(val);
                                        } else if (!strcasecmp(var, "rfc2833-pt")) {
                                                profile->te = (switch_payload_t) atoi(val);
                                        } else if (!strcasecmp(var, "cng-pt") && !(sofia_test_pflag(profile, PFLAG_SUPPRESS_CNG))) {
@@ -2726,6 +2730,10 @@ switch_status_t config_sofia(int reload, char *profile_name)
                                                } else {
                                                        sofia_clear_pflag(profile, PFLAG_STUN_AUTO_DISABLE); 
                                                }
+                                       } else if (!strcasecmp(var, "user-agent-filter")) {
+                                               profile->user_agent_filter = switch_core_strdup(profile->pool, val);
+                                       } else if (!strcasecmp(var, "max-registrations-per-extension")) {
+                                               profile->max_registrations_perext = atoi(val);
                                        } else if (!strcasecmp(var, "rfc2833-pt")) {
                                                profile->te = (switch_payload_t) atoi(val);
                                        } else if (!strcasecmp(var, "cng-pt") && !sofia_test_pflag(profile, PFLAG_SUPPRESS_CNG)) {
index 201ad05810a6dde54ae796725252631957c9b553..9f98b243dbcfda724b062eb7f05f03cf6c175da7 100644 (file)
@@ -1647,6 +1647,15 @@ static int sofia_reg_nonce_callback(void *pArg, int argc, char **argv, char **co
        return 0;
 }
 
+static int sofia_reg_regcount_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+       int *ret = (int *) pArg;
+       if (argc == 1) {
+               *ret = atoi(argv[0]);
+       }
+       return 0;
+}
+
 auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, 
                                                                sip_authorization_t const *authorization, 
                                                                sip_t const *sip, 
@@ -1682,6 +1691,9 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
        const char *auth_acl = NULL;
        long ncl = 0;
        sip_unknown_t *un;
+       const char *user_agent = NULL;
+       const char *user_agent_filter = profile->user_agent_filter;
+       uint32_t max_registrations_perext = profile->max_registrations_perext;
 
        username = realm = nonce = uri = qop = cnonce = nc = response = NULL;
 
@@ -1741,6 +1753,8 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
                }
        }
 
+       user_agent = (sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown";
+
        if (zstr(np)) {
                nonce_cb_t cb = { 0 };
                long nc_long = 0;
@@ -1777,8 +1791,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
        switch_assert(params);
        switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "sip_auth");
        switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
-       switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_user_agent",
-                                                                  (sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown");
+       switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_user_agent", user_agent);
        switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_username", username);
        switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_realm", realm);
        switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_nonce", nonce);
@@ -1905,6 +1918,13 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
                        if (!strcasecmp(var, "mwi-account")) {
                                mwi_account = val;
                        }
+                       
+                       if (!strcasecmp(var, "user-agent-filter")) {
+                               user_agent_filter = val;
+                       }
+                       if (!strcasecmp(var, "max-registrations-per-extension")) {
+                               max_registrations_perext = atoi(val);
+                       }
                }
        }
 
@@ -1932,6 +1952,13 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
                        if (!strcasecmp(var, "mwi-account")) {
                                mwi_account = val;
                        }
+
+                       if (!strcasecmp(var, "user-agent-filter")) {
+                               user_agent_filter = val;
+                       }
+                       if (!strcasecmp(var, "max-registrations-per-extension")) {
+                               max_registrations_perext = atoi(val);
+                       }
                }
        }
 
@@ -1959,6 +1986,12 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
                        if (!strcasecmp(var, "mwi-account")) {
                                mwi_account = val;
                        }
+                       if (!strcasecmp(var, "user-agent-filter")) {
+                               user_agent_filter = val;
+                       }
+                       if (!strcasecmp(var, "max-registrations-per-extension")) {
+                               max_registrations_perext = atoi(val);
+                       }
                }
        }
 
@@ -2046,6 +2079,41 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
 
        }
 
+       if (user_agent_filter) {
+               if (switch_regex_match(user_agent, user_agent_filter) == SWITCH_STATUS_SUCCESS) {
+                       if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SIP auth OK (REGISTER) due to user-agent-filter.  Filter \"%s\" User-Agent \"%s\"\n", user_agent_filter, user_agent);
+                       }
+               } else {
+                       ret = AUTH_FORBIDDEN;
+                       if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth failure (REGISTER) due to user-agent-filter.  Filter \"%s\" User-Agent \"%s\"\n", user_agent_filter, user_agent);
+                       }
+                       goto end;
+               }
+       }
+
+       if (max_registrations_perext > 0 && 
+          (sip && sip->sip_contact && 
+          (sip->sip_contact->m_expires == NULL || atol(sip->sip_contact->m_expires) > 0))) {
+          /* if expires is null still process */
+          /* expires == 0 means the phone is going to unregiser, so don't count against max */
+               int count = 0;
+                               
+               sql = switch_mprintf("select count(sip_user) from sip_registrations where sip_user='%q'", username);
+               switch_assert(sql != NULL);
+               sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_regcount_callback, &count);
+               free(sql);
+               
+               if (count+1 > max_registrations_perext) {
+                       ret = AUTH_FORBIDDEN;
+                       if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth failure (REGISTER) due to reaching max allowed registrations.  Count: %d\n", count);
+                       }
+                       goto end;
+               }
+       }
+       
   for_the_sake_of_interop:
 
        if ((input = switch_mprintf("%s:%q", regstr, uri))) {