res_pjsip res_pjsip_mwi: Misc fixes and cleanups.
[asterisk/asterisk.git] / res / res_pjsip_acl.c
index c44704c..5c10e57 100644 (file)
                <synopsis>SIP ACL module</synopsis>
                <description><para>
                        <emphasis>ACL</emphasis>
-                       </para>
-                       <para>The ACL module used by <literal>res_pjsip</literal>. This module is
+                       </para><para>
+                       The ACL module used by <literal>res_pjsip</literal>. This module is
                        independent of <literal>endpoints</literal> and operates on all inbound
                        SIP communication using res_pjsip.
                        </para><para>
-                       It should be noted that this module can also reference ACLs from
-                       <filename>acl.conf</filename>.
+                       There are two main ways of defining your ACL with the options
+                       provided. You can use the <literal>permit</literal> and <literal>deny</literal> options
+                       which act on <emphasis>IP</emphasis> addresses, or the <literal>contactpermit</literal>
+                       and <literal>contactdeny</literal> options which act on <emphasis>Contact header</emphasis>
+                       addresses in incoming REGISTER requests. You can combine the various options to
+                       create a mixed ACL.
                        </para><para>
-                       There are two main ways of creating an access list: <literal>IP-Domain</literal>
-                       and <literal>Contact Header</literal>. It is possible to create a combined ACL using
-                       both IP and Contact.
+                       Additionally, instead of defining an ACL with options, you can reference IP or
+                       Contact header ACLs from the file <filename>acl.conf</filename> by using the <literal>acl</literal>
+                       or <literal>contactacl</literal> options.
                </para></description>
                <configFile name="pjsip.conf">
                        <configObject name="acl">
                                <synopsis>Access Control List</synopsis>
                                <configOption name="acl">
-                                       <synopsis>Name of IP ACL</synopsis>
+                                       <synopsis>List of IP ACL section names in acl.conf</synopsis>
                                        <description><para>
-                                               This matches sections configured in <literal>acl.conf</literal>
+                                               This matches sections configured in <literal>acl.conf</literal>. The value is
+                                               defined as a list of comma-delimited section names.
                                        </para></description>
                                </configOption>
-                               <configOption name="contactacl">
-                                       <synopsis>Name of Contact ACL</synopsis>
+                               <configOption name="contact_acl">
+                                       <synopsis>List of Contact ACL section names in acl.conf</synopsis>
                                        <description><para>
-                                               This matches sections configured in <literal>acl.conf</literal>
+                                               This matches sections configured in <literal>acl.conf</literal>. The value is
+                                               defined as a list of comma-delimited section names.
                                        </para></description>
                                </configOption>
-                               <configOption name="contactdeny">
-                                       <synopsis>List of Contact Header addresses to Deny</synopsis>
+                               <configOption name="contact_deny">
+                                       <synopsis>List of Contact header addresses to deny</synopsis>
+                                       <description><para>
+                                               The value is a comma-delimited list of IP addresses. IP addresses may
+                                               have a subnet mask appended. The subnet mask may be written in either
+                                               CIDR or dotted-decimal notation. Separate the IP address and subnet
+                                               mask with a slash ('/')
+                                       </para></description>
                                </configOption>
-                               <configOption name="contactpermit">
-                                       <synopsis>List of Contact Header addresses to Permit</synopsis>
+                               <configOption name="contact_permit">
+                                       <synopsis>List of Contact header addresses to permit</synopsis>
+                                       <description><para>
+                                               The value is a comma-delimited list of IP addresses. IP addresses may
+                                               have a subnet mask appended. The subnet mask may be written in either
+                                               CIDR or dotted-decimal notation. Separate the IP address and subnet
+                                               mask with a slash ('/')
+                                       </para></description>
                                </configOption>
                                <configOption name="deny">
-                                       <synopsis>List of IP-domains to deny access from</synopsis>
+                                       <synopsis>List of IP addresses to deny access from</synopsis>
+                                       <description><para>
+                                               The value is a comma-delimited list of IP addresses. IP addresses may
+                                               have a subnet mask appended. The subnet mask may be written in either
+                                               CIDR or dotted-decimal notation. Separate the IP address and subnet
+                                               mask with a slash ('/')
+                                       </para></description>
                                </configOption>
                                <configOption name="permit">
