summaryrefslogtreecommitdiff
path: root/main/http.c
diff options
context:
space:
mode:
authorAshley Sanders <asanders@digium.com>2015-01-30 16:52:12 +0000
committerAshley Sanders <asanders@digium.com>2015-01-30 16:52:12 +0000
commit112d23c73e0a81f5870ba9f58aa588b89ae31c44 (patch)
tree7c4896840f1c084aebe51c9e9c6206c1c50f62d2 /main/http.c
parent43dd42d8aeee1eff844f605544901016047348e2 (diff)
HTTP: For httpd server, need option to define server name for security purposes
Added a new config property [servername] to the http.conf file; updated the http server to use the new property when sending responses, for showing http status through the CLI and when reporting status through the 'httpstatus' webpage. ASTERISK-24316 #close Reported By: Andrew Nagy Review: https://reviewboard.asterisk.org/r/4374/ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@431471 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/http.c')
-rw-r--r--main/http.c172
1 files changed, 113 insertions, 59 deletions
diff --git a/main/http.c b/main/http.c
index a9e50cbc2..ef3b4b22b 100644
--- a/main/http.c
+++ b/main/http.c
@@ -77,6 +77,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define MIN_INITIAL_REQUEST_TIMEOUT 10000
/*! (ms) Idle time between HTTP requests */
#define DEFAULT_SESSION_KEEP_ALIVE 15000
+/*! Max size for the http server name */
+#define MAX_SERVER_NAME_LENGTH 128
+/*! Max size for the http response header */
+#define DEFAULT_RESPONSE_HEADER_LENGTH 512
/*! Maximum application/json or application/x-www-form-urlencoded body content length. */
#if !defined(LOW_MEMORY)
@@ -92,6 +96,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define MAX_HTTP_LINE_LENGTH 1024
#endif /* !defined(LOW_MEMORY) */
+static char http_server_name[MAX_SERVER_NAME_LENGTH];
+
static int session_limit = DEFAULT_SESSION_LIMIT;
static int session_inactivity = DEFAULT_SESSION_INACTIVITY;
static int session_keep_alive = DEFAULT_SESSION_KEEP_ALIVE;
@@ -375,6 +381,7 @@ static int httpstatus_callback(struct ast_tcptls_session_instance *ser,
"<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n"
"<h2>&nbsp;&nbsp;Asterisk&trade; HTTP Status</h2></td></tr>\r\n");
+ ast_str_append(&out, 0, "<tr><td><i>Server</i></td><td><b>%s</b></td></tr>\r\n", http_server_name);
ast_str_append(&out, 0, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix);
ast_str_append(&out, 0, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
ast_sockaddr_stringify_addr(&http_desc.old_address));
@@ -446,14 +453,23 @@ void ast_http_send(struct ast_tcptls_session_instance *ser,
char timebuf[80];
int content_length = 0;
int close_connection;
+ struct ast_str *server_header_field = ast_str_create(MAX_SERVER_NAME_LENGTH);
- if (!ser || !ser->f) {
+ if (!ser || !ser->f || !server_header_field) {
/* The connection is not open. */
ast_free(http_header);
ast_free(out);
+ ast_free(server_header_field);
return;
}
+ if(!ast_strlen_zero(http_server_name)) {
+ ast_str_set(&server_header_field,
+ 0,
+ "Server: %s\r\n",
+ http_server_name);
+ }
+
/*
* We shouldn't be sending non-final status codes to this
* function because we may close the connection before
@@ -491,7 +507,7 @@ void ast_http_send(struct ast_tcptls_session_instance *ser,
/* send http header */
fprintf(ser->f,
"HTTP/1.1 %d %s\r\n"
- "Server: Asterisk/%s\r\n"
+ "%s"
"Date: %s\r\n"
"%s"
"%s"
@@ -499,7 +515,7 @@ void ast_http_send(struct ast_tcptls_session_instance *ser,
"Content-Length: %d\r\n"
"\r\n",
status_code, status_title ? status_title : "OK",
- ast_get_version(),
+ ast_str_buffer(server_header_field),
timebuf,
close_connection ? "Connection: close\r\n" : "",
static_content ? "" : "Cache-Control: no-cache, no-store\r\n",
@@ -532,6 +548,7 @@ void ast_http_send(struct ast_tcptls_session_instance *ser,
ast_free(http_header);
ast_free(out);
+ ast_free(server_header_field);
if (close_connection) {
ast_debug(1, "HTTP closing session. status_code:%d\n", status_code);
@@ -541,76 +558,101 @@ void ast_http_send(struct ast_tcptls_session_instance *ser,
}
}
-void ast_http_auth(struct ast_tcptls_session_instance *ser, const char *realm,
- const unsigned long nonce, const unsigned long opaque, int stale,
- const char *text)
+void ast_http_create_response(struct ast_tcptls_session_instance *ser, int status_code,
+ const char *status_title, struct ast_str *http_header_data, const char *text)
{
- struct ast_str *http_headers = ast_str_create(128);
- struct ast_str *out = ast_str_create(512);
+ char server_name[MAX_SERVER_NAME_LENGTH];
+ struct ast_str *server_address = ast_str_create(MAX_SERVER_NAME_LENGTH);
+ struct ast_str *out = ast_str_create(MAX_CONTENT_LENGTH);
- if (!http_headers || !out) {
- ast_free(http_headers);
+ if (!http_header_data || !server_address || !out) {
+ ast_free(http_header_data);
+ ast_free(server_address);
ast_free(out);
if (ser && ser->f) {
- ast_debug(1, "HTTP closing session. Auth OOM\n");
+ ast_debug(1, "HTTP closing session. OOM.\n");
ast_tcptls_close_session_file(ser);
}
return;
}
- ast_str_set(&http_headers, 0,
- "WWW-authenticate: Digest algorithm=MD5, realm=\"%s\", nonce=\"%08lx\", qop=\"auth\", opaque=\"%08lx\"%s\r\n"
- "Content-type: text/html\r\n",
- realm ? realm : "Asterisk",
- nonce,
- opaque,
- stale ? ", stale=true" : "");
-
- ast_str_set(&out, 0,
- "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
- "<html><head>\r\n"
- "<title>401 Unauthorized</title>\r\n"
- "</head><body>\r\n"
- "<h1>401 Unauthorized</h1>\r\n"
- "<p>%s</p>\r\n"
- "<hr />\r\n"
- "<address>Asterisk Server</address>\r\n"
- "</body></html>\r\n",
- text ? text : "");
-
- ast_http_send(ser, AST_HTTP_UNKNOWN, 401, "Unauthorized", http_headers, out, 0, 0);
+ if(!ast_strlen_zero(http_server_name)) {
+ ast_xml_escape(http_server_name, server_name, sizeof(server_name));
+ ast_str_set(&server_address,
+ 0,
+ "<address>%s</address>\r\n",
+ server_name);
+ }
+
+ ast_str_set(&out,
+ 0,
+ "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
+ "<html><head>\r\n"
+ "<title>%d %s</title>\r\n"
+ "</head><body>\r\n"
+ "<h1>%s</h1>\r\n"
+ "<p>%s</p>\r\n"
+ "<hr />\r\n"
+ "%s"
+ "</body></html>\r\n",
+ status_code,
+ status_title,
+ status_title,
+ text ? text : "",
+ ast_str_buffer(server_address));
+
+ ast_free(server_address);
+
+ ast_http_send(ser,
+ AST_HTTP_UNKNOWN,
+ status_code,
+ status_title,
+ http_header_data,
+ out,
+ 0,
+ 0);
}
-void ast_http_error(struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, const char *text)
+void ast_http_auth(struct ast_tcptls_session_instance *ser, const char *realm,
+ const unsigned long nonce, const unsigned long opaque, int stale,
+ const char *text)
{
- struct ast_str *http_headers = ast_str_create(40);
- struct ast_str *out = ast_str_create(256);
-
- if (!http_headers || !out) {
- ast_free(http_headers);
- ast_free(out);
- if (ser && ser->f) {
- ast_debug(1, "HTTP closing session. error OOM\n");
- ast_tcptls_close_session_file(ser);
- }
- return;
- }
+ int status_code = 401;
+ char *status_title = "Unauthorized";
+ struct ast_str *http_header_data = ast_str_create(DEFAULT_RESPONSE_HEADER_LENGTH);
+
+ if (http_header_data) {
+ ast_str_set(&http_header_data,
+ 0,
+ "WWW-authenticate: Digest algorithm=MD5, realm=\"%s\", nonce=\"%08lx\", qop=\"auth\", opaque=\"%08lx\"%s\r\n"
+ "Content-type: text/html\r\n",
+ realm ? realm : "Asterisk",
+ nonce,
+ opaque,
+ stale ? ", stale=true" : "");
+ }
+
+ ast_http_create_response(ser,
+ status_code,
+ status_title,
+ http_header_data,
+ text);
+}
- ast_str_set(&http_headers, 0, "Content-type: text/html\r\n");
+void ast_http_error(struct ast_tcptls_session_instance *ser, int status_code,
+ const char *status_title, const char *text)
+{
+ struct ast_str *http_header_data = ast_str_create(DEFAULT_RESPONSE_HEADER_LENGTH);
- ast_str_set(&out, 0,
- "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
- "<html><head>\r\n"
- "<title>%d %s</title>\r\n"
- "</head><body>\r\n"
- "<h1>%s</h1>\r\n"
- "<p>%s</p>\r\n"
- "<hr />\r\n"
- "<address>Asterisk Server</address>\r\n"
- "</body></html>\r\n",
- status_code, status_title, status_title, text);
+ if (http_header_data) {
+ ast_str_set(&http_header_data, 0, "Content-type: text/html\r\n");
+ }
- ast_http_send(ser, AST_HTTP_UNKNOWN, status_code, status_title, http_headers, out, 0, 0);
+ ast_http_create_response(ser,
+ status_code,
+ status_title,
+ http_header_data,
+ text);
}
/*!
@@ -2029,6 +2071,7 @@ static int __ast_http_load(int reload)
int enabled=0;
int newenablestatic=0;
char newprefix[MAX_PREFIX] = "";
+ char server_name[MAX_SERVER_NAME_LENGTH];
struct http_uri_redirect *redirect;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
uint32_t bindport = DEFAULT_PORT;
@@ -2071,6 +2114,8 @@ static int __ast_http_load(int reload)
session_inactivity = DEFAULT_SESSION_INACTIVITY;
session_keep_alive = DEFAULT_SESSION_KEEP_ALIVE;
+ snprintf(server_name, sizeof(server_name), "Asterisk/%s", ast_get_version());
+
v = ast_variable_browse(cfg, "general");
for (; v; v = v->next) {
/* read tls config options while preventing unsupported options from being set */
@@ -2087,7 +2132,13 @@ static int __ast_http_load(int reload)
continue;
}
- if (!strcasecmp(v->name, "enabled")) {
+ if (!strcasecmp(v->name, "servername")) {
+ if (!ast_strlen_zero(v->value)) {
+ ast_copy_string(server_name, v->value, sizeof(server_name));
+ } else {
+ server_name[0] = '\0';
+ }
+ } else if (!strcasecmp(v->name, "enabled")) {
enabled = ast_true(v->value);
} else if (!strcasecmp(v->name, "enablestatic")) {
newenablestatic = ast_true(v->value);
@@ -2139,6 +2190,8 @@ static int __ast_http_load(int reload)
if (strcmp(prefix, newprefix)) {
ast_copy_string(prefix, newprefix, sizeof(prefix));
}
+
+ ast_copy_string(http_server_name, server_name, sizeof(http_server_name));
enablestatic = newenablestatic;
if (num_addrs && enabled) {
@@ -2209,6 +2262,7 @@ static char *handle_show_http(struct ast_cli_entry *e, int cmd, struct ast_cli_a
}
ast_cli(a->fd, "HTTP Server Status:\n");
ast_cli(a->fd, "Prefix: %s\n", prefix);
+ ast_cli(a->fd, "Server: %s\n", http_server_name);
if (ast_sockaddr_isnull(&http_desc.old_address)) {
ast_cli(a->fd, "Server Disabled\n\n");
} else {