[Git][NTPsec/ntpsec][master] 4 commits: Allow WILDCARDs on certificate hostnames

Hal Murray gitlab at mg.gitlab.com
Thu Feb 14 05:54:29 UTC 2019


Hal Murray pushed to branch master at NTPsec / ntpsec


Commits:
ca908cf3 by Hal Murray at 2019-02-14T00:38:11Z
Allow WILDCARDs on certificate hostnames

- - - - -
0b215d3f by Hal Murray at 2019-02-14T02:15:47Z
NTS initialization cleanup

- - - - -
9ccd9c6d by Hal Murray at 2019-02-14T03:59:47Z
Minor tweak to mention FQDN with nts

- - - - -
7ddff3f2 by Hal Murray at 2019-02-14T04:36:50Z
Call NTS-KE client from DNS lookup thread

- - - - -


10 changed files:

- docs/includes/auth-commands.adoc
- include/ntpd.h
- include/nts.h
- libntp/wscript
- + ntpd/ntp_dns.c
- ntpd/ntp_proto.c
- ntpd/ntpd.c
- ntpd/nts_client.c
- ntpd/nts_server.c
- ntpd/wscript


Changes:

=====================================
docs/includes/auth-commands.adoc
=====================================
@@ -85,6 +85,10 @@ The following options of the +server+ command configure NTS.
   key service running in the same host as the NTP server adding this
   option is normally all you need to do.
 
+Note that the server name must match the name on the certificate.
+That is probably a FQDN rather than a short alias that you would
+probably use to talk to an internal server.
+
 +ask+ _address_::
   Use Network Time Security for authentication and encryption.  Ask
   for a specific NTS server, which may differ from the NTP server.


=====================================
include/ntpd.h
=====================================
@@ -421,7 +421,7 @@ extern const uint8_t	num_refclock_conf;
 #endif
 
 /* nts.c */
-void nts_start_server(void);
+void nts_init(void);
 bool nts_probe(struct peer *peer);
 int nts_client_ke_request(struct ntscfg_t *);
 int nts_server_ke_verify(struct ntscfg_t *);


