[asterisk-commits] lmadsen: tag 1.8.4-rc3 r315145 - in /tags/1.8.4-rc3: channels/ channels/sip/i...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Apr 25 10:11:37 CDT 2011


Author: lmadsen
Date: Mon Apr 25 10:11:30 2011
New Revision: 315145

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

Modified:
    tags/1.8.4-rc3/channels/chan_sip.c
    tags/1.8.4-rc3/channels/chan_skinny.c
    tags/1.8.4-rc3/channels/sip/include/sip.h
    tags/1.8.4-rc3/configs/http.conf.sample
    tags/1.8.4-rc3/configs/manager.conf.sample
    tags/1.8.4-rc3/configs/sip.conf.sample
    tags/1.8.4-rc3/configs/skinny.conf.sample
    tags/1.8.4-rc3/main/http.c
    tags/1.8.4-rc3/main/manager.c
    tags/1.8.4-rc3/main/tcptls.c

Modified: tags/1.8.4-rc3/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.8.4-rc3/channels/chan_sip.c?view=diff&rev=315145&r1=315144&r2=315145
==============================================================================
--- tags/1.8.4-rc3/channels/chan_sip.c (original)
+++ tags/1.8.4-rc3/channels/chan_sip.c Mon Apr 25 10:11:30 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 =
 {
@@ -2438,21 +2442,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.
@@ -2461,6 +2492,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;
 		}
@@ -2492,12 +2539,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;
 		}
 
@@ -2531,6 +2606,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);
@@ -2549,6 +2647,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);
@@ -2607,6 +2728,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");
@@ -21378,6 +21503,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)) {
@@ -23608,8 +23735,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
@@ -24095,6 +24224,11 @@
 		}
 	}
 	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));
@@ -26753,6 +26887,8 @@
 	global_qualifyfreq = DEFAULT_QUALIFYFREQ;
 	global_t38_maxdatagram = -1;
 	global_shrinkcallerid = 1;
+	authlimit = DEFAULT_AUTHLIMIT;
+	authtimeout = DEFAULT_AUTHTIMEOUT;
 
 	sip_cfg.matchexternaddrlocally = DEFAULT_MATCHEXTERNADDRLOCALLY;
 
@@ -27014,6 +27150,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: tags/1.8.4-rc3/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.8.4-rc3/channels/chan_skinny.c?view=diff&rev=315145&r1=315144&r2=315145
==============================================================================
--- tags/1.8.4-rc3/channels/chan_skinny.c (original)
+++ tags/1.8.4-rc3/channels/chan_skinny.c Mon Apr 25 10:11:30 2011
@@ -157,6 +157,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;
@@ -168,6 +170,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 */
@@ -1364,6 +1369,7 @@
 struct skinnysession {
 	pthread_t t;
 	ast_mutex_t lock;
+	time_t start;
 	struct sockaddr_in sin;
 	int fd;
 	char inbuf[SKINNY_MAX_PACKET];
@@ -4785,6 +4791,8 @@
 
 		return 0;
 	}
+	ast_atomic_fetchadd_int(&unauth_sessions, -1);
+
 	ast_verb(3, "Device '%s' successfully registered\n", name);
 
 	d = s->device;
@@ -6322,6 +6330,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);
@@ -6337,13 +6348,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) {
@@ -6352,8 +6380,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;
 	}
@@ -6486,18 +6519,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);
@@ -6651,6 +6701,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: tags/1.8.4-rc3/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/tags/1.8.4-rc3/channels/sip/include/sip.h?view=diff&rev=315145&r1=315144&r2=315145
==============================================================================
--- tags/1.8.4-rc3/channels/sip/include/sip.h (original)
+++ tags/1.8.4-rc3/channels/sip/include/sip.h Mon Apr 25 10:11:30 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 */
@@ -744,6 +747,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: tags/1.8.4-rc3/configs/http.conf.sample
URL: http://svnview.digium.com/svn/asterisk/tags/1.8.4-rc3/configs/http.conf.sample?view=diff&rev=315145&r1=315144&r2=315145
==============================================================================
--- tags/1.8.4-rc3/configs/http.conf.sample (original)
+++ tags/1.8.4-rc3/configs/http.conf.sample Mon Apr 25 10:11:30 2011
@@ -31,6 +31,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: tags/1.8.4-rc3/configs/manager.conf.sample
URL: http://svnview.digium.com/svn/asterisk/tags/1.8.4-rc3/configs/manager.conf.sample?view=diff&rev=315145&r1=315144&r2=315145
==============================================================================
--- tags/1.8.4-rc3/configs/manager.conf.sample (original)
+++ tags/1.8.4-rc3/configs/manager.conf.sample Mon Apr 25 10:11:30 2011
@@ -62,6 +62,17 @@
 
 ; debug = on	; enable some debugging info in AMI messages (default off).
 		; Also accessible through the "manager debug" CLI command.
