session FEATURE callhome fully implemented
Also, some refactoring in client Call Home
functions.
diff --git a/src/session_server_tls.c b/src/session_server_tls.c
index e9a99b7..1dd5cf9 100644
--- a/src/session_server_tls.c
+++ b/src/session_server_tls.c
@@ -34,12 +34,19 @@
#include "session_server.h"
extern struct nc_server_opts server_opts;
+
struct nc_tls_server_opts tls_opts = {
.tls_ctx_lock = PTHREAD_MUTEX_INITIALIZER,
.crl_lock = PTHREAD_MUTEX_INITIALIZER,
.ctn_lock = PTHREAD_MUTEX_INITIALIZER
};
+struct nc_tls_server_opts tls_ch_opts = {
+ .tls_ctx_lock = PTHREAD_MUTEX_INITIALIZER,
+ .crl_lock = PTHREAD_MUTEX_INITIALIZER,
+ .ctn_lock = PTHREAD_MUTEX_INITIALIZER
+};
+
static pthread_key_t verify_key;
static pthread_once_t verify_once = PTHREAD_ONCE_INIT;
@@ -284,7 +291,7 @@
/* return: 0 - OK, 1 - no match, -1 - error */
static int
-nc_tls_cert_to_name(X509 *cert, NC_TLS_CTN_MAPTYPE *map_type, const char **name)
+nc_tls_cert_to_name(struct nc_ctn *ctn_first, X509 *cert, NC_TLS_CTN_MAPTYPE *map_type, const char **name)
{
char *digest_md5 = NULL, *digest_sha1 = NULL, *digest_sha224 = NULL;
char *digest_sha256 = NULL, *digest_sha384 = NULL, *digest_sha512 = NULL;
@@ -293,15 +300,12 @@
int ret = 0;
struct nc_ctn *ctn;
- if (!cert || !map_type || !name) {
+ if (!ctn_first || !cert || !map_type || !name) {
free(buf);
return -1;
}
- /* LOCK */
- pthread_mutex_lock(&tls_opts.ctn_lock);
-
- for (ctn = tls_opts.ctn; ctn; ctn = ctn->next) {
+ for (ctn = ctn_first; ctn; ctn = ctn->next) {
/* MD5 */
if (!strncmp(ctn->fingerprint, "01", 2)) {
if (!digest_md5) {
@@ -439,9 +443,6 @@
}
cleanup:
- /* UNLOCK */
- pthread_mutex_unlock(&tls_opts.ctn_lock);
-
free(digest_md5);
free(digest_sha1);
free(digest_sha224);
@@ -465,6 +466,7 @@
STACK_OF(X509) *cert_stack;
EVP_PKEY *pubkey;
struct nc_session* session;
+ struct nc_tls_server_opts *opts;
long serial;
int i, n, rc, depth;
char *cp;
@@ -474,6 +476,12 @@
/* get the thread session */
session = pthread_getspecific(verify_key);
+ if (!session) {
+ ERRINT;
+ return 0;
+ }
+
+ opts = (session->flags & NC_SESSION_CALLHOME ? &tls_ch_opts : &tls_opts);
/* get the last certificate, that is the peer (client) certificate */
if (!session->tls_cert) {
@@ -528,14 +536,14 @@
OPENSSL_free(cp);
/* LOCK */
- pthread_mutex_lock(&tls_opts.crl_lock);
+ pthread_mutex_lock(&opts->crl_lock);
/* check for revocation if set */
- if (tls_opts.crl_store) {
+ if (opts->crl_store) {
/* try to retrieve a CRL corresponding to the _subject_ of
* the current certificate in order to verify it's integrity */
memset((char *)&obj, 0, sizeof(obj));
- X509_STORE_CTX_init(&store_ctx, tls_opts.crl_store, NULL, NULL);
+ X509_STORE_CTX_init(&store_ctx, opts->crl_store, NULL, NULL);
rc = X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, subject, &obj);
X509_STORE_CTX_cleanup(&store_ctx);
crl = obj.data.crl;
@@ -563,7 +571,7 @@
EVP_PKEY_free(pubkey);
}
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.crl_lock);
+ pthread_mutex_unlock(&opts->crl_lock);
return 0;
}
if (pubkey) {
@@ -576,7 +584,7 @@
X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
X509_OBJECT_free_contents(&obj);
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.crl_lock);
+ pthread_mutex_unlock(&opts->crl_lock);
return 0;
}
if (X509_cmp_current_time(next_update) < 0) {
@@ -584,7 +592,7 @@
X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_CRL_HAS_EXPIRED);
X509_OBJECT_free_contents(&obj);
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.crl_lock);
+ pthread_mutex_unlock(&opts->crl_lock);
return 0;
}
X509_OBJECT_free_contents(&obj);
@@ -593,7 +601,7 @@
/* try to retrieve a CRL corresponding to the _issuer_ of
* the current certificate in order to check for revocation */
memset((char *)&obj, 0, sizeof(obj));
- X509_STORE_CTX_init(&store_ctx, tls_opts.crl_store, NULL, NULL);
+ X509_STORE_CTX_init(&store_ctx, opts->crl_store, NULL, NULL);
rc = X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, issuer, &obj);
X509_STORE_CTX_cleanup(&store_ctx);
crl = obj.data.crl;
@@ -610,7 +618,7 @@
X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_CERT_REVOKED);
X509_OBJECT_free_contents(&obj);
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.crl_lock);
+ pthread_mutex_unlock(&opts->crl_lock);
return 0;
}
}
@@ -619,15 +627,20 @@
}
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.crl_lock);
+ pthread_mutex_unlock(&opts->crl_lock);
/* cert-to-name already successful */
if (session->username) {
return 1;
}
+ /* LOCK */
+ pthread_mutex_lock(&opts->ctn_lock);
/* cert-to-name */
- rc = nc_tls_cert_to_name(cert, &map_type, &username);
+ rc = nc_tls_cert_to_name(opts->ctn, cert, &map_type, &username);
+ /* UNLOCK */
+ pthread_mutex_unlock(&opts->ctn_lock);
+
if (rc) {
if (rc == -1) {
/* fatal error */
@@ -669,9 +682,10 @@
return 0;
}
-API int
-nc_tls_server_set_cert(const char *cert)
+static int
+_nc_tls_server_set_cert(const char *cert, int ch)
{
+ struct nc_tls_server_opts *opts;
X509 *x509_cert;
if (!cert) {
@@ -679,20 +693,22 @@
return -1;
}
- /* LOCK */
- pthread_mutex_lock(&tls_opts.tls_ctx_lock);
+ opts = (ch ? &tls_ch_opts : &tls_opts);
- if (!tls_opts.tls_ctx) {
- tls_opts.tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
- if (!tls_opts.tls_ctx) {
+ /* LOCK */
+ pthread_mutex_lock(&opts->tls_ctx_lock);
+
+ if (!opts->tls_ctx) {
+ opts->tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
+ if (!opts->tls_ctx) {
ERR("Failed to create TLS context.");
goto fail;
}
- SSL_CTX_set_verify(tls_opts.tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
+ SSL_CTX_set_verify(opts->tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
}
x509_cert = base64der_to_cert(cert);
- if (!x509_cert || (SSL_CTX_use_certificate(tls_opts.tls_ctx, x509_cert) != 1)) {
+ if (!x509_cert || (SSL_CTX_use_certificate(opts->tls_ctx, x509_cert) != 1)) {
ERR("Loading the server certificate failed (%s).", ERR_reason_error_string(ERR_get_error()));
X509_free(x509_cert);
goto fail;
@@ -700,53 +716,82 @@
X509_free(x509_cert);
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
return 0;
fail:
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
+ return -1;
+}
+
+API int
+nc_tls_server_set_cert(const char *cert)
+{
+ return _nc_tls_server_set_cert(cert, 0);
+}
+
+API int
+nc_tls_server_ch_set_cert(const char *cert)
+{
+ return _nc_tls_server_set_cert(cert, 1);
+}
+
+static int
+_nc_tls_server_set_cert_path(const char *cert_path, int ch)
+{
+ struct nc_tls_server_opts *opts;
+
+ if (!cert_path) {
+ ERRARG;
+ return -1;
+ }
+
+ opts = (ch ? &tls_ch_opts : &tls_opts);
+
+ /* LOCK */
+ pthread_mutex_lock(&opts->tls_ctx_lock);
+
+ if (!opts->tls_ctx) {
+ opts->tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
+ if (!opts->tls_ctx) {
+ ERR("Failed to create TLS context.");
+ goto fail;
+ }
+ SSL_CTX_set_verify(opts->tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
+ }
+
+ if (SSL_CTX_use_certificate_file(opts->tls_ctx, cert_path, SSL_FILETYPE_PEM) != 1) {
+ ERR("Loading the server certificate failed (%s).", ERR_reason_error_string(ERR_get_error()));
+ goto fail;
+ }
+
+ /* UNLOCK */
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
+ return 0;
+
+fail:
+ /* UNLOCK */
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
return -1;
}
API int
nc_tls_server_set_cert_path(const char *cert_path)
{
- if (!cert_path) {
- ERRARG;
- return -1;
- }
-
- /* LOCK */
- pthread_mutex_lock(&tls_opts.tls_ctx_lock);
-
- if (!tls_opts.tls_ctx) {
- tls_opts.tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
- if (!tls_opts.tls_ctx) {
- ERR("Failed to create TLS context.");
- goto fail;
- }
- SSL_CTX_set_verify(tls_opts.tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
- }
-
- if (SSL_CTX_use_certificate_file(tls_opts.tls_ctx, cert_path, SSL_FILETYPE_PEM) != 1) {
- ERR("Loading the server certificate failed (%s).", ERR_reason_error_string(ERR_get_error()));
- goto fail;
- }
-
- /* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
- return 0;
-
-fail:
- /* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
- return -1;
+ return _nc_tls_server_set_cert_path(cert_path, 0);
}
API int
-nc_tls_server_set_key(const char *privkey, int is_rsa)
+nc_tls_server_ch_set_cert_path(const char *cert_path)
{
+ return _nc_tls_server_set_cert_path(cert_path, 1);
+}
+
+static int
+_nc_tls_server_set_key(const char *privkey, int is_rsa, int ch)
+{
+ struct nc_tls_server_opts *opts;
EVP_PKEY *key;;
if (!privkey) {
@@ -754,20 +799,22 @@
return -1;
}
- /* LOCK */
- pthread_mutex_lock(&tls_opts.tls_ctx_lock);
+ opts = (ch ? &tls_ch_opts : &tls_opts);
- if (!tls_opts.tls_ctx) {
- tls_opts.tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
- if (!tls_opts.tls_ctx) {
+ /* LOCK */
+ pthread_mutex_lock(&opts->tls_ctx_lock);
+
+ if (!opts->tls_ctx) {
+ opts->tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
+ if (!opts->tls_ctx) {
ERR("Failed to create TLS context.");
goto fail;
}
- SSL_CTX_set_verify(tls_opts.tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
+ SSL_CTX_set_verify(opts->tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
}
key = base64der_to_privatekey(privkey, is_rsa);
- if (!key || (SSL_CTX_use_PrivateKey(tls_opts.tls_ctx, key) != 1)) {
+ if (!key || (SSL_CTX_use_PrivateKey(opts->tls_ctx, key) != 1)) {
ERR("Loading the server private key failed (%s).", ERR_reason_error_string(ERR_get_error()));
EVP_PKEY_free(key);
goto fail;
@@ -775,53 +822,82 @@
EVP_PKEY_free(key);
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
return 0;
fail:
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
+ return -1;
+}
+
+API int
+nc_tls_server_set_key(const char *privkey, int is_rsa)
+{
+ return _nc_tls_server_set_key(privkey, is_rsa, 0);
+}
+
+API int
+nc_tls_server_ch_set_key(const char *privkey, int is_rsa)
+{
+ return _nc_tls_server_set_key(privkey, is_rsa, 1);
+}
+
+static int
+_nc_tls_server_set_key_path(const char *privkey_path, int ch)
+{
+ struct nc_tls_server_opts *opts;
+
+ if (!privkey_path) {
+ ERRARG;
+ return -1;
+ }
+
+ opts = (ch ? &tls_ch_opts : &tls_opts);
+
+ /* LOCK */
+ pthread_mutex_lock(&opts->tls_ctx_lock);
+
+ if (!opts->tls_ctx) {
+ opts->tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
+ if (!opts->tls_ctx) {
+ ERR("Failed to create TLS context.");
+ goto fail;
+ }
+ SSL_CTX_set_verify(opts->tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
+ }
+
+ if (SSL_CTX_use_PrivateKey_file(opts->tls_ctx, privkey_path, SSL_FILETYPE_PEM) != 1) {
+ ERR("Loading the server private key failed (%s).", ERR_reason_error_string(ERR_get_error()));
+ goto fail;
+ }
+
+ /* UNLOCK */
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
+ return 0;
+
+fail:
+ /* UNLOCK */
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
return -1;
}
API int
nc_tls_server_set_key_path(const char *privkey_path)
{
- if (!privkey_path) {
- ERRARG;
- return -1;
- }
-
- /* LOCK */
- pthread_mutex_lock(&tls_opts.tls_ctx_lock);
-
- if (!tls_opts.tls_ctx) {
- tls_opts.tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
- if (!tls_opts.tls_ctx) {
- ERR("Failed to create TLS context.");
- goto fail;
- }
- SSL_CTX_set_verify(tls_opts.tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
- }
-
- if (SSL_CTX_use_PrivateKey_file(tls_opts.tls_ctx, privkey_path, SSL_FILETYPE_PEM) != 1) {
- ERR("Loading the server private key failed (%s).", ERR_reason_error_string(ERR_get_error()));
- goto fail;
- }
-
- /* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
- return 0;
-
-fail:
- /* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
- return -1;
+ return _nc_tls_server_set_key_path(privkey_path, 0);
}
API int
-nc_tls_server_add_trusted_cert(const char *cert)
+nc_tls_server_ch_set_key_path(const char *privkey_path)
{
+ return _nc_tls_server_set_key_path(privkey_path, 1);
+}
+
+static int
+_nc_tls_server_add_trusted_cert(const char *cert, int ch)
+{
+ struct nc_tls_server_opts *opts;
X509_STORE *cert_store;
X509 *x509_cert;
@@ -830,22 +906,24 @@
return -1;
}
- /* LOCK */
- pthread_mutex_lock(&tls_opts.tls_ctx_lock);
+ opts = (ch ? &tls_ch_opts : &tls_opts);
- if (!tls_opts.tls_ctx) {
- tls_opts.tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
- if (!tls_opts.tls_ctx) {
+ /* LOCK */
+ pthread_mutex_lock(&opts->tls_ctx_lock);
+
+ if (!opts->tls_ctx) {
+ opts->tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
+ if (!opts->tls_ctx) {
ERR("Failed to create TLS context.");
goto fail;
}
- SSL_CTX_set_verify(tls_opts.tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
+ SSL_CTX_set_verify(opts->tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
}
- cert_store = SSL_CTX_get_cert_store(tls_opts.tls_ctx);
+ cert_store = SSL_CTX_get_cert_store(opts->tls_ctx);
if (!cert_store) {
cert_store = X509_STORE_new();
- SSL_CTX_set_cert_store(tls_opts.tls_ctx, cert_store);
+ SSL_CTX_set_cert_store(opts->tls_ctx, cert_store);
}
x509_cert = base64der_to_cert(cert);
@@ -857,18 +935,31 @@
X509_free(x509_cert);
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
return 0;
fail:
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
return -1;
}
API int
-nc_tls_server_add_trusted_cert_path(const char *cert_path)
+nc_tls_server_add_trusted_cert(const char *cert)
{
+ return _nc_tls_server_add_trusted_cert(cert, 0);
+}
+
+API int
+nc_tls_server_ch_add_trusted_cert(const char *cert)
+{
+ return _nc_tls_server_add_trusted_cert(cert, 1);
+}
+
+static int
+_nc_tls_server_add_trusted_cert_path(const char *cert_path, int ch)
+{
+ struct nc_tls_server_opts *opts;
X509_STORE *cert_store;
X509 *x509_cert;
@@ -877,22 +968,24 @@
return -1;
}
- /* LOCK */
- pthread_mutex_lock(&tls_opts.tls_ctx_lock);
+ opts = (ch ? &tls_ch_opts : &tls_opts);
- if (!tls_opts.tls_ctx) {
- tls_opts.tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
- if (!tls_opts.tls_ctx) {
+ /* LOCK */
+ pthread_mutex_lock(&opts->tls_ctx_lock);
+
+ if (!opts->tls_ctx) {
+ opts->tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
+ if (!opts->tls_ctx) {
ERR("Failed to create TLS context.");
goto fail;
}
- SSL_CTX_set_verify(tls_opts.tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
+ SSL_CTX_set_verify(opts->tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
}
- cert_store = SSL_CTX_get_cert_store(tls_opts.tls_ctx);
+ cert_store = SSL_CTX_get_cert_store(opts->tls_ctx);
if (!cert_store) {
cert_store = X509_STORE_new();
- SSL_CTX_set_cert_store(tls_opts.tls_ctx, cert_store);
+ SSL_CTX_set_cert_store(opts->tls_ctx, cert_store);
}
errno = 0;
@@ -906,18 +999,31 @@
X509_free(x509_cert);
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
return 0;
fail:
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
return -1;
}
API int
-nc_tls_server_set_trusted_cacert_locations(const char *cacert_file_path, const char *cacert_dir_path)
+nc_tls_server_add_trusted_cert_path(const char *cert_path)
{
+ return _nc_tls_server_add_trusted_cert_path(cert_path, 0);
+}
+
+API int
+nc_tls_server_ch_add_trusted_cert_path(const char *cert_path)
+{
+ return _nc_tls_server_add_trusted_cert_path(cert_path, 1);
+}
+
+static int
+_nc_tls_server_set_trusted_cacert_locations(const char *cacert_file_path, const char *cacert_dir_path, int ch)
+{
+ struct nc_tls_server_opts *opts;
X509_STORE *cert_store;
X509_LOOKUP *lookup;
@@ -926,22 +1032,24 @@
return -1;
}
- /* LOCK */
- pthread_mutex_lock(&tls_opts.tls_ctx_lock);
+ opts = (ch ? &tls_ch_opts : &tls_opts);
- if (!tls_opts.tls_ctx) {
- tls_opts.tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
- if (!tls_opts.tls_ctx) {
+ /* LOCK */
+ pthread_mutex_lock(&opts->tls_ctx_lock);
+
+ if (!opts->tls_ctx) {
+ opts->tls_ctx = SSL_CTX_new(TLSv1_2_server_method());
+ if (!opts->tls_ctx) {
ERR("Failed to create TLS context.");
goto fail;
}
- SSL_CTX_set_verify(tls_opts.tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
+ SSL_CTX_set_verify(opts->tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_tlsclb_verify);
}
- cert_store = SSL_CTX_get_cert_store(tls_opts.tls_ctx);
+ cert_store = SSL_CTX_get_cert_store(opts->tls_ctx);
if (!cert_store) {
cert_store = X509_STORE_new();
- SSL_CTX_set_cert_store(tls_opts.tls_ctx, cert_store);
+ SSL_CTX_set_cert_store(opts->tls_ctx, cert_store);
}
if (cacert_file_path) {
@@ -971,7 +1079,7 @@
}
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
return 0;
fail:
@@ -980,28 +1088,57 @@
return -1;
}
-API void
-nc_tls_server_destroy_certs(void)
+API int
+nc_tls_server_set_trusted_cacert_locations(const char *cacert_file_path, const char *cacert_dir_path)
{
- /* LOCK */
- pthread_mutex_lock(&tls_opts.tls_ctx_lock);
-
- if (!tls_opts.tls_ctx) {
- /* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
- return;
- }
-
- SSL_CTX_free(tls_opts.tls_ctx);
- tls_opts.tls_ctx = NULL;
-
- /* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
+ return _nc_tls_server_set_trusted_cacert_locations(cacert_file_path, cacert_dir_path, 0);
}
API int
-nc_tls_server_set_crl_locations(const char *crl_file_path, const char *crl_dir_path)
+nc_tls_server_ch_set_trusted_cacert_locations(const char *cacert_file_path, const char *cacert_dir_path)
{
+ return _nc_tls_server_set_trusted_cacert_locations(cacert_file_path, cacert_dir_path, 1);
+}
+
+static void
+_nc_tls_server_destroy_certs(int ch)
+{
+ struct nc_tls_server_opts *opts;
+
+ opts = (ch ? &tls_ch_opts : &tls_opts);
+
+ /* LOCK */
+ pthread_mutex_lock(&opts->tls_ctx_lock);
+
+ if (!opts->tls_ctx) {
+ /* UNLOCK */
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
+ return;
+ }
+
+ SSL_CTX_free(opts->tls_ctx);
+ opts->tls_ctx = NULL;
+
+ /* UNLOCK */
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
+}
+
+API void
+nc_tls_server_destroy_certs(void)
+{
+ _nc_tls_server_destroy_certs(0);
+}
+
+API void
+nc_tls_server_ch_destroy_certs(void)
+{
+ _nc_tls_server_destroy_certs(1);
+}
+
+static int
+_nc_tls_server_set_crl_locations(const char *crl_file_path, const char *crl_dir_path, int ch)
+{
+ struct nc_tls_server_opts *opts;
X509_LOOKUP *lookup;
if (!crl_file_path && !crl_dir_path) {
@@ -1009,15 +1146,17 @@
return -1;
}
- /* LOCK */
- pthread_mutex_lock(&tls_opts.crl_lock);
+ opts = (ch ? &tls_ch_opts : &tls_opts);
- if (!tls_opts.crl_store) {
- tls_opts.crl_store = X509_STORE_new();
+ /* LOCK */
+ pthread_mutex_lock(&opts->crl_lock);
+
+ if (!opts->crl_store) {
+ opts->crl_store = X509_STORE_new();
}
if (crl_file_path) {
- lookup = X509_STORE_add_lookup(tls_opts.crl_store, X509_LOOKUP_file());
+ lookup = X509_STORE_add_lookup(opts->crl_store, X509_LOOKUP_file());
if (!lookup) {
ERR("Failed to add a lookup method.");
goto fail;
@@ -1030,7 +1169,7 @@
}
if (crl_dir_path) {
- lookup = X509_STORE_add_lookup(tls_opts.crl_store, X509_LOOKUP_hash_dir());
+ lookup = X509_STORE_add_lookup(opts->crl_store, X509_LOOKUP_hash_dir());
if (!lookup) {
ERR("Failed to add a lookup method.");
goto fail;
@@ -1043,37 +1182,66 @@
}
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.crl_lock);
+ pthread_mutex_unlock(&opts->crl_lock);
return 0;
fail:
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.crl_lock);
+ pthread_mutex_unlock(&opts->crl_lock);
return -1;
}
+API int
+nc_tls_server_set_crl_locations(const char *crl_file_path, const char *crl_dir_path)
+{
+ return _nc_tls_server_set_crl_locations(crl_file_path, crl_dir_path, 0);
+}
+
+API int
+nc_tls_server_ch_set_crl_locations(const char *crl_file_path, const char *crl_dir_path)
+{
+ return _nc_tls_server_set_crl_locations(crl_file_path, crl_dir_path, 1);
+}
+
+static void
+_nc_tls_server_destroy_crls(int ch)
+{
+ struct nc_tls_server_opts *opts;
+
+ opts = (ch ? &tls_ch_opts : &tls_opts);
+
+ /* LOCK */
+ pthread_mutex_lock(&opts->crl_lock);
+
+ if (!opts->crl_store) {
+ /* UNLOCK */
+ pthread_mutex_unlock(&opts->crl_lock);
+ return;
+ }
+
+ X509_STORE_free(opts->crl_store);
+ opts->crl_store = NULL;
+
+ /* UNLOCK */
+ pthread_mutex_unlock(&opts->crl_lock);
+}
+
API void
nc_tls_server_destroy_crls(void)
{
- /* LOCK */
- pthread_mutex_lock(&tls_opts.crl_lock);
-
- if (!tls_opts.crl_store) {
- /* UNLOCK */
- pthread_mutex_unlock(&tls_opts.crl_lock);
- return;
- }
-
- X509_STORE_free(tls_opts.crl_store);
- tls_opts.crl_store = NULL;
-
- /* UNLOCK */
- pthread_mutex_unlock(&tls_opts.crl_lock);
+ _nc_tls_server_destroy_crls(0);
}
-API int
-nc_tls_server_add_ctn(uint32_t id, const char *fingerprint, NC_TLS_CTN_MAPTYPE map_type, const char *name)
+API void
+nc_tls_server_ch_destroy_crls(void)
{
+ _nc_tls_server_destroy_crls(1);
+}
+
+static int
+_nc_tls_server_add_ctn(uint32_t id, const char *fingerprint, NC_TLS_CTN_MAPTYPE map_type, const char *name, int ch)
+{
+ struct nc_tls_server_opts *opts;
struct nc_ctn *ctn, *new;
if (!fingerprint || !map_type || ((map_type == NC_TLS_CTN_SPECIFIED) && !name)
@@ -1082,6 +1250,8 @@
return -1;
}
+ opts = (ch ? &tls_ch_opts : &tls_opts);
+
new = malloc(sizeof *new);
nc_ctx_lock(-1, NULL);
@@ -1093,39 +1263,54 @@
new->next = NULL;
/* LOCK */
- pthread_mutex_lock(&tls_opts.ctn_lock);
+ pthread_mutex_lock(&opts->ctn_lock);
- if (!tls_opts.ctn) {
+ if (!opts->ctn) {
/* the first item */
- tls_opts.ctn = new;
- } else if (tls_opts.ctn->id > id) {
+ opts->ctn = new;
+ } else if (opts->ctn->id > id) {
/* insert at the beginning */
- new->next = tls_opts.ctn;
- tls_opts.ctn = new;
+ new->next = opts->ctn;
+ opts->ctn = new;
} else {
- for (ctn = tls_opts.ctn; ctn->next && ctn->next->id <= id; ctn = ctn->next);
+ for (ctn = opts->ctn; ctn->next && ctn->next->id <= id; ctn = ctn->next);
/* insert after ctn */
new->next = ctn->next;
ctn->next = new;
}
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.ctn_lock);
+ pthread_mutex_unlock(&opts->ctn_lock);
return 0;
}
API int
-nc_tls_server_del_ctn(int64_t id, const char *fingerprint, NC_TLS_CTN_MAPTYPE map_type, const char *name)
+nc_tls_server_add_ctn(uint32_t id, const char *fingerprint, NC_TLS_CTN_MAPTYPE map_type, const char *name)
{
- int ret = -1;
+ return _nc_tls_server_add_ctn(id, fingerprint, map_type, name, 0);
+}
+
+API int
+nc_tls_server_ch_add_ctn(uint32_t id, const char *fingerprint, NC_TLS_CTN_MAPTYPE map_type, const char *name)
+{
+ return _nc_tls_server_add_ctn(id, fingerprint, map_type, name, 1);
+}
+
+static int
+_nc_tls_server_del_ctn(int64_t id, const char *fingerprint, NC_TLS_CTN_MAPTYPE map_type, const char *name, int ch)
+{
+ struct nc_tls_server_opts *opts;
struct nc_ctn *ctn, *next, *prev;
+ int ret = -1;
+
+ opts = (ch ? &tls_ch_opts : &tls_opts);
/* LOCK */
- pthread_mutex_lock(&tls_opts.ctn_lock);
+ pthread_mutex_lock(&opts->ctn_lock);
if ((id < 0) && !fingerprint && !map_type && !name) {
- ctn = tls_opts.ctn;
+ ctn = opts->ctn;
nc_ctx_lock(-1, NULL);
while (ctn) {
lydict_remove(server_opts.ctx, ctn->fingerprint);
@@ -1141,7 +1326,7 @@
tls_opts.ctn = NULL;
} else {
prev = NULL;
- ctn = tls_opts.ctn;
+ ctn = opts->ctn;
while (ctn) {
if (((id < 0) || (ctn->id == id))
&& (!fingerprint || !strcmp(ctn->fingerprint, fingerprint))
@@ -1171,17 +1356,33 @@
}
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.ctn_lock);
+ pthread_mutex_unlock(&opts->ctn_lock);
return ret;
}
+API int
+nc_tls_server_del_ctn(int64_t id, const char *fingerprint, NC_TLS_CTN_MAPTYPE map_type, const char *name)
+{
+ return _nc_tls_server_del_ctn(id, fingerprint, map_type, name, 0);
+}
+
+API int
+nc_tls_server_ch_del_ctn(int64_t id, const char *fingerprint, NC_TLS_CTN_MAPTYPE map_type, const char *name)
+{
+ return _nc_tls_server_del_ctn(id, fingerprint, map_type, name, 1);
+}
+
API void
nc_tls_server_free_opts(void)
{
nc_tls_server_destroy_certs();
nc_tls_server_destroy_crls();
nc_tls_server_del_ctn(-1, NULL, 0, NULL);
+
+ nc_tls_server_ch_destroy_certs();
+ nc_tls_server_ch_destroy_crls();
+ nc_tls_server_ch_del_ctn(-1, NULL, 0, NULL);
}
static void
@@ -1191,11 +1392,14 @@
}
int
-nc_accept_tls_session(struct nc_session *session, int sock, int timeout)
+nc_accept_tls_session(struct nc_session *session, int sock, int timeout, int ch)
{
- int ret, elapsed = 0;
+ struct nc_tls_server_opts *opts;
struct pollfd pfd;
struct timespec old_ts, new_ts;
+ int ret, elapsed = 0;
+
+ opts = (ch ? &tls_ch_opts : &tls_opts);
pfd.fd = sock;
pfd.events = POLLIN;
@@ -1230,15 +1434,15 @@
session->ti_type = NC_TI_OPENSSL;
/* LOCK */
- ret = nc_timedlock(&tls_opts.tls_ctx_lock, timeout, &elapsed);
+ ret = nc_timedlock(&opts->tls_ctx_lock, timeout, &elapsed);
if (ret < 1) {
return ret;
}
- session->ti.tls = SSL_new(tls_opts.tls_ctx);
+ session->ti.tls = SSL_new(opts->tls_ctx);
/* UNLOCK */
- pthread_mutex_unlock(&tls_opts.tls_ctx_lock);
+ pthread_mutex_unlock(&opts->tls_ctx_lock);
if (!session->ti.tls) {
ERR("Failed to create TLS structure from context.");