=====================================
include/nts.h
=====================================
@@ -115,6 +115,9 @@ enum aead_ciphers {
 
 extern struct ntsconfig_t ntsconfig;
 
+bool nts_server_init(void);
+bool nts_client_init(void);
+
 int nts_get_key_length(int aead);
 bool nts_load_ciphers(SSL_CTX *ctx);
 bool nts_load_versions(SSL_CTX *ctx);


=====================================
libntp/wscript
=====================================
@@ -16,7 +16,6 @@ def build(ctx):
         "macencrypt.c",
         "netof.c",
         "ntp_endian.c",
-        "ntp_dns.c",
         "numtoa.c",
         "refidsmear.c",
         "socket.c",


=====================================
ntpd/ntp_dns.c
=====================================
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright 2015 by the NTPsec project contributors
+ * SPDX-License-Identifier: BSD-4-Clause-UC
+ */
+
+#include "config.h"
+
+#include <signal.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef HAVE_RES_INIT
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#endif
+
+#include "ntpd.h"
+#include "ntp_dns.h"
+
+
+/* Notes:
+
+  Only one DNS lookup active at a time
+
+  peer->srcadr holds IPv4/IPv6/UNSPEC flag
+  peer->hmode holds DNS retry time (log 2)
+  FLAG_DNS used in server case to indicate need DNS
+
+  Server can't lookup again after finding an answer
+    answer uses same peer slot, turns off FLAG_DNS
+    srcadr+hmode changed by normal code
+    server can't lookup again if answer stops responding
+  Pool case makes new peer slots, pool slot unchanged
+    so OK for another lookup
+*/
+
+static struct peer* active = NULL;  /* busy flag */
+static pthread_t worker;
+static int gai_rc;
+static struct addrinfo *answer;
+
+static void* dns_lookup(void* arg);
+
+
+bool dns_probe(struct peer* pp)
+{
+	int rc;
+        sigset_t        block_mask, saved_sig_mask;
+	const char	* busy = "";
+
+	/* Comment out the next two lines to get (much) more
+	 * printout when we are busy.
+	 */
+        if (NULL != active)
+		return false;
+
+	if (NULL != active)
+		busy = ", busy";
+	msyslog(LOG_INFO, "DNS: dns_probe: %s, cast_flags:%x, flags:%x%s",
+		pp->hostname, pp->cast_flags, pp->cfg.flags, busy);
+        if (NULL != active)	/* normally redundant */
+		return false;
+
+	active = pp;
+
+        sigfillset(&block_mask);
+        pthread_sigmask(SIG_BLOCK, &block_mask, &saved_sig_mask);
+	rc = pthread_create(&worker, NULL, dns_lookup, pp);
+        if (rc) {
+	  msyslog(LOG_ERR, "DNS: dns_probe: error from pthread_create: %s, %s",
+	      pp->hostname, strerror(rc));
+	  return true;  /* don't try again */
+	}
+        pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);
+
+	return true;
+}
+
+void dns_check(void)
+{
+	int rc;
+	struct addrinfo *ai;
+	DNS_Status status;
+
+	msyslog(LOG_INFO, "DNS: dns_check: processing %s, %x, %x",
+		active->hostname, active->cast_flags, (unsigned int)active->cfg.flags);
+
+	rc = pthread_join(worker, NULL);
+	if (0 != rc) {
+		msyslog(LOG_ERR, "DNS: dns_check: join failed %s", strerror(rc));
+		return;  /* leaves active set */
+	}
+	if (0 != gai_rc) {
+		msyslog(LOG_INFO, "DNS: dns_check: DNS error: %d, %s",
+			gai_rc, gai_strerror(gai_rc));
+		answer = NULL;
+	}
+
+	for (ai = answer; NULL != ai; ai = ai->ai_next) {
+		sockaddr_u sockaddr;
+		memcpy(&sockaddr, ai->ai_addr, ai->ai_addrlen);
+		/* Both dns_take_pool and dns_take_server log something. */
+		// msyslog(LOG_INFO, "DNS: Take %s=>%s",
+		//		socktoa(ai->ai_addr), socktoa(&sockaddr));
+		if (active->cast_flags & MDF_POOL)
+			dns_take_pool(active, &sockaddr);
+		else
+			dns_take_server(active, &sockaddr);
+	}
+
+	switch (gai_rc) {
+		case 0:
+			status = DNS_good;
+			break;
+
+		case EAI_AGAIN:
+			status = DNS_temp;
+			break;
+
+		/* Treat all other errors as permanent.
+		 * Some values from man page weren't in headers.
+		 */
+		default:
+			status = DNS_error;
+	}
+
+	dns_take_status(active, status);
+
+	if (NULL != answer)
+		freeaddrinfo(answer);
+	active = NULL;
+}
+
+/* Beware: no calls to msyslog from here.
+ * It's not thread safe.
+ * This is the only other thread in ntpd.
+ */
+static void* dns_lookup(void* arg)
+{
+	struct peer *pp = (struct peer *) arg;
+	struct addrinfo hints;
+
+#ifdef HAVE_RES_INIT
+	/* Reload DNS servers from /etc/resolv.conf in case DHCP has updated it.
+	 * We only need to do this occasionally, but it's not expensive
+	 * and simpler to do it every time than it is to figure out when
+	 * to do it.
+	 * This res_init() covers NTS too.
+	 */
+	res_init();
+#endif
+
+	if (pp->cfg.nts_cfg.flags & FLAG_NTS) {
+		pp->cfg.nts_cfg.flags &= !FLAG_NTS;
+		nts_probe(pp);
+	}
+
+
+	ZERO(hints);
+	hints.ai_protocol = IPPROTO_UDP;
+	hints.ai_socktype = SOCK_DGRAM;
+	hints.ai_family = AF(&pp->srcadr);
+	gai_rc = getaddrinfo(pp->hostname, "ntp", &hints, &answer);
+
+	kill(getpid(), SIGDNS);
+	pthread_exit(NULL);
+
+	/* Prevent compiler warning.
+	 * More portable than an attribute or directive
+	 */
+	return (void *)NULL;
+}
+


