add web API port access list; #2636
Costa Tsaousis (ktsaou) committed
Sep 17, 2017 at 14:24 UTC
06884d65023130a49b3103f66e4a465402dcb0bd
6 files changed
+31
-6
src/main.c
+2
@@ -83,6 +83,8 @@ void web_server_config_options(void) {
83
web_x_frame_options = config_get(CONFIG_SECTION_WEB, "x-frame-options response header", "");
84
if(!*web_x_frame_options) web_x_frame_options = NULL;
85
86
+ web_client_access_list = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "global allow from", "127.* ::1 *"), SIMPLE_PATTERN_EXACT);
87
+
88
#ifdef NETDATA_WITH_ZLIB
89
web_enable_gzip = config_get_boolean(CONFIG_SECTION_WEB, "enable gzip compression", web_enable_gzip);
90
src/socket.c
+18
-3
@@ -857,7 +857,7 @@ int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags) {
857
// --------------------------------------------------------------------------------------------------------------------
858
// accept_socket() - accept a socket and store client IP and port
859
860
-int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize) {
860
+int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize, SIMPLE_PATTERN *access_list) {
861
struct sockaddr_storage sadr;
862
socklen_t addrlen = sizeof(sadr);
863
@@ -881,7 +881,8 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
881
if (strncmp(client_ip, "::ffff:", 7) == 0) {
882
memmove(client_ip, &client_ip[7], strlen(&client_ip[7]) + 1);
883
debug(D_LISTENER, "New IPv4 web client from %s port %s on socket %d.", client_ip, client_port, fd);
884
- } else
884
+ }
885
+ else
886
debug(D_LISTENER, "New IPv6 web client from %s port %s on socket %d.", client_ip, client_port, fd);
887
break;
888
@@ -889,6 +890,17 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
890
debug(D_LISTENER, "New UNKNOWN web client from %s port %s on socket %d.", client_ip, client_port, fd);
891
break;
892
}
893
+
894
+ if(access_list) {
895
+ if(unlikely(!simple_pattern_matches(access_list, client_ip))) {
896
+ errno = 0;
897
+ debug(D_LISTENER, "Permission denied for client '%s', port '%s'", client_ip, client_port);
898
+ error("DENIED ACCESS to client '%s'", client_ip);
899
+ close(nfd);
900
+ nfd = -1;
901
+ errno = EPERM;
902
+ }
903
+ }
904
}
905
#ifdef HAVE_ACCEPT4
906
else if(errno == ENOSYS)
@@ -1104,6 +1116,7 @@ void poll_events(LISTEN_SOCKETS *sockets
1116
, void (*del_callback)(int fd, void *data)
1117
, int (*rcv_callback)(int fd, int socktype, void *data, short int *events)
1118
, int (*snd_callback)(int fd, int socktype, void *data, short int *events)
1119
+ , SIMPLE_PATTERN *access_list
1120
, void *data
1121
) {
1122
int retval;
@@ -1182,7 +1195,7 @@ void poll_events(LISTEN_SOCKETS *sockets
1195
char client_port[NI_MAXSERV + 1];
1196
1197
debug(D_POLLFD, "POLLFD: LISTENER: calling accept4() slot %zu (fd %d)", i, fd);
1185
- nfd = accept_socket(fd, SOCK_NONBLOCK, client_ip, NI_MAXHOST + 1, client_port, NI_MAXSERV + 1);
1198
+ nfd = accept_socket(fd, SOCK_NONBLOCK, client_ip, NI_MAXHOST + 1, client_port, NI_MAXSERV + 1, access_list);
1199
if (nfd < 0) {
1200
// accept failed
1201
@@ -1212,6 +1225,8 @@ void poll_events(LISTEN_SOCKETS *sockets
1225
1226
debug(D_POLLFD, "POLLFD: LISTENER: reading data from UDP slot %zu (fd %d)", i, fd);
1227
1228
+ // FIXME: access_list is not applied to UDP
1229
+
1230
p.rcv_callback(fd, pi->socktype, pi->data, &pf->events);
1231
break;
1232
}
src/socket.h
+2
-1
@@ -35,7 +35,7 @@ extern int sock_setreuse_port(int fd, int reuse);
35
extern int sock_enlarge_in(int fd);
36
extern int sock_enlarge_out(int fd);
37
38
-extern int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize);
38
+extern int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize, SIMPLE_PATTERN *access_list);
39
40
#ifndef HAVE_ACCEPT4
41
extern int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags);
@@ -56,6 +56,7 @@ extern void poll_events(LISTEN_SOCKETS *sockets
56
, void (*del_callback)(int fd, void *data)
57
, int (*rcv_callback)(int fd, int socktype, void *data, short int *events)
58
, int (*snd_callback)(int fd, int socktype, void *data, short int *events)
59
+ , SIMPLE_PATTERN *access_list
60
, void *data
61
);
62
src/statsd.c
+1
@@ -912,6 +912,7 @@ void *statsd_collector_thread(void *ptr) {
912
, statsd_del_callback
913
, statsd_rcv_callback
914
, statsd_snd_callback
915
+ , NULL
916
, (void *)d
917
);
918
src/web_client.c
+7
-2
@@ -8,6 +8,8 @@ int web_client_timeout = DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS;
8
int respect_web_browser_do_not_track_policy = 0;
9
char *web_x_frame_options = NULL;
10
11
+SIMPLE_PATTERN *web_client_access_list = NULL;
12
+
13
#ifdef NETDATA_WITH_ZLIB
14
int web_enable_gzip = 1, web_gzip_level = 3, web_gzip_strategy = Z_DEFAULT_STRATEGY;
15
#endif /* NETDATA_WITH_ZLIB */
@@ -58,9 +60,12 @@ struct web_client *web_client_create(int listener) {
60
w->mode = WEB_CLIENT_MODE_NORMAL;
61
62
{
61
- w->ifd = accept_socket(listener, SOCK_NONBLOCK, w->client_ip, sizeof(w->client_ip), w->client_port, sizeof(w->client_port));
63
+ w->ifd = accept_socket(listener, SOCK_NONBLOCK, w->client_ip, sizeof(w->client_ip), w->client_port, sizeof(w->client_port), web_client_access_list);
64
if (w->ifd == -1) {
63
- error("%llu: Cannot accept new incoming connection.", w->id);
65
+
66
+ if(errno != EPERM)
67
+ error("%llu: Failed to accept new incoming connection.", w->id);
68
+
69
freez(w);
70
return NULL;
71
}
src/web_client.h
+1
@@ -142,6 +142,7 @@ struct web_client {
142
};
143
144
extern struct web_client *web_clients;
145
+extern SIMPLE_PATTERN *web_client_access_list;
146
147
extern uid_t web_files_uid(void);
148
extern uid_t web_files_gid(void);