[asterisk-commits] mnicholson: trunk r314666 - in /trunk: ./ channels/ channels/sip/include/ con...

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


Author: mnicholson
Date: Thu Apr 21 13:32:50 2011
New Revision: 314666

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=314666
Log:
Merged revisions 314628 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.8

................
  r314628 | mnicholson | 2011-04-21 13:24:05 -0500 (Thu, 21 Apr 2011) | 27 lines
  
  Merged revisions 314620 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.6.2
  
  ................
    r314620 | mnicholson | 2011-04-21 13:22:19 -0500 (Thu, 21 Apr 2011) | 20 lines
    
    Merged revisions 314607 via svnmerge from 
    https://origsvn.digium.com/svn/asterisk/branches/1.4
    
    ........
      r314607 | mnicholson | 2011-04-21 13:19:21 -0500 (Thu, 21 Apr 2011) | 14 lines
      
      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:
    trunk/   (props changed)
    trunk/channels/chan_sip.c
    trunk/channels/chan_skinny.c
    trunk/channels/sip/include/sip.h
    trunk/configs/http.conf.sample
    trunk/configs/sip.conf.sample
    trunk/configs/skinny.conf.sample
    trunk/main/http.c
    trunk/main/manager.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=314666&r1=314665&r2=314666
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Thu Apr 21 13:32:50 2011
@@ -559,6 +559,10 @@
 static int default_expiry = DEFAULT_DEFAULT_EXPIRY;
 static int mwi_expiry = DEFAULT_MWI_EXPIRY;
 
+static int unauth_sessions = 0;
+static int authlimit = DEFAULT_AUTHLIMIT;
+static int authtimeout = DEFAULT_AUTHTIMEOUT;
+
 /*! \brief Global jitterbuffer configuration - by default, jb is disabled */
 static struct ast_jb_conf default_jbconf =
 {
@@ -2456,21 +2460,48 @@
 	return _sip_tcp_helper_thread(NULL, tcptls_session);
 }
 
+/*! \brief Check if the authtimeout has expired.
+ * \param start the time when the session started
+ *
+ * \retval 0 the timeout has expired
+ * \retval -1 error
+ * \return the number of milliseconds until the timeout will expire
+ */
+static int sip_check_authtimeout(time_t start)
+{
+	int timeout;
+	time_t now;
+	if(time(&now) == -1) {
+		ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
+		return -1;
+	}
+
+	timeout = (authtimeout - (now - start)) * 1000;
+	if (timeout < 0) {
+		/* we have timed out */
+		return 0;
+	}
+
+	return timeout;
+}
+
 /*! \brief SIP TCP thread management function
 	This function reads from the socket, parses the packet into a request
 */
 static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *tcptls_session)
 {
-	int res, cl;
+	int res, cl, timeout = -1, authenticated = 0, flags;
+	time_t start;
 	struct sip_request req = { 0, } , reqcpy = { 0, };
 	struct sip_threadinfo *me = NULL;
 	char buf[1024] = "";
 	struct pollfd fds[2] = { { 0 }, { 0 }, };
 	struct ast_tcptls_session_args *ca = NULL;
 
-	/* If this is a server session, then the connection has already been setup,
-	 * simply create the threadinfo object so we can access this thread for writing.
-	 * 
+	/* If this is a server session, then the connection has already been
+	 * setup. Check if the authlimit has been reached and if not create the
+	 * threadinfo object so we can access this thread for writing.
+	 *
 	 * if this is a client connection more work must be done.
 	 * 1. We own the parent session args for a client connection.  This pointer needs
 	 *    to be held on to so we can decrement it's ref count on thread destruction.
@@ -2479,6 +2510,22 @@
 	 * 3. Last, the tcptls_session must be started.
 	 */
 	if (!tcptls_session->client) {
+		if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
+			/* unauth_sessions is decremented in the cleanup code */
+			goto cleanup;
+		}
+
+		if ((flags = fcntl(tcptls_session->fd, F_GETFL)) == -1) {
+			ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno));
+			goto cleanup;
+		}
+
+		flags |= O_NONBLOCK;
+		if (fcntl(tcptls_session->fd, F_SETFL, flags) == -1) {
+			ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno));
+			goto cleanup;
+		}
+
 		if (!(me = sip_threadinfo_create(tcptls_session, tcptls_session->ssl ? SIP_TRANSPORT_TLS : SIP_TRANSPORT_TCP))) {
 			goto cleanup;
 		}