=====================================
ntpd/ntp_proto.c
=====================================
@@ -829,14 +829,7 @@ transmit(
 		return;
 	}
 
-	/* Does server need NTS lookup? */
-	if (peer->cfg.nts_cfg.flags & FLAG_NTS) {
-                peer->cfg.nts_cfg.flags &= !FLAG_NTS;
-                nts_probe(peer);
-		return;
-        }
-
-	/* Does server need DNS lookup? */
+	/* Does server need DNS or NTS lookup? */
 	if (peer->cfg.flags & FLAG_DNS) {
 		peer->outdate = current_time;
 		if (!dns_probe(peer)) return;


=====================================
ntpd/ntpd.c
=====================================
@@ -906,8 +906,7 @@ ntpdmain(
 	    msyslog(LOG_ERR, "statistics directory %s does not exist or is unwriteable, error %s", statsdir, strerror(errno));
 	}
 
-	if (ntsconfig.ntsenable)
-            nts_start_server();
+        nts_init();
 
 	mainloop();
         /* unreachable, mainloop() never returns */


=====================================
ntpd/nts_client.c
=====================================
@@ -25,38 +25,14 @@
 #include "ntpd.h"
 #include "nts.h"
 
+#define PORT "123"
 
 int open_TCP_socket(const char *hostname);
 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
-void HackBlockSignals(void);
-void HackUnblockSignals(void);
 
-
-
-bool nts_probe(struct peer * peer) {
-
-  SSL_CTX *ctx;
-  SSL     *ssl;
-  int      server = 0;
-  X509    *cert = NULL;
-  uint8_t  buff[1000];
-  int      transfered;
-  bool     ok = true;
-
-  HackBlockSignals();
-
-  server = open_TCP_socket(peer->hostname);
-  if (-1 == server) {
-    HackUnblockSignals();
-    return false;
-  }
-
-  // FIXME
-  // Not much error checking yet.
-  // Ugly since most SSL routines return 1 on success.
+SSL_CTX *client_ctx = NULL;
 
 // Fedora 29:  0x1010101fL  1.1.1a
 // Fedora 28:  0x1010009fL  1.1.0i
@@ -68,46 +44,72 @@ bool nts_probe(struct peer * peer) {
 // NetBSD 7:   0x1000115fL  1.0.1u
 // FreeBSD 12: 0x1010101fL  1.1.1a-freebsd
 // FreeBSD 11: 0x100020ffL  1.0.2o-freebsd
+
+bool nts_client_init(void) {
+  bool     ok = true;
 #if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
-  ctx = SSL_CTX_new(TLS_client_method());
+  client_ctx = SSL_CTX_new(TLS_client_method());
 #else
-  ctx = SSL_CTX_new(TLSv1_2_client_method());
+  client_ctx = SSL_CTX_new(TLSv1_2_client_method());
 #endif
 
 #if (OPENSSL_VERSION_NUMBER > 0x1000200fL)
   {
   // 4., ALPN, RFC 7301
   static unsigned char alpn [] = { 7, 'n', 't', 's', 'k', 'e', '/', '1' };
-  SSL_CTX_set_alpn_protos(ctx, alpn, sizeof(alpn));
+  SSL_CTX_set_alpn_protos(client_ctx, alpn, sizeof(alpn));
   }
 #endif
 
-  SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
+  SSL_CTX_set_session_cache_mode(client_ctx, SSL_SESS_CACHE_OFF);
 
-  ok &= nts_load_versions(ctx);
-  ok &= nts_load_ciphers(ctx);
-  ok &= nts_set_cert_search(ctx);
+  ok &= nts_load_versions(client_ctx);
+  ok &= nts_load_ciphers(client_ctx);
+  ok &= nts_set_cert_search(client_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;
+    msyslog(LOG_ERR, "NTSc: Troubles setting up client SSL CTX");
+    if (1) {
+      msyslog(LOG_ERR, "NTSc: Maybe should bail.");   // FIXME
+      return true;
+    }
+    SSL_CTX_free(client_ctx);
+    client_ctx = NULL;
+    return false;
   };
 
-  ssl = SSL_new(ctx);
+  return true;
+}
+
+bool nts_probe(struct peer * peer) {
+  SSL     *ssl;
+  int      server = 0;
+  X509    *cert = NULL;
+  uint8_t  buff[1000];
+  int      transfered;
+
+  if (NULL == client_ctx)
+    return false;
+
+  server = open_TCP_socket(peer->hostname);
+  if (-1 == server)
+    return false;
+
+  // FIXME
+  // Not much error checking yet.
+  // Ugly since most SSL routines return 1 on success.
+
+  ssl = SSL_new(client_ctx);
   SSL_set_fd(ssl, server);
 
 // https://wiki.openssl.org/index.php/Hostname_validation
 #if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
-  SSL_set_hostflags(ssl, X509_CHECK_FLAG_NO_WILDCARDS);
+  // SSL_set_hostflags(ssl, X509_CHECK_FLAG_NO_WILDCARDS);
   SSL_set1_host(ssl, peer->hostname);
 #elif (OPENSSL_VERSION_NUMBER > 0x1000200fL)
 {
   X509_VERIFY_PARAM *param = SSL_get0_param(ssl);
-  X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_WILDCARDS);
+  // X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_WILDCARDS);
   if (1 != X509_VERIFY_PARAM_set1_host(param,
           peer->hostname, strlen(peer->hostname))) {
       msyslog(LOG_ERR, "NTSc: troubles setting hostflags");
@@ -198,8 +200,6 @@ bail:
   SSL_shutdown(ssl);
   SSL_free(ssl);
   close(server);
-  SSL_CTX_free(ctx);
-  HackUnblockSignals();
 
   return false;
 }
@@ -211,15 +211,11 @@ int open_TCP_socket(const char *hostname) {
   int gai_rc, err;
   int sockfd;
 
-#ifdef HAVE_RES_INIT
-  res_init();  /* see comment in ntp_dns */
-#endif
-
   ZERO(hints);
   hints.ai_protocol = IPPROTO_TCP;
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_family = AF_UNSPEC;
-  gai_rc = getaddrinfo(hostname, "443", &hints, &answer);  // FIXME
+  gai_rc = getaddrinfo(hostname, PORT, &hints, &answer);  // FIXME
   if (0 != gai_rc) {
     msyslog(LOG_INFO, "NTSc: nts_probe: DNS error: %d, %s",
       gai_rc, gai_strerror(gai_rc));
@@ -227,8 +223,8 @@ int open_TCP_socket(const char *hostname) {
   }
 
   memcpy(&sockaddr, answer->ai_addr, answer->ai_addrlen);
-  msyslog(LOG_INFO, "NTSc: nts_probe connecting to %s=%s",
-    hostname, socktoa(&sockaddr));
+  msyslog(LOG_INFO, "NTSc: nts_probe connecting to %s=%s, port %s",
+    hostname, socktoa(&sockaddr), PORT);
   sockfd = socket(AF_INET, SOCK_STREAM, 0);
   if (-1 == sockfd) {
     msyslog(LOG_INFO, "NTSc: nts_probe: no socket: %m");
@@ -415,26 +411,4 @@ bool nts_set_cert_search(SSL_CTX *ctx) {
   return false;
 }
 
-
-/* ********************************** */
-
-// FIXME - hack until we move this to a thread
-static sigset_t blockMask, runMask;
-
-void HackBlockSignals(void) {
-  sigemptyset(&blockMask);
-  sigaddset(&blockMask, SIGALRM);
-  sigaddset(&blockMask, MOREDEBUGSIG);
-  sigaddset(&blockMask, LESSDEBUGSIG);
-  sigaddset(&blockMask, SIGINT);
-  sigaddset(&blockMask, SIGQUIT);
-  sigaddset(&blockMask, SIGTERM);
-  sigaddset(&blockMask, SIGHUP);
-  pthread_sigmask(SIG_BLOCK, &blockMask, &runMask);
-}
-
-void HackUnblockSignals(void) {
-  pthread_sigmask(SIG_SETMASK, &runMask, NULL);
-}
-
 /* end */


=====================================
ntpd/nts_server.c
=====================================
@@ -24,16 +24,28 @@
 #define NTS_CERT_FILE "/etc/ntp/cert-chain.pem"
 #define NTS_KEY_FILE "/etc/ntp/key.pem"
 
+int nts_ke_port = 123;
+
 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 int nts_translate_version(const char *arg);
 
-int nts_ke_port = 123;
+static SSL_CTX *server_ctx = NULL;
+
+void nts_init(void) {
+    bool ok = true;
+    if (ntsconfig.ntsenable)
+        ok &= nts_server_init();
+    ok &= nts_client_init();
+    if (!ok) {
+      msyslog(LOG_ERR, "NTS: troubles during init.  Bailing.");
+      exit(1);
+    }
+}
 
-void nts_start_server(void) {
-    SSL_CTX *ctx;
+bool nts_server_init(void) {
     pthread_t worker;
     sigset_t block_mask, saved_sig_mask;
     int rc;
@@ -43,36 +55,38 @@ void nts_start_server(void) {
         nts_ke_port);
 
 #if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
-    ctx = SSL_CTX_new(TLS_server_method());
+    server_ctx = SSL_CTX_new(TLS_server_method());
 #else
-    ctx = SSL_CTX_new(TLSv1_2_server_method());
+    server_ctx = SSL_CTX_new(TLSv1_2_server_method());
 #endif
 
-    SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
+    SSL_CTX_set_session_cache_mode(server_ctx, SSL_SESS_CACHE_OFF);
 
-    ok &= nts_load_versions(ctx);
-    ok &= nts_load_ciphers(ctx);
-    ok &= nts_load_certificate(ctx);
+    ok &= nts_load_versions(server_ctx);
+    ok &= nts_load_ciphers(server_ctx);
+    ok &= nts_load_certificate(server_ctx);
 
     if (!ok) {
       msyslog(LOG_ERR, "NTSs: Disabling NTS-KE server");
-      SSL_CTX_free(ctx);
-      return;
+      SSL_CTX_free(server_ctx);
+      server_ctx = NULL;
+      return false;
     };
 
 #if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
     msyslog(LOG_INFO, "NTSs: OpenSSL security level is %d",
-        SSL_CTX_get_security_level(ctx));
+        SSL_CTX_get_security_level(server_ctx));
 #endif
 
     sigfillset(&block_mask);
     pthread_sigmask(SIG_BLOCK, &block_mask, &saved_sig_mask);
-    rc = pthread_create(&worker, NULL, nts_ke_listener, ctx);
+    rc = pthread_create(&worker, NULL, nts_ke_listener, server_ctx);
     if (rc) {
       msyslog(LOG_ERR, "NTSs: nts_start_server: error from pthread_create: %m");
     }
     pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);
 
+    return true;
 }
 
 void* nts_ke_listener(void* arg) {


=====================================
ntpd/wscript
=====================================
@@ -113,6 +113,7 @@ def build(ctx):
         "ntp_scanner.c",
         "ntp_signd.c",
         "ntp_timer.c",
+        "ntp_dns.c",
         "ntpd.c",
         ctx.bldnode.parent.find_node("host/ntpd/ntp_parser.tab.c")
     ]



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/b1a56e1e884019a6c550c281db3c030ee376124a...7ddff3f24af3ef55100c4b565ce991d6048c97f0

-- 
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/b1a56e1e884019a6c550c281db3c030ee376124a...7ddff3f24af3ef55100c4b565ce991d6048c97f0
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/20190214/3ebb4a43/attachment-0001.html>


More information about the vc mailing list