[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