mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-01 19:43:03 +00:00
Merged revisions 312764 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.6.2 ................ r312764 | mnicholson | 2011-04-05 09:13:07 -0500 (Tue, 05 Apr 2011) | 15 lines Merged revisions 312761 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r312761 | mnicholson | 2011-04-05 09:10:34 -0500 (Tue, 05 Apr 2011) | 8 lines 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 ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@312766 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -63,6 +63,17 @@ bindaddr = 0.0.0.0
|
||||
; 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
|
||||
; b) httptimeout is the amount of time the webserver waits
|
||||
|
||||
@@ -860,6 +860,8 @@ static const int DEFAULT_DISPLAYCONNECTS = 1; /*!< Default setting for displayin
|
||||
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 httptimeout;
|
||||
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 @@ struct mansession_session {
|
||||
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;
|
||||
@@ -2935,6 +2941,7 @@ static int action_login(struct mansession *s, const struct message *m)
|
||||
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));
|
||||
}
|
||||
@@ -4522,6 +4529,8 @@ static int get_input(struct mansession *s, char *output)
|
||||
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
|
||||
@@ -4550,6 +4559,20 @@ static int get_input(struct mansession *s, char *output)
|
||||
}
|
||||
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;
|
||||
@@ -4559,7 +4582,7 @@ static int get_input(struct mansession *s, char *output)
|
||||
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;
|
||||
@@ -4594,6 +4617,7 @@ static int do_message(struct mansession *s)
|
||||
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 */
|
||||
@@ -4602,6 +4626,19 @@ static int do_message(struct mansession *s)
|
||||
}
|
||||
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)) {
|
||||
@@ -4635,10 +4672,18 @@ static void *session_do(void *data)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -4677,7 +4722,15 @@ static void *session_do(void *data)
|
||||
|
||||
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 || s.write_error) {
|
||||
@@ -4690,6 +4743,7 @@ static void *session_do(void *data)
|
||||
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));
|
||||
}
|
||||
@@ -6202,6 +6256,8 @@ static int __init_manager(int reload)
|
||||
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");
|
||||
@@ -6264,6 +6320,22 @@ static int __init_manager(int reload)
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user