[asterisk-commits] lmadsen: tag 1.4.41 r315205 - in /tags/1.4.41: channels/ configs/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Apr 25 12:36:02 CDT 2011


Author: lmadsen
Date: Mon Apr 25 12:35:58 2011
New Revision: 315205

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=315205
Log:
Merge changes for AST-2011-005 and AST-2011-006

Modified:
    tags/1.4.41/channels/chan_skinny.c
    tags/1.4.41/configs/http.conf.sample
    tags/1.4.41/configs/manager.conf.sample
    tags/1.4.41/configs/skinny.conf.sample
    tags/1.4.41/main/http.c
    tags/1.4.41/main/manager.c

Modified: tags/1.4.41/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.4.41/channels/chan_skinny.c?view=diff&rev=315205&r1=315204&r2=315205
==============================================================================
--- tags/1.4.41/channels/chan_skinny.c (original)
+++ tags/1.4.41/channels/chan_skinny.c Mon Apr 25 12:35:58 2011
@@ -96,8 +96,13 @@
 #define DEFAULT_SKINNY_PORT	2000
 #define DEFAULT_SKINNY_BACKLOG	2
 #define SKINNY_MAX_PACKET	1000
+#define DEFAULT_AUTH_TIMEOUT	30
+#define DEFAULT_AUTH_LIMIT	50
 
 static int keep_alive = 120;
+static int auth_timeout = DEFAULT_AUTH_TIMEOUT;
+static int auth_limit = DEFAULT_AUTH_LIMIT;
+static int unauth_sessions = 0;
 static char date_format[6] = "D-M-Y";
 static char version_id[16] = "P002F202";
 
@@ -1060,6 +1065,7 @@
 static struct skinnysession {
 	pthread_t t;
 	ast_mutex_t lock;
+	time_t start;
 	struct sockaddr_in sin;
 	int fd;
 	char inbuf[SKINNY_MAX_PACKET];
@@ -3064,6 +3070,7 @@
 		transmit_response(s, req);
 		return 0;
 	}
+	ast_atomic_fetchadd_int(&unauth_sessions, -1);
 	if (option_verbose > 2)
 		ast_verbose(VERBOSE_PREFIX_3 "Device '%s' successfully registered\n", name);
 
@@ -4427,6 +4434,9 @@
 		if (s->fd > -1) {
 			close(s->fd);
 		}
+		if (!s->device) {
+			ast_atomic_fetchadd_int(&unauth_sessions, -1);
+		}
 		ast_mutex_destroy(&s->lock);
 		free(s);
 	} else {
@@ -4439,13 +4449,30 @@
 {
 	int res;
 	int dlen = 0;
+	int timeout = keep_alive * 1100;
+	time_t now;
 	int *bufaddr;
 	struct pollfd fds[1];
+
+	if (!s->device) {
+		if(time(&now) == -1) {
+			ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
+			return -1;
+		}
+
+		timeout = (auth_timeout - (now - s->start)) * 1000;
+		if (timeout < 0) {
+			/* we have timed out */
+			if (skinnydebug)
+				ast_verbose("Skinny Client failed to authenticate in %d seconds\n", auth_timeout);
+			return -1;
+		}
+	}
 
  	fds[0].fd = s->fd;
 	fds[0].events = POLLIN;
 	fds[0].revents = 0;
-	res = ast_poll(fds, 1, (keep_alive * 1100)); /* If nothing has happen, client is dead */
+	res = ast_poll(fds, 1, timeout); /* If nothing has happen, client is dead */
 						 /* we add 10% to the keep_alive to deal */
 						 /* with network delays, etc */
 	if (res < 0) {
@@ -4454,8 +4481,13 @@
 			return res;
 		}
  	} else if (res == 0) {
-		if (skinnydebug)
-			ast_verbose("Skinny Client was lost, unregistering\n");
+		if (skinnydebug) {
+			if (s->device) {
+				ast_verbose("Skinny Client was lost, unregistering\n");
+			} else {
+				ast_verbose("Skinny Client failed to authenticate in %d seconds\n", auth_timeout);
+			}
+		}
 		skinny_unregister(NULL, s);
 		return -1;
 	}
@@ -4594,18 +4626,35 @@
 			ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
 			continue;
 		}
+
+		if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= auth_limit) {
+			close(as);
+			ast_atomic_fetchadd_int(&unauth_sessions, -1);
+			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 Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
 			}
 		}
-		if (!(s = ast_calloc(1, sizeof(struct skinnysession))))
+		if (!(s = ast_calloc(1, sizeof(struct skinnysession)))) {
+			close(as);
+			ast_atomic_fetchadd_int(&unauth_sessions, -1);
 			continue;
+		}
 
 		memcpy(&s->sin, &sin, sizeof(sin));
 		ast_mutex_init(&s->lock);
 		s->fd = as;
