diff options
author | zuul <zuul@gerrit.asterisk.org> | 2016-06-16 17:59:32 -0500 |
---|---|---|
committer | Gerrit Code Review <gerrit2@gerrit.digium.api> | 2016-06-16 17:59:32 -0500 |
commit | 947f76a971ee54bd263ca5b50ac9446618ae06b1 (patch) | |
tree | 8145f872419f47d885122435fc9793b4e3a081fa | |
parent | 3c80f84cd03d3857e7c90b280c5101d60767b277 (diff) | |
parent | 80ff7912a18619f9549d2090be2cf4c9dbeea356 (diff) |
Merge "chan_sip: bigger buffers for headers, better failure mode"
-rw-r--r-- | channels/chan_sip.c | 77 |
1 files changed, 46 insertions, 31 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 8f547bf1a..a317879e4 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -14154,9 +14154,10 @@ static void build_contact(struct sip_pvt *p, struct sip_request *req, int incomi /*! \brief Initiate new SIP request to peer/user */ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, const char * const explicit_uri) { - struct ast_str *invite = ast_str_alloca(256); - char from[256]; - char to[256]; +#define SIPHEADER 256 + struct ast_str *invite = ast_str_create(SIPHEADER); + struct ast_str *from = ast_str_create(SIPHEADER); + struct ast_str *to = ast_str_create(SIPHEADER); char tmp_n[SIPBUFSIZE/2]; /* build a local copy of 'n' if needed */ char tmp_l[SIPBUFSIZE/2]; /* build a local copy of 'l' if needed */ const char *l = NULL; /* XXX what is this, exactly ? */ @@ -14258,34 +14259,40 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho ourport = (p->fromdomainport && (p->fromdomainport != STANDARD_SIP_PORT)) ? p->fromdomainport : ast_sockaddr_port(&p->ourip); if (!sip_standard_port(p->socket.type, ourport)) { - ret = snprintf(from, sizeof(from), "<sip:%s@%s:%d>;tag=%s", tmp_l, d, ourport, p->tag); + ret = ast_str_set(&from, 0, "<sip:%s@%s:%d>;tag=%s", tmp_l, d, ourport, p->tag); } else { - ret = snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%s", tmp_l, d, p->tag); + ret = ast_str_set(&from, 0, "<sip:%s@%s>;tag=%s", tmp_l, d, p->tag); } - if (ret < 0 || ret >= sizeof(from)) { /* a return value of size or more means that the output was truncated */ + if (ret == AST_DYNSTR_BUILD_FAILED) { /* We don't have an escape path from here... */ ast_log(LOG_ERROR, "The From header was truncated in call '%s'. This call setup will fail.\n", p->callid); + /* Make sure that the field contains something non-broken. + See https://issues.asterisk.org/jira/browse/ASTERISK-26069 + */ + ast_str_set(&from, 3, "<>"); + } /* If a caller id name was specified, prefix a display name, if there is enough room. */ if (cid_has_name || !cid_has_num) { - size_t written = strlen(from); - ssize_t left = sizeof(from) - written - 4; /* '"" \0' */ - if (left > 0) { - size_t name_len; - if (sip_cfg.pedanticsipchecking) { - ast_escape_quoted(n, tmp_n, MIN(left + 1, sizeof(tmp_n))); - n = tmp_n; - } - name_len = strlen(n); - if (left < name_len) { - name_len = left; - } - memmove(from + name_len + 3, from, written + 1); - from[0] = '"'; - memcpy(from + 1, n, name_len); - from[name_len + 1] = '"'; - from[name_len + 2] = ' '; + size_t written = ast_str_strlen(from); + size_t name_len; + if (sip_cfg.pedanticsipchecking) { + ast_escape_quoted(n, tmp_n, sizeof(tmp_n)); + n = tmp_n; + } + name_len = strlen(n); + ret = ast_str_make_space(&from, name_len + written + 4); + + if (ret == 0) { + /* needed again, as ast_str_make_space coud've changed the pointer */ + char *from_buf = ast_str_buffer(from); + + memmove(from_buf + name_len + 3, from_buf, written + 1); + from_buf[0] = '"'; + memcpy(from_buf + 1, n, name_len); + from_buf[name_len + 1] = '"'; + from_buf[name_len + 2] = ' '; } } @@ -14328,24 +14335,28 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho /*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */ if (!strchr(p->todnid, '@')) { /* We have no domain in the dnid */ - ret = snprintf(to, sizeof(to), "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); + ret = ast_str_set(&to, 0, "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); } else { - ret = snprintf(to, sizeof(to), "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); + ret = ast_str_set(&to, 0, "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); } } else { if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) { /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */ - ret = snprintf(to, sizeof(to), "<%s%s>;tag=%s", (strncasecmp(p->uri, "sip:", 4) ? "sip:" : ""), p->uri, p->theirtag); + ret = ast_str_set(&to, 0, "<%s%s>;tag=%s", (strncasecmp(p->uri, "sip:", 4) ? "sip:" : ""), p->uri, p->theirtag); } else if (p->options && p->options->vxml_url) { /* If there is a VXML URL append it to the SIP URL */ - ret = snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url); + ret = ast_str_set(&to, 0, "<%s>;%s", p->uri, p->options->vxml_url); } else { - ret = snprintf(to, sizeof(to), "<%s>", p->uri); + ret = ast_str_set(&to, 0, "<%s>", p->uri); } } - if (ret < 0 || ret >= sizeof(to)) { /* a return value of size or more means that the output was truncated */ + if (ret == AST_DYNSTR_BUILD_FAILED) { /* We don't have an escape path from here... */ ast_log(LOG_ERROR, "The To header was truncated in call '%s'. This call setup will fail.\n", p->callid); + /* Make sure that the field contains something non-broken. + See https://issues.asterisk.org/jira/browse/ASTERISK-26069 + */ + ast_str_set(&to, 3, "<>"); } init_req(req, sipmethod, p->uri); @@ -14360,8 +14371,8 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho */ add_route(req, &p->route, 0); - add_header(req, "From", from); - add_header(req, "To", to); + add_header(req, "From", ast_str_buffer(from)); + add_header(req, "To", ast_str_buffer(to)); ast_string_field_set(p, exten, l); build_contact(p, req, 0); add_header(req, "Contact", p->our_contact); @@ -14370,6 +14381,10 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho if (!ast_strlen_zero(global_useragent)) { add_header(req, "User-Agent", global_useragent); } + + ast_free(from); + ast_free(to); + ast_free(invite); } /*! \brief Add "Diversion" header to outgoing message |