summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
authorAndrew Moss <1043609+amoss@users.noreply.github.com>2019-09-18 16:45:52 +0200
committerChris Akritidis <43294513+cakrit@users.noreply.github.com>2019-09-18 16:45:52 +0200
commit187620911c06585882350ff871ef49bb6e6acd1e (patch)
treec47356692e6e9378b2e9767131e745340cf2f9ba /web
parent217cd7b939218cf00b11addd6a75df1468c32ee5 (diff)
Allow hostnames in Access Control Lists (#6796)
##### Summary The Access Control List (ACL) configuration parameters can now use hostnames with simple patterns. Incoming connections are resolved using reverse DNS to obtain the hostname. Where a hostname is resolved, forward DNS resolution is performed to check the IP address is really associated with the hostname. If the checks pass then the patterns supplied are checked. Any patterns supplied for numeric ip addresses are also checked. ##### Component Name daemon ##### Additional Information Fixes #6438 * Reverse lookup on ip to get hostname * Forward lookup on hostname to get IP addresses. * Validation that the incomming ip is associated with the host. If these checks fail the hostname is discarded so it cannot match against the access-list patterns. If these checks validate the ip successfully then the resolved hostname is pattern-matched as described in the previous commit.
Diffstat (limited to 'web')
-rw-r--r--web/server/static/static-threaded.c31
-rw-r--r--web/server/web_client.c6
-rw-r--r--web/server/web_client.h7
-rw-r--r--web/server/web_server.c24
4 files changed, 42 insertions, 26 deletions
diff --git a/web/server/static/static-threaded.c b/web/server/static/static-threaded.c
index 5dda27000b..c432b9bf30 100644
--- a/web/server/static/static-threaded.c
+++ b/web/server/static/static-threaded.c
@@ -7,23 +7,26 @@ int web_client_timeout = DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS;
int web_client_first_request_timeout = DEFAULT_TIMEOUT_TO_RECEIVE_FIRST_WEB_REQUEST;
long web_client_streaming_rate_t = 0L;
-// ----------------------------------------------------------------------------
-// high level web clients connection management
-
-static struct web_client *web_client_create_on_fd(int fd, const char *client_ip, const char *client_port, int port_acl) {
+/*
+ * --------------------------------------------------------------------------------------------------------------------
+ * Build web_client state from the pollinfo that describes an accepted connection.
+ */
+static struct web_client *web_client_create_on_fd(POLLINFO *pi) {
struct web_client *w;
w = web_client_get_from_cache_or_allocate();
- w->ifd = w->ofd = fd;
+ w->ifd = w->ofd = pi->fd;
- strncpyz(w->client_ip, client_ip, sizeof(w->client_ip) - 1);
- strncpyz(w->client_port, client_port, sizeof(w->client_port) - 1);
+ strncpyz(w->client_ip, pi->client_ip, sizeof(w->client_ip) - 1);
+ strncpyz(w->client_port, pi->client_port, sizeof(w->client_port) - 1);
+ strncpyz(w->client_host, pi->client_host, sizeof(w->client_host) - 1);
if(unlikely(!*w->client_ip)) strcpy(w->client_ip, "-");
if(unlikely(!*w->client_port)) strcpy(w->client_port, "-");
- w->port_acl = port_acl;
+ w->port_acl = pi->port_acl;
web_client_initialize_connection(w);
+ w->pollinfo_slot = pi->slot;
return(w);
}
@@ -76,7 +79,7 @@ static void *web_server_file_add_callback(POLLINFO *pi, short int *events, void
return w;
}
-static void web_werver_file_del_callback(POLLINFO *pi) {
+static void web_server_file_del_callback(POLLINFO *pi) {
struct web_client *w = (struct web_client *)pi->data;
debug(D_WEB_CLIENT, "%llu: RELEASE FILE READ ON FD %d", w->id, pi->fd);
@@ -138,7 +141,7 @@ static int web_server_file_write_callback(POLLINFO *pi, short int *events) {
// web server clients
static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data) {
- (void)data;
+ (void)data; // Supress warning on unused argument
worker_private->connected++;
@@ -149,10 +152,9 @@ static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data
*events = POLLIN;
debug(D_WEB_CLIENT_ACCESS, "LISTENER on %d: new connection.", pi->fd);
- struct web_client *w = web_client_create_on_fd(pi->fd, pi->client_ip, pi->client_port, pi->port_acl);
- w->pollinfo_slot = pi->slot;
+ struct web_client *w = web_client_create_on_fd(pi);
- if ( !strncmp(pi->client_port,"UNIX",4)){
+ if (!strncmp(pi->client_port, "UNIX", 4)) {
web_client_set_unix(w);
} else {
web_client_set_tcp(w);
@@ -270,8 +272,9 @@ static int web_server_rcv_callback(POLLINFO *pi, short int *events) {
, POLLINFO_FLAG_CLIENT_SOCKET
, "FILENAME"
, ""
+ , ""
, web_server_file_add_callback
- , web_werver_file_del_callback
+ , web_server_file_del_callback
, web_server_file_read_callback
, web_server_file_write_callback
, (void *) w
diff --git a/web/server/web_client.c b/web/server/web_client.c
index db078b966b..5cf597a5bd 100644
--- a/web/server/web_client.c
+++ b/web/server/web_client.c
@@ -791,7 +791,7 @@ static inline char *http_header_parse(struct web_client *w, char *s, int parse_u
w->auth_bearer_token = strdupz(v);
}
else if(hash == hash_host && !strcasecmp(s, "Host")){
- strncpyz(w->host, v, ((size_t)(ve - v) < sizeof(w->host)-1 ? (size_t)(ve - v) : sizeof(w->host)-1));
+ strncpyz(w->server_host, v, ((size_t)(ve - v) < sizeof(w->server_host)-1 ? (size_t)(ve - v) : sizeof(w->server_host)-1));
}
#ifdef NETDATA_WITH_ZLIB
else if(hash == hash_accept_encoding && !strcasecmp(s, "Accept-Encoding")) {
@@ -1147,8 +1147,8 @@ static inline void web_client_send_http_header(struct web_client *w) {
char headerbegin[8328];
if (w->response.code == HTTP_RESP_MOVED_PERM) {
memcpy(headerbegin,"\r\nLocation: https://",20);
- size_t headerlength = strlen(w->host);
- memcpy(&headerbegin[20],w->host,headerlength);
+ size_t headerlength = strlen(w->server_host);
+ memcpy(&headerbegin[20],w->server_host,headerlength);
headerlength += 20;
size_t tmp = strlen(w->last_url);
memcpy(&headerbegin[headerlength],w->last_url,tmp);
diff --git a/web/server/web_client.h b/web/server/web_client.h
index 38a433523b..c785a7fdac 100644
--- a/web/server/web_client.h
+++ b/web/server/web_client.h
@@ -154,13 +154,14 @@ struct web_client {
int ifd;
int ofd;
- char client_ip[NI_MAXHOST+1];
- char client_port[NI_MAXSERV+1];
+ char client_ip[INET6_ADDRSTRLEN]; // Defined buffer sizes include null-terminators
+ char client_port[NI_MAXSERV];
+ char server_host[NI_MAXHOST];
+ char client_host[NI_MAXHOST];
char decoded_url[NETDATA_WEB_REQUEST_URL_SIZE + 1]; // we decode the URL in this buffer
char decoded_query_string[NETDATA_WEB_REQUEST_URL_SIZE + 1]; // we decode the Query String in this buffer
char last_url[NETDATA_WEB_REQUEST_URL_SIZE+1]; // we keep a copy of the decoded URL here
- char host[256];
size_t url_path_length;
char separator; // This value can be either '?' or 'f'
char *url_search_path; //A pointer to the search path sent by the client
diff --git a/web/server/web_server.c b/web/server/web_server.c
index 9e51c81feb..b8b84bc36e 100644
--- a/web/server/web_server.c
+++ b/web/server/web_server.c
@@ -86,22 +86,34 @@ SIMPLE_PATTERN *web_allow_netdataconf_from = NULL;
void web_client_update_acl_matches(struct web_client *w) {
w->acl = WEB_CLIENT_ACL_NONE;
- if(!web_allow_dashboard_from || simple_pattern_matches(web_allow_dashboard_from, w->client_ip))
+ if (!web_allow_dashboard_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_dashboard_from, "dashboard"))
w->acl |= WEB_CLIENT_ACL_DASHBOARD;
- if(!web_allow_registry_from || simple_pattern_matches(web_allow_registry_from, w->client_ip))
+ if (!web_allow_registry_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_registry_from, "registry"))
w->acl |= WEB_CLIENT_ACL_REGISTRY;
- if(!web_allow_badges_from || simple_pattern_matches(web_allow_badges_from, w->client_ip))
+ if (!web_allow_badges_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_badges_from, "badges"))
w->acl |= WEB_CLIENT_ACL_BADGE;
- if(!web_allow_mgmt_from || simple_pattern_matches(web_allow_mgmt_from, w->client_ip))
+ if (!web_allow_mgmt_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_mgmt_from, "management"))
w->acl |= WEB_CLIENT_ACL_MGMT;
- if(!web_allow_streaming_from || simple_pattern_matches(web_allow_streaming_from, w->client_ip))
+ if (!web_allow_streaming_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_streaming_from, "streaming"))
w->acl |= WEB_CLIENT_ACL_STREAMING;
- if(!web_allow_netdataconf_from || simple_pattern_matches(web_allow_netdataconf_from, w->client_ip))
+ if (!web_allow_netdataconf_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_netdataconf_from, "netdata.conf"))
w->acl |= WEB_CLIENT_ACL_NETDATACONF;
w->acl &= w->port_acl;