mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 12:36:58 +00:00
res_pjsip: Endpoint IP Access Controls
With the old SIP module we can use IP access controls per peer. PJSIP module missing this feature. This patch added next configuration Endpoint options: "acl" - list of IP ACL section names in acl.conf "deny" - List of IP addresses to deny access from "permit" - List of IP addresses to permit access from "contact_acl" - List of Contact ACL section names in acl.conf "contact_deny" - List of Contact header addresses to deny "contact_permit" - List of Contact header addresses to permit This patch also better logging failed request: add custom message instead of "No matching endpoint found" add SIP method to logging ASTERISK-25900 Change-Id: I456dea3909d929d413864fb347d28578415ebf02
This commit is contained in:
9
CHANGES
9
CHANGES
@@ -282,6 +282,15 @@ res_fax
|
|||||||
|
|
||||||
res_pjsip
|
res_pjsip
|
||||||
------------------
|
------------------
|
||||||
|
* Endpoint IP Access Controls
|
||||||
|
Added new configuration Endpoint options:
|
||||||
|
"acl" - list of IP ACL section names in acl.conf
|
||||||
|
"deny" - List of IP addresses to deny access from
|
||||||
|
"permit" - List of IP addresses to permit access from
|
||||||
|
"contact_acl" - List of Contact ACL section names in acl.conf
|
||||||
|
"contact_deny" - List of Contact header addresses to deny
|
||||||
|
"contact_permit" - List of Contact header addresses to permit
|
||||||
|
|
||||||
* Added new status Updated to AMI event ContactStatus on update registration
|
* Added new status Updated to AMI event ContactStatus on update registration
|
||||||
|
|
||||||
* Added "reg_server" to contacts.
|
* Added "reg_server" to contacts.
|
||||||
|
@@ -0,0 +1,32 @@
|
|||||||
|
"""Add PJSIP Endpoint IP Access Control options
|
||||||
|
|
||||||
|
Revision ID: d7e3c73eb2bf
|
||||||
|
Revises: 6be31516058d
|
||||||
|
Create Date: 2016-05-13 12:45:45.071871
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'd7e3c73eb2bf'
|
||||||
|
down_revision = '6be31516058d'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column('ps_endpoints', sa.Column('deny', sa.String(95)))
|
||||||
|
op.add_column('ps_endpoints', sa.Column('permit', sa.String(95)))
|
||||||
|
op.add_column('ps_endpoints', sa.Column('acl', sa.String(40)))
|
||||||
|
op.add_column('ps_endpoints', sa.Column('contact_deny', sa.String(95)))
|
||||||
|
op.add_column('ps_endpoints', sa.Column('contact_permit', sa.String(95)))
|
||||||
|
op.add_column('ps_endpoints', sa.Column('contact_acl', sa.String(40)))
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_column('ps_endpoints', 'contact_acl')
|
||||||
|
op.drop_column('ps_endpoints', 'contact_permit')
|
||||||
|
op.drop_column('ps_endpoints', 'contact_deny')
|
||||||
|
op.drop_column('ps_endpoints', 'acl')
|
||||||
|
op.drop_column('ps_endpoints', 'permit')
|
||||||
|
op.drop_column('ps_endpoints', 'deny')
|
@@ -738,6 +738,10 @@ struct ast_sip_endpoint {
|
|||||||
unsigned int usereqphone;
|
unsigned int usereqphone;
|
||||||
/*! Whether to pass through hold and unhold using re-invites with recvonly and sendrecv */
|
/*! Whether to pass through hold and unhold using re-invites with recvonly and sendrecv */
|
||||||
unsigned int moh_passthrough;
|
unsigned int moh_passthrough;
|
||||||
|
/* Access control list */
|
||||||
|
struct ast_acl_list *acl;
|
||||||
|
/* Restrict what IPs are allowed in the Contact header (for registration) */
|
||||||
|
struct ast_acl_list *contact_acl;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@@ -849,6 +849,56 @@
|
|||||||
channel is hung up. By default this option is set to 0, which means do not check.
|
channel is hung up. By default this option is set to 0, which means do not check.
|
||||||
</para></description>
|
</para></description>
|
||||||
</configOption>
|
</configOption>
|
||||||
|
<configOption name="acl">
|
||||||
|
<synopsis>List of IP ACL section names in acl.conf</synopsis>
|
||||||
|
<description><para>
|
||||||
|
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="deny">
|
||||||
|
<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 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="contact_acl">
|
||||||
|
<synopsis>List of Contact ACL section names in acl.conf</synopsis>
|
||||||
|
<description><para>
|
||||||
|
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="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="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>
|
||||||
</configObject>
|
</configObject>
|
||||||
<configObject name="auth">
|
<configObject name="auth">
|
||||||
<synopsis>Authentication type</synopsis>
|
<synopsis>Authentication type</synopsis>
|
||||||
|
@@ -262,6 +262,65 @@ static const struct ast_sorcery_observer endpoint_observers = {
|
|||||||
.deleted = endpoint_deleted_observer,
|
.deleted = endpoint_deleted_observer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int endpoint_acl_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
|
||||||
|
{
|
||||||
|
struct ast_sip_endpoint *endpoint = obj;
|
||||||
|
int error = 0;
|
||||||
|
int ignore;
|
||||||
|
|
||||||
|
if (ast_strlen_zero(var->value)) return 0;
|
||||||
|
|
||||||
|
if (!strncmp(var->name, "contact_", 8)) {
|
||||||
|
ast_append_acl(var->name + 8, var->value, &endpoint->contact_acl, &error, &ignore);
|
||||||
|
} else {
|
||||||
|
ast_append_acl(var->name, var->value, &endpoint->acl, &error, &ignore);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int acl_to_str(const void *obj, const intptr_t *args, char **buf)
|
||||||
|
{
|
||||||
|
const struct ast_sip_endpoint *endpoint = obj;
|
||||||
|
struct ast_acl_list *acl_list;
|
||||||
|
struct ast_acl *first_acl;
|
||||||
|
|
||||||
|
if (endpoint && !ast_acl_list_is_empty(acl_list=endpoint->acl)) {
|
||||||
|
AST_LIST_LOCK(acl_list);
|
||||||
|
first_acl = AST_LIST_FIRST(acl_list);
|
||||||
|
if (ast_strlen_zero(first_acl->name)) {
|
||||||
|
*buf = "deny/permit";
|
||||||
|
} else {
|
||||||
|
*buf = first_acl->name;
|
||||||
|
}
|
||||||
|
AST_LIST_UNLOCK(acl_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
*buf = ast_strdup(*buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int contact_acl_to_str(const void *obj, const intptr_t *args, char **buf)
|
||||||
|
{
|
||||||
|
const struct ast_sip_endpoint *endpoint = obj;
|
||||||
|
struct ast_acl_list *acl_list;
|
||||||
|
struct ast_acl *first_acl;
|
||||||
|
|
||||||
|
if (endpoint && !ast_acl_list_is_empty(acl_list=endpoint->contact_acl)) {
|
||||||
|
AST_LIST_LOCK(acl_list);
|
||||||
|
first_acl = AST_LIST_FIRST(acl_list);
|
||||||
|
if (ast_strlen_zero(first_acl->name)) {
|
||||||
|
*buf = "deny/permit";
|
||||||
|
} else {
|
||||||
|
*buf = first_acl->name;
|
||||||
|
}
|
||||||
|
AST_LIST_UNLOCK(acl_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
*buf = ast_strdup(*buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
|
static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
|
||||||
{
|
{
|
||||||
struct ast_sip_endpoint *endpoint = obj;
|
struct ast_sip_endpoint *endpoint = obj;
|
||||||
@@ -272,8 +331,8 @@ static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var,
|
|||||||
endpoint->dtmf = AST_SIP_DTMF_INBAND;
|
endpoint->dtmf = AST_SIP_DTMF_INBAND;
|
||||||
} else if (!strcasecmp(var->value, "info")) {
|
} else if (!strcasecmp(var->value, "info")) {
|
||||||
endpoint->dtmf = AST_SIP_DTMF_INFO;
|
endpoint->dtmf = AST_SIP_DTMF_INFO;
|
||||||
} else if (!strcasecmp(var->value, "auto")) {
|
} else if (!strcasecmp(var->value, "auto")) {
|
||||||
endpoint->dtmf = AST_SIP_DTMF_AUTO;
|
endpoint->dtmf = AST_SIP_DTMF_AUTO;
|
||||||
} else if (!strcasecmp(var->value, "none")) {
|
} else if (!strcasecmp(var->value, "none")) {
|
||||||
endpoint->dtmf = AST_SIP_DTMF_NONE;
|
endpoint->dtmf = AST_SIP_DTMF_NONE;
|
||||||
} else {
|
} else {
|
||||||
@@ -295,7 +354,7 @@ static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf)
|
|||||||
case AST_SIP_DTMF_INFO :
|
case AST_SIP_DTMF_INFO :
|
||||||
*buf = "info"; break;
|
*buf = "info"; break;
|
||||||
case AST_SIP_DTMF_AUTO :
|
case AST_SIP_DTMF_AUTO :
|
||||||
*buf = "auto"; break;
|
*buf = "auto"; break;
|
||||||
default:
|
default:
|
||||||
*buf = "none";
|
*buf = "none";
|
||||||
}
|
}
|
||||||
@@ -1760,6 +1819,12 @@ int ast_res_pjsip_initialize_configuration(void)
|
|||||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "set_var", "", set_var_handler, set_var_to_str, set_var_to_vl, 0, 0);
|
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "set_var", "", set_var_handler, set_var_to_str, set_var_to_vl, 0, 0);
|
||||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "message_context", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, message_context));
|
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "message_context", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, message_context));
|
||||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "accountcode", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, accountcode));
|
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "accountcode", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, accountcode));
|
||||||
|
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "deny", "", endpoint_acl_handler, NULL, NULL, 0, 0);
|
||||||
|
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "permit", "", endpoint_acl_handler, NULL, NULL, 0, 0);
|
||||||
|
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "acl", "", endpoint_acl_handler, acl_to_str, NULL, 0, 0);
|
||||||
|
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_deny", "", endpoint_acl_handler, NULL, NULL, 0, 0);
|
||||||
|
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_permit", "", endpoint_acl_handler, NULL, NULL, 0, 0);
|
||||||
|
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_acl", "", endpoint_acl_handler, contact_acl_to_str, NULL, 0, 0);
|
||||||
|
|
||||||
if (ast_sip_initialize_sorcery_transport()) {
|
if (ast_sip_initialize_sorcery_transport()) {
|
||||||
ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
|
ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#include <pjsip.h>
|
#include <pjsip.h>
|
||||||
|
|
||||||
#include "asterisk/res_pjsip.h"
|
#include "asterisk/res_pjsip.h"
|
||||||
|
#include "asterisk/acl.h"
|
||||||
#include "include/res_pjsip_private.h"
|
#include "include/res_pjsip_private.h"
|
||||||
#include "asterisk/taskprocessor.h"
|
#include "asterisk/taskprocessor.h"
|
||||||
#include "asterisk/threadpool.h"
|
#include "asterisk/threadpool.h"
|
||||||
@@ -380,19 +381,21 @@ struct ast_sip_endpoint *ast_sip_get_artificial_endpoint(void)
|
|||||||
return artificial_endpoint;
|
return artificial_endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void log_unidentified_request(pjsip_rx_data *rdata, unsigned int count, unsigned int period)
|
static void log_failed_request(pjsip_rx_data *rdata, char *msg, unsigned int count, unsigned int period)
|
||||||
{
|
{
|
||||||
char from_buf[PJSIP_MAX_URL_SIZE];
|
char from_buf[PJSIP_MAX_URL_SIZE];
|
||||||
char callid_buf[PJSIP_MAX_URL_SIZE];
|
char callid_buf[PJSIP_MAX_URL_SIZE];
|
||||||
|
char method_buf[PJSIP_MAX_URL_SIZE];
|
||||||
pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, rdata->msg_info.from->uri, from_buf, PJSIP_MAX_URL_SIZE);
|
pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, rdata->msg_info.from->uri, from_buf, PJSIP_MAX_URL_SIZE);
|
||||||
ast_copy_pj_str(callid_buf, &rdata->msg_info.cid->id, PJSIP_MAX_URL_SIZE);
|
ast_copy_pj_str(callid_buf, &rdata->msg_info.cid->id, PJSIP_MAX_URL_SIZE);
|
||||||
|
ast_copy_pj_str(method_buf, &rdata->msg_info.msg->line.req.method.name, PJSIP_MAX_URL_SIZE);
|
||||||
if (count) {
|
if (count) {
|
||||||
ast_log(LOG_NOTICE, "Request from '%s' failed for '%s:%d' (callid: %s) - No matching endpoint found"
|
ast_log(LOG_NOTICE, "Request '%s' from '%s' failed for '%s:%d' (callid: %s) - %s"
|
||||||
" after %u tries in %.3f ms\n",
|
" after %u tries in %.3f ms\n",
|
||||||
from_buf, rdata->pkt_info.src_name, rdata->pkt_info.src_port, callid_buf, count, period / 1000.0);
|
method_buf, from_buf, rdata->pkt_info.src_name, rdata->pkt_info.src_port, callid_buf, msg, count, period / 1000.0);
|
||||||
} else {
|
} else {
|
||||||
ast_log(LOG_NOTICE, "Request from '%s' failed for '%s:%d' (callid: %s) - No matching endpoint found\n",
|
ast_log(LOG_NOTICE, "Request '%s' from '%s' failed for '%s:%d' (callid: %s) - %s\n",
|
||||||
from_buf, rdata->pkt_info.src_name, rdata->pkt_info.src_port, callid_buf);
|
method_buf, from_buf, rdata->pkt_info.src_name, rdata->pkt_info.src_port, callid_buf, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,7 +408,7 @@ static void check_endpoint(pjsip_rx_data *rdata, struct unidentified_request *un
|
|||||||
unid->count++;
|
unid->count++;
|
||||||
|
|
||||||
if (ms < (unidentified_period * 1000) && unid->count >= unidentified_count) {
|
if (ms < (unidentified_period * 1000) && unid->count >= unidentified_count) {
|
||||||
log_unidentified_request(rdata, unid->count, ms);
|
log_failed_request(rdata, "No matching endpoint found", unid->count, ms);
|
||||||
ast_sip_report_invalid_endpoint(name, rdata);
|
ast_sip_report_invalid_endpoint(name, rdata);
|
||||||
}
|
}
|
||||||
ao2_unlock(unid);
|
ao2_unlock(unid);
|
||||||
@@ -479,7 +482,7 @@ static pj_bool_t endpoint_lookup(pjsip_rx_data *rdata)
|
|||||||
ao2_ref(unid, -1);
|
ao2_ref(unid, -1);
|
||||||
ao2_unlock(unidentified_requests);
|
ao2_unlock(unidentified_requests);
|
||||||
} else {
|
} else {
|
||||||
log_unidentified_request(rdata, 0, 0);
|
log_failed_request(rdata, "No matching endpoint found", 0, 0);
|
||||||
ast_sip_report_invalid_endpoint(name, rdata);
|
ast_sip_report_invalid_endpoint(name, rdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -487,6 +490,79 @@ static pj_bool_t endpoint_lookup(pjsip_rx_data *rdata)
|
|||||||
return PJ_FALSE;
|
return PJ_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int apply_endpoint_acl(pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint)
|
||||||
|
{
|
||||||
|
struct ast_sockaddr addr;
|
||||||
|
|
||||||
|
if (ast_acl_list_is_empty(endpoint->acl)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
ast_sockaddr_parse(&addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID);
|
||||||
|
ast_sockaddr_set_port(&addr, rdata->pkt_info.src_port);
|
||||||
|
|
||||||
|
if (ast_apply_acl(endpoint->acl, &addr, "SIP ACL: ") != AST_SENSE_ALLOW) {
|
||||||
|
log_failed_request(rdata, "Not match Endpoint ACL", 0, 0);
|
||||||
|
ast_sip_report_failed_acl(endpoint, rdata, "not_match_endpoint_acl");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int extract_contact_addr(pjsip_contact_hdr *contact, struct ast_sockaddr **addrs)
|
||||||
|
{
|
||||||
|
pjsip_sip_uri *sip_uri;
|
||||||
|
char host[256];
|
||||||
|
|
||||||
|
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);
|
||||||
|
ast_copy_pj_str(host, &sip_uri->host, sizeof(host));
|
||||||
|
return ast_sockaddr_resolve(addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int apply_endpoint_contact_acl(pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint)
|
||||||
|
{
|
||||||
|
int num_contact_addrs;
|
||||||
|
int forbidden = 0;
|
||||||
|
struct ast_sockaddr *contact_addrs;
|
||||||
|
int i;
|
||||||
|
pjsip_contact_hdr *contact = (pjsip_contact_hdr *)&rdata->msg_info.msg->hdr;
|
||||||
|
|
||||||
|
if (ast_acl_list_is_empty(endpoint->contact_acl)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, contact->next))) {
|
||||||
|
num_contact_addrs = extract_contact_addr(contact, &contact_addrs);
|
||||||
|
if (num_contact_addrs <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (i = 0; i < num_contact_addrs; ++i) {
|
||||||
|
if (ast_apply_acl(endpoint->contact_acl, &contact_addrs[i], "SIP Contact ACL: ") != AST_SENSE_ALLOW) {
|
||||||
|
log_failed_request(rdata, "Not match Endpoint Contact ACL", 0, 0);
|
||||||
|
ast_sip_report_failed_acl(endpoint, rdata, "not_match_endpoint_contact_acl");
|
||||||
|
forbidden = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast_free(contact_addrs);
|
||||||
|
if (forbidden) {
|
||||||
|
/* No use checking other contacts if we already have failed ACL check */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return forbidden;
|
||||||
|
}
|
||||||
|
|
||||||
static pj_bool_t authenticate(pjsip_rx_data *rdata)
|
static pj_bool_t authenticate(pjsip_rx_data *rdata)
|
||||||
{
|
{
|
||||||
RAII_VAR(struct ast_sip_endpoint *, endpoint, ast_pjsip_rdata_get_endpoint(rdata), ao2_cleanup);
|
RAII_VAR(struct ast_sip_endpoint *, endpoint, ast_pjsip_rdata_get_endpoint(rdata), ao2_cleanup);
|
||||||
@@ -494,6 +570,15 @@ static pj_bool_t authenticate(pjsip_rx_data *rdata)
|
|||||||
|
|
||||||
ast_assert(endpoint != NULL);
|
ast_assert(endpoint != NULL);
|
||||||
|
|
||||||
|
if (endpoint!=artificial_endpoint) {
|
||||||
|
if (apply_endpoint_acl(rdata, endpoint) || apply_endpoint_contact_acl(rdata, endpoint)) {
|
||||||
|
if (!is_ack) {
|
||||||
|
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
return PJ_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_ack && ast_sip_requires_authentication(endpoint, rdata)) {
|
if (!is_ack && ast_sip_requires_authentication(endpoint, rdata)) {
|
||||||
pjsip_tx_data *tdata;
|
pjsip_tx_data *tdata;
|
||||||
struct unidentified_request *unid;
|
struct unidentified_request *unid;
|
||||||
@@ -515,10 +600,12 @@ static pj_bool_t authenticate(pjsip_rx_data *rdata)
|
|||||||
pjsip_tx_data_dec_ref(tdata);
|
pjsip_tx_data_dec_ref(tdata);
|
||||||
return PJ_FALSE;
|
return PJ_FALSE;
|
||||||
case AST_SIP_AUTHENTICATION_FAILED:
|
case AST_SIP_AUTHENTICATION_FAILED:
|
||||||
|
log_failed_request(rdata, "Failed to authenticate", 0, 0);
|
||||||
ast_sip_report_auth_failed_challenge_response(endpoint, rdata);
|
ast_sip_report_auth_failed_challenge_response(endpoint, rdata);
|
||||||
pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL);
|
pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL);
|
||||||
return PJ_TRUE;
|
return PJ_TRUE;
|
||||||
case AST_SIP_AUTHENTICATION_ERROR:
|
case AST_SIP_AUTHENTICATION_ERROR:
|
||||||
|
log_failed_request(rdata, "Error to authenticate", 0, 0);
|
||||||
ast_sip_report_auth_failed_challenge_response(endpoint, rdata);
|
ast_sip_report_auth_failed_challenge_response(endpoint, rdata);
|
||||||
pjsip_tx_data_dec_ref(tdata);
|
pjsip_tx_data_dec_ref(tdata);
|
||||||
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
|
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
|
||||||
|
Reference in New Issue
Block a user