summaryrefslogtreecommitdiffstats
path: root/libnetdata/socket
diff options
context:
space:
mode:
Diffstat (limited to 'libnetdata/socket')
-rw-r--r--libnetdata/socket/security.c77
-rw-r--r--libnetdata/socket/security.h5
-rw-r--r--libnetdata/socket/socket.c66
-rw-r--r--libnetdata/socket/socket.h8
4 files changed, 121 insertions, 35 deletions
diff --git a/libnetdata/socket/security.c b/libnetdata/socket/security.c
index dcbd3f65..ab324a16 100644
--- a/libnetdata/socket/security.c
+++ b/libnetdata/socket/security.c
@@ -7,8 +7,6 @@ SSL_CTX *netdata_client_ctx=NULL;
SSL_CTX *netdata_srv_ctx=NULL;
const char *security_key=NULL;
const char *security_cert=NULL;
-int netdata_use_ssl_on_stream = NETDATA_SSL_OPTIONAL;
-int netdata_use_ssl_on_http = NETDATA_SSL_FORCE; //We force SSL due safety reasons
int netdata_validate_server = NETDATA_SSL_VALID_CERTIFICATE;
/**
@@ -20,7 +18,7 @@ int netdata_validate_server = NETDATA_SSL_VALID_CERTIFICATE;
* @param where the variable with the flags set.
* @param ret the return of the caller
*/
-static void security_info_callback(const SSL *ssl, int where, int ret) {
+static void security_info_callback(const SSL *ssl, int where, int ret __maybe_unused) {
(void)ssl;
if (where & SSL_CB_ALERT) {
debug(D_WEB_CLIENT,"SSL INFO CALLBACK %s %s", SSL_alert_type_string(ret), SSL_alert_desc_string_long(ret));
@@ -166,7 +164,7 @@ void security_start_ssl(int selector) {
switch (selector) {
case NETDATA_SSL_CONTEXT_SERVER: {
struct stat statbuf;
- if (stat(security_key,&statbuf) || stat(security_cert,&statbuf)) {
+ if (stat(security_key, &statbuf) || stat(security_cert, &statbuf)) {
info("To use encryption it is necessary to set \"ssl certificate\" and \"ssl key\" in [web] !\n");
return;
}
@@ -176,6 +174,9 @@ void security_start_ssl(int selector) {
}
case NETDATA_SSL_CONTEXT_STREAMING: {
netdata_client_ctx = security_initialize_openssl_client();
+ //This is necessary for the stream, because it is working sometimes with nonblock socket.
+ //It returns the bitmask afte to change, there is not any description of errors in the documentation
+ SSL_CTX_set_mode(netdata_client_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE |SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |SSL_MODE_AUTO_RETRY);
break;
}
case NETDATA_SSL_CONTEXT_OPENTSDB: {
@@ -185,6 +186,11 @@ void security_start_ssl(int selector) {
}
}
+/**
+ * Clean Open SSL
+ *
+ * Clean all the allocated contexts from netdata.
+ */
void security_clean_openssl() {
if (netdata_srv_ctx)
{
@@ -206,6 +212,17 @@ void security_clean_openssl() {
#endif
}
+/**
+ * Process accept
+ *
+ * Process the SSL handshake with the client case it is necessary.
+ *
+ * @param ssl is a pointer for the SSL structure
+ * @param msg is a copy of the first 8 bytes of the initial message received
+ *
+ * @return it returns 0 case it performs the handshake, 8 case it is clean connection
+ * and another integer power of 2 otherwise.
+ */
int security_process_accept(SSL *ssl,int msg) {
int sock = SSL_get_fd(ssl);
int test;
@@ -250,9 +267,18 @@ int security_process_accept(SSL *ssl,int msg) {
debug(D_WEB_CLIENT_ACCESS,"SSL Handshake finished %s errno %d on socket fd %d", ERR_error_string((long)SSL_get_error(ssl, test), NULL), errno, sock);
}
- return 0;
+ return NETDATA_SSL_HANDSHAKE_COMPLETE;
}
+/**
+ * Test Certificate
+ *
+ * Check the certificate of Netdata master
+ *
+ * @param ssl is the connection structure
+ *
+ * @return It returns 0 on success and -1 otherwise
+ */
int security_test_certificate(SSL *ssl) {
X509* cert = SSL_get_peer_certificate(ssl);
int ret;
@@ -271,7 +297,48 @@ int security_test_certificate(SSL *ssl) {
} else {
ret = 0;
}
+
return ret;
}
+/**
+ * Location for context
+ *
+ * Case the user give us a directory with the certificates available and
+ * the Netdata master certificate, we use this function to validate the certificate.
+ *
+ * @param ctx the context where the path will be set.
+ * @param file the file with Netdata master certificate.
+ * @param path the directory where the certificates are stored.
+ *
+ * @return It returns 0 on success and -1 otherwise.
+ */
+int security_location_for_context(SSL_CTX *ctx, char *file, char *path) {
+ struct stat statbuf;
+ if (stat(file, &statbuf)) {
+ info("Netdata does not have a SSL master certificate, so it will use the default OpenSSL configuration to validate certificates!");
+ return 0;
+ }
+
+ ERR_clear_error();
+ u_long err;
+ char buf[256];
+ if(!SSL_CTX_load_verify_locations(ctx, file, path)) {
+ goto slfc;
+ }
+
+ if(!SSL_CTX_set_default_verify_paths(ctx)) {
+ goto slfc;
+ }
+
+ return 0;
+
+slfc:
+ while ((err = ERR_get_error()) != 0) {
+ ERR_error_string_n(err, buf, sizeof(buf));
+ error("Cannot set the directory for the certificates and the master SSL certificate: %s",buf);
+ }
+ return -1;
+}
+
#endif
diff --git a/libnetdata/socket/security.h b/libnetdata/socket/security.h
index 8beb9672..697e0fda 100644
--- a/libnetdata/socket/security.h
+++ b/libnetdata/socket/security.h
@@ -25,7 +25,7 @@
struct netdata_ssl{
SSL *conn; //SSL connection
- int flags;
+ int flags; //The flags for SSL connection
};
extern SSL_CTX *netdata_opentsdb_ctx;
@@ -33,9 +33,8 @@ extern SSL_CTX *netdata_client_ctx;
extern SSL_CTX *netdata_srv_ctx;
extern const char *security_key;
extern const char *security_cert;
-extern int netdata_use_ssl_on_stream;
-extern int netdata_use_ssl_on_http;
extern int netdata_validate_server;
+extern int security_location_for_context(SSL_CTX *ctx,char *file,char *path);
void security_openssl_library();
void security_clean_openssl();
diff --git a/libnetdata/socket/socket.c b/libnetdata/socket/socket.c
index 28271008..22abb47f 100644
--- a/libnetdata/socket/socket.c
+++ b/libnetdata/socket/socket.c
@@ -301,39 +301,47 @@ void listen_sockets_close(LISTEN_SOCKETS *sockets) {
sockets->failed = 0;
}
-WEB_CLIENT_ACL socket_ssl_acl(char *ssl) {
+/*
+ * SSL ACL
+ *
+ * Search the SSL acl and apply it case it is set.
+ *
+ * @param acl is the acl given by the user.
+ */
+WEB_CLIENT_ACL socket_ssl_acl(char *acl) {
+ char *ssl = strchr(acl,'^');
+ if(ssl) {
+ //Due the format of the SSL command it is always the last command,
+ //we finish it here to avoid problems with the ACLs
+ *ssl = '\0';
#ifdef ENABLE_HTTPS
- if (!strcmp(ssl,"optional")) {
- netdata_use_ssl_on_http = NETDATA_SSL_OPTIONAL;
- return WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING;
- }
- else if (!strcmp(ssl,"force")) {
- netdata_use_ssl_on_stream = NETDATA_SSL_FORCE;
- return WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING;
- }
+ ssl++;
+ if (!strncmp("SSL=",ssl,4)) {
+ ssl += 4;
+ if (!strcmp(ssl,"optional")) {
+ return WEB_CLIENT_ACL_SSL_OPTIONAL;
+ }
+ else if (!strcmp(ssl,"force")) {
+ return WEB_CLIENT_ACL_SSL_FORCE;
+ }
+ }
#endif
+ }
return WEB_CLIENT_ACL_NONE;
}
WEB_CLIENT_ACL read_acl(char *st) {
- char *ssl = strchr(st,'^');
- if (ssl) {
- ssl++;
- if (!strncmp("SSL=",ssl,4)) {
- ssl += 4;
- }
- socket_ssl_acl(ssl);
- }
+ WEB_CLIENT_ACL ret = socket_ssl_acl(st);
- if (!strcmp(st,"dashboard")) return WEB_CLIENT_ACL_DASHBOARD;
- if (!strcmp(st,"registry")) return WEB_CLIENT_ACL_REGISTRY;
- if (!strcmp(st,"badges")) return WEB_CLIENT_ACL_BADGE;
- if (!strcmp(st,"management")) return WEB_CLIENT_ACL_MGMT;
- if (!strcmp(st,"streaming")) return WEB_CLIENT_ACL_STREAMING;
- if (!strcmp(st,"netdata.conf")) return WEB_CLIENT_ACL_NETDATACONF;
+ if (!strcmp(st,"dashboard")) ret |= WEB_CLIENT_ACL_DASHBOARD;
+ if (!strcmp(st,"registry")) ret |= WEB_CLIENT_ACL_REGISTRY;
+ if (!strcmp(st,"badges")) ret |= WEB_CLIENT_ACL_BADGE;
+ if (!strcmp(st,"management")) ret |= WEB_CLIENT_ACL_MGMT;
+ if (!strcmp(st,"streaming")) ret |= WEB_CLIENT_ACL_STREAMING;
+ if (!strcmp(st,"netdata.conf")) ret |= WEB_CLIENT_ACL_NETDATACONF;
- return socket_ssl_acl(st);
+ return ret;
}
static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition, uint16_t default_port, int listen_backlog) {
@@ -375,7 +383,7 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
error("LISTENER: Cannot create unix socket '%s'", path);
sockets->failed++;
} else {
- acl_flags = WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING;
+ acl_flags = WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING | WEB_CLIENT_ACL_SSL_DEFAULT;
listen_sockets_add(sockets, fd, AF_UNIX, socktype, protocol_str, path, 0, acl_flags);
added++;
}
@@ -425,7 +433,13 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
}
acl_flags |= read_acl(portconfig);
} else {
- acl_flags = WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING;
+ acl_flags = WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING | WEB_CLIENT_ACL_SSL_DEFAULT;
+ }
+
+ //Case the user does not set the option SSL in the "bind to", but he has
+ //the certificates, I must redirect, so I am assuming here the default option
+ if(!(acl_flags & WEB_CLIENT_ACL_SSL_OPTIONAL) && !(acl_flags & WEB_CLIENT_ACL_SSL_FORCE)) {
+ acl_flags |= WEB_CLIENT_ACL_SSL_DEFAULT;
}
uint32_t scope_id = 0;
diff --git a/libnetdata/socket/socket.h b/libnetdata/socket/socket.h
index 9ea83bcc..76b15def 100644
--- a/libnetdata/socket/socket.h
+++ b/libnetdata/socket/socket.h
@@ -17,7 +17,10 @@ typedef enum web_client_acl {
WEB_CLIENT_ACL_BADGE = 1 << 2,
WEB_CLIENT_ACL_MGMT = 1 << 3,
WEB_CLIENT_ACL_STREAMING = 1 << 4,
- WEB_CLIENT_ACL_NETDATACONF = 1 << 5
+ WEB_CLIENT_ACL_NETDATACONF = 1 << 5,
+ WEB_CLIENT_ACL_SSL_OPTIONAL = 1 << 6,
+ WEB_CLIENT_ACL_SSL_FORCE = 1 << 7,
+ WEB_CLIENT_ACL_SSL_DEFAULT = 1 << 8
} WEB_CLIENT_ACL;
#define web_client_can_access_dashboard(w) ((w)->acl & WEB_CLIENT_ACL_DASHBOARD)
@@ -26,6 +29,9 @@ typedef enum web_client_acl {
#define web_client_can_access_mgmt(w) ((w)->acl & WEB_CLIENT_ACL_MGMT)
#define web_client_can_access_stream(w) ((w)->acl & WEB_CLIENT_ACL_STREAMING)
#define web_client_can_access_netdataconf(w) ((w)->acl & WEB_CLIENT_ACL_NETDATACONF)
+#define web_client_is_using_ssl_optional(w) ((w)->port_acl & WEB_CLIENT_ACL_SSL_OPTIONAL)
+#define web_client_is_using_ssl_force(w) ((w)->port_acl & WEB_CLIENT_ACL_SSL_FORCE)
+#define web_client_is_using_ssl_default(w) ((w)->port_acl & WEB_CLIENT_ACL_SSL_DEFAULT)
typedef struct listen_sockets {
struct config *config; // the config file to use