@@ -2510,12 +2557,40 @@
 		goto cleanup;
 	}
 
+	if(time(&start) == -1) {
+		ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
+		goto cleanup;
+	}
+
 	for (;;) {
 		struct ast_str *str_save;
 
-		res = ast_poll(fds, 2, -1); /* polls for both socket and alert_pipe */
+		if (!tcptls_session->client && req.authenticated && !authenticated) {
+			authenticated = 1;
+			ast_atomic_fetchadd_int(&unauth_sessions, -1);
+		}
+
+		/* calculate the timeout for unauthenticated server sessions */
+		if (!tcptls_session->client && !authenticated ) {
+			if ((timeout = sip_check_authtimeout(start)) < 0) {
+				goto cleanup;
+			}
+
+			if (timeout == 0) {
+				ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP");
+				goto cleanup;
+			}
+		} else {
+			timeout = -1;
+		}
+
+		res = ast_poll(fds, 2, timeout); /* polls for both socket and alert_pipe */
 		if (res < 0) {
 			ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res);
+			goto cleanup;
+		} else if (res == 0) {
+			/* timeout */
+			ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP");
 			goto cleanup;
 		}
 
@@ -2549,6 +2624,29 @@
 
 			/* Read in headers one line at a time */
 			while (req.len < 4 || strncmp(REQ_OFFSET_TO_STR(&req, len - 4), "\r\n\r\n", 4)) {
+				if (!tcptls_session->client && !authenticated ) {
+					if ((timeout = sip_check_authtimeout(start)) < 0) {
+						goto cleanup;
+					}
+
+					if (timeout == 0) {
+						ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP");
+						goto cleanup;
+					}
+				} else {
+					timeout = -1;
+				}
+
+				res = ast_wait_for_input(tcptls_session->fd, timeout);
+				if (res < 0) {
+					ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res);
+					goto cleanup;
+				} else if (res == 0) {
+					/* timeout */
+					ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP");
+					goto cleanup;
+				}
+
 				ast_mutex_lock(&tcptls_session->lock);
 				if (!fgets(buf, sizeof(buf), tcptls_session->f)) {
 					ast_mutex_unlock(&tcptls_session->lock);
@@ -2567,6 +2665,29 @@
 			if (sscanf(get_header(&reqcpy, "Content-Length"), "%30d", &cl)) {
 				while (cl > 0) {
 					size_t bytes_read;
+					if (!tcptls_session->client && !authenticated ) {
+						if ((timeout = sip_check_authtimeout(start)) < 0) {
+							goto cleanup;
+						}
+
+						if (timeout == 0) {
+							ast_debug(2, "SIP %s server timed out", tcptls_session->ssl ? "SSL": "TCP");
+							goto cleanup;
+						}
+					} else {
+						timeout = -1;
+					}
+
+					res = ast_wait_for_input(tcptls_session->fd, timeout);
+					if (res < 0) {
+						ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res);
+						goto cleanup;
+					} else if (res == 0) {
+						/* timeout */
+						ast_debug(2, "SIP %s server timed out", tcptls_session->ssl ? "SSL": "TCP");
+						goto cleanup;
+					}
+
 					ast_mutex_lock(&tcptls_session->lock);
 					if (!(bytes_read = fread(buf, 1, MIN(sizeof(buf) - 1, cl), tcptls_session->f))) {
 						ast_mutex_unlock(&tcptls_session->lock);
@@ -2626,6 +2747,10 @@
 	ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP");
 
 cleanup:
+	if (!tcptls_session->client && !authenticated) {
+		ast_atomic_fetchadd_int(&unauth_sessions, -1);
+	}
+
 	if (me) {
 		ao2_t_unlink(threadt, me, "Removing tcptls helper thread, thread is closing");
 		ao2_t_ref(me, -1, "Removing tcp_helper_threads threadinfo ref");
@@ -21789,6 +21914,8 @@
 			}
 		}
 
+		req->authenticated = 1;
+
 		/* We have a successful authentication, process the SDP portion if there is one */
 		if (find_sdp(req)) {
 			if (process_sdp(p, req, SDP_T38_INITIATE)) {
@@ -24020,8 +24147,10 @@
 			get_header(req, "To"), ast_sockaddr_stringify(addr),
 			reason);
 		append_history(p, "RegRequest", "Failed : Account %s : %s", get_header(req, "To"), reason);
-	} else
+	} else {
+		req->authenticated = 1;
 		append_history(p, "RegRequest", "Succeeded : Account %s", get_header(req, "To"));
+	}
 
 	if (res < 1) {
 		/* Destroy the session, but keep us around for just a bit in case they don't
@@ -24406,6 +24535,11 @@
 
 	copy_socket_data(&p->socket, &req->socket);
 	ast_sockaddr_copy(&p->recv, addr);
+
+	/* if we have an owner, then this request has been authenticated */
+	if (p->owner) {
+		req->authenticated = 1;
+	}
 
 	if (p->do_history) /* This is a request or response, note what it was for */
 		append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), REQ_OFFSET_TO_STR(req, rlPart2));
