[asterisk-commits] mnicholson: branch 1.6.1 r312763 - in /branches/1.6.1: configs/ main/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Apr 5 09:11:50 CDT 2011
Author: mnicholson
Date: Tue Apr 5 09:11:46 2011
New Revision: 312763
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=312763
Log:
Limit the number of unauthenticated manager sessions and also limit the time they have to authenticate.
AST-2011-005
(closes issue #18996)
Reported by: tzafrir
Tested by: mnicholson
Modified:
branches/1.6.1/configs/manager.conf.sample
branches/1.6.1/main/manager.c
Modified: branches/1.6.1/configs/manager.conf.sample
URL: http://svnview.digium.com/svn/asterisk/branches/1.6.1/configs/manager.conf.sample?view=diff&rev=312763&r1=312762&r2=312763
==============================================================================
--- branches/1.6.1/configs/manager.conf.sample (original)
+++ branches/1.6.1/configs/manager.conf.sample Tue Apr 5 09:11:46 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: branches/1.6.1/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.6.1/main/manager.c?view=diff&rev=312763&r1=312762&r2=312763
==============================================================================
--- branches/1.6.1/main/manager.c (original)
+++ branches/1.6.1/main/manager.c Tue Apr 5 09:11:46 2011
@@ -119,6 +119,9 @@
static AST_LIST_HEAD_STATIC(all_events, eventqent);
+#define DEFAULT_AUTHTIMEOUT 30
+#define DEFAULT_AUTHLIMIT 50
+
static int displayconnects = 1;
static int allowmultiplelogin = 1;
static int timestampevents;
@@ -126,9 +129,12 @@
static int broken_events_action = 0;
static int manager_enabled = 0;
static int webmanager_enabled = 0;
+static int authtimeout = DEFAULT_AUTHTIMEOUT;
+static int authlimit = DEFAULT_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 */
@@ -206,6 +212,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;
@@ -1754,6 +1761,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));
@@ -3074,6 +3082,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
@@ -3101,6 +3111,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) {
@@ -3111,7 +3135,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;
@@ -3144,6 +3168,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 */
@@ -3151,6 +3176,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))
@@ -3174,13 +3210,22 @@
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;
- 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;
+ }
session->writetimeout = 100;
session->waiting_thread = AST_PTHREADT_NULL;
@@ -3210,6 +3255,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 || s.write_error)
@@ -3221,6 +3273,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));
@@ -4187,6 +4240,24 @@
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);
+ authtimeout = DEFAULT_AUTHTIMEOUT;
+ } 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);
+ authlimit = DEFAULT_AUTHLIMIT;
+ } 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