+
+		if(time(&s->start) == -1) {
+			ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
+			destroy_session(s);
+			continue;
+		}
+
 		ast_mutex_lock(&sessionlock);
 		s->next = sessions;
 		sessions = s;
@@ -4756,6 +4805,24 @@
 			}
 		} else if (!strcasecmp(v->name, "keepalive")) {
 			keep_alive = atoi(v->value);
+		} else if (!strcasecmp(v->name, "authtimeout")) {
+			int timeout = atoi(v->value);
+
+			if (timeout < 1) {
+				ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", v->value);
+				auth_timeout = DEFAULT_AUTH_TIMEOUT;
+			} else {
+				auth_timeout = timeout;
+			}
+		} else if (!strcasecmp(v->name, "authlimit")) {
+			int limit = atoi(v->value);
+
+			if (limit < 1) {
+				ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", v->value);
+				auth_limit = DEFAULT_AUTH_LIMIT;
+			} else {
+				auth_limit = limit;
+			}
 		} else if (!strcasecmp(v->name, "dateformat")) {
 			memcpy(date_format, v->value, sizeof(date_format));
 		} else if (!strcasecmp(v->name, "allow")) {

Modified: tags/1.4.41/configs/http.conf.sample
URL: http://svnview.digium.com/svn/asterisk/tags/1.4.41/configs/http.conf.sample?view=diff&rev=315205&r1=315204&r2=315205
==============================================================================
--- tags/1.4.41/configs/http.conf.sample (original)
+++ tags/1.4.41/configs/http.conf.sample Mon Apr 25 12:35:58 2011
@@ -26,7 +26,12 @@
 ; requests must begin with /asterisk
 ;
 ;prefix=asterisk
-
+;
+; sessionlimit specifies the maximum number of httpsessions that will be
+; allowed to exist at any given time. (default: 100)
+;
+;sessionlimit=100
+;
 ; The post_mappings section maps URLs to real paths on the filesystem.  If a
 ; POST is done from within an authenticated manager session to one of the
 ; configured POST mappings, then any files in the POST will be placed in the

Modified: tags/1.4.41/configs/manager.conf.sample
URL: http://svnview.digium.com/svn/asterisk/tags/1.4.41/configs/manager.conf.sample?view=diff&rev=315205&r1=315204&r2=315205
==============================================================================
--- tags/1.4.41/configs/manager.conf.sample (original)
+++ tags/1.4.41/configs/manager.conf.sample Mon Apr 25 12:35:58 2011
@@ -25,6 +25,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

Modified: tags/1.4.41/configs/skinny.conf.sample
URL: http://svnview.digium.com/svn/asterisk/tags/1.4.41/configs/skinny.conf.sample?view=diff&rev=315205&r1=315204&r2=315205
==============================================================================
--- tags/1.4.41/configs/skinny.conf.sample (original)
+++ tags/1.4.41/configs/skinny.conf.sample Mon Apr 25 12:35:58 2011
@@ -8,6 +8,15 @@
 			; "A" may also be used, but it must be at the end.
 			; Use M for month, D for day, Y for year, A for 12-hour time.
 keepalive=120
+
+;authtimeout = 30       ; 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)
+
+;authlimit = 50         ; authlimit specifies the maximum number of
+			; unauthenticated sessions that will be allowed to
+                        ; connect at any given time. (default: 50)
 
 ;allow=all		; see doc/rtp-packetization for framing options
 ;disallow=

Modified: tags/1.4.41/main/http.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.4.41/main/http.c?view=diff&rev=315205&r1=315204&r2=315205
==============================================================================
--- tags/1.4.41/main/http.c (original)
+++ tags/1.4.41/main/http.c Mon Apr 25 12:35:58 2011
@@ -60,6 +60,7 @@
 
 #define MAX_PREFIX 80
 #define DEFAULT_PREFIX "/asterisk"
+#define DEFAULT_SESSION_LIMIT 100
 
 struct ast_http_server_instance {
 	FILE *f;
@@ -77,6 +78,8 @@
 static int prefix_len;
 static struct sockaddr_in oldsin;
 static int enablestatic;
+static int session_limit = DEFAULT_SESSION_LIMIT;
+static int session_count = 0;
 
 /*! \brief Limit the kinds of files we're willing to serve up */
 static struct {
@@ -516,6 +519,7 @@
 	}
 	fclose(ser->f);
 	free(ser);
+	ast_atomic_fetchadd_int(&session_count, -1);
 	return NULL;
 }
 
@@ -534,15 +538,23 @@
 		ast_wait_for_input(httpfd, -1);
 		sinlen = sizeof(sin);
 		fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen);
