[Git][NTPsec/ntpsec][master] More work on NTS server parameters
Hal Murray
gitlab at mg.gitlab.com
Wed Feb 13 13:02:11 UTC 2019
Hal Murray pushed to branch master at NTPsec / ntpsec
Commits:
b1a56e1e by Hal Murray at 2019-02-13T13:01:01Z
More work on NTS server parameters
- - - - -
6 changed files:
- docs/includes/auth-commands.adoc
- include/nts.h
- ntpd/ntp_config.c
- ntpd/nts.c
- ntpd/nts_client.c
- ntpd/nts_server.c
Changes:
=====================================
docs/includes/auth-commands.adoc
=====================================
@@ -57,11 +57,13 @@ The options are as follows:
+disable+::
Disable NTS-KE server.
-+mintls+ _number_::
++mintls+ _string_::
Set the lowest allowable TLS version to negotiate. Will be useful in
- the wake of a TLS compromise.
+ the wake of a TLS compromise. Reasonable values are _TLS1.2_ and
+ _TLS1.3_ if your system supports it. TLS1.3 was first supported in
+ OpenSSL version 1.1.1.
-+maxtls+ _number_::
++maxtls+ _string_::
Set the highest allowable TLS version to negotiate. By setting
+mintls+ and +maxtls+ equal, you can force the TLS version for testing.
=====================================
include/nts.h
=====================================
@@ -45,8 +45,8 @@ struct ntsstate_t {
/* Configuration data for an NTS server or client instance */
struct ntsconfig_t {
bool ntsenable; /* enable NTS KE server on this ntpd */
- float mintls; /* minimum TLS version allowed */
- float maxtls; /* maximum TLS version allowed */
+ const char * mintls; /* minimum TLS version allowed */
+ const char * maxtls; /* maximum TLS version allowed */
const char *tlsciphers; /* allowed TLS 1.2 ciphers */
const char *tlsciphersuites;/* allowed TLS 1.3 ciphersuites */
const char *cert; /* server certificate key */
@@ -115,9 +115,11 @@ enum aead_ciphers {
extern struct ntsconfig_t ntsconfig;
-int get_key_length(int aead);
+int nts_get_key_length(int aead);
+bool nts_load_ciphers(SSL_CTX *ctx);
+bool nts_load_versions(SSL_CTX *ctx);
bool nts_make_keys(SSL *ssl, uint8_t *c2s, uint8_t *s2c, int keylen);
-int make_cookie(uint8_t *cookie, uint16_t aead,
+int nts_make_cookie(uint8_t *cookie, uint16_t aead,
uint8_t *c2s, uint8_t *s2c, int keylen);
#define NO_OLD_VERSIONS SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1
=====================================
ntpd/ntp_config.c
=====================================
@@ -2014,11 +2014,11 @@ config_nts(
break;
case T_Maxtls:
- ntsconfig.maxtls = nts->value.d;
+ ntsconfig.maxtls = estrdup(nts->value.s);
break;
case T_Mintls:
- ntsconfig.mintls = nts->value.d;
+ ntsconfig.mintls = estrdup(nts->value.s);
break;
case T_Tlsciphers:
=====================================
ntpd/nts.c
=====================================
@@ -20,8 +20,8 @@
struct ntsconfig_t ntsconfig = {
.ntsenable = false,
- .mintls = 0,
- .maxtls = 0,
+ .mintls = NULL,
+ .maxtls = NULL,
.tlsciphers = NULL,
.tlsciphersuites = NULL,
.cert = NULL,
=====================================
ntpd/nts_client.c
=====================================
@@ -27,7 +27,7 @@
int open_TCP_socket(const char *hostname);
-void nts_set_cert_search(SSL_CTX *ctx);
+bool nts_set_cert_search(SSL_CTX *ctx);
bool process_recv_data(struct peer* peer, SSL *ssl);
// FIXME - hack until we move this to a thread
@@ -44,6 +44,7 @@ bool nts_probe(struct peer * peer) {
X509 *cert = NULL;
uint8_t buff[1000];
int transfered;
+ bool ok = true;
HackBlockSignals();
@@ -69,15 +70,8 @@ bool nts_probe(struct peer * peer) {
// FreeBSD 11: 0x100020ffL 1.0.2o-freebsd
#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
ctx = SSL_CTX_new(TLS_client_method());
- SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); // FIXME
- SSL_CTX_set_max_proto_version(ctx, 0);
#else
- /* Older versions of OpenSSL don't support min/max version requests.
- * That's OK, since we don't want anything older than 1.2 and
- * they don't support anything newer.
- * There is similar code in nts_start_server(). */
ctx = SSL_CTX_new(TLSv1_2_client_method());
- SSL_CTX_set_options(ctx, NO_OLD_VERSIONS);
#endif
#if (OPENSSL_VERSION_NUMBER > 0x1000200fL)
@@ -88,20 +82,20 @@ bool nts_probe(struct peer * peer) {
}
#endif
- if (NULL != ntsconfig.tlsciphers) {
- if (1 != SSL_CTX_set_cipher_list(ctx, ntsconfig.tlsciphers)) {
- msyslog(LOG_ERR, "NTSc: error setting TLS ciphers");
- }
- }
-#ifdef TLS1_3_VERSION
- if (NULL != ntsconfig.tlsciphersuites) {
- if (1 != SSL_CTX_set_ciphersuites(ctx, ntsconfig.tlsciphersuites)) {
- msyslog(LOG_ERR, "NTSc: error setting TLS ciphersuites");
- }
- }
-#endif
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
+
+ ok &= nts_load_versions(ctx);
+ ok &= nts_load_ciphers(ctx);
+ ok &= nts_set_cert_search(ctx);
- nts_set_cert_search(ctx);
+ if (!ok) {
+ msyslog(LOG_ERR, "NTSc: Troubles setting up SSL CTX: %s", peer->hostname);
+ msyslog(LOG_ERR, "NTSc: Maybe should bail.");
+ // close(server);
+ // SSL_CTX_free(ctx);
+ // HackUnblockSignals();
+ // return;
+ };
ssl = SSL_new(ctx);
SSL_set_fd(ssl, server);
@@ -194,7 +188,7 @@ bool nts_probe(struct peer * peer) {
/* We are using AEAD_AES_SIV_CMAC_256, from RFC 5297
* There are no alternatives and no clean API yet.
*/
- peer->nts_state.keylen = get_key_length(AEAD_AES_SIV_CMAC_256);
+ peer->nts_state.keylen = nts_get_key_length(AEAD_AES_SIV_CMAC_256);
nts_make_keys(ssl,
peer->nts_state.c2s,
peer->nts_state.s2c,
@@ -398,26 +392,27 @@ bool process_recv_data(struct peer* peer, SSL *ssl) {
return true;
}
-void nts_set_cert_search(SSL_CTX *ctx) {
+bool nts_set_cert_search(SSL_CTX *ctx) {
struct stat statbuf;
if (NULL == ntsconfig.ca) {
SSL_CTX_set_default_verify_paths(ctx); // Use system root certs
- return;
+ return true;
}
if (0 == stat(ntsconfig.ca, &statbuf)) {
if (S_ISDIR(statbuf.st_mode)) {
SSL_CTX_load_verify_locations(ctx, NULL, ntsconfig.ca);
- return;
+ return true;
}
if (S_ISREG(statbuf.st_mode)) {
SSL_CTX_load_verify_locations(ctx, ntsconfig.ca, NULL);
- return;
+ return true;
}
msyslog(LOG_ERR, "NTSc: cert dir/file isn't dir or file: %s. mode 0x%x",
ntsconfig.ca, statbuf.st_mode);
- return;
+ return false;
}
msyslog(LOG_ERR, "NTSc: can't stat cert dir/file: %s, %m", ntsconfig.ca);
+ return false;
}
=====================================
ntpd/nts_server.c
=====================================
@@ -24,10 +24,11 @@
#define NTS_CERT_FILE "/etc/ntp/cert-chain.pem"
#define NTS_KEY_FILE "/etc/ntp/key.pem"
+static bool nts_load_certificate(SSL_CTX *ctx);
static int create_listener(int port);
static void* nts_ke_listener(void*);
static void nts_ke_request(SSL *ssl);
-static void nts_load_certificate(SSL_CTX *ctx);
+static int nts_translate_version(const char *arg);
int nts_ke_port = 123;
@@ -36,30 +37,34 @@ void nts_start_server(void) {
pthread_t worker;
sigset_t block_mask, saved_sig_mask;
int rc;
+ bool ok = true;
msyslog(LOG_INFO, "NTSs: starting NTS-KE server listening on port %d",
nts_ke_port);
#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
ctx = SSL_CTX_new(TLS_server_method());
- SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); // FIXME
- SSL_CTX_set_max_proto_version(ctx, 0);
#else
- /* Older versions of OpenSSL don't support min/max version requests.
- * That's OK, since we don't want anything older than 1.2 and
- * they don't support anything newer.
- * There is similar code in nts_probe(). */
ctx = SSL_CTX_new(TLSv1_2_server_method());
- SSL_CTX_set_options(ctx, NO_OLD_VERSIONS);
#endif
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
+
+ ok &= nts_load_versions(ctx);
+ ok &= nts_load_ciphers(ctx);
+ ok &= nts_load_certificate(ctx);
+
+ if (!ok) {
+ msyslog(LOG_ERR, "NTSs: Disabling NTS-KE server");
+ SSL_CTX_free(ctx);
+ return;
+ };
+
#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
msyslog(LOG_INFO, "NTSs: OpenSSL security level is %d",
SSL_CTX_get_security_level(ctx));
#endif
- nts_load_certificate(ctx);
-
sigfillset(&block_mask);
pthread_sigmask(SIG_BLOCK, &block_mask, &saved_sig_mask);
rc = pthread_create(&worker, NULL, nts_ke_listener, ctx);
@@ -137,7 +142,7 @@ void nts_ke_request(SSL *ssl) {
buf.next = buff;
buf.left = sizeof(buff);
- keylen = get_key_length(aead);
+ keylen = nts_get_key_length(aead);
nts_make_keys(ssl, c2s, s2c, keylen);
/* 4.1.2 Next Protocol, 0 for NTP */
@@ -146,7 +151,7 @@ void nts_ke_request(SSL *ssl) {
nts_append_record_uint16(&buf, nts_algorithm_negotiation, aead);
for (int i=0; i<NTS_MAX_COOKIES; i++) {
- cookielen = make_cookie(cookie, aead, c2s, s2c, keylen);
+ cookielen = nts_make_cookie(cookie, aead, c2s, s2c, keylen);
nts_append_record_bytes(&buf, nts_new_cookie, cookie, cookielen);
}
@@ -191,7 +196,7 @@ int create_listener(int port) {
return sock;
}
-int get_key_length(int aead) {
+int nts_get_key_length(int aead) {
switch (aead) {
case IANA_AEAD_AES_SIV_CMAC_256:
return AEAD_AES_SIV_CMAC_256_KEYLEN;
@@ -203,7 +208,7 @@ int get_key_length(int aead) {
// FIXME - this is a total hack to test pack/unpack
/* returns actual length */
-int make_cookie(uint8_t *cookie,
+int nts_make_cookie(uint8_t *cookie,
uint16_t aead,
uint8_t *c2s, uint8_t *s2c, int keylen) {
@@ -220,7 +225,73 @@ int make_cookie(uint8_t *cookie,
}
-void nts_load_certificate(SSL_CTX *ctx) {
+bool nts_load_versions(SSL_CTX *ctx) {
+ int minver, maxver;
+ minver = nts_translate_version(ntsconfig.mintls);
+ maxver = nts_translate_version(ntsconfig.maxtls);
+ if ((-1 == minver) || (-1 == maxver))
+ return false;
+#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
+ if(0 == minver) minver = TLS1_2_VERSION; // 3.
+ SSL_CTX_set_min_proto_version(ctx, minver);
+ SSL_CTX_set_max_proto_version(ctx, maxver);
+#else
+ /* Older versions of OpenSSL don't support min/max version requests.
+ * That's OK, since we don't want anything older than 1.2 and
+ * they don't support anything newer. */
+ SSL_CTX_set_options(ctx, NO_OLD_VERSIONS);
+#endif
+ return true;
+}
+
+/* 0 is default, -1 is error */
+int nts_translate_version(const char *arg) {
+ if (NULL == arg)
+ return 0;
+ if (0 == strcmp(arg, "TLS1.2"))
+ return TLS1_2_VERSION;
+ if (0 == strcmp(arg, "TLS1.3")) {
+#ifdef TLS1_3_VERSION
+ return TLS1_3_VERSION;
+#else
+ msyslog(LOG_ERR, "NTS: TLS1.3 not supported by this version of OpenSSL.");
+ return -1;
+#endif
+ }
+ msyslog(LOG_ERR, "NTS: unreconized version string: %s.", arg);
+ return -1;
+}
+
+bool nts_load_ciphers(SSL_CTX *ctx) {
+ /* SSL set_ciphers(uites) ignores typos or ciphers it doesn't support.
+ * There is no SSL_CTX_get_cipher_list, so we can't easily read back
+ * the ciphers to see what it took.
+ * We could make a dummy SSL, read the list, then free it.
+ */
+ if (NULL != ntsconfig.tlsciphers) {
+ if (1 != SSL_CTX_set_cipher_list(ctx, ntsconfig.tlsciphers)) {
+ msyslog(LOG_ERR, "NTS: troubles setting ciphers.");
+ return false;
+ } else {
+ msyslog(LOG_INFO, "NTS: set ciphers.");
+ }
+ }
+ if (NULL != ntsconfig.tlsciphersuites) {
+#ifdef TLS1_3_VERSION
+ if (1 != SSL_CTX_set_ciphersuites(ctx, ntsconfig.tlsciphersuites)) {
+ msyslog(LOG_ERR, "NTS: troubles setting ciphersuites.");
+ return false;
+ } else {
+ msyslog(LOG_INFO, "NTS: set ciphersuites.");
+ }
+#else
+ msyslog(LOG_ERR, "NTS: ciphersuites not supported on this version of OpenSSL.");
+#endif
+ }
+ return true;
+}
+
+bool nts_load_certificate(SSL_CTX *ctx) {
const char *cert = NTS_CERT_FILE;
const char *key = NTS_KEY_FILE;
@@ -231,23 +302,27 @@ void nts_load_certificate(SSL_CTX *ctx) {
if (1 != SSL_CTX_use_certificate_chain_file(ctx, cert)) {
// FIXME log SSL errors
- msyslog(LOG_ERR, "NTSs: can't load certicicate (chain) from %s", cert);
+ msyslog(LOG_ERR, "NTSs: can't load certificate (chain) from %s", cert);
+ return false;
} else {
- msyslog(LOG_ERR, "NTSs: loaded certicicate (chain) from %s", cert);
+ msyslog(LOG_ERR, "NTSs: loaded certificate (chain) from %s", cert);
}
if (1 != SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
// FIXME log SSL errors
msyslog(LOG_ERR, "NTSs: can't load private key from %s", key);
+ return false;
} else {
msyslog(LOG_ERR, "NTSs: loaded private key from %s", key);
}
if (1 != SSL_CTX_check_private_key(ctx)) {
msyslog(LOG_ERR, "NTSs: Private Key doesn't work ******");
+ return false;
} else {
msyslog(LOG_INFO, "NTSs: Private Key OK");
}
+ return true;
}
/* end */
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/b1a56e1e884019a6c550c281db3c030ee376124a
--
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/b1a56e1e884019a6c550c281db3c030ee376124a
You're receiving this email because of your account on gitlab.com.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20190213/58c26435/attachment-0001.html>
More information about the vc
mailing list