[Pkg-voip-commits] r7883 - in /asterisk/branches/lenny-security/debian: asterisk.examples changelog patches/AST-2009-001 patches/AST-2009-002 patches/AST-2009-003 patches/AST-2009-008 patches/AST-2009-010 patches/r132790 patches/r171264 patches/series

paravoid at alioth.debian.org paravoid at alioth.debian.org
Sun Dec 13 23:17:34 UTC 2009


Author: paravoid
Date: Sun Dec 13 23:17:34 2009
New Revision: 7883

URL: http://svn.debian.org/wsvn/pkg-voip/?sc=1&rev=7883
Log:
Import security-related changes from the lenny branch

Added:
    asterisk/branches/lenny-security/debian/patches/AST-2009-001
    asterisk/branches/lenny-security/debian/patches/AST-2009-002
    asterisk/branches/lenny-security/debian/patches/AST-2009-003
    asterisk/branches/lenny-security/debian/patches/AST-2009-008
    asterisk/branches/lenny-security/debian/patches/AST-2009-010
    asterisk/branches/lenny-security/debian/patches/r132790
    asterisk/branches/lenny-security/debian/patches/r171264
Modified:
    asterisk/branches/lenny-security/debian/asterisk.examples
    asterisk/branches/lenny-security/debian/changelog
    asterisk/branches/lenny-security/debian/patches/series

Modified: asterisk/branches/lenny-security/debian/asterisk.examples
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/asterisk.examples?rev=7883&op=diff
==============================================================================
--- asterisk/branches/lenny-security/debian/asterisk.examples (original)
+++ asterisk/branches/lenny-security/debian/asterisk.examples Sun Dec 13 23:17:34 2009
@@ -1,3 +1,2 @@
 sample.call
-static-http
 contrib/scripts/vmail.cgi

