mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
AST-2014-007: Fix DOS by consuming the number of allowed HTTP connections.
Simply establishing a TCP connection and never sending anything to the configured HTTP port in http.conf will tie up a HTTP connection. Since there is a maximum number of open HTTP sessions allowed at a time you can block legitimate connections. A similar problem exists if a HTTP request is started but never finished. * Added http.conf session_inactivity timer option to close HTTP connections that aren't doing anything. Defaults to 30000 ms. * Removed the undocumented manager.conf block-sockets option. It interferes with TCP/TLS inactivity timeouts. * AMI and SIP TLS connections now have better authentication timeout protection. Though I didn't remove the bizzare TLS timeout polling code from chan_sip. * chan_sip can now handle SSL certificate renegotiations in the middle of a session. It couldn't do that before because the socket was non-blocking and the SSL calls were not restarted as documented by the OpenSSL documentation. * Fixed an off nominal leak of the ssl struct in handle_tcptls_connection() if the FILE stream failed to open and the SSL certificate negotiations failed. The patch creates a custom FILE stream handler to give the created FILE streams inactivity timeout and timeout after a specific moment in time capability. This approach eliminates the need for code using the FILE stream to be redesigned to deal with the timeouts. This patch indirectly fixes most of ASTERISK-18345 by fixing the usage of the SSL_read/SSL_write operations. ASTERISK-23673 #close Reported by: Richard Mudgett ........ Merged revisions 415841 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 415854 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/12@415896 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -1123,7 +1123,6 @@ 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 struct stasis_subscription *acl_change_sub;
|
||||
|
||||
@@ -1770,15 +1769,7 @@ static void session_destructor(void *obj)
|
||||
}
|
||||
|
||||
if (session->f != NULL) {
|
||||
/*
|
||||
* Issuing shutdown() is necessary here to avoid a race
|
||||
* condition where the last data written may not appear
|
||||
* in the the TCP stream. See ASTERISK-23548
|
||||
*/
|
||||
fflush(session->f);
|
||||
if (session->fd != -1) {
|
||||
shutdown(session->fd, SHUT_RDWR);
|
||||
}
|
||||
fclose(session->f);
|
||||
}
|
||||
if (eqe) {
|
||||
@@ -5886,12 +5877,9 @@ static void *session_do(void *data)
|
||||
ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY, getprotobyname(\"tcp\") failed\nSome manager actions may be slow to respond.\n");
|
||||
}
|
||||
|
||||
/* make sure socket is non-blocking */
|
||||
flags = fcntl(ser->fd, F_GETFL);
|
||||
if (!block_sockets) { /* make sure socket is non-blocking */
|
||||
flags |= O_NONBLOCK;
|
||||
} else {
|
||||
flags &= ~O_NONBLOCK;
|
||||
}
|
||||
flags |= O_NONBLOCK;
|
||||
fcntl(ser->fd, F_SETFL, flags);
|
||||
|
||||
ao2_lock(session);
|
||||
@@ -5917,11 +5905,17 @@ static void *session_do(void *data)
|
||||
}
|
||||
ao2_unlock(session);
|
||||
|
||||
ast_tcptls_stream_set_timeout_sequence(ser->stream_cookie,
|
||||
ast_tvnow(), authtimeout * 1000);
|
||||
|
||||
astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */
|
||||
for (;;) {
|
||||
if ((res = do_message(&s)) < 0 || s.write_error) {
|
||||
break;
|
||||
}
|
||||
if (session->authenticated) {
|
||||
ast_tcptls_stream_set_timeout_disable(ser->stream_cookie);
|
||||
}
|
||||
}
|
||||
/* session is over, explain why and terminate */
|
||||
if (session->authenticated) {
|
||||
@@ -6728,6 +6722,30 @@ static void xml_translate(struct ast_str **out, char *in, struct ast_variable *g
|
||||
}
|
||||
}
|
||||
|
||||
static void close_mansession_file(struct mansession *s)
|
||||
{
|
||||
if (s->f) {
|
||||
if (fclose(s->f)) {
|
||||
ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno));
|
||||
}
|
||||
s->f = NULL;
|
||||
s->fd = -1;
|
||||
} else if (s->fd != -1) {
|
||||
/*
|
||||
* Issuing shutdown() is necessary here to avoid a race
|
||||
* condition where the last data written may not appear
|
||||
* in the TCP stream. See ASTERISK-23548
|
||||
*/
|
||||
shutdown(s->fd, SHUT_RDWR);
|
||||
if (close(s->fd)) {
|
||||
ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno));
|
||||
}
|
||||
s->fd = -1;
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Attempted to close file/file descriptor on mansession without a valid file or file descriptor.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void process_output(struct mansession *s, struct ast_str **out, struct ast_variable *params, enum output_format format)
|
||||
{
|
||||
char *buf;
|
||||
@@ -6755,29 +6773,7 @@ static void process_output(struct mansession *s, struct ast_str **out, struct as
|
||||
xml_translate(out, "", params, format);
|
||||
}
|
||||
|
||||
if (s->f) {
|
||||
/*
|
||||
* Issuing shutdown() is necessary here to avoid a race
|
||||
* condition where the last data written may not appear
|
||||
* in the the TCP stream. See ASTERISK-23548
|
||||
*/
|
||||
if (s->fd != -1) {
|
||||
shutdown(s->fd, SHUT_RDWR);
|
||||
}
|
||||
if (fclose(s->f)) {
|
||||
ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno));
|
||||
}
|
||||
s->f = NULL;
|
||||
s->fd = -1;
|
||||
} else if (s->fd != -1) {
|
||||
shutdown(s->fd, SHUT_RDWR);
|
||||
if (close(s->fd)) {
|
||||
ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno));
|
||||
}
|
||||
s->fd = -1;
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "process output attempted to close file/file descriptor on mansession without a valid file or file descriptor.\n");
|
||||
}
|
||||
close_mansession_file(s);
|
||||
}
|
||||
|
||||
static int generic_http_callback(struct ast_tcptls_session_instance *ser,
|
||||
@@ -7568,7 +7564,6 @@ static char *handle_manager_show_settings(struct ast_cli_entry *e, int cmd, stru
|
||||
ast_cli(a->fd, FORMAT, "Timestamp events:", AST_CLI_YESNO(timestampevents));
|
||||
ast_cli(a->fd, FORMAT, "Channel vars:", S_OR(manager_channelvars, ""));
|
||||
ast_cli(a->fd, FORMAT, "Debug:", AST_CLI_YESNO(manager_debug));
|
||||
ast_cli(a->fd, FORMAT, "Block sockets:", AST_CLI_YESNO(block_sockets));
|
||||
#undef FORMAT
|
||||
#undef FORMAT2
|
||||
|
||||
@@ -8171,8 +8166,6 @@ static int __init_manager(int reload, int by_external_config)
|
||||
|
||||
if (!strcasecmp(var->name, "enabled")) {
|
||||
manager_enabled = ast_true(val);
|
||||
} else if (!strcasecmp(var->name, "block-sockets")) {
|
||||
block_sockets = ast_true(val);
|
||||
} else if (!strcasecmp(var->name, "webenabled")) {
|
||||
webmanager_enabled = ast_true(val);
|
||||
} else if (!strcasecmp(var->name, "port")) {
|
||||
|
Reference in New Issue
Block a user