+
+; 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.8.4-rc3/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/tags/1.8.4-rc3/configs/sip.conf.sample?view=diff&rev=315145&r1=315144&r2=315145
==============================================================================
--- tags/1.8.4-rc3/configs/sip.conf.sample (original)
+++ tags/1.8.4-rc3/configs/sip.conf.sample Mon Apr 25 10:11:30 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: tags/1.8.4-rc3/configs/skinny.conf.sample
URL: http://svnview.digium.com/svn/asterisk/tags/1.8.4-rc3/configs/skinny.conf.sample?view=diff&rev=315145&r1=315144&r2=315145
==============================================================================
--- tags/1.8.4-rc3/configs/skinny.conf.sample (original)
+++ tags/1.8.4-rc3/configs/skinny.conf.sample Mon Apr 25 10:11:30 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: tags/1.8.4-rc3/main/http.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.8.4-rc3/main/http.c?view=diff&rev=315145&r1=315144&r2=315145
==============================================================================
--- tags/1.8.4-rc3/main/http.c (original)
+++ tags/1.8.4-rc3/main/http.c Mon Apr 25 10:11:30 2011
@@ -55,11 +55,15 @@
 #include "asterisk/astobj2.h"
 
 #define MAX_PREFIX 80
+#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;
 
@@ -844,6 +848,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;
 	}
@@ -909,17 +917,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);
 	}
@@ -1071,6 +1081,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: tags/1.8.4-rc3/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.8.4-rc3/main/manager.c?view=diff&rev=315145&r1=315144&r2=315145
==============================================================================
--- tags/1.8.4-rc3/main/manager.c (original)
+++ tags/1.8.4-rc3/main/manager.c Mon Apr 25 10:11:30 2011
@@ -860,6 +860,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 displayconnects;
 static int allowmultiplelogin = 1;
@@ -868,12 +870,15 @@
 static int broken_events_action;
 static int manager_enabled = 0;
 static int webmanager_enabled = 0;
+static int authtimeout;
+static int authlimit;
 static char *manager_channelvars;
 
 #define DEFAULT_REALM		"asterisk"
 static char global_realm[MAXHOSTNAMELEN];	/*!< Default realm */
 
 static int block_sockets;
+static int unauth_sessions = 0;
 
 static int manager_debug;	/*!< enable some debugging code in the manager */
 
@@ -951,6 +956,7 @@
 	int send_events;	/*!<  XXX what ? */
 	struct eventqent *last_ev;	/*!< last event processed. */
 	int writetimeout;	/*!< Timeout for ast_carefulwrite() */
+	time_t authstart;
 	int pending_event;         /*!< Pending events indicator in case when waiting_thread is NULL */
 	time_t noncetime;	/*!< Timer for nonce value expiration */
 	struct ao2_container *whitefilters;
@@ -2928,6 +2934,7 @@
 		return -1;
 	}
 	s->session->authenticated = 1;
+	ast_atomic_fetchadd_int(&unauth_sessions, -1);
 	if (manager_displayconnects(s->session)) {
 		ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
 	}
@@ -3870,6 +3877,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") ||      /* 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);
 
