[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