Modified: asterisk/branches/lenny-security/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/changelog?rev=7883&op=diff
==============================================================================
--- asterisk/branches/lenny-security/debian/changelog (original)
+++ asterisk/branches/lenny-security/debian/changelog Sun Dec 13 23:17:34 2009
@@ -1,3 +1,20 @@
+asterisk (1:1.4.21.2~dfsg-3+lenny1) stable-security; urgency=high
+
+  * Multiple security fixes:
+    - "Information leak in IAX2 authentication", AST-2009-001, CVE-2009-0041.
+    - "Remote Crash Vulnerability in SIP channel driver", AST-2009-002.
+    - "SIP responses expose valid usernames", AST-2009-003, CVE-2008-3903.
+      (Closes: #522528)
+    - "SIP responses expose valid usernames", AST-2009-008, CVE-2009-3727.
+      (Closes: #554487)
+    - Stop shipping old static-http code in examples. Among other things, it
+      includes a vulnerable version of the prototype Javascript library.
+      AST-2009-009, CVE-2008-7220. (Closes: #554486)
+    - "RTP Remote Crash Vulnerability", AST-2009-010, CVE-2009-4055.
+      (Closes: #559103)
+
+ -- Faidon Liambotis <paravoid at debian.org>  Mon, 14 Dec 2009 01:11:44 +0200
+
 asterisk (1:1.4.21.2~dfsg-3) unstable; urgency=medium
 
   [ Faidon Liambotis ]

Added: asterisk/branches/lenny-security/debian/patches/AST-2009-001
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/patches/AST-2009-001?rev=7883&op=file
==============================================================================
--- asterisk/branches/lenny-security/debian/patches/AST-2009-001 (added)
+++ asterisk/branches/lenny-security/debian/patches/AST-2009-001 Sun Dec 13 23:17:34 2009
@@ -1,0 +1,256 @@
+Index: channels/chan_iax2.c
+===================================================================
+--- a/channels/chan_iax2.c	(revision 166591)
++++ b/channels/chan_iax2.c	(working copy)
+@@ -155,6 +155,7 @@
+ static int authdebug = 1;
+ static int autokill = 0;
+ static int iaxcompat = 0;
++static int last_authmethod = 0;
+ 
+ static int iaxdefaultdpcache=10 * 60;	/* Cache dialplan entries for 10 minutes by default */
+ 
+@@ -228,10 +229,9 @@
+ static ast_cond_t sched_cond;
+ 
+ enum {
+-	IAX_STATE_STARTED = 		(1 << 0),
+-	IAX_STATE_AUTHENTICATED = 	(1 << 1),
+-	IAX_STATE_TBD = 		(1 << 2),
+-	IAX_STATE_UNCHANGED = 		(1 << 3),
++	IAX_STATE_STARTED =			(1 << 0),
++	IAX_STATE_AUTHENTICATED =	(1 << 1),
++	IAX_STATE_TBD =				(1 << 2),
+ } iax2_state;
+ 
+ struct iax2_context {
+@@ -512,7 +512,7 @@
+ 	/*! The jitterbuffer */
+         jitterbuf *jb;
+ 	/*! active jb read scheduler id */
+-        int jbid;                       
++        int jbid;
+ 	/*! LAG */
+ 	int lag;
+ 	/*! Error, as discovered by the manager */
+@@ -568,7 +568,8 @@
+ 		AST_STRING_FIELD(mohinterpret);
+ 		AST_STRING_FIELD(mohsuggest);
+ 	);
+-	
++	/*! AUTHREJ all AUTHREP frames */
++	int authrej;
+ 	/*! permitted authentication methods */
+ 	int authmethods;
+ 	/*! permitted encryption methods */
+@@ -5400,6 +5401,18 @@
+ 			ast_string_field_set(iaxs[callno], secret, user->secret);
+ 		res = 0;
+ 		user = user_unref(user);
++	} else {
++		 /* user was not found, but we should still fake an AUTHREQ.
++		  * Set authmethods to the last known authmethod used by the system
++		  * Set a fake secret, it's not looked at, just required to attempt authentication.
++		  * Set authrej so the AUTHREP is rejected without even looking at its contents */
++		iaxs[callno]->authmethods = last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
++		ast_string_field_set(iaxs[callno], secret, "badsecret");
++		iaxs[callno]->authrej = 1;
++		if (!ast_strlen_zero(iaxs[callno]->username)) {
++			/* only send the AUTHREQ if a username was specified. */
++			res = 0;
++		}
+ 	}
+ 	ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK);	
+ 	return res;
+@@ -5506,6 +5519,9 @@
+ 		.name = p->username,	
+ 	};
+ 
++	if (p->authrej) {
++		return res;
++	}
+ 	user = ao2_find(users, &tmp_user, OBJ_POINTER);
+ 	if (user) {
+ 		if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
+@@ -5583,7 +5599,7 @@
+ 	int expire = 0;
+ 	int res = -1;
+ 
+-	ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED);
++	ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
+ 	/* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
+ 	if (ies->username)
+ 		ast_copy_string(peer, ies->username, sizeof(peer));
+@@ -5606,8 +5622,29 @@
+ 	p = find_peer(peer, 1);
+ 	ast_mutex_lock(&iaxsl[callno]);
+ 	if (!p || !iaxs[callno]) {
++		if (iaxs[callno]) {
++			int plaintext = ((last_authmethod & IAX_AUTH_PLAINTEXT) | (iaxs[callno]->authmethods & IAX_AUTH_PLAINTEXT));
++
++			ast_string_field_set(iaxs[callno], secret, "badsecret");
++
++			/* An AUTHREQ must be sent in response to a REGREQ of an invalid peer unless
++			 * 1. A challenge already exists indicating a AUTHREQ was already sent out.
++			 * 2. A plaintext secret is present in ie as result of a previous AUTHREQ requesting it.
++			 * 3. A plaintext secret is present in the ie and the last_authmethod used by a peer happened
++			 *    to be plaintext, indicating it is an authmethod used by other peers on the system. 
++			 *
++			 * If none of these cases exist, res will be returned as 0 without authentication indicating
++			 * an AUTHREQ needs to be sent out. */
++
++			if (ast_strlen_zero(iaxs[callno]->challenge) &&
++				!(!ast_strlen_zero(secret) && plaintext)) {
++				/* by setting res to 0, an REGAUTH will be sent */
++				res = 0;
++			}
++		}
+ 		if (authdebug && !p)
+ 			ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
++
+ 		goto return_unref;
+ 	}
+ 
+@@ -5622,8 +5659,6 @@
+ 			ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
+ 		goto return_unref;
+ 	}
+-	if (!inaddrcmp(&p->addr, sin))
+-		ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED);
+ 	ast_string_field_set(iaxs[callno], secret, p->secret);
+ 	ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
+ 	/* Check secret against what we have on file */
+@@ -5639,7 +5674,7 @@
+ 				if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
+ 					ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
+ 					break;
+-				} else if (!key) 
++				} else if (!key)
+ 					ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
+ 				keyn = strsep(&stringp, ":");
+ 			}
+@@ -5657,7 +5692,7 @@
+ 		struct MD5Context md5;
+ 		unsigned char digest[16];
+ 		char *tmppw, *stringp;
+-		
++
+ 		tmppw = ast_strdupa(p->secret);
+ 		stringp = tmppw;
+ 		while((tmppw = strsep(&stringp, ";"))) {
+@@ -5667,7 +5702,7 @@
+ 			MD5Final(digest, &md5);
+ 			for (x=0;x<16;x++)
+ 				sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
+-			if (!strcasecmp(requeststr, md5secret)) 
++			if (!strcasecmp(requeststr, md5secret))
+ 				break;
+ 		}
+ 		if (tmppw) {
+@@ -5685,24 +5720,25 @@
+ 			goto return_unref;
+ 		} else
+ 			ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
+-	} else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) {
+-		if (authdebug)
+-			ast_log(LOG_NOTICE, "Inappropriate authentication received\n");
++	} else if (!ast_strlen_zero(iaxs[callno]->challenge) && ast_strlen_zero(md5secret) && ast_strlen_zero(rsasecret)) {
++		/* if challenge has been sent, but no challenge response if given, reject. */
+ 		goto return_unref;
+ 	}
+-	ast_string_field_set(iaxs[callno], peer, peer);
+-	/* Choose lowest expiry number */
+-	if (expire && (expire < iaxs[callno]->expiry)) 
+-		iaxs[callno]->expiry = expire;
+-
+ 	ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
+ 
++	/* either Authentication has taken place, or a REGAUTH must be sent before verifying registration */
+ 	res = 0;
++return_unref:
++	if (iaxs[callno]) {
++		ast_string_field_set(iaxs[callno], peer, peer);
++	}
++	/* Choose lowest expiry number */
++	if (expire && (expire < iaxs[callno]->expiry)) {
++		iaxs[callno]->expiry = expire;
++	}
+ 
+-return_unref:
+ 	if (p)
+ 		peer_unref(p);
+-
+ 	return res;
+ }
+ 
+@@ -6375,24 +6411,33 @@
+ 	struct iax2_peer *p;
+ 	char challenge[10];
+ 	const char *peer_name;
+-	int res = -1;
++	int sentauthmethod;
+ 
+ 	peer_name = ast_strdupa(iaxs[callno]->peer);
+ 
+ 	/* SLD: third call to find_peer in registration */
+ 	ast_mutex_unlock(&iaxsl[callno]);
+-	p = find_peer(peer_name, 1);
++	if ((p = find_peer(peer_name, 1))) {
++		last_authmethod = p->authmethods;
++	}
++
+ 	ast_mutex_lock(&iaxsl[callno]);
+ 	if (!iaxs[callno])
+ 		goto return_unref;
++
++	memset(&ied, 0, sizeof(ied));
++	/* The selection of which delayed reject is sent may leak information,
++	 * if it sets a static response.  For example, if a host is known to only
++	 * use MD5 authentication, then an RSA response would indicate that the
++	 * peer does not exist, and vice-versa.
++	 * Therefore, we use whatever the last peer used (which may vary over the
++	 * course of a server, which should leak minimal information). */
++	sentauthmethod = p ? p->authmethods : last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
+ 	if (!p) {
+-		ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
+-		goto return_unref;
++		iaxs[callno]->authmethods = sentauthmethod;
+ 	}
+-	
+-	memset(&ied, 0, sizeof(ied));
+-	iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
+-	if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
++	iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, sentauthmethod);
++	if (sentauthmethod & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
+ 		/* Build the challenge */
+ 		snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
+ 		ast_string_field_set(iaxs[callno], challenge, challenge);
+@@ -6400,12 +6445,12 @@
+ 	}
+ 	iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
+ 
+-	res = 0;
+-
+ return_unref:
+-	peer_unref(p);
++	if (p) {
++		peer_unref(p);
++	}
+ 
+-	return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
++	return iaxs[callno] ? send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1) : -1;
+ }
+ 
+ static int registry_rerequest(struct iax_ies *ies, int callno, struct sockaddr_in *sin)
+@@ -8347,8 +8392,9 @@
+ 					ast_mutex_unlock(&iaxsl[fr->callno]);
+ 					return 1;
+ 				}
+-				if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || 
+-						ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED)) {
++				if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) ||
++						ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED)) {
++
+ 					if (f.subclass == IAX_COMMAND_REGREL)
+ 						memset(&sin, 0, sizeof(sin));
+ 					if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh))

