summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES10
-rw-r--r--configs/samples/pjsip.conf.sample8
-rw-r--r--contrib/ast-db-manage/config/versions/20abce6d1e3c_add_pjsip_identify_by_ip.py46
-rw-r--r--include/asterisk/res_pjsip.h2
-rw-r--r--res/res_pjsip.c25
-rw-r--r--res/res_pjsip/pjsip_configuration.c9
-rw-r--r--res/res_pjsip_endpoint_identifier_ip.c7
7 files changed, 93 insertions, 14 deletions
diff --git a/CHANGES b/CHANGES
index 68617a441..683a164ab 100644
--- a/CHANGES
+++ b/CHANGES
@@ -27,6 +27,16 @@ chan_sip
dialplan in the hash TRANSFER_DATA.
------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 15.1.0 to Asterisk 15.2.0 ------------
+------------------------------------------------------------------------------
+
+res_pjsip
+------------------
+ * The "identify_by" on endpoints can now be set to "ip" to restrict an endpoint
+ being matched based only on IP address. To ensure no behavior change the
+ default has been changed to "username,ip".
+
+------------------------------------------------------------------------------
--- Functionality changes from Asterisk 15.0.0 to Asterisk 15.1.0 ------------
------------------------------------------------------------------------------
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index c535aaf04..800ff0f44 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -634,9 +634,11 @@
; identified.
; "username": Identify by the From or To username and domain
; "auth_username": Identify by the Authorization username and realm
- ; In all cases, if an exact match on username and domain/realm fails,
- ; the match will be retried with just the username.
- ; (default: "username")
+ ; "ip": Identify by the source IP address
+ ; In username and auth_username cases, if an exact match on
+ ; username and domain/realm fails, the match will be retried
+ ; with just the username.
+ ; (default: "username,ip")
;redirect_method=user ; How redirects received from an endpoint are handled
; (default: "user")
;mailboxes= ; NOTIFY the endpoint when state changes for any of the specified mailboxes.
diff --git a/contrib/ast-db-manage/config/versions/20abce6d1e3c_add_pjsip_identify_by_ip.py b/contrib/ast-db-manage/config/versions/20abce6d1e3c_add_pjsip_identify_by_ip.py
new file mode 100644
index 000000000..d457c9233
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/20abce6d1e3c_add_pjsip_identify_by_ip.py
@@ -0,0 +1,46 @@
+"""add pjsip identify by ip
+
+Revision ID: 20abce6d1e3c
+Revises: a1698e8bb9c5
+Create Date: 2017-10-24 15:44:06.404774
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '20abce6d1e3c'
+down_revision = 'a1698e8bb9c5'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def enum_update(table_name, column_name, enum_name, enum_values):
+ if op.get_context().bind.dialect.name != 'postgresql':
+ if op.get_context().bind.dialect.name == 'mssql':
+ op.drop_constraint('ck_ps_endpoints_identify_by_pjsip_identify_by_values', 'ps_endpoints')
+ op.alter_column(table_name, column_name,
+ type_=sa.Enum(*enum_values, name=enum_name))
+ return
+
+ # Postgres requires a few more steps
+ tmp = enum_name + '_tmp'
+
+ op.execute('ALTER TYPE ' + enum_name + ' RENAME TO ' + tmp)
+
+ updated = sa.Enum(*enum_values, name=enum_name)
+ updated.create(op.get_bind(), checkfirst=False)
+
+ op.execute('ALTER TABLE ' + table_name + ' ALTER COLUMN ' + column_name +
+ ' TYPE ' + enum_name + ' USING identify_by::text::' + enum_name)
+
+ op.execute('DROP TYPE ' + tmp)
+
+
+def upgrade():
+ enum_update('ps_endpoints', 'identify_by', 'pjsip_identify_by_values',
+ ['username', 'auth_username', 'ip'])
+
+
+def downgrade():
+ enum_update('ps_endpoints', 'identify_by', 'pjsip_identify_by_values',
+ ['username', 'auth_username'])
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index e6ccf0a1d..e71eb98d7 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -437,6 +437,8 @@ enum ast_sip_endpoint_identifier_type {
AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME = (1 << 0),
/*! Identify based on user name in Auth header first, then From header */
AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME = (1 << 1),
+ /*! Identify based on source IP address */
+ AST_SIP_ENDPOINT_IDENTIFY_BY_IP = (1 << 2),
};
AST_VECTOR(ast_sip_identify_by_vector, enum ast_sip_endpoint_identifier_type);
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index f81d34ca4..7499ded3e 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -268,15 +268,17 @@
<configOption name="ice_support" default="no">
<synopsis>Enable the ICE mechanism to help traverse NAT</synopsis>
</configOption>
- <configOption name="identify_by" default="username,location">
+ <configOption name="identify_by" default="username,ip">
<synopsis>Way(s) for Endpoint to be identified</synopsis>
<description><para>
Endpoints and aors can be identified in multiple ways. Currently, the supported
options are <literal>username</literal>, which matches the endpoint or aor id based on
- the username and domain in the From header (or To header for aors), and
+ the username and domain in the From header (or To header for aors),
<literal>auth_username</literal>, which matches the endpoint or aor id based on the
- username and realm in the Authentication header. In all cases, if an exact match
- on both username and domain/realm fails, the match will be retried with just the username.
+ username and realm in the Authentication header, and <literal>ip</literal> which matches
+ an endpoint based on the source IP address. In the <literal>username</literal> and
+ <literal>auth_username</literal> cases, if an exact match on both username and
+ domain/realm fails, the match will be retried with just the username.
</para>
<note><para>
Identification by auth_username has some security considerations because an
@@ -292,14 +294,19 @@
configuration object.
</para></note>
<note><para>Endpoints can also be identified by IP address; however, that method
- of identification is not handled by this configuration option. See the documentation
- for the <literal>identify</literal> configuration section for more details on that
- method of endpoint identification. If this option is set and an <literal>identify</literal>
- configuration section exists for the endpoint, then the endpoint can be identified in
- multiple ways.</para></note>
+ of identification is not configured but simply allowed by this configuration option.
+ See the documentation for the <literal>identify</literal> configuration section for
+ more details on that method of endpoint identification.</para></note>
+ <note><para>
+ This option controls both how an endpoint is matched for incoming traffic and also how
+ an AoR is determined if a registration occurs. If <literal>ip</literal> is set alone
+ then incoming registration will not find an AoR and the registration attempt will fail.
+ If you want to allow incoming registrations to succeed you must set a second identify
+ method such as <literal>username</literal> in this case.</para></note>
<enumlist>
<enum name="username" />
<enum name="auth_username" />
+ <enum name="ip" />
</enumlist>
</description>
</configOption>
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 653cb98ac..6db5b3898 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -582,8 +582,10 @@ static int ident_handler(const struct aco_option *opt, struct ast_variable *var,
if (!strcasecmp(val, "username")) {
method = AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME;
- } else if (!strcasecmp(val, "auth_username")) {
+ } else if (!strcasecmp(val, "auth_username")) {
method = AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME;
+ } else if (!strcasecmp(val, "ip")) {
+ method = AST_SIP_ENDPOINT_IDENTIFY_BY_IP;
} else {
ast_log(LOG_ERROR, "Unrecognized identification method %s specified for endpoint %s\n",
val, ast_sorcery_object_get_id(endpoint));
@@ -628,6 +630,9 @@ static int ident_to_str(const void *obj, const intptr_t *args, char **buf)
case AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME :
method = "auth_username";
break;
+ case AST_SIP_ENDPOINT_IDENTIFY_BY_IP :
+ method = "ip";
+ break;
default:
continue;
}
@@ -1901,7 +1906,7 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aors", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, aors));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.address));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "bind_rtp_to_media_address", "no", OPT_BOOL_T, 1, STRFLDSET(struct ast_sip_endpoint, media.bind_rtp_to_media_address));
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username", ident_handler, ident_to_str, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username,ip", ident_handler, ident_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "direct_media", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.direct_media.enabled));
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_method", "invite", direct_media_method_handler, direct_media_method_to_str, NULL, 0, 0);
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "connected_line_method", "invite", connected_line_method_handler, connected_line_method_to_str, NULL, 0, 0);
diff --git a/res/res_pjsip_endpoint_identifier_ip.c b/res/res_pjsip_endpoint_identifier_ip.c
index 30bfc2618..8b92cef27 100644
--- a/res/res_pjsip_endpoint_identifier_ip.c
+++ b/res/res_pjsip_endpoint_identifier_ip.c
@@ -227,7 +227,14 @@ static struct ast_sip_endpoint *ip_identify(pjsip_rx_data *rdata)
}
endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", match->endpoint_name);
+
if (endpoint) {
+ if (!(endpoint->ident_method & AST_SIP_ENDPOINT_IDENTIFY_BY_IP)) {
+ ast_debug(3, "Endpoint '%s' found for '%s' but 'ip' method not supported'\n", match->endpoint_name,
+ ast_sockaddr_stringify(&addr));
+ ao2_cleanup(endpoint);
+ return NULL;
+ }
ast_debug(3, "Retrieved endpoint %s\n", ast_sorcery_object_get_id(endpoint));
} else {
ast_log(LOG_WARNING, "Identify section '%s' points to endpoint '%s' but endpoint could not be looked up\n",