+
 		if (fd < 0) {
 			if ((errno != EAGAIN) && (errno != EINTR))
 				ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
 			continue;
 		}
+
+		if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) {
+			close(fd);
+			continue;
+		}
+
 		ser = ast_calloc(1, sizeof(*ser));
 		if (!ser) {
 			ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
 			close(fd);
+			ast_atomic_fetchadd_int(&session_count, -1);
 			continue;
 		}
 		flags = fcntl(fd, F_GETFL);
@@ -557,12 +569,14 @@
 				ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
 				fclose(ser->f);
 				free(ser);
+				ast_atomic_fetchadd_int(&session_count, -1);
 			}
 			pthread_attr_destroy(&attr);
 		} else {
 			ast_log(LOG_WARNING, "fdopen failed!\n");
 			close(ser->fd);
 			free(ser);
+			ast_atomic_fetchadd_int(&session_count, -1);
 		}
 	}
 	return NULL;
@@ -679,8 +693,17 @@
 				} else {
 					newprefix[0] = '\0';
 				}
-					
+			} else if (!strcasecmp(v->name, "sessionlimit")) {
+				int limit = atoi(v->value);
+
+				if (limit < 1) {
+					ast_log(LOG_WARNING, "Invalid sessionlimit value '%s', using default value\n", v->value);
+					session_limit = DEFAULT_SESSION_LIMIT;
+				} else {
+					session_limit = limit;
+				}
 			}
+
 			v = v->next;
 		}
 		ast_config_destroy(cfg);

Modified: tags/1.4.41/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.4.41/main/manager.c?view=diff&rev=315205&r1=315204&r2=315205
==============================================================================
--- tags/1.4.41/main/manager.c (original)
+++ tags/1.4.41/main/manager.c Mon Apr 25 12:35:58 2011
@@ -104,6 +104,8 @@
 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;
@@ -113,10 +115,13 @@
 static int timestampevents;
 static int httptimeout;
 static int broken_events_action;
+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;
@@ -222,6 +227,7 @@
 	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_session) list;
 };
@@ -2305,6 +2311,7 @@
 				return -1;
 			} else {
 				s->session->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", 
@@ -2354,6 +2361,8 @@
 	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 */
@@ -2372,7 +2381,22 @@
 	}
 	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;
@@ -2382,7 +2406,7 @@
 		s->waiting_thread = pthread_self();
 		ast_mutex_unlock(&s->__lock);
 
-		res = ast_poll(fds, 1, -1);
+		res = ast_poll(fds, 1, timeout);
 
 		ast_mutex_lock(&s->__lock);
 		s->waiting_thread = AST_PTHREADT_NULL;
@@ -2400,6 +2424,9 @@
 			if (res < 1)
 				return -1;
 			break;
+		} else {
+			/* timeout */
+			return 0;
 		}
 	} while(1);
 	s->inlen += res;
@@ -2412,6 +2439,7 @@
 	struct message m = { 0 };
 	char header_buf[sizeof(s->session->inbuf)] = { '\0' };
 	int res;
+	time_t now;
 
 	for (;;) {
 		/* Check if any events are pending and do them if needed */
@@ -2421,6 +2449,17 @@
 		}
 		res = get_input(s->session, header_buf);
 		if (res == 0) {
+			if (!s->session->authenticated) {
+				if(time(&now) == -1) {
+					ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
+					return -1;
+				}
+
+				if (now - s->session->authstart > authtimeout) {
+					ast_log(LOG_EVENT, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout);
+					return -1;
+				}
+			}
 			continue;
 		} else if (res > 0) {
 			/* Strip trailing \r\n */
@@ -2455,6 +2494,7 @@
 		}
 		ast_log(LOG_EVENT, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->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(session->sin.sin_addr));
@@ -2528,14 +2568,25 @@
 			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;
@@ -2562,8 +2613,16 @@
 			s->eventq = s->eventq->next;
 		ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
 		AST_LIST_UNLOCK(&sessions);
-		if (ast_pthread_create_background(&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(&t, &attr, session_do, s)) {
+			ast_atomic_fetchadd_int(&unauth_sessions, -1);
+			destroy_session(s);
+		}
 	}
 	pthread_attr_destroy(&attr);
 	return NULL;
@@ -3100,6 +3159,8 @@
 	block_sockets = DEFAULT_BLOCKSOCKETS;
 	timestampevents = DEFAULT_TIMESTAMPEVENTS;
 	httptimeout = DEFAULT_HTTPTIMEOUT;
+	authtimeout = DEFAULT_AUTHTIMEOUT;
+	authlimit = DEFAULT_AUTHLIMIT;
 
 	cfg = ast_config_load("manager.conf");
 	if (!cfg) {
@@ -3136,6 +3197,26 @@
 
 	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;




More information about the asterisk-commits mailing list