-                                       <synopsis>List of IP-domains to allow access from</synopsis>
+                                       <synopsis>List of IP addresses to permit access from</synopsis>
+                                       <description><para>
+                                               The value is a comma-delimited list of IP addresses. IP addresses may
+                                               have a subnet mask appended. The subnet mask may be written in either
+                                               CIDR or dotted-decimal notation. Separate the IP address and subnet
+                                               mask with a slash ('/')
+                                       </para></description>
                                </configOption>
                                <configOption name="type">
-                                       <synopsis>Must be of type 'security'.</synopsis>
+                                       <synopsis>Must be of type 'acl'.</synopsis>
                                </configOption>
                        </configObject>
                </configFile>
@@ -108,10 +138,12 @@ static int extract_contact_addr(pjsip_contact_hdr *contact, struct ast_sockaddr
        pjsip_sip_uri *sip_uri;
        char host[256];
 
-       if (!contact) {
+       if (!contact || contact->star) {
+               *addrs = NULL;
                return 0;
        }
        if (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
+               *addrs = NULL;
                return 0;
        }
        sip_uri = pjsip_uri_get_uri(contact->uri);
@@ -203,10 +235,24 @@ static int acl_handler(const struct aco_option *opt, struct ast_variable *var, v
        struct ast_sip_acl *sip_acl = obj;
        int error = 0;
        int ignore;
-       if (!strncmp(var->name, "contact", 7)) {
-               ast_append_acl(var->name + 7, var->value, &sip_acl->contact_acl, &error, &ignore);
+
+       if (!strncmp(var->name, "contact_", 8)) {
+               ast_append_acl(var->name + 8, var->value, &sip_acl->contact_acl, &error, &ignore);
+               if (error) {
+                       ast_log(LOG_ERROR, "Bad contact ACL '%s' at line '%d' of pjsip.conf\n",
+                                       var->value, var->lineno);
+               }
        } else {
                ast_append_acl(var->name, var->value, &sip_acl->acl, &error, &ignore);
+               if (error) {
+                       ast_log(LOG_ERROR, "Bad ACL '%s' at line '%d' of pjsip.conf\n",
+                                       var->value, var->lineno);
+               }
+       }
+
+       if (error) {
+               ast_log(LOG_ERROR, "There is an error in ACL configuration. Blocking ALL SIP traffic.\n");
+               ast_append_acl("deny", "0.0.0.0/0.0.0.0", &sip_acl->acl, NULL, &ignore);
        }
 
        return error;
@@ -236,6 +282,9 @@ static void *acl_alloc(const char *name)
 
 static int load_module(void)
 {
+       CHECK_PJSIP_MODULE_LOADED();
+
+       ast_sorcery_apply_config(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE);
        ast_sorcery_apply_default(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE,
                                  "config", "pjsip.conf,criteria=type=acl");
 
@@ -248,12 +297,14 @@ static int load_module(void)
        }
 
        ast_sorcery_object_field_register(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "type", "", OPT_NOOP_T, 0, 0);
-       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "permit", "", acl_handler, NULL, 0, 0);
-       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "deny", "", acl_handler, NULL, 0, 0);
-       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "acl", "", acl_handler, NULL, 0, 0);
-       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "contactpermit", "", acl_handler, NULL, 0, 0);
-       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "contactdeny", "", acl_handler, NULL, 0, 0);
-       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "contactacl", "", acl_handler, NULL, 0, 0);
+       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "permit", "", acl_handler, NULL, NULL, 0, 0);
+       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "deny", "", acl_handler, NULL, NULL, 0, 0);
+       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "acl", "", acl_handler, NULL, NULL, 0, 0);
+       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "contact_permit", "", acl_handler, NULL, NULL, 0, 0);
+       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "contact_deny", "", acl_handler, NULL, NULL, 0, 0);
+       ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE, "contact_acl", "", acl_handler, NULL, NULL, 0, 0);
+
+       ast_sorcery_load_object(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE);
 
        ast_sip_register_service(&acl_module);
        return AST_MODULE_LOAD_SUCCESS;
@@ -266,7 +317,8 @@ static int unload_module(void)
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP ACL Resource",
-               .load = load_module,
-               .unload = unload_module,
-               .load_pri = AST_MODPRI_APP_DEPEND,
-              );
+       .support_level = AST_MODULE_SUPPORT_CORE,
+       .load = load_module,
+       .unload = unload_module,
+       .load_pri = AST_MODPRI_APP_DEPEND,
+);