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.

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to