@@ -27073,6 +27207,8 @@
 	global_qualifyfreq = DEFAULT_QUALIFYFREQ;
 	global_t38_maxdatagram = -1;
 	global_shrinkcallerid = 1;
+	authlimit = DEFAULT_AUTHLIMIT;
+	authtimeout = DEFAULT_AUTHTIMEOUT;
 
 	sip_cfg.matchexternaddrlocally = DEFAULT_MATCHEXTERNADDRLOCALLY;
 
@@ -27335,6 +27471,18 @@
 			mwi_expiry = atoi(v->value);
 			if (mwi_expiry < 1) {
 				mwi_expiry = DEFAULT_MWI_EXPIRY;
+			}
+		} else if (!strcasecmp(v->name, "tcpauthtimeout")) {
+			if (ast_parse_arg(v->value, PARSE_INT32|PARSE_DEFAULT|PARSE_IN_RANGE,
+					  &authtimeout, DEFAULT_AUTHTIMEOUT, 1, INT_MAX)) {
+				ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n",
+					v->name, v->value, v->lineno, config);
+			}
+		} else if (!strcasecmp(v->name, "tcpauthlimit")) {
+			if (ast_parse_arg(v->value, PARSE_INT32|PARSE_DEFAULT|PARSE_IN_RANGE,
+					  &authlimit, DEFAULT_AUTHLIMIT, 1, INT_MAX)) {
+				ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n",
+					v->name, v->value, v->lineno, config);
 			}
 		} else if (!strcasecmp(v->name, "sipdebug")) {
 			if (ast_true(v->value))

Modified: trunk/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_skinny.c?view=diff&rev=314666&r1=314665&r2=314666
==============================================================================
--- trunk/channels/chan_skinny.c (original)
+++ trunk/channels/chan_skinny.c Thu Apr 21 13:32:50 2011
@@ -164,6 +164,8 @@
 #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 struct {
 	unsigned int tos;
@@ -175,6 +177,9 @@
 } qos = { 0, 0, 0, 0, 0, 0 };
 
 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 global_vmexten[AST_MAX_EXTENSION];      /* Voicemail pilot number */
 static char used_context[AST_MAX_EXTENSION]; /* placeholder to check if context are already used in regcontext */
 static char regcontext[AST_MAX_CONTEXT];     /* Context for auto-extension */