@@ -3905,21 +3930,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.");
-			return 0;
-		}
 		res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
 	} else {
 		if (exten && context && pi) {
@@ -4511,6 +4521,8 @@
 	int res, x;
 	int maxlen = sizeof(s->session->inbuf) - 1;
 	char *src = s->session->inbuf;
+	int timeout = -1;
+	time_t now;
 
 	/*
 	 * Look for \r\n within the buffer. If found, copy to the output
@@ -4539,6 +4551,20 @@
 	}
 	res = 0;
 	while (res == 0) {
+		/* calculate a timeout if we are not authenticated */
+		if (!s->session->authenticated) {
+			if(time(&now) == -1) {
+				ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
+				return -1;
+			}
+
+			timeout = (authtimeout - (now - s->session->authstart)) * 1000;
+			if (timeout < 0) {
+				/* we have timed out */
+				return 0;
+			}
+		}
+
 		ao2_lock(s->session);
 		if (s->session->pending_event) {
 			s->session->pending_event = 0;
@@ -4548,7 +4574,7 @@
 		s->session->waiting_thread = pthread_self();
 		ao2_unlock(s->session);
 
-		res = ast_wait_for_input(s->session->fd, -1);	/* return 0 on timeout ? */
+		res = ast_wait_for_input(s->session->fd, timeout);
 
 		ao2_lock(s->session);
 		s->session->waiting_thread = AST_PTHREADT_NULL;
@@ -4583,6 +4609,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 */
@@ -4591,6 +4618,19 @@
 		}
 		res = get_input(s, 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) {
+					if (displayconnects) {
+						ast_verb(2, "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) {
 			if (ast_strlen_zero(header_buf)) {
@@ -4624,10 +4664,18 @@
 	struct sockaddr_in ser_remote_address_tmp;
 	struct protoent *p;
 
+	if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
+		fclose(ser->f);
+		ast_atomic_fetchadd_int(&unauth_sessions, -1);
+		goto done;
+	}
+
 	ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
 	session = build_mansession(ser_remote_address_tmp);
 
 	if (session == NULL) {
+		fclose(ser->f);
+		ast_atomic_fetchadd_int(&unauth_sessions, -1);
 		goto done;
 	}
 
@@ -4666,7 +4714,15 @@
 
 	AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
 
+	if(time(&session->authstart) == -1) {
+		ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
+		ast_atomic_fetchadd_int(&unauth_sessions, -1);
+		ao2_unlock(session);
+		session_destroy(session);
+		goto done;
+	}
 	ao2_unlock(session);
+
 	astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION);	/* welcome prompt */
 	for (;;) {
 		if ((res = do_message(&s)) < 0) {
@@ -4679,6 +4735,7 @@
 			ast_verb(2, "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 (displayconnects) {
 			ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
 		}
@@ -6191,6 +6248,8 @@
 	block_sockets = DEFAULT_BLOCKSOCKETS;
 	timestampevents = DEFAULT_TIMESTAMPEVENTS;
 	httptimeout = DEFAULT_HTTPTIMEOUT;
+	authtimeout = DEFAULT_AUTHTIMEOUT;
+	authlimit = DEFAULT_AUTHLIMIT;
 
 	if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
 		ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf, or configuration is invalid. Asterisk management interface (AMI) disabled.\n");
@@ -6253,6 +6312,22 @@
 			manager_debug = ast_true(val);
 		} else if (!strcasecmp(var->name, "httptimeout")) {
 			newhttptimeout = atoi(val);
+		} else if (!strcasecmp(var->name, "authtimeout")) {
+			int timeout = atoi(var->value);
+
+			if (timeout < 1) {
+				ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", var->value);
+			} else {
+				authtimeout = timeout;
+			}
+		} else if (!strcasecmp(var->name, "authlimit")) {
+			int limit = atoi(var->value);
+
+			if (limit < 1) {
+				ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", var->value);
+			} else {
+				authlimit = limit;
+			}
 		} else if (!strcasecmp(var->name, "channelvars")) {
 			struct manager_channel_variable *mcv;
 			char *remaining = ast_strdupa(val), *next;

Modified: tags/1.8.4-rc3/main/tcptls.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.8.4-rc3/main/tcptls.c?view=diff&rev=315145&r1=315144&r2=315145
==============================================================================
--- tags/1.8.4-rc3/main/tcptls.c (original)
+++ tags/1.8.4-rc3/main/tcptls.c Mon Apr 25 10:11:30 2011
@@ -293,9 +293,12 @@
 	SSLeay_add_ssl_algorithms();
 
 	if (client) {
+#ifndef OPENSSL_NO_SSL2
 		if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) {
 			cfg->ssl_ctx = SSL_CTX_new(SSLv2_client_method());
-		} else if (ast_test_flag(&cfg->flags, AST_SSL_SSLV3_CLIENT)) {
+		} else
+#endif
+		if (ast_test_flag(&cfg->flags, AST_SSL_SSLV3_CLIENT)) {
 			cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
 		} else if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) {
 			cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method());




More information about the asterisk-commits mailing list