From 1296b9dcbd3c1bfbf0aa2f80754873cdad2a29f0 Mon Sep 17 00:00:00 2001 From: jpeeler Date: Mon, 6 Dec 2010 21:57:15 +0000 Subject: Improve handling of REGISTER requests with multiple contact headers. The changes here attempt to more strictly follow RFC 3261 section 10.3. Basically the following will now cause a 400 Bad Response to be returned, if: - multiple Contact headers are present with one set to expire all bindings ("*") - wildcard parameter is specified for Contact without Expires header or Expires header is not set to zero. ABE-2442 ABE-2443 git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@297603 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'channels') diff --git a/channels/chan_sip.c b/channels/chan_sip.c index f42a7cc81..bdc375ce4 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -8812,8 +8812,12 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st struct hostent *hp; struct ast_hostent ahp; struct sockaddr_in oldsin, testsin; + char *firstcuri = NULL; + int start = 0; + int wildcard_found = 0; + int single_binding_found; - ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact)); + ast_copy_string(contact, __get_header(req, "Contact", &start), sizeof(contact)); if (ast_strlen_zero(expires)) { /* No expires header */ expires = strcasestr(contact, ";expires="); @@ -8828,11 +8832,31 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st } } - /* Look for brackets */ - curi = contact; - if (strchr(contact, '<') == NULL) /* No <, check for ; and strip it */ - strsep(&curi, ";"); /* This is Header options, not URI options */ - curi = get_in_brackets(contact); + do { + /* Look for brackets */ + curi = contact; + if (strchr(contact, '<') == NULL) /* No <, check for ; and strip it */ + strsep(&curi, ";"); /* This is Header options, not URI options */ + curi = get_in_brackets(contact); + if (!firstcuri) { + firstcuri = ast_strdupa(curi); + } + + if (!strcasecmp(curi, "*")) { + wildcard_found = 1; + } else { + single_binding_found = 1; + } + + if (wildcard_found && (ast_strlen_zero(expires) || expiry != 0 || single_binding_found)) { + /* Contact header parameter "*" detected, so punt if: Expires header is missing, + * Expires value is not zero, or another Contact header is present. */ + return PARSE_REGISTER_FAILED; + } + + ast_copy_string(contact, __get_header(req, "Contact", &start), sizeof(contact)); + } while (!ast_strlen_zero(contact)); + curi = firstcuri; /* if they did not specify Contact: or Expires:, they are querying what we currently have stored as their contact address, so return -- cgit v1.2.3