[asterisk-commits] lmadsen: tag 1.6.2.18 r315201 - in /tags/1.6.2.18: ./ channels/ configs/ main/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Apr 25 12:20:57 CDT 2011
Author: lmadsen
Date: Mon Apr 25 12:20:45 2011
New Revision: 315201
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=315201
Log:
Update .version, ChangeLog, merge changes from AST-2011-005 and AST-2011-006
Removed:
tags/1.6.2.18/asterisk-1.6.2.18-rc1-summary.html
tags/1.6.2.18/asterisk-1.6.2.18-rc1-summary.txt
Modified:
tags/1.6.2.18/.version
tags/1.6.2.18/ChangeLog
tags/1.6.2.18/channels/chan_sip.c
tags/1.6.2.18/channels/chan_skinny.c
tags/1.6.2.18/configs/http.conf.sample
tags/1.6.2.18/configs/manager.conf.sample
tags/1.6.2.18/configs/sip.conf.sample
tags/1.6.2.18/configs/skinny.conf.sample
tags/1.6.2.18/main/http.c
tags/1.6.2.18/main/manager.c
Modified: tags/1.6.2.18/.version
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.2.18/.version?view=diff&rev=315201&r1=315200&r2=315201
==============================================================================
--- tags/1.6.2.18/.version (original)
+++ tags/1.6.2.18/.version Mon Apr 25 12:20:45 2011
@@ -1,1 +1,1 @@
-1.6.2.18-rc1
+1.6.2.18
Modified: tags/1.6.2.18/ChangeLog
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.2.18/ChangeLog?view=diff&rev=315201&r1=315200&r2=315201
==============================================================================
--- tags/1.6.2.18/ChangeLog (original)
+++ tags/1.6.2.18/ChangeLog Mon Apr 25 12:20:45 2011
@@ -1,3 +1,9 @@
+2011-04-25 Leif Madsen <lmadsen at digium.com>
+
+ * Asterisk 1.6.2.18 Released.
+
+ * AST-2011-005, AST-2011-006
+
2011-02-23 Leif Madsen <lmadsen at digium.com>
* Asterisk 1.6.2.18-rc1 Released.
Modified: tags/1.6.2.18/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.2.18/channels/chan_sip.c?view=diff&rev=315201&r1=315200&r2=315201
==============================================================================
--- tags/1.6.2.18/channels/chan_sip.c (original)
+++ tags/1.6.2.18/channels/chan_sip.c Mon Apr 25 12:20:45 2011
@@ -500,6 +500,8 @@
#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 */
@@ -551,6 +553,10 @@
#define DEFAULT_MIN_SE 90 /*!< Session-Timer Default Min-SE period (RFC 4028) */
#define SDP_MAX_RTPMAP_CODECS 32 /*!< Maximum number of codecs allowed in received SDP */
+
+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 =
@@ -1205,6 +1211,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 */
/* Array of offsets into the request string of each SIP header*/
ptrdiff_t header[SIP_MAX_HEADERS];
/* Array of offsets into the request string of each SDP line*/
@@ -2913,21 +2920,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.
@@ -2936,6 +2970,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;
}
@@ -2965,13 +3015,40 @@
if (!(reqcpy.data = ast_str_create(SIP_MIN_PACKET)))
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;
}
@@ -3005,6 +3082,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);
@@ -3022,6 +3122,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);
@@ -3079,6 +3202,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");
@@ -20471,6 +20598,8 @@
}
}
+ req->authenticated = 1;
+
/* We have a succesful authentication, process the SDP portion if there is one */
if (find_sdp(req)) {
if (process_sdp(p, req, SDP_T38_INITIATE)) {
@@ -22044,8 +22173,10 @@
get_header(req, "To"), ast_inet_ntoa(sin->sin_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
@@ -22499,6 +22630,11 @@
}
}
p->recv = *sin;
+
+ /* 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));
@@ -25062,6 +25198,8 @@
global_qualifyfreq = DEFAULT_QUALIFYFREQ;
global_t38_maxdatagram = -1;
global_shrinkcallerid = 1;
+ authlimit = DEFAULT_AUTHLIMIT;
+ authtimeout = DEFAULT_AUTHTIMEOUT;
sip_cfg.matchexterniplocally = DEFAULT_MATCHEXTERNIPLOCALLY;
@@ -25308,6 +25446,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))
sipdebug |= sip_debug_config;
Modified: tags/1.6.2.18/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.2.18/channels/chan_skinny.c?view=diff&rev=315201&r1=315200&r2=315201
==============================================================================
--- tags/1.6.2.18/channels/chan_skinny.c (original)
+++ tags/1.6.2.18/channels/chan_skinny.c Mon Apr 25 12:20:45 2011
@@ -100,6 +100,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;
@@ -111,6 +113,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 */
@@ -1307,6 +1312,7 @@
struct skinnysession {
pthread_t t;
ast_mutex_t lock;
+ time_t start;
struct sockaddr_in sin;
int fd;
char inbuf[SKINNY_MAX_PACKET];
@@ -4558,6 +4564,8 @@
return 0;
}
+ ast_atomic_fetchadd_int(&unauth_sessions, -1);
+
ast_verb(3, "Device '%s' successfully registered\n", name);
d = s->device;
@@ -6244,6 +6252,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);
@@ -6259,13 +6270,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) {
@@ -6274,8 +6302,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;
}
@@ -6408,18 +6441,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);
@@ -6573,6 +6623,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.6.2.18/configs/http.conf.sample
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.2.18/configs/http.conf.sample?view=diff&rev=315201&r1=315200&r2=315201
==============================================================================
--- tags/1.6.2.18/configs/http.conf.sample (original)
+++ tags/1.6.2.18/configs/http.conf.sample Mon Apr 25 12:20:45 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.6.2.18/configs/manager.conf.sample
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.2.18/configs/manager.conf.sample?view=diff&rev=315201&r1=315200&r2=315201
==============================================================================
--- tags/1.6.2.18/configs/manager.conf.sample (original)
+++ tags/1.6.2.18/configs/manager.conf.sample Mon Apr 25 12:20:45 2011
@@ -24,6 +24,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.6.2.18/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.2.18/configs/sip.conf.sample?view=diff&rev=315201&r1=315200&r2=315201
==============================================================================
--- tags/1.6.2.18/configs/sip.conf.sample (original)
+++ tags/1.6.2.18/configs/sip.conf.sample Mon Apr 25 12:20:45 2011
@@ -143,6 +143,16 @@
; A string specifying which SSL ciphers to use or not use
; A list of valid SSL cipher strings can be found at:
; http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS
+
+;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.6.2.18/configs/skinny.conf.sample
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.2.18/configs/skinny.conf.sample?view=diff&rev=315201&r1=315200&r2=315201
==============================================================================
--- tags/1.6.2.18/configs/skinny.conf.sample (original)
+++ tags/1.6.2.18/configs/skinny.conf.sample Mon Apr 25 12:20:45 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.6.2.18/main/http.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.2.18/main/http.c?view=diff&rev=315201&r1=315200&r2=315201
==============================================================================
--- tags/1.6.2.18/main/http.c (original)
+++ tags/1.6.2.18/main/http.c Mon Apr 25 12:20:45 2011
@@ -53,11 +53,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;
@@ -677,6 +681,10 @@
unsigned int static_content = 0;
struct ast_variable *tail = headers;
+ if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) {
+ goto done;
+ }
+
if (!fgets(buf, sizeof(buf), ser->f)) {
goto done;
}
@@ -787,6 +795,7 @@
}
done:
+ ast_atomic_fetchadd_int(&session_count, -1);
fclose(ser->f);
ao2_ref(ser, -1);
ser = NULL;
@@ -936,6 +945,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.6.2.18/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.2.18/main/manager.c?view=diff&rev=315201&r1=315200&r2=315201
==============================================================================
--- tags/1.6.2.18/main/manager.c (original)
+++ tags/1.6.2.18/main/manager.c Mon Apr 25 12:20:45 2011
@@ -127,6 +127,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;
@@ -135,9 +137,12 @@
static int broken_events_action;
static int manager_enabled = 0;
static int webmanager_enabled = 0;
+static int authtimeout;
+static int authlimit;
static int block_sockets;
static int num_sessions;
+static int unauth_sessions = 0;
static int manager_debug; /*!< enable some debugging code in the manager */
@@ -214,6 +219,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 */
AST_LIST_HEAD_NOLOCK(mansession_datastores, ast_datastore) datastores; /*!< Data stores on the session */
AST_LIST_ENTRY(mansession_session) list;
@@ -1787,6 +1793,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));
ast_log(LOG_EVENT, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
@@ -2499,6 +2506,25 @@
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);
@@ -2532,21 +2558,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)
@@ -3121,6 +3132,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
@@ -3148,6 +3161,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;
+ }
+ }
+
/* XXX do we really need this locking ? */
ast_mutex_lock(&s->session->__lock);
if (s->session->pending_event) {
@@ -3158,7 +3185,7 @@
s->session->waiting_thread = pthread_self();
ast_mutex_unlock(&s->session->__lock);
- res = ast_wait_for_input(s->session->fd, -1); /* return 0 on timeout ? */
+ res = ast_wait_for_input(s->session->fd, timeout);
ast_mutex_lock(&s->session->__lock);
s->session->waiting_thread = AST_PTHREADT_NULL;
@@ -3191,6 +3218,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 */
@@ -3198,6 +3226,17 @@
return -1;
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) {
+ 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) {
if (ast_strlen_zero(header_buf))
@@ -3221,14 +3260,23 @@
static void *session_do(void *data)
{
struct ast_tcptls_session_instance *ser = data;
- struct mansession_session *session = ast_calloc(1, sizeof(*session));
+ struct mansession_session *session = NULL;
struct mansession s = {.session = NULL, };
int flags;
int res;
struct protoent *p;
- if (session == NULL)
+ if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
+ fclose(ser->f);
+ ast_atomic_fetchadd_int(&unauth_sessions, -1);
goto done;
+ }
+
+ if ((session = ast_calloc(1, sizeof(*session))) == NULL) {
+ fclose(ser->f);
+ ast_atomic_fetchadd_int(&unauth_sessions, -1);
+ goto done;
+ }
/* here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
* This is necessary to prevent delays (caused by buffering) as we
@@ -3271,6 +3319,13 @@
ast_atomic_fetchadd_int(&num_sessions, 1);
AST_LIST_UNLOCK(&sessions);
+ 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);
+ destroy_session(session);
+ goto done;
+ }
+
astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */
for (;;) {
if ((res = do_message(&s)) < 0)
@@ -3282,6 +3337,7 @@
ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
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 (displayconnects)
ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
ast_log(LOG_EVENT, "Failed attempt from %s\n", ast_inet_ntoa(session->sin.sin_addr));
@@ -4177,6 +4233,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");
@@ -4241,6 +4299,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 {
ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n",
var->name, val);
More information about the asterisk-commits
mailing list