@@ -1374,6 +1379,7 @@
 struct skinnysession {
 	pthread_t t;
 	ast_mutex_t lock;
+	time_t start;
 	struct sockaddr_in sin;
 	int fd;
 	char inbuf[SKINNY_MAX_PACKET];
@@ -6119,6 +6125,7 @@
 		break;
 	case REGISTER_MESSAGE:
 		if (skinny_register(req, s)) {
+			ast_atomic_fetchadd_int(&unauth_sessions, -1);
 			ast_verb(3, "Device '%s' successfully registered\n", s->device->name);
 			transmit_registerack(s->device);
 			transmit_capabilitiesreq(s->device);
@@ -6286,6 +6293,9 @@
 			if (s->fd > -1) 
 				close(s->fd);
 			
+			if (!s->device)
+				ast_atomic_fetchadd_int(&unauth_sessions, -1);
+
 			ast_mutex_destroy(&s->lock);
 			
 			ast_free(s);
@@ -6301,13 +6311,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_verb(1, "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) {
@@ -6316,8 +6343,13 @@
 			return res;
 		}
 	} else if (res == 0) {
-		if (skinnydebug)
-			ast_verb(1, "Skinny Client was lost, unregistering\n");
+		if (skinnydebug) {
+			if (s->device) {
+				ast_verb(1, "Skinny Client was lost, unregistering\n");
+			} else {
+				ast_verb(1, "Skinny Client failed to authenticate in %d seconds\n", auth_timeout);
+			}
+		}
 		skinny_unregister(NULL, s);
 		return -1;
 	}
@@ -6450,18 +6482,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_LIST_LOCK(&sessions);
 		AST_LIST_INSERT_HEAD(&sessions, s, list);
 		AST_LIST_UNLOCK(&sessions);
@@ -6611,6 +6660,26 @@
  			} else if (!strcasecmp(v->name, "keepalive")) {
  				keep_alive = atoi(v->value);
  				continue;
+			} 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;
+				}
+				continue;
+			} 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;
+				}
+				continue;
  			} else if (!strcasecmp(v->name, "regcontext")) {
  				ast_copy_string(newcontexts, v->value, sizeof(newcontexts));
  				stringp = newcontexts;

Modified: trunk/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sip/include/sip.h?view=diff&rev=314666&r1=314665&r2=314666
==============================================================================
--- trunk/channels/sip/include/sip.h (original)
+++ trunk/channels/sip/include/sip.h Thu Apr 21 13:32:50 2011
@@ -58,6 +58,9 @@
 #define DEFAULT_MWI_EXPIRY           3600
 #define DEFAULT_REGISTRATION_TIMEOUT 20
 #define DEFAULT_MAX_FORWARDS         70
+
+#define DEFAULT_AUTHLIMIT            100
+#define DEFAULT_AUTHTIMEOUT          30
 
 /* guard limit must be larger than guard secs */
 /* guard min must be < 1000, and should be >= 250 */
@@ -743,6 +746,7 @@
 	char debug;             /*!< print extra debugging if non zero */
 	char has_to_tag;        /*!< non-zero if packet has To: tag */
 	char ignore;            /*!< if non-zero This is a re-transmit, ignore it */
+	char authenticated;     /*!< non-zero if this request was authenticated */
 	ptrdiff_t header[SIP_MAX_HEADERS]; /*!< Array of offsets into the request string of each SIP header*/
 	ptrdiff_t line[SIP_MAX_LINES];     /*!< Array of offsets into the request string of each SDP line*/
 	struct ast_str *data;	

Modified: trunk/configs/http.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/http.conf.sample?view=diff&rev=314666&r1=314665&r2=314666
==============================================================================
--- trunk/configs/http.conf.sample (original)
+++ trunk/configs/http.conf.sample Thu Apr 21 13:32:50 2011
@@ -33,6 +33,11 @@
 ; all 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
 ;
 ; Whether Asterisk should serve static content from http-static
 ; Default is no.

Modified: trunk/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/sip.conf.sample?view=diff&rev=314666&r1=314665&r2=314666
==============================================================================
--- trunk/configs/sip.conf.sample (original)
+++ trunk/configs/sip.conf.sample Thu Apr 21 13:32:50 2011
@@ -201,6 +201,16 @@
                                 ; certificate, so you don't want to bind a TLS socket to multiple IP addresses.
                                 ; For details how to construct a certificate for SIP see 
                                 ; http://tools.ietf.org/html/draft-ietf-sip-domain-certs
+
+;tcpauthtimeout = 30            ; tcpauthtimeout 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)
+
+;tcpauthlimit = 100             ; tcpauthlimit specifies the maximum number of
+				; unauthenticated sessions that will be allowed
+                                ; to connect at any given time. (default: 100)
 
 srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
                                 ; Note: Asterisk only uses the first host

