The fix for CVE-2006-5445 in the 1.2 branch appears to be: http://svn.digium.com/view/asterisk/branches/1.2/channels/chan_sip.c?r1=45306&r2=45380
There's no corresponding fix in the 1.0 branch. Here's my attempt at backporting it. This is untested, since I don't run Asterisk myself. The initialisation of the SIP context (sip_pvt) is a bit different in 1.0 and I've copied what looks like the corresponding code from sip_alloc() into transmit_response_using_temp(). I added a call to build_contact() because __send_response() indirectly uses the our_contact member. In 1.0 there's no validate commands before the call find_call() and there's no sip_method array. Therefore I wrote string comparisons against all the commands that are allowed to create a new SIP context based on the flags in the 1.2 code, minus "PUBLISH" because that isn't supported at all (I'm not sure this is correct; we may end up sending the wrong error message). Ben. --- asterisk-1.0.7.dfsg.1/channels/chan_sip.c.orig 2006-11-18 20:25:43.000000000 +0000 +++ asterisk-1.0.7.dfsg.1/channels/chan_sip.c 2006-11-18 23:22:41.000000000 +0000 @@ -557,6 +557,7 @@ static struct ast_ha *localaddr; static struct ast_frame *sip_read(struct ast_channel *ast); +static int transmit_response_using_temp(char *callid, struct sockaddr_in *sin, int useglobal_nat, struct sip_request *req, char *msg); static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req); static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans); static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *rand, int reliable, char *header); @@ -2364,7 +2365,7 @@ char *callid; char tmp[256] = ""; char iabuf[INET_ADDRSTRLEN]; - char *cmd; + const char *cmd = req->rlPart1; char *tag = "", *c; callid = get_header(req, "Call-ID"); @@ -2378,11 +2379,6 @@ SIP implementations, and thus Asterisk does not enable this behavior by default. Short version: You'll need this option to support conferencing on the pingtel */ - strncpy(tmp, req->header[0], sizeof(tmp) - 1); - cmd = tmp; - c = strchr(tmp, ' '); - if (c) - *c = '\0'; if (!strcasecmp(cmd, "SIP/2.0")) strncpy(tmp, get_header(req, "To"), sizeof(tmp) - 1); else @@ -2414,9 +2410,19 @@ p = p->next; } ast_mutex_unlock(&iflock); - p = sip_alloc(callid, sin, 1); - if (p) - ast_mutex_lock(&p->lock); + + if (strcasecmp(cmd, "REGISTER") + && strcasecmp(cmd, "OPTIONS") + && strcasecmp(cmd, "INVITE") + && strcasecmp(cmd, "SUBSCRIBE") + && strcasecmp(cmd, "MESSAGE")) { + if (strcasecmp(cmd, "RESPONSE")) + transmit_response_using_temp(callid, sin, 1, req, "481 Call leg/transaction does not exist"); + } else { + p = sip_alloc(callid, sin, 1); + if (p) + ast_mutex_lock(&p->lock); + } return p; } @@ -3218,6 +3224,45 @@ return send_response(p, &resp, reliable, seqno); } +/*--- transmit_response_using_temp: Transmit response, no retransmits, using temporary pvt */ +static int transmit_response_using_temp(char *callid, struct sockaddr_in *sin, int useglobal_nat, struct sip_request *req, char *msg) +{ + struct sip_pvt *p = alloca(sizeof(*p)); + char iabuf[INET_ADDRSTRLEN]; + + memset(p, 0, sizeof(*p)); + + if (sin) { + memcpy(&p->sa, sin, sizeof(p->sa)); + if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip)) + memcpy(&p->ourip, &__ourip, sizeof(p->ourip)); + } else + memcpy(&p->ourip, &__ourip, sizeof(p->ourip)); + p->branch = rand(); + p->tag = rand(); + p->ocseq = 101; + + if (useglobal_nat && sin) { + /* Setup NAT structure according to global settings if we have an address */ + p->nat = global_nat; + memcpy(&p->recv, sin, sizeof(p->recv)); + } + + strncpy(p->fromdomain, default_fromdomain, sizeof(p->fromdomain) - 1); + /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ + if (p->nat != SIP_NAT_NEVER) + snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch); + else + snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch); + strncpy(p->callid, callid, sizeof(p->callid) - 1); + + build_contact(p); + + __transmit_response(p, msg, req, 0); + + return 0; +} + /*--- transmit_response: Transmit response, no retransmits */ static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req) { -- END -- -- Ben Hutchings Reality is just a crutch for people who can't handle science fiction.
signature.asc
Description: This is a digitally signed message part