Added: asterisk/branches/lenny-security/debian/patches/AST-2009-002
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/patches/AST-2009-002?rev=7883&op=file
==============================================================================
--- asterisk/branches/lenny-security/debian/patches/AST-2009-002 (added)
+++ asterisk/branches/lenny-security/debian/patches/AST-2009-002 Sun Dec 13 23:17:34 2009
@@ -1,0 +1,70 @@
+Index: channels/chan_sip.c
+===================================================================
+--- a/channels/chan_sip.c	(revision 174081)
++++ b/channels/chan_sip.c	(revision 174082)
+@@ -14012,19 +14012,32 @@
+  */
+ static int sip_uri_params_cmp(const char *input1, const char *input2) 
+ {
+-	char *params1 = ast_strdupa(input1);
+-	char *params2 = ast_strdupa(input2);
++	char *params1 = NULL;
++	char *params2 = NULL;
+ 	char *pos1;
+ 	char *pos2;
++	int zerolength1 = 0;
++	int zerolength2 = 0;
+ 	int maddrmatch = 0;
+ 	int ttlmatch = 0;
+ 	int usermatch = 0;
+ 	int methodmatch = 0;
+ 
++	if (ast_strlen_zero(input1)) {
++		zerolength1 = 1;
++	} else {
++		params1 = ast_strdupa(input1);
++	}
++	if (ast_strlen_zero(input2)) {
++		zerolength2 = 1;
++	} else {
++		params2 = ast_strdupa(input2);
++	}
++
+ 	/*Quick optimization. If both params are zero-length, then
+ 	 * they match
+ 	 */
+-	if (ast_strlen_zero(params1) && ast_strlen_zero(params2)) {
++	if (zerolength1 && zerolength2) {
+ 		return 0;
+ 	}
+ 
+@@ -14139,13 +14152,25 @@
+  */
+ static int sip_uri_headers_cmp(const char *input1, const char *input2)
+ {
+-	char *headers1 = ast_strdupa(input1);
+-	char *headers2 = ast_strdupa(input2);
+-	int zerolength1 = ast_strlen_zero(headers1);
+-	int zerolength2 = ast_strlen_zero(headers2);
++	char *headers1 = NULL;
++	char *headers2 = NULL;
++	int zerolength1 = 0;
++	int zerolength2 = 0;
+ 	int different = 0;
+ 	char *header1;
+ 
++	if (ast_strlen_zero(input1)) {
++		zerolength1 = 1;
++	} else {
++		headers1 = ast_strdupa(input1);
++	}
++	
++	if (ast_strlen_zero(input2)) {
++		zerolength2 = 1;
++	} else {
++		headers2 = ast_strdupa(input2);
++	}
++
+ 	if ((zerolength1 && !zerolength2) ||
+ 			(zerolength2 && !zerolength1))
+ 		return 1;

Added: asterisk/branches/lenny-security/debian/patches/AST-2009-003
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/patches/AST-2009-003?rev=7883&op=file
==============================================================================
--- asterisk/branches/lenny-security/debian/patches/AST-2009-003 (added)
+++ asterisk/branches/lenny-security/debian/patches/AST-2009-003 Sun Dec 13 23:17:34 2009
@@ -1,0 +1,164 @@
+Index: channels/chan_sip.c
+===================================================================
+--- a/channels/chan_sip.c	(revision 183280)
++++ b/channels/chan_sip.c	(working copy)
+@@ -1266,7 +1266,7 @@
+ static int transmit_response_with_unsupported(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *unsupported);
+ static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale);
+ static int transmit_response_with_allow(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
+-static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable);
++static void transmit_fake_auth_response(struct sip_pvt *p, int sipmethod, struct sip_request *req, enum xmittype reliable);
+ static int transmit_request(struct sip_pvt *p, int sipmethod, int inc, enum xmittype reliable, int newbranch);
+ static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch);
+ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init);
+@@ -8873,10 +8873,96 @@
+ /*! \brief Send a fake 401 Unauthorized response when the administrator
+   wants to hide the names of local users/peers from fishers
+  */
+-static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable)
++static void transmit_fake_auth_response(struct sip_pvt *p, int sipmethod, struct sip_request *req, enum xmittype reliable)
+ {
+-	ast_string_field_build(p, randdata, "%08lx", ast_random());	/* Create nonce for challenge */
+-	transmit_response_with_auth(p, "401 Unauthorized", req, p->randdata, reliable, "WWW-Authenticate", 0);
++	/* We have to emulate EXACTLY what we'd get with a good peer
++	 * and a bad password, or else we leak information. */
++	const char *response = "407 Proxy Authentication Required";
++	const char *reqheader = "Proxy-Authorization";
++	const char *respheader = "Proxy-Authenticate";
++	const char *authtoken;
++	struct ast_dynamic_str *buf;
++	char *c;
++
++	/* table of recognised keywords, and their value in the digest */
++	enum keys { K_NONCE, K_LAST };
++	struct x {
++		const char *key;
++		const char *s;
++	} *i, keys[] = {
++		[K_NONCE] = { "nonce=", "" },
++		[K_LAST] = { NULL, NULL}
++	};
++
++	if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) {
++		response = "401 Unauthorized";
++		reqheader = "Authorization";
++		respheader = "WWW-Authenticate";
++	}
++	authtoken = get_header(req, reqheader);
++	if (ast_test_flag(req, SIP_PKT_IGNORE) && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) {
++		/* This is a retransmitted invite/register/etc, don't reconstruct authentication
++		 * information */
++		transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0);
++		/* Schedule auto destroy in 32 seconds (according to RFC 3261) */
++		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
++		return;
++	} else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) {
++		/* We have no auth, so issue challenge and request authentication */
++		ast_string_field_build(p, randdata, "%08lx", ast_random());	/* Create nonce for challenge */
++		transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0);
++		/* Schedule auto destroy in 32 seconds */
++		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
++		return;
++	}
++
++	if (!(buf = ast_dynamic_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) {
++		transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
++		return;
++	}
++
++	/* Make a copy of the response and parse it */
++	if (ast_dynamic_str_thread_set(&buf, 0, &check_auth_buf, "%s", authtoken) == AST_DYNSTR_BUILD_FAILED) {
++		transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
++		return;
++	}
++
++	c = buf->str;
++
++	while (c && *(c = ast_skip_blanks(c))) { /* lookup for keys */
++		for (i = keys; i->key != NULL; i++) {
++			const char *separator = ",";	/* default */
++
++			if (strncasecmp(c, i->key, strlen(i->key)) != 0) {
++				continue;
++			}
++			/* Found. Skip keyword, take text in quotes or up to the separator. */
++			c += strlen(i->key);
++			if (*c == '"') { /* in quotes. Skip first and look for last */
++				c++;
++				separator = "\"";
++			}
++			i->s = c;
++			strsep(&c, separator);
++			break;
++		}
++		if (i->key == NULL) { /* not found, jump after space or comma */
++			strsep(&c, " ,");
++		}
++	}
++
++	/* Verify nonce from request matches our nonce.  If not, send 401 with new nonce */
++	if (strcasecmp(p->randdata, keys[K_NONCE].s)) {
++		if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
++			ast_string_field_build(p, randdata, "%08lx", ast_random());
++		}
++		transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, FALSE);
++
++		/* Schedule auto destroy in 32 seconds */
++		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
++	} else {
++		transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
++	}
+ }
+ 
+ /*! \brief Verify registration of user 
+@@ -9010,6 +9096,14 @@
+ 			}
+ 		}
+ 	}
++	if (!peer && global_alwaysauthreject) {
++		/* If we found a peer, we transmit a 100 Trying.  Therefore, if we're
++		 * trying to avoid leaking information, we MUST also transmit the same
++		 * response when we DON'T find a peer. */
++		transmit_response(p, "100 Trying", req);
++		/* Insert a fake delay between the 100 and the subsequent failure. */
++		sched_yield();
++	}
+ 	if (!res) {
+ 		ast_device_state_changed("SIP/%s", peer->name);
+ 	}
+@@ -9020,7 +9114,7 @@
+ 			transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
+ 			break;
+ 		case AUTH_USERNAME_MISMATCH:
+-			/* Username and digest username does not match. 
++			/* Username and digest username does not match.
+ 			   Asterisk uses the From: username for authentication. We need the
+ 			   users to use the same authentication user name until we support
+ 			   proper authentication by digest auth name */
+@@ -9030,7 +9124,7 @@
+ 		case AUTH_PEER_NOT_DYNAMIC:
+ 		case AUTH_ACL_FAILED:
+ 			if (global_alwaysauthreject) {
+-				transmit_fake_auth_response(p, &p->initreq, XMIT_UNRELIABLE);
++				transmit_fake_auth_response(p, SIP_REGISTER, &p->initreq, XMIT_UNRELIABLE);
+ 			} else {
+ 				/* URI not found */
+ 				if (res == AUTH_PEER_NOT_DYNAMIC)
+@@ -14557,7 +14651,7 @@
+ 		if (res < 0) { /* Something failed in authentication */
+ 			if (res == AUTH_FAKE_AUTH) {
+ 				ast_log(LOG_NOTICE, "Sending fake auth rejection for user %s\n", get_header(req, "From"));
+-				transmit_fake_auth_response(p, req, XMIT_RELIABLE);
++				transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE);
+ 			} else {
+   				ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From"));
+ 				transmit_response_reliable(p, "403 Forbidden", req);
+@@ -15594,7 +15688,7 @@
+ 	if (res < 0) {
+ 		if (res == AUTH_FAKE_AUTH) {
+ 			ast_log(LOG_NOTICE, "Sending fake auth rejection for user %s\n", get_header(req, "From"));
+-			transmit_fake_auth_response(p, req, XMIT_UNRELIABLE);
++			transmit_fake_auth_response(p, SIP_SUBSCRIBE, req, XMIT_UNRELIABLE);
+ 		} else {
+ 			ast_log(LOG_NOTICE, "Failed to authenticate user %s for SUBSCRIBE\n", get_header(req, "From"));
+ 			transmit_response_reliable(p, "403 Forbidden", req);

Added: asterisk/branches/lenny-security/debian/patches/AST-2009-008
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/patches/AST-2009-008?rev=7883&op=file
==============================================================================
--- asterisk/branches/lenny-security/debian/patches/AST-2009-008 (added)
+++ asterisk/branches/lenny-security/debian/patches/AST-2009-008 Sun Dec 13 23:17:34 2009
@@ -1,0 +1,13 @@
+Index: channels/chan_sip.c
+===================================================================
+--- a/channels/chan_sip.c	(revision 226137)
++++ b/channels/chan_sip.c	(working copy)
+@@ -9346,8 +9346,6 @@
+ 			   Asterisk uses the From: username for authentication. We need the
+ 			   users to use the same authentication user name until we support
+ 			   proper authentication by digest auth name */
+-			transmit_response(p, "403 Authentication user name does not match account name", &p->initreq);
+-			break;
+ 		case AUTH_NOT_FOUND:
+ 		case AUTH_PEER_NOT_DYNAMIC:
+ 		case AUTH_ACL_FAILED:

Added: asterisk/branches/lenny-security/debian/patches/AST-2009-010
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/patches/AST-2009-010?rev=7883&op=file
==============================================================================
--- asterisk/branches/lenny-security/debian/patches/AST-2009-010 (added)
+++ asterisk/branches/lenny-security/debian/patches/AST-2009-010 Sun Dec 13 23:17:34 2009
@@ -1,0 +1,20 @@
+Source: http://svn.digium.com/svn/asterisk/branches/1.4@231441
+Debian Issue: #559103
+CVE: CVE-2009-4055
+Date: Mon Nov 30 17:14:08 2009 +0000
+Upstream Issue: https://issues.asterisk.org/view.php?id=16242
+
+fixes crash caused by RTP comfort noise payload greater than 24 bytes
+
+diff --git a/main/rtp.c b/main/rtp.c
+index 12e3638..a124bb7 100644
+--- a/main/rtp.c
++++ b/main/rtp.c
+@@ -848,7 +848,6 @@ static struct ast_frame *process_rfc3389(struct ast_rtp *rtp, unsigned char *dat
+ 	}
+ 	rtp->f.frametype = AST_FRAME_CNG;
+ 	rtp->f.subclass = data[0] & 0x7f;
+-	rtp->f.datalen = len - 1;
+ 	rtp->f.samples = 0;
+ 	rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
+ 	f = &rtp->f;

Added: asterisk/branches/lenny-security/debian/patches/r132790
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/patches/r132790?rev=7883&op=file
==============================================================================
--- asterisk/branches/lenny-security/debian/patches/r132790 (added)
+++ asterisk/branches/lenny-security/debian/patches/r132790 Sun Dec 13 23:17:34 2009
@@ -1,0 +1,360 @@
+Upstream r132790
+
+Allow Spiraled INVITEs to work correctly within Asterisk.
+
+Prior to this change, a spiraled INVITE would cause a 482
+Loop Detected to be sent to the caller. With this change,
+if a potential loop is detected, the Request-URI is inspected
+to see if it has changed from what was originally received. If
+pedantic mode is on, then this inspection is fully RFC 3261
+compliant. If pedantic mode is not on, then a string comparison
+is used to test the equality of the two R-URIs.
+
+This has been tested by using OpenSER to rewrite the R-URI
+and send the INVITE back to Asterisk.
+
+(closes issue #7403)
+
+--- a/channels/chan_sip.c	(revision 132789)
++++ b/channels/chan_sip.c	(revision 132790)
+@@ -4643,8 +4643,6 @@
+ 			if (!found && option_debug > 4)
+ 				ast_log(LOG_DEBUG, "= Being pedantic: This is not our match on request: Call ID: %s Ourtag <null> Totag %s Method %s\n", p->callid, totag, sip_methods[req->method].text);
+ 		}
+-
+-
+ 		if (found) {
+ 			/* Found the call */
+ 			ast_mutex_lock(&p->lock);
+@@ -7204,7 +7202,7 @@
+ 		add_header_contentLength(&req, 0);
+ 	}
+ 
+-	if (!p->initreq.headers)
++	if (!p->initreq.headers || init > 2)
+ 		initialize_initreq(p, &req);
+ 	p->lastinvite = p->ocseq;
+ 	return send_request(p, &req, init ? XMIT_CRITICAL : XMIT_RELIABLE, p->ocseq);
+@@ -13767,7 +13765,264 @@
+ 	return 0;
+ }
+ 
++/*! \brief helper routine for sip_uri_cmp
++ *
++ * This takes the parameters from two SIP URIs and determines
++ * if the URIs match. The rules for parameters *suck*. Here's a breakdown
++ * 1. If a parameter appears in both URIs, then they must have the same value
++ *    in order for the URIs to match
++ * 2. If one URI has a user, maddr, ttl, or method parameter, then the other
++ *    URI must also have that parameter and must have the same value
++ *    in order for the URIs to match
++ * 3. All other headers appearing in only one URI are not considered when
++ *    determining if URIs match
++ *
++ * \param input1 Parameters from URI 1
++ * \param input2 Parameters from URI 2
++ * \return Return 0 if the URIs' parameters match, 1 if they do not
++ */
++static int sip_uri_params_cmp(const char *input1, const char *input2) 
++{
++	char *params1 = ast_strdupa(input1);
++	char *params2 = ast_strdupa(input2);
++	char *pos1;
++	char *pos2;
++	int maddrmatch = 0;
++	int ttlmatch = 0;
++	int usermatch = 0;
++	int methodmatch = 0;
+ 
++	/*Quick optimization. If both params are zero-length, then
++	 * they match
++	 */
++	if (ast_strlen_zero(params1) && ast_strlen_zero(params2)) {
++		return 0;
++	}
++
++	pos1 = params1;
++	while (!ast_strlen_zero(pos1)) {
++		char *name1 = pos1;
++		char *value1 = strchr(pos1, '=');
++		char *semicolon1 = strchr(pos1, ';');
++		int matched = 0;
++		if (semicolon1) {
++			*semicolon1++ = '\0';
++		}
++		if (!value1) {
++			goto fail;
++		}
++		*value1++ = '\0';
++		/* Checkpoint reached. We have the name and value parsed for param1 
++		 * We have to duplicate params2 each time through the second loop
++		 * or else we can't search and replace the semicolons with \0 each
++		 * time
++		 */
++		pos2 = ast_strdupa(params2);
++		while (!ast_strlen_zero(pos2)) {
++			char *name2 = pos2;
++			char *value2 = strchr(pos2, '=');
++			char *semicolon2 = strchr(pos2, ';');
++			if (semicolon2) {
++				*semicolon2++ = '\0';
++			}
++			if (!value2) {
++				goto fail;
++			}
++			if (!strcasecmp(name1, name2)) {
++				if (strcasecmp(value1, value2)) {
++					goto fail;
++				} else {
++					matched = 1;
++					break;
++				}
++			}
++			pos2 = semicolon2;
++		}
++		/* Need to see if the parameter we're looking at is one of the 'must-match' parameters */
++		if (!strcasecmp(name1, "maddr")) {
++			if (matched) {
++				maddrmatch = 1;
++			} else {
++				goto fail;
++			}
++		} else if (!strcasecmp(name1, "ttl")) {
++			if (matched) {
++				ttlmatch = 1;
++			} else {
++				goto fail;
++			}
++		} else if (!strcasecmp(name1, "user")) {
++			if (matched) {
++				usermatch = 1;
++			} else {
++				goto fail;
++			}
++		} else if (!strcasecmp(name1, "method")) {
++			if (matched) {
++				methodmatch = 1;
++			} else {
++				goto fail;
++			}
++		}
++		pos1 = semicolon1;
++	}
++
++	/* We've made it out of that horrible O(m*n) construct and there are no
++	 * failures yet. We're not done yet, though, because params2 could have
++	 * an maddr, ttl, user, or method header and params1 did not.
++	 */
++	pos2 = params2;
++	while (!ast_strlen_zero(pos2)) {
++		char *name2 = pos2;
++		char *value2 = strchr(pos2, '=');
++		char *semicolon2 = strchr(pos2, ';');
++		if (semicolon2) {
++			*semicolon2++ = '\0';
++		}
++		if (!value2) {
++			goto fail;
++		}
++		if ((!strcasecmp(name2, "maddr") && !maddrmatch) ||
++				(!strcasecmp(name2, "ttl") && !ttlmatch) ||
++				(!strcasecmp(name2, "user") && !usermatch) ||
++				(!strcasecmp(name2, "method") && !methodmatch)) {
++			goto fail;
++		}
++	}
++	return 0;
++
++fail:
++	return 1;
++}
++
++/*! \brief helper routine for sip_uri_cmp
++ *
++ * This takes the "headers" from two SIP URIs and determines
++ * if the URIs match. The rules for headers is simple. If a header
++ * appears in one URI, then it must also appear in the other URI. The
++ * order in which the headers appear does not matter.
++ *
++ * \param input1 Headers from URI 1
++ * \param input2 Headers from URI 2
++ * \return Return 0 if the URIs' headers match, 1 if they do not
++ */
++static int sip_uri_headers_cmp(const char *input1, const char *input2)
++{
++	char *headers1 = ast_strdupa(input1);
++	char *headers2 = ast_strdupa(input2);
++	int zerolength1 = ast_strlen_zero(headers1);
++	int zerolength2 = ast_strlen_zero(headers2);
++	int different = 0;
++	char *header1;
++
++	if ((zerolength1 && !zerolength2) ||
++			(zerolength2 && !zerolength1))
++		return 1;
++
++	if (zerolength1 && zerolength2)
++		return 0;
++
++	/* At this point, we can definitively state that both inputs are
++	 * not zero-length. First, one more optimization. If the length
++	 * of the headers is not equal, then we definitely have no match
++	 */
++	if (strlen(headers1) != strlen(headers2)) {
++		return 1;
++	}
++
++	for (header1 = strsep(&headers1, "&"); header1; header1 = strsep(&headers1, "&")) {
++		if (!strcasestr(headers2, header1)) {
++			different = 1;
++			break;
++		}
++	}
++
++	return different;
++}
++
++static int sip_uri_cmp(const char *input1, const char *input2)
++{
++	char *uri1 = ast_strdupa(input1);
++	char *uri2 = ast_strdupa(input2);
++	char *host1;
++	char *host2;
++	char *params1;
++	char *params2;
++	char *headers1;
++	char *headers2;
++
++	/* Strip off "sip:" from the URI. We know this is present
++	 * because it was checked back in parse_request()
++	 */
++	strsep(&uri1, ":");
++	strsep(&uri2, ":");
++
++	if ((host1 = strchr(uri1, '@'))) {
++		*host1++ = '\0';
++	}
++	if ((host2 = strchr(uri2, '@'))) {
++		*host2++ = '\0';
++	}
++
++	/* Check for mismatched username and passwords. This is the
++	 * only case-sensitive comparison of a SIP URI
++	 */
++	if ((host1 && !host2) ||
++			(host2 && !host1) ||
++			(host1 && host2 && strcmp(uri1, uri2))) {
++		return 1;
++	}
++
++	if (!host1)
++		host1 = uri1;
++	if (!host2)
++		host2 = uri2;
++
++	/* Strip off the parameters and headers so we can compare
++	 * host and port
++	 */
++
++	if ((params1 = strchr(host1, ';'))) {
++		*params1++ = '\0';
++	}
++	if ((params2 = strchr(host2, ';'))) {
++		*params2++ = '\0';
++	}
++
++	/* Headers come after parameters, but there may be headers without
++	 * parameters, thus the S_OR
++	 */
++	if ((headers1 = strchr(S_OR(params1, host1), '?'))) {
++		*headers1++ = '\0';
++	}
++	if ((headers2 = strchr(S_OR(params2, host2), '?'))) {
++		*headers2++ = '\0';
++	}
++
++	/* Now the host/port are properly isolated. We can get by with a string comparison
++	 * because the SIP URI checking rules have some interesting exceptions that make
++	 * this possible. I will note 2 in particular
++	 * 1. hostnames which resolve to the same IP address as well as a hostname and its
++	 *    IP address are not considered a match with SIP URI's.
++	 * 2. If one URI specifies a port and the other does not, then the URIs do not match.
++	 *    This includes if one URI explicitly contains port 5060 and the other implies it
++	 *    by not having a port specified.
++	 */
++
++	if (strcasecmp(host1, host2)) {
++		return 1;
++	}
++
++	/* Headers have easier rules to follow, so do those first */
++	if (sip_uri_headers_cmp(headers1, headers2)) {
++		return 1;
++	}
++
++	/* And now the parameters. Ugh */
++	return sip_uri_params_cmp(params1, params2);
++}
++
++
+ /*! \brief Handle incoming INVITE request
+ \note 	If the INVITE has a Replaces header, it is part of an
+  *	attended transfer. If so, we do not go through the dial
+@@ -13814,10 +14069,44 @@
+ 	   	being able to call yourself */
+ 		/* If pedantic is on, we need to check the tags. If they're different, this is
+ 	   	in fact a forked call through a SIP proxy somewhere. */
+-		transmit_response(p, "482 Loop Detected", req);
+-		p->invitestate = INV_COMPLETED;
+-		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+-		return 0;
++		int different;
++		if (pedanticsipchecking)
++			different = sip_uri_cmp(p->initreq.rlPart2, req->rlPart2);
++		else
++			different = strcmp(p->initreq.rlPart2, req->rlPart2);
++		if (!different) {
++			transmit_response(p, "482 Loop Detected", req);
++			p->invitestate = INV_COMPLETED;
++			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
++			return 0;
++		} else {
++			/* This is a spiral. What we need to do is to just change the outgoing INVITE
++			 * so that it now routes to the new Request URI. Since we created the INVITE ourselves
++			 * that should be all we need to do.
++			 */
++			char *uri = ast_strdupa(req->rlPart2);
++			char *at = strchr(uri, '@');
++			char *peerorhost;
++			struct sip_pkt *pkt = NULL;
++			if (option_debug > 2) {
++				ast_log(LOG_DEBUG, "Potential spiral detected. Original RURI was %s, new RURI is %s\n", p->initreq.rlPart2, req->rlPart2);
++			}
++			if (at) {
++				*at = '\0';
++			}
++			/* Parse out "sip:" */
++			if ((peerorhost = strchr(uri, ':'))) {
++				*peerorhost++ = '\0';
++			}
++			create_addr(p, peerorhost);
++			ast_string_field_free(p, theirtag);
++			for (pkt = p->packets; pkt; pkt = pkt->next) {
++				if (pkt->seqno == p->icseq && pkt->method == SIP_INVITE) {
++					AST_SCHED_DEL(sched, pkt->retransid);
++				}
++			}
++			return transmit_invite(p, SIP_INVITE, 1, 3);
++		}
+ 	}
+ 	
+ 	if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->pendinginvite) {
+@@ -15332,7 +15621,7 @@
+ 		if (!p->initreq.headers) {
+ 			if (option_debug)
+ 				ast_log(LOG_DEBUG, "That's odd...  Got a response on a call we dont know about. Cseq %d Cmd %s\n", seqno, cmd);
+-			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
++			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ 			return 0;
+ 		} else if (p->ocseq && (p->ocseq < seqno) && (seqno != p->lastnoninvite)) {
+ 			if (option_debug)

Added: asterisk/branches/lenny-security/debian/patches/r171264
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/patches/r171264?rev=7883&op=file
==============================================================================
--- asterisk/branches/lenny-security/debian/patches/r171264 (added)
+++ asterisk/branches/lenny-security/debian/patches/r171264 Sun Dec 13 23:17:34 2009
@@ -1,0 +1,53 @@
+Upstream r171264
+
+Don't retransmit 401 on REGISTER requests when alwaysauthreject=yes
+
+(closes issue #14284)
+
+--- a/channels/chan_sip.c	(revision 171263)
++++ b/channels/chan_sip.c	(revision 171264)
+@@ -1264,7 +1264,7 @@
+ static int transmit_response_with_unsupported(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *unsupported);
+ static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale);
+ static int transmit_response_with_allow(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
+-static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, int reliable);
++static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable);
+ static int transmit_request(struct sip_pvt *p, int sipmethod, int inc, enum xmittype reliable, int newbranch);
+ static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch);
+ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init);
+@@ -8774,7 +8774,7 @@
+ /*! \brief Send a fake 401 Unauthorized response when the administrator
+   wants to hide the names of local users/peers from fishers
+  */
+-static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, int reliable)
++static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable)
+ {
+ 	ast_string_field_build(p, randdata, "%08lx", ast_random());	/* Create nonce for challenge */
+ 	transmit_response_with_auth(p, "401 Unauthorized", req, p->randdata, reliable, "WWW-Authenticate", 0);
+@@ -8931,7 +8931,7 @@
+ 		case AUTH_PEER_NOT_DYNAMIC:
+ 		case AUTH_ACL_FAILED:
+ 			if (global_alwaysauthreject) {
+-				transmit_fake_auth_response(p, &p->initreq, 1);
++				transmit_fake_auth_response(p, &p->initreq, XMIT_UNRELIABLE);
+ 			} else {
+ 				/* URI not found */
+ 				if (res == AUTH_PEER_NOT_DYNAMIC)
+@@ -14421,7 +14421,7 @@
+ 		if (res < 0) { /* Something failed in authentication */
+ 			if (res == AUTH_FAKE_AUTH) {
+ 				ast_log(LOG_NOTICE, "Sending fake auth rejection for user %s\n", get_header(req, "From"));
+-				transmit_fake_auth_response(p, req, 1);
++				transmit_fake_auth_response(p, req, XMIT_RELIABLE);
+ 			} else {
+   				ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From"));
+ 				transmit_response_reliable(p, "403 Forbidden", req);
+@@ -15458,7 +15458,7 @@
+ 	if (res < 0) {
+ 		if (res == AUTH_FAKE_AUTH) {
+ 			ast_log(LOG_NOTICE, "Sending fake auth rejection for user %s\n", get_header(req, "From"));
+-			transmit_fake_auth_response(p, req, 1);
++			transmit_fake_auth_response(p, req, XMIT_UNRELIABLE);
+ 		} else {
+ 			ast_log(LOG_NOTICE, "Failed to authenticate user %s for SUBSCRIBE\n", get_header(req, "From"));
+ 			transmit_response_reliable(p, "403 Forbidden", req);

Modified: asterisk/branches/lenny-security/debian/patches/series
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/patches/series?rev=7883&op=diff
==============================================================================
--- asterisk/branches/lenny-security/debian/patches/series (original)
+++ asterisk/branches/lenny-security/debian/patches/series Sun Dec 13 23:17:34 2009
@@ -87,3 +87,16 @@
 zap-fix-timing-source
 zap-fix-deadlock
 zap-fix-cause34
+
+### lenny fixes
+AST-2009-001
+
+r132790
+AST-2009-002
+
+r171264
+AST-2009-003
+
+AST-2009-008
+
+AST-2009-010




More information about the Pkg-voip-commits mailing list