summaryrefslogtreecommitdiff
path: root/res/res_pjsip/location.c
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2016-04-18 12:12:37 -0500
committerGeorge Joseph <gjoseph@digium.com>2016-04-19 10:47:18 -0500
commit0235a6653262fa3bebdaf1f89aac5e570442da5c (patch)
tree8d7eba962dffc6f63212281f1b358c5154fb8f61 /res/res_pjsip/location.c
parent64b03ec7029d6d313f7ebdb12603f11fa4df501d (diff)
PJSIP: Remove PJSIP parsing functions from uri length validation.
The PJSIP parsing functions provide a nice concise way to check the length of a hostname in a SIP URI. The problem is that in order to use those parsing functions, it's required to use them from a thread that has registered with PJLib. On startup, when parsing AOR configuration, the permanent URI handler may not be run from a PJLib-registered thread. Specifically, this could happen when Asterisk was started in daemon mode rather than console-mode. If PJProject were compiled with assertions enabled, then this would cause Asterisk to crash on startup. The solution presented here is to do our own parsing of the contact URI in order to ensure that the hostname in the URI is not too long. The parsing does not attempt to perform a full SIP URI parse/validation, since the hostname in the URI is what is important. ASTERISK-25928 #close Reported by Joshua Colp Change-Id: Ic3d6c20ff3502507c17244a8b7e2ca761dc7fb60
Diffstat (limited to 'res/res_pjsip/location.c')
-rw-r--r--res/res_pjsip/location.c56
1 files changed, 41 insertions, 15 deletions
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c
index 0a82f3a08..db4f9ac09 100644
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -412,38 +412,64 @@ static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, in
int ast_sip_validate_uri_length(const char *contact_uri)
{
- pjsip_uri *uri;
- pjsip_sip_uri *sip_uri;
- pj_pool_t *pool;
int max_length = pj_max_hostname - 1;
+ char *contact = ast_strdupa(contact_uri);
+ char *host;
+ char *at;
+ int theres_a_port = 0;
if (strlen(contact_uri) > pjsip_max_url_size - 1) {
return -1;
}
- if (!(pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "uri validation", 512, 512))) {
- ast_log(LOG_ERROR, "Unable to allocate pool for uri validation\n");
+ contact = ast_strip_quoted(contact, "<", ">");
+
+ if (!strncasecmp(contact, "sip:", 4)) {
+ host = contact + 4;
+ } else if (!strncasecmp(contact, "sips:", 5)) {
+ host = contact + 5;
+ } else {
+ /* Not a SIP URI */
return -1;
}
- if (!(uri = pjsip_parse_uri(pool, (char *)contact_uri, strlen(contact_uri), 0)) ||
- (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
- pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
- return -1;
+ at = strchr(contact, '@');
+ if (at) {
+ /* sip[s]:user@host */
+ host = at + 1;
+ }
+
+ if (host[0] == '[') {
+ /* Host is an IPv6 address. Just get up to the matching bracket */
+ char *close_bracket;
+
+ close_bracket = strchr(host, ']');
+ if (!close_bracket) {
+ return -1;
+ }
+ close_bracket++;
+ if (*close_bracket == ':') {
+ theres_a_port = 1;
+ }
+ *close_bracket = '\0';
+ } else {
+ /* uri parameters could contain ';' so trim them off first */
+ host = strsep(&host, ";?");
+ /* Host is FQDN or IPv4 address. Need to find closing delimiter */
+ if (strchr(host, ':')) {
+ theres_a_port = 1;
+ host = strsep(&host, ":");
+ }
}
- sip_uri = pjsip_uri_get_uri(uri);
- if (sip_uri->port == 0) {
+ if (!theres_a_port) {
max_length -= strlen("_sips.tcp.");
}
- if (sip_uri->host.slen > max_length) {
- pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
+ if (strlen(host) > max_length) {
return -1;
}
- pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
-
return 0;
}