[asterisk-commits] mnicholson: branch 1.4 r314607 - in /branches/1.4: channels/ configs/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Apr 21 13:19:27 CDT 2011


Author: mnicholson
Date: Thu Apr 21 13:19:21 2011
New Revision: 314607

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=314607
Log:
Added limits to the number of unauthenticated sessions TCP based protocols are allowed to have open simultaneously.  Also added timeouts for unauthenticated sessions where it made sense to do so.

Unrelated, the manager interface now properly checks if the user has the "system" privilege before executing shell commands via the Originate action. 

AST-2011-005
AST-2011-006

(closes issue #18787)
Reported by: kobaz

(related to issue #18996)
Reported by: tzafrir


Modified:
    branches/1.4/channels/chan_skinny.c
    branches/1.4/configs/http.conf.sample
    branches/1.4/configs/skinny.conf.sample
    branches/1.4/main/http.c
    branches/1.4/main/manager.c

Modified: branches/1.4/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/channels/chan_skinny.c?view=diff&rev=314607&r1=314606&r2=314607
==============================================================================
--- branches/1.4/channels/chan_skinny.c (original)
+++ branches/1.4/channels/chan_skinny.c Thu Apr 21 13:19:21 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: branches/1.4/configs/http.conf.sample
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/configs/http.conf.sample?view=diff&rev=314607&r1=314606&r2=314607
==============================================================================
--- branches/1.4/configs/http.conf.sample (original)
+++ branches/1.4/configs/http.conf.sample Thu Apr 21 13:19:21 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: branches/1.4/configs/skinny.conf.sample
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/configs/skinny.conf.sample?view=diff&rev=314607&r1=314606&r2=314607
==============================================================================
--- branches/1.4/configs/skinny.conf.sample (original)
+++ branches/1.4/configs/skinny.conf.sample Thu Apr 21 13:19:21 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: branches/1.4/main/http.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/main/http.c?view=diff&rev=314607&r1=314606&r2=314607
==============================================================================
--- branches/1.4/main/http.c (original)
+++ branches/1.4/main/http.c Thu Apr 21 13:19:21 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: branches/1.4/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/main/manager.c?view=diff&rev=314607&r1=314606&r2=314607
==============================================================================
--- branches/1.4/main/manager.c (original)
+++ branches/1.4/main/manager.c Thu Apr 21 13:19:21 2011
@@ -2017,6 +2017,24 @@
 		format = 0;
 		ast_parse_allow_disallow(NULL, &format, codecs, 1);
 	}
+	if (!ast_strlen_zero(app)) {
+		/* To run the System application (or anything else that goes to
+		 * shell), you must have the additional System privilege */
+		if (!(s->session->writeperm & EVENT_FLAG_SYSTEM)
+			&& (
+				strcasestr(app, "system") == 0 || /* System(rm -rf /)
+				                                     TrySystem(rm -rf /)       */
+				strcasestr(app, "exec") ||        /* Exec(System(rm -rf /))
+				                                     TryExec(System(rm -rf /)) */
+				strcasestr(app, "agi") ||         /* AGI(/bin/rm,-rf /)
+				                                     EAGI(/bin/rm,-rf /)       */
+				strstr(appdata, "SHELL") ||       /* NoOp(${SHELL(rm -rf /)})  */
+				strstr(appdata, "EVAL")           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
+				)) {
+			astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have.");
+			return 0;
+		}
+	}
 	/* Allocate requested channel variables */
 	vars = astman_get_variables(m);
 




More information about the asterisk-commits mailing list