[Pkg-voip-commits] r8848 - in /asterisk/branches/lenny-security/debian: changelog patches/AST-2011-005 patches/manager_bugfix_reload patches/series

tzafrir at alioth.debian.org tzafrir at alioth.debian.org
Wed Apr 6 20:27:03 UTC 2011


Author: tzafrir
Date: Wed Apr  6 20:27:02 2011
New Revision: 8848

URL: http://svn.debian.org/wsvn/pkg-voip/?sc=1&rev=8848
Log:
* Patch AST-2011-005: Resource exhaustion in Asterisk Manager Interface
* Patches AST-2011-003, manager_manager_bugfix_reload - its pre-requirements.

Added:
    asterisk/branches/lenny-security/debian/patches/AST-2011-005
    asterisk/branches/lenny-security/debian/patches/manager_bugfix_reload
Modified:
    asterisk/branches/lenny-security/debian/changelog
    asterisk/branches/lenny-security/debian/patches/series

Modified: asterisk/branches/lenny-security/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/changelog?rev=8848&op=diff
==============================================================================
--- asterisk/branches/lenny-security/debian/changelog (original)
+++ asterisk/branches/lenny-security/debian/changelog Wed Apr  6 20:27:02 2011
@@ -2,8 +2,9 @@
 
   * AST-2011-002 (CVE-2011-1147): Multiple crash vulnerabilities in UDPTL code
     (Closes: #614580).
-  * AST-2011-003: Resource exhaustion in Asterisk Manager Interface
+  * Patch AST-2011-005: Resource exhaustion in Asterisk Manager Interface
     (Closes: #618790).
+  * Patches AST-2011-003, manager_manager_bugfix_reload - its pre-requirements.
   * My new @debian.org address
 
  -- Tzafrir Cohen <tzafrir at debian.org>  Thu, 17 Mar 2011 12:21:06 +0200

Added: asterisk/branches/lenny-security/debian/patches/AST-2011-005
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/patches/AST-2011-005?rev=8848&op=file
==============================================================================
--- asterisk/branches/lenny-security/debian/patches/AST-2011-005 (added)
+++ asterisk/branches/lenny-security/debian/patches/AST-2011-005 Wed Apr  6 20:27:02 2011
@@ -1,0 +1,247 @@
+From: Matthew Nicholson <mnicholson at digium.com>
+Date: Tue, 5 Apr 2011 14:10:34 +0000
+Subject:  Limit the number of unauthenticated manager and their time
+Bug: https://issues.asterisk.org/view.php?id=18996
+Origin: http://svnview.digium.com/svn/asterisk?view=rev&rev=312761
+
+Keeping many open manager connections at the initial unauthenticated
+stage can cause Asterisk to exhaust available CPU and memory resources.
+
+The manager interface is disabled by default in upstream, but enabled
+by default (listening on localhost only) in the version in Debian 5.0 (Lenny)
+and 6.0 (Squeeze).
+
+See also http://downloads.asterisk.org/pub/security/AST-2011-005.html
+
+---
+ configs/manager.conf.sample |   11 +++++
+ main/manager.c              |   87 +++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 95 insertions(+), 3 deletions(-)
+
+--- a/configs/manager.conf.sample
++++ b/configs/manager.conf.sample
+@@ -26,6 +26,17 @@ enabled = no
+ ;webenabled = yes
+ port = 5038
+ 
++; authtimeout specifies the maximum number of seconds a client has to
++; authenticate.  If the client does not authenticate beofre this timeout
++; expires, the client will be disconnected. (default: 30 seconds)
++
++;authtimeout = 30
++
++; authlimit specifies the maximum number of unauthenticated sessions that will
++; be allowed to connect at any given time.
++
++;authlimit = 50
++
+ ;httptimeout = 60
+ ; a) httptimeout sets the Max-Age of the http cookie
+ ; b) httptimeout is the amount of time the webserver waits 
+--- a/main/manager.c
++++ b/main/manager.c
+@@ -106,6 +106,8 @@ static const int DEFAULT_DISPLAYCONNECTS
+ static const int DEFAULT_TIMESTAMPEVENTS	= 0;	/*!< Default setting for timestampevents */	
+ static const int DEFAULT_HTTPTIMEOUT 		= 60;	/*!< Default manager http timeout */
+ static const int DEFAULT_BROKENEVENTSACTION	= 0;	/*!< Default setting for brokeneventsaction */
++static const int DEFAULT_AUTHTIMEOUT		= 30;	/*!< Default setting for authtimeout */
++static const int DEFAULT_AUTHLIMIT		= 50;	/*!< Default setting for authlimit */
+ 
+ 
+ static int enabled;
+@@ -114,10 +116,13 @@ static int asock = -1;
+ static int displayconnects;
+ static int timestampevents;
+ static int httptimeout;
++static int authtimeout;
++static int authlimit;
+ 
+ static pthread_t t;
+ static int block_sockets;
+ static int num_sessions;
++static int unauth_sessions = 0;
+ 
+ /* Protected by the sessions list lock */
+ struct eventqent *master_eventq = NULL;
+@@ -193,6 +198,7 @@ struct mansession {
+ 	struct eventqent *eventq;
+ 	/* Timeout for ast_carefulwrite() */
+ 	int writetimeout;
++	time_t authstart;
+ 	int pending_event;         /*!< Pending events indicator in case when waiting_thread is NULL */
+ 	AST_LIST_ENTRY(mansession) list;
+ 	int write_error:1;
+@@ -2290,6 +2296,7 @@ static int process_message(struct manses
+ 				return -1;
+ 			} else {
+ 				s->authenticated = 1;
++				ast_atomic_fetchadd_int(&unauth_sessions, -1);
+ 				if (option_verbose > 1) {
+ 					if (displayconnects) {
+ 						ast_verbose(VERBOSE_PREFIX_2 "%sManager '%s' logged on from %s\n", 
+@@ -2336,6 +2343,8 @@ static int get_input(struct mansession *
+ 	int res;
+ 	int x;
+ 	struct pollfd fds[1];
++	int timeout = -1;
++	time_t now;
+ 	for (x = 1; x < s->inlen; x++) {
+ 		if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r')) {
+ 			/* Copy output data up to and including \r\n */
+@@ -2354,7 +2363,22 @@ static int get_input(struct mansession *
+ 	}
+ 	fds[0].fd = s->fd;
+ 	fds[0].events = POLLIN;
++
+ 	do {
++		/* calculate a timeout if we are not authenticated */
++		if (!s->authenticated) {
++			if(time(&now) == -1) {
++				ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
++				return -1;
++			}
++
++			timeout = (authtimeout - (now - s->authstart)) * 1000;
++			if (timeout < 0) {
++				/* we have timed out */
++				return 0;
++			}
++		}
++
+ 		ast_mutex_lock(&s->__lock);
+ 		if (s->pending_event) {
+ 			s->pending_event = 0;
+@@ -2364,7 +2388,7 @@ static int get_input(struct mansession *
+ 		s->waiting_thread = pthread_self();
+ 		ast_mutex_unlock(&s->__lock);
+ 
+-		res = poll(fds, 1, -1);
++		res = poll(fds, 1, timeout);
+ 
+ 		ast_mutex_lock(&s->__lock);
+ 		s->waiting_thread = AST_PTHREADT_NULL;
+@@ -2382,6 +2406,9 @@ static int get_input(struct mansession *
+ 			if (res < 1)
+ 				return -1;
+ 			break;
++		} else {
++			/* timeout */
++			return 0;
+ 		}
+ 	} while(1);
+ 	s->inlen += res;
+@@ -2394,6 +2421,7 @@ static int do_message(struct mansession
+ 	struct message m = { 0 };
+ 	char header_buf[sizeof(s->inbuf)] = { '\0' };
+ 	int res;
++	time_t now;
+ 
+ 	for (;;) {
+ 		/* Check if any events are pending and do them if needed */
+@@ -2403,6 +2431,17 @@ static int do_message(struct mansession
+ 		}
+ 		res = get_input(s, header_buf);
+ 		if (res == 0) {
++			if (!s->authenticated) {
++				if(time(&now) == -1) {
++					ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
++					return -1;
++				}
++
++				if (now - s->authstart > authtimeout) {
++					ast_log(LOG_EVENT, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->sin.sin_addr), authtimeout);
++					return -1;
++				}
++			}
+ 			continue;
+ 		} else if (res > 0) {
+ 			/* Strip trailing \r\n */
+@@ -2436,6 +2475,7 @@ static void *session_do(void *data)
+ 		}
+ 		ast_log(LOG_EVENT, "Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));
+ 	} else {
++		ast_atomic_fetchadd_int(&unauth_sessions, -1);
+ 		if (option_verbose > 1) {
+ 			if (displayconnects)
+ 				ast_verbose(VERBOSE_PREFIX_2 "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(s->sin.sin_addr));
+@@ -2515,14 +2555,25 @@ static void *accept_thread(void *ignore)
+ 			ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
+ 			continue;
+ 		}
++
++		if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
++			close(as);
++			ast_atomic_fetchadd_int(&unauth_sessions, -1);
++			ast_log(LOG_WARNING, "manager connection rejected, too many unauthenticated sessions.\n");
++			continue;
++		}
++
+ 		p = getprotobyname("tcp");
+ 		if (p) {
+ 			if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
+ 				ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
+ 			}
+ 		}
+-		if (!(s = ast_calloc(1, sizeof(*s))))
++		if (!(s = ast_calloc(1, sizeof(*s)))) {
++			close(as);
++			ast_atomic_fetchadd_int(&unauth_sessions, -1);
+ 			continue;
++		}
+ 
+ 		memcpy(&s->sin, &sin, sizeof(sin));
+ 		s->writetimeout = 100;
+@@ -2549,8 +2600,16 @@ static void *accept_thread(void *ignore)
+ 			s->eventq = s->eventq->next;
+ 		ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
+ 		AST_LIST_UNLOCK(&sessions);
+-		if (ast_pthread_create_background(&s->t, &attr, session_do, s))
++		if(time(&s->authstart) == -1) {
++			ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
++			ast_atomic_fetchadd_int(&unauth_sessions, -1);
+ 			destroy_session(s);
++			continue;
++		}
++		if (ast_pthread_create_background(&s->t, &attr, session_do, s)) {
++			ast_atomic_fetchadd_int(&unauth_sessions, -1);
++			destroy_session(s);
++		}
+ 	}
+ 	pthread_attr_destroy(&attr);
+ 	return NULL;
+@@ -3037,6 +3096,8 @@ int init_manager(void)
+ 	block_sockets = DEFAULT_BLOCKSOCKETS;
+ 	timestampevents = DEFAULT_TIMESTAMPEVENTS;
+ 	httptimeout = DEFAULT_HTTPTIMEOUT;
++	authtimeout = DEFAULT_AUTHTIMEOUT;
++	authlimit = DEFAULT_AUTHLIMIT;
+ 
+ 	cfg = ast_config_load("manager.conf");
+ 	if (!cfg) {
+@@ -3071,6 +3132,26 @@ int init_manager(void)
+ 	if ((val = ast_variable_retrieve(cfg, "general", "httptimeout")))
+ 		newhttptimeout = atoi(val);
+ 
++	if ((val = ast_variable_retrieve(cfg, "general", "authtimeout"))) {
++		int timeout = atoi(val);
++
++		if (timeout < 1) {
++			ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", val);
++		} else {
++			authtimeout = timeout;
++		}
++	}
++
++	if ((val = ast_variable_retrieve(cfg, "general", "authlimit"))) {
++		int limit = atoi(val);
++
++		if (limit < 1) {
++			ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", val);
++		} else {
++			authlimit = limit;
++		}
++	}
++
+ 	memset(&ba, 0, sizeof(ba));
+ 	ba.sin_family = AF_INET;
+ 	ba.sin_port = htons(portno);

Added: asterisk/branches/lenny-security/debian/patches/manager_bugfix_reload
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/patches/manager_bugfix_reload?rev=8848&op=file
==============================================================================
--- asterisk/branches/lenny-security/debian/patches/manager_bugfix_reload (added)
+++ asterisk/branches/lenny-security/debian/patches/manager_bugfix_reload Wed Apr  6 20:27:02 2011
@@ -1,0 +1,67 @@
+From: Brett Bryant <bbryant at digium.com>
+Date: Thu, 2 Sep 2010 20:25:03 +0000
+Origin: http://svnview.digium.com/svn/asterisk?view=rev&rev=284777
+Bug: https://issues.asterisk.org/view.php?id=17917
+Subject: Properly reset default manager.conf values on reload
+
+Fixes a bug in manager.c where the default configuration values weren't
+reset when the manager configuration was reloaded.
+
+This is a simple bugfix required for cleanly applying AST-2011-005
+
+---
+ main/manager.c |   28 +++++++++++++++++++++-------
+ 1 files changed, 21 insertions(+), 7 deletions(-)
+
+--- a/main/manager.c
++++ b/main/manager.c
+@@ -99,12 +99,21 @@ struct eventqent {
+ 	char eventdata[1];
+ };
+ 
++static const int DEFAULT_ENABLED			= 0;	/*!< Default setting for manager to be enabled */
++static const int DEFAULT_WEBENABLED			= 0;	/*!< Default setting for the web interface to be enabled */
++static const int DEFAULT_BLOCKSOCKETS		= 0;	/*!< Default setting for block-sockets */
++static const int DEFAULT_DISPLAYCONNECTS	= 1;	/*!< Default setting for displaying manager connections */
++static const int DEFAULT_TIMESTAMPEVENTS	= 0;	/*!< Default setting for timestampevents */	
++static const int DEFAULT_HTTPTIMEOUT 		= 60;	/*!< Default manager http timeout */
++static const int DEFAULT_BROKENEVENTSACTION	= 0;	/*!< Default setting for brokeneventsaction */
++
++
+ static int enabled;
+ static int portno = DEFAULT_MANAGER_PORT;
+ static int asock = -1;
+-static int displayconnects = 1;
++static int displayconnects;
+ static int timestampevents;
+-static int httptimeout = 60;
++static int httptimeout;
+ 
+ static pthread_t t;
+ static int block_sockets;
+@@ -2989,8 +2998,8 @@ int init_manager(void)
+ 	static struct sockaddr_in ba;
+ 	int x = 1;
+ 	int flags;
+-	int webenabled = 0;
+-	int newhttptimeout = 60;
++	int webenabled = DEFAULT_WEBENABLED;
++	int newhttptimeout = DEFAULT_HTTPTIMEOUT;
+ 	struct ast_manager_user *user = NULL;
+ 
+ 	if (!registered) {
+@@ -3022,8 +3031,13 @@ int init_manager(void)
+ 		/* Append placeholder event so master_eventq never runs dry */
+ 		append_event("Event: Placeholder\r\n\r\n", 0);
+ 	}
++
+ 	portno = DEFAULT_MANAGER_PORT;
+-	displayconnects = 1;
++	displayconnects = DEFAULT_DISPLAYCONNECTS;
++	block_sockets = DEFAULT_BLOCKSOCKETS;
++	timestampevents = DEFAULT_TIMESTAMPEVENTS;
++	httptimeout = DEFAULT_HTTPTIMEOUT;
++
+ 	cfg = ast_config_load("manager.conf");
+ 	if (!cfg) {
+ 		ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf.  Call management disabled.\n");

Modified: asterisk/branches/lenny-security/debian/patches/series
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny-security/debian/patches/series?rev=8848&op=diff
==============================================================================
--- asterisk/branches/lenny-security/debian/patches/series (original)
+++ asterisk/branches/lenny-security/debian/patches/series Wed Apr  6 20:27:02 2011
@@ -104,3 +104,5 @@
 AST-2011-001
 AST-2011-002
 AST-2011-003
+manager_bugfix_reload
+AST-2011-005




More information about the Pkg-voip-commits mailing list