Modified: trunk/configs/skinny.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/skinny.conf.sample?view=diff&rev=314666&r1=314665&r2=314666
==============================================================================
--- trunk/configs/skinny.conf.sample (original)
+++ trunk/configs/skinny.conf.sample Thu Apr 21 13:32:50 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)
 
 ;vmexten=8500		; Systemwide voicemailmain pilot number
 			; It must be in the same context as the calling

Modified: trunk/main/http.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/http.c?view=diff&rev=314666&r1=314665&r2=314666
==============================================================================
--- trunk/main/http.c (original)
+++ trunk/main/http.c Thu Apr 21 13:32:50 2011
@@ -57,11 +57,15 @@
 #define MAX_PREFIX 80
 #define DEFAULT_PORT 8088
 #define DEFAULT_TLS_PORT 8089
+#define DEFAULT_SESSION_LIMIT 100
 
 /* See http.h for more information about the SSL implementation */
 #if defined(HAVE_OPENSSL) && (defined(HAVE_FUNOPEN) || defined(HAVE_FOPENCOOKIE))
 #define	DO_SSL	/* comment in/out if you want to support ssl */
 #endif
+
+static int session_limit = DEFAULT_SESSION_LIMIT;
+static int session_count = 0;
 
 static struct ast_tls_config http_tls_cfg;
 
@@ -829,6 +833,10 @@
 	char *uri, *method;
 	enum ast_http_method http_method = AST_HTTP_UNKNOWN;
 
+	if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) {
+		goto done;
+	}
+
 	if (!fgets(buf, sizeof(buf), ser->f)) {
 		goto done;
 	}
@@ -894,17 +902,19 @@
 
 	if (!*uri) {
 		ast_http_error(ser, 400, "Bad Request", "Invalid Request");
-		return NULL;
+		goto done;
 	}
 
 	handle_uri(ser, uri, http_method, headers);
 
-	/* Clean up all the header information pulled as well */
+done:
+	ast_atomic_fetchadd_int(&session_count, -1);
+
+	/* clean up all the header information */
 	if (headers) {
 		ast_variables_destroy(headers);
 	}
 
-done:
 	if (ser->f) {
 		fclose(ser->f);
 	}
@@ -1044,6 +1054,12 @@
 				}
 			} else if (!strcasecmp(v->name, "redirect")) {
 				add_redirect(v->value);
+			} else if (!strcasecmp(v->name, "sessionlimit")) {
+				if (ast_parse_arg(v->value, PARSE_INT32|PARSE_DEFAULT|PARSE_IN_RANGE,
+							&session_limit, DEFAULT_SESSION_LIMIT, 1, INT_MAX)) {
+					ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
+							v->name, v->value, v->lineno);
+				}
 			} else {
 				ast_log(LOG_WARNING, "Ignoring unknown option '%s' in http.conf\n", v->name);
 			}

Modified: trunk/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/manager.c?view=diff&rev=314666&r1=314665&r2=314666
==============================================================================
--- trunk/main/manager.c (original)
+++ trunk/main/manager.c Thu Apr 21 13:32:50 2011
@@ -3891,6 +3891,27 @@
 		ast_format_cap_remove_all(cap);
 		ast_parse_allow_disallow(NULL, cap, 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") ||      /* 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.");
+			res = 0;
+			goto fast_orig_cleanup;
+		}
+	}
+
 	/* Allocate requested channel variables */
 	vars = astman_get_variables(m);
 
@@ -3928,22 +3949,6 @@
 			}
 		}
 	} else 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") ||      /* 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.");
-			res = 0;
-			goto fast_orig_cleanup;
-		}
 		res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
 	} else {
 		if (exten && context && pi) {




More information about the asterisk-commits mailing list