[Git][NTPsec/ntpsec][master] 12 commits: Update to OpenSSL 1.1.1j and 3.0.0 alpha12

Hal Murray (@hal.murray) gitlab at mg.gitlab.com
Tue Jun 29 19:20:34 UTC 2021



Hal Murray pushed to branch master at NTPsec / ntpsec


Commits:
4fca64d5 by Hal Murray at 2021-06-29T12:10:26-07:00
Update to OpenSSL 1.1.1j and 3.0.0 alpha12

- - - - -
f273b6cc by Hal Murray at 2021-06-29T12:10:27-07:00
Minor cleanup of some formatting

- - - - -
13149588 by Hal Murray at 2021-06-29T12:10:27-07:00
Update to OpenSSL alpha 13

- - - - -
2090d1dc by Hal Murray at 2021-06-29T12:10:27-07:00
Cleanup printout from IsEqual in tests/libntp/lfptest.h
  Add test case for debugging priintout from IsEqual

- - - - -
2b49068f by Hal Murray at 2021-06-29T12:10:27-07:00
Fix typo on picture of bit layout
  Drop unused FRACTION_PREC

- - - - -
162b460d by Hal Murray at 2021-06-29T12:10:27-07:00
Remove various symbols that aren't referenced at all
  More cleanup work needed.

- - - - -
ba368822 by Hal Murray at 2021-06-29T12:10:27-07:00
Update to OpenSSL 3.0.0-alpha15

- - - - -
aaa5f405 by Hal Murray at 2021-06-29T12:10:27-07:00
Update to OpenSSL 1.1.1k and 3.0.0-alpha15

- - - - -
b43bfbd1 by Hal Murray at 2021-06-29T12:10:27-07:00
Update to OpenSSL alpha16

- - - - -
ddce5c21 by Hal Murray at 2021-06-29T12:10:27-07:00
Update to OpenSSL 3.0.0-alpha17

- - - - -
1ab21cfa by Hal Murray at 2021-06-29T12:17:36-07:00
Update to 3.0.0-beta1

- - - - -
bc270426 by Hal Murray at 2021-06-29T12:19:44-07:00
FreeBSD now uses ns resolution on receive time stamps

- - - - -


9 changed files:

- HOWTO-OpenSSL
- NEWS.adoc
- attic/cmac-timing.c
- devel/ifdex-ignores
- include/ntp_fp.h
- ntpd/ntp_packetstamp.c
- ntpd/ntp_util.c
- tests/libntp/hextolfp.c
- tests/libntp/lfptest.h


Changes:

=====================================
HOWTO-OpenSSL
=====================================
@@ -2,8 +2,8 @@ NTS needs TLS 1.3 or newer.
 That was first supported in OpenSSL 1.1.1
   (1.1.1a is broken)
 Some OSes/Distros don't support a new enough version of OpenSSL
-This file contains notes on how to download, build, and install 1.1.1g
-It also works for testing 3.0.0 alpha
+This file contains notes on how to download, build, and install 1.1.1k
+It also works for testing 3.0.0 alpha and beta
 
 It's rough.  Don't be surprised by bugs/oversights.
 Corrections, clarifications and feedback encouraged.
@@ -13,37 +13,64 @@ Download OpenSSL source from here:
   https://www.openssl.org/source/old/1.1.1/
 
 You should be able to cut/paste many of these lines.
+But check for the latest versions first.
 
 cd xxx
 mkdir OpenSSL
 cd OpenSSL
-for OpenSSL 1.1.1g
-  wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz
-  tar -xzf openssl-1.1.1g.tar.gz
-  cd openssl-1.1.1g
-for OpenSSL 3.0.0 alpha9
-  wget https://www.openssl.org/source/openssl-3.0.0-alpha9.tar.gz
-  tar -xzf openssl-3.0.0-alpha9.tar.gz
-  cd openssl-3.0.0-alpha9
+for OpenSSL 1.1.1k
+  wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
+  tar -xzf openssl-1.1.1k.tar.gz
+  cd openssl-1.1.1k
+for OpenSSL 3.0.0 beta1
+  wget https://www.openssl.org/source/openssl-3.0.0-beta1.tar.gz
+  tar -xzf openssl-3.0.0-beta1.tar.gz
+  cd openssl-3.0.0-beta1
 
 # Check NOTES.PERL
 #   for CentOS, you need
   sudo yum install perl-core
-    Fedora needs
-  sudo dnf install perl-IPC-Cmd
-For make test on Fedora
-  sudo dnf install perl-Test-Harness perl perl-Pod-Html
+# Fedora 33+34 for 3.0.0-alpha and beta
+  # ./config needs
+  sudo dnf install perl-FindBin 'perl(IPC::Cmd)' 'perl(File::Compare)'
+  # make needs
+  # make test needs
+  sudo dnf install 'perl(Test::Harness)' 'perl(Test::More)' 'perl(File::Copy)'
+  # make install also needs:
+  sudo dnf install 'perl(Pod::Html)'
+# On FreeBSD for 3.0.0-alpha and beta
+  sudo pkg install perl5
 
 On Linux
   ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl shared
 	enable-des
-make
+
+***   If you encounter a problem while building, please open an    ***
+***   issue on GitHub <https://github.com/openssl/openssl/issues>  ***
+***   and include the output from the following command:           ***
+***                                                                ***
+***       perl configdata.pm --dump                                ***
+
+time make
+time make test
+time make build_docs
 sudo make install
 
-cd /etc/ld.so.conf.d
-echo "/usr/local/ssl/lib" > openssl-1.1.1g.conf
-echo "/usr/local/ssl/lib" > openssl-3.0.0-alpha.conf
-ldconfig
+sudo su
+  cd /etc/ld.so.conf.d
+  echo "/usr/local/ssl/lib" > openssl-1.1.1k.conf
+  echo "/usr/local/ssl/lib" > openssl-3.0.0-beta.conf
+  ldconfig
+
+On FreeBSD, I couldn't figure out how it is supposed to work.
+  Probably, I just need the magic to ldconfig.
+  echo "/usr/local/ssl/lib" >> /etc/ld-elf.so.conf
+  reboot
+or something close to that.
+
+NetBSD:
+  echo "/usr/local/ssl/lib" >> /etc/ld.so.conf
+(no ldconfig on my search path.  Doesn't seem to be needed.)
 
 # check with
 /usr/local/ssl/bin/openssl version


=====================================
NEWS.adoc
=====================================
@@ -14,6 +14,8 @@ on user-visible changes.
 
 Fix hash validation in ntpleapfetch again.
 
+FreeBSD now gets ns resolution on receive time stamps.
+
 == 2021-06-06: 1.2.1 ==
 
 Update ntpkeygen/keygone to properly filter `#` characters. (CVE-2021-22212)


=====================================
attic/cmac-timing.c
=====================================
@@ -225,28 +225,14 @@ static void DoPKEY(
 #if OPENSSL_VERSION_NUMBER > 0x20000000L
 static size_t One_EVP_MAC(
   EVP_MAC_CTX *ctx,         /* context  */
-  char *cipher,
   uint8_t *key,             /* key pointer */
   int     keylength,        /* key length */
   uint8_t *pkt,             /* packet pointer */
   int     pktlength         /* packet length */
 ) {
-	OSSL_PARAM params[3];
 	size_t len = EVP_MAX_MD_SIZE;
 
-	params[0] =
-          OSSL_PARAM_construct_utf8_string("cipher", cipher, 0);
-	params[1] =
-          OSSL_PARAM_construct_octet_string("key", key, keylength);
-	params[2] = OSSL_PARAM_construct_end();
-	if (0 == EVP_MAC_CTX_set_params(ctx, params)) {
-		unsigned long err = ERR_get_error();
-		char * str = ERR_error_string(err, NULL);
-		printf("## Oops, EVP_MAC_CTX_set_params() failed: %s.\n", str);
-		return 0;
-	}
-
-	if (0 == EVP_MAC_init(ctx)) {
+	if (0 == EVP_MAC_init(ctx, key, keylength, NULL)) {
 		unsigned long err = ERR_get_error();
 		char * str = ERR_error_string(err, NULL);
 		printf("## Oops, EVP_MAC_init() failed: %s.\n", str);
@@ -255,13 +241,13 @@ static size_t One_EVP_MAC(
 	if (0 == EVP_MAC_update(ctx, pkt, pktlength)) {
 		unsigned long err = ERR_get_error();
 		char * str = ERR_error_string(err, NULL);
-		printf("## Oops, EVP_MAC_init() failed: %s.\n", str);
+		printf("## Oops, EVP_MAC_update() failed: %s.\n", str);
 		return 0;
 	}
 	if (0 == EVP_MAC_final(ctx, answer, &len, sizeof(answer))) {
 		unsigned long err = ERR_get_error();
 		char * str = ERR_error_string(err, NULL);
-		printf("## Oops, EVP_MAC_init() failed: %s.\n", str);
+		printf("## Oops, EVP_MAC_final() failed: %s.\n", str);
 		return 0;
 	}
 	return len;
@@ -290,7 +276,7 @@ static void Do_EVP_MAC(
 
 	clock_gettime(CLOCK_MONOTONIC, &start);
 	for (int i = 0; i < SAMPLESIZE; i++) {
-		digestlength = One_EVP_MAC(evp, cbc, key, keylength, pkt, pktlength);
+		digestlength = One_EVP_MAC(evp, key, keylength, pkt, pktlength);
 if (0 == digestlength) break;
 	}
 	clock_gettime(CLOCK_MONOTONIC, &stop);
@@ -305,26 +291,31 @@ static size_t One_EVP_MAC2(
   uint8_t *pkt,             /* packet pointer */
   int     pktlength         /* packet length */
 ) {
+	EVP_MAC_CTX *dup;
 	size_t len = EVP_MAX_MD_SIZE;
 
-	if (0 == EVP_MAC_init(ctx)) {
+	// dup = ctx;
+	dup = EVP_MAC_CTX_dup(ctx);
+
+	if (0 == EVP_MAC_init(dup, NULL, 0, NULL)) {
 		unsigned long err = ERR_get_error();
 		char * str = ERR_error_string(err, NULL);
 		printf("## Oops, EVP_MAC_init() failed: %s.\n", str);
 		return 0;
 	}
-	if (0 == EVP_MAC_update(ctx, pkt, pktlength)) {
+	if (0 == EVP_MAC_update(dup, pkt, pktlength)) {
 		unsigned long err = ERR_get_error();
 		char * str = ERR_error_string(err, NULL);
-		printf("## Oops, EVP_MAC_init() failed: %s.\n", str);
+		printf("## Oops, EVP_MAC_update() failed: %s.\n", str);
 		return 0;
 	}
-	if (0 == EVP_MAC_final(ctx, answer, &len, sizeof(answer))) {
+	if (0 == EVP_MAC_final(dup, answer, &len, sizeof(answer))) {
 		unsigned long err = ERR_get_error();
 		char * str = ERR_error_string(err, NULL);
-		printf("## Oops, EVP_MAC_init() failed: %s.\n", str);
+		printf("## Oops, EVP_MAC_final() failed: %s.\n", str);
 		return 0;
 	}
+	EVP_MAC_CTX_free(dup);
 	return len;
 }
 


=====================================
devel/ifdex-ignores
=====================================
@@ -85,11 +85,6 @@ TEST_LIBPARSE
 
 # Purely internal symbols
 CONFIG_H
-BITSPERCHAR		# Only used in the Arcron refclock
-BACKTRACE_MAXFRAME	# Internal to the ISC backtrace code
-BACKTRACE_LIBC
-BACKTRACE_GCC
-BACKTRACE_DISABLED
 CMOCK			# Internal to the Unity test framework
 CONFIG_FILE		# Only used in ntp_config.h
 DEVOLATILE		# Only used in work_thread.c
@@ -133,10 +128,6 @@ UNUSED_LOCAL		# Used to quiet compiler warnings
 UPDATE_GRACE		# ntp_io.c only
 USE_COMPILETIME_PIVOT	# Use build date in disambiguating time.
 
-USE_SCM_BINTIME		# to grab timestamp for recv packet
-USE_SCM_TIMESTAMP	# "
-USE_SCM_TIMESTAMPNS	# "
-
 USE_IPV6_MULTICAST_SUPPORT
 USE_LIFC_FAMILY
 USE_LIFC_FLAGS
@@ -145,13 +136,10 @@ USE_PCM_STYLE_SOUND
 USE_ROUTING_SOCKET
 YY_YY_NTP_PARSER_TAB_H_INCLUDED
 calloc			# In Unity
-close			# In Windows port config
 free			# In Unity and ntpd/ntp_parser.tab.c
 malloc			# In Unity and ntpd/ntp_parser.tab.c
-in_addr6		# In Windows port config
 lifr_addrlen		# ISC interface-iterator code
 mac			# Avoid name conflict.
-ntohl			# In Windows port config
 realloc			# Internal to Unity
 sem_timedwait		# In worker-thread code
 short			# In ntpd/ntp_parser.tab.c
@@ -176,9 +164,7 @@ CMAC_VERSION_CUTOFF	# Cruft from the attic
 DoSLOW			# Cruft from the attic
 
 # seccomp-related symbols that may not be available on all systems
-__NR_mmap
-__NR_openat
-__NR_prlimit64
+__NR_*
 
 # Exposed by some versions of glibc
 NI_MAXSERV


=====================================
include/ntp_fp.h
=====================================
@@ -75,12 +75,6 @@ static inline l_fp lfpinit_u(uint32_t sec, uint32_t frac) {
 	return tmp;
 }
 
-/*
- * Fractional precision (of an l_fp) is actually the number of
- * bits in an int32_t/uint32_t.
- */
-#define	FRACTION_PREC	(32)
-
 /*
  * The second fixed point format is 32 bits, with the decimal between
  * bits 15 and 16.  There is a signed version (s_fp) and an unsigned
@@ -90,7 +84,7 @@ static inline l_fp lfpinit_u(uint32_t sec, uint32_t frac) {
  * dispersion values (in local byte order).  In network byte order
  * it looks like:
  *
- *    0               1               2               3
+ *    0                   1                   2                   3
  *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *   |		  Integer Part	     |	   Fraction Part	     |


=====================================
ntpd/ntp_packetstamp.c
=====================================
@@ -14,14 +14,16 @@
 #include "ntp_stdlib.h"
 #include "timespecops.h"
 
-/* We handle 2 flavors of timestamp:
- * SO_TIMESTAMPNS/SCM_TIMESTAMPNS  Linux
- * SO_TIMESTAMP/SCM_TIMESTAMP      FreeBSD, NetBSD, OpenBSD, Linux, macOS,
- *                                 Solaris
+/* We handle 3 flavors of timestamp:
+ * SO_TIMESTAMPNS/SCM_TIMESTAMPNS  Linux (maybe others)
+ * SO_TS_CLOCK/SCM_REALTIME        FreeBSD
+ * SO_TIMESTAMP/SCM_TIMESTAMP      Everybody else
  *
  * Linux supports both SO_TIMESTAMP and SO_TIMESTAMPNS so it's
  * important to check for SO_TIMESTAMPNS first to get the better accuracy.
  *
+ * FreeBSD needs 2 setsockopt, SO_TIMESTAMP and SO_TS_CLOCK
+ *
  * Note that the if/elif tests are done in several places.
  * It's important that they all check in the same order to
  * be consistent in case some systems support more than one.
@@ -29,10 +31,6 @@
  * If SO_xxx exists, we assume that SCM_xxx does too.
  * All flavors assume the CMSG_xxx macros exist.
  *
- * FreeBSD has SO_BINTIME/SCM_BINTIME
- *   It has better resolution, but it doesn't work for IPv6
- *   bintime documentation is at
- *   http://phk.freebsd.dk/pubs/timecounter.pdf
  */
 
 
@@ -44,11 +42,14 @@ enable_packetstamps(
 {
 	const int	on = 1;
 	static bool	once = false;
+#if defined(SO_TS_CLOCK)
+	const int	ts_type = SO_TS_REALTIME;
+#endif
 
 #if defined (SO_TIMESTAMPNS)
 	if (!once) {
 		once = true;
-		msyslog(LOG_INFO, "INIT: Using SO_TIMESTAMPNS");
+		msyslog(LOG_INFO, "INIT: Using SO_TIMESTAMPNS(ns)");
 	}
 	if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPNS,
 			       (const void *)&on, sizeof(on)))
@@ -59,10 +60,12 @@ enable_packetstamps(
 		DPRINT(4, ("ERR: setsockopt SO_TIMESTAMPNS enabled on fd %d address %s\n",
 				    fd, socktoa(addr)));
 #elif defined(SO_TIMESTAMP)
+#if !defined(SO_TS_CLOCK)
 	if (!once) {
 		once = true;
-		msyslog(LOG_INFO, "INIT: Using SO_TIMESTAMP");
+		msyslog(LOG_INFO, "INIT: Using SO_TIMESTAMP(us)");
 	}
+#endif
 	if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP,
 			       (const void*)&on, sizeof(on)))
 		msyslog(LOG_DEBUG,
@@ -71,6 +74,21 @@ enable_packetstamps(
 	else
 		DPRINT(4, ("setsockopt SO_TIMESTAMP enabled on fd %d address %s\n",
 			    fd, socktoa(addr)));
+#if defined(SO_TS_CLOCK)
+	/* FreeBSD */
+	if (!once) {
+		once = true;
+		msyslog(LOG_INFO, "INIT: Using SO_TS_CLOCK(ns)");
+	}
+	if (setsockopt(fd, SOL_SOCKET, SO_TS_CLOCK,
+			       (const void*)&ts_type, sizeof(ts_type)))
+		msyslog(LOG_DEBUG,
+			"ERR: setsockop SO_TS_CLOCK on fails on address %s: %s",
+			socktoa(addr), strerror(errno));
+	else
+		DPRINT(4, ("setsockopt SO_TS_CLOCK enabled on fd %d address %s\n",
+			    fd, socktoa(addr)));
+#endif
 #else
 # error "Can't get packet timestamp"
 #endif
@@ -86,7 +104,7 @@ fetch_packetstamp(
 	)
 {
 	struct cmsghdr *	cmsghdr;
-#if defined(SO_TIMESTAMPNS)
+#if defined(SO_TIMESTAMPNS) || defined(SO_TS_CLOCK)
 	struct timespec *	tsp;
 #elif defined(SO_TIMESTAMP)
 	struct timeval *	tvp;
@@ -107,7 +125,11 @@ fetch_packetstamp(
 		/* return ts;	** Kludge to use time from select. */
 	}
 #if defined(SO_TIMESTAMPNS)
+	/* Linux and ?? */
 	if (SCM_TIMESTAMPNS != cmsghdr->cmsg_type) {
+#elif defined(SO_TS_CLOCK)
+	/* FreeBSD */
+	if (SCM_REALTIME != cmsghdr->cmsg_type) {
 #elif defined(SO_TIMESTAMP)
 	if (SCM_TIMESTAMP != cmsghdr->cmsg_type) {
 #else
@@ -126,7 +148,7 @@ fetch_packetstamp(
 
 /* cmsghdr now points to a timestamp slot */
 
-#if defined(SO_TIMESTAMPNS)
+#if defined(SO_TIMESTAMPNS) || defined(SO_TS_CLOCK)
 	tsp = (struct timespec *)CMSG_DATA(cmsghdr);
 #ifdef ENABLE_FUZZ
 	if (sys_tick > measured_tick && sys_tick > S_PER_NS) {
@@ -135,7 +157,7 @@ fetch_packetstamp(
 	}
 #endif
 	DPRINT(4, ("fetch_timestamp: system nsec network time stamp: %ld.%09ld\n",
-		tsp->tv_sec, tsp->tv_nsec));
+		(long)tsp->tv_sec, tsp->tv_nsec));
 	nts = tspec_stamp_to_lfp(*tsp);
 #elif defined(SO_TIMESTAMP)
 	tvp = (struct timeval *)CMSG_DATA(cmsghdr);


=====================================
ntpd/ntp_util.c
=====================================
@@ -670,14 +670,14 @@ void record_use_stats(void)
 	clock_gettime(CLOCK_REALTIME, &now);
 	filegen_setup(&usestats, now.tv_sec);
 	if (usestats.fp != NULL) {
-		double utime, stimex;
+		double utime, stimex; /* stime() is in time.h */
 		getrusage(RUSAGE_SELF, &usage);
-		utime =  usage.ru_utime.tv_usec - oldusage.ru_utime.tv_usec;
+		utime = usage.ru_utime.tv_usec - oldusage.ru_utime.tv_usec;
 		utime /= 1E6;
-		utime += usage.ru_utime.tv_sec -  oldusage.ru_utime.tv_sec;
-		stimex =  usage.ru_stime.tv_usec - oldusage.ru_stime.tv_usec;
+		utime += usage.ru_utime.tv_sec - oldusage.ru_utime.tv_sec;
+		stimex = usage.ru_stime.tv_usec - oldusage.ru_stime.tv_usec;
 		stimex /= 1E6;
-		stimex += usage.ru_stime.tv_sec -  oldusage.ru_stime.tv_sec;
+		stimex += usage.ru_stime.tv_sec - oldusage.ru_stime.tv_sec;
 		fprintf(usestats.fp,
 		    "%s %u %.3f %.3f %ld %ld %ld %ld %ld %ld %ld %ld %ld\n",
 		    timespec_to_MJDtime(&now), current_time - stat_use_stattime(),


=====================================
tests/libntp/hextolfp.c
=====================================
@@ -13,6 +13,20 @@ TEST_TEAR_DOWN(hextolfp) {}
 
 #include "lfptest.h"
 
+TEST(hextolfp, ExerciseIsEqualPrinting) {
+	const char *str = "12345678.00800001";
+	l_fp actual, expected;
+
+	TEST_ASSERT_TRUE(hextolfp(str, &actual));
+        expected = actual;
+	/* uncomment the next line to generate an error
+         * and exercise the printout burried in IsEqual
+         * which lives in tests/libntp/lfptest.h
+         */
+        // expected += 1;
+	TEST_ASSERT_TRUE(IsEqual(&expected, &actual));
+}
+
 TEST(hextolfp, PositiveInteger) {
 	const char *str = "00001000.00000000";
 	l_fp actual;
@@ -68,6 +82,7 @@ TEST(hextolfp, IllegalChar) {
 }
 
 TEST_GROUP_RUNNER(hextolfp) {
+	RUN_TEST_CASE(hextolfp, ExerciseIsEqualPrinting);
 	RUN_TEST_CASE(hextolfp, PositiveInteger);
 	RUN_TEST_CASE(hextolfp, NegativeInteger);
 	RUN_TEST_CASE(hextolfp, PositiveFraction);


=====================================
tests/libntp/lfptest.h
=====================================
@@ -3,14 +3,18 @@
 
 #include "ntp_fp.h"
 
+
+#define Frac10(x) ((unsigned long long)(ldexp(lfpfrac(x), -32)*1E10))
+
 static bool IsEqual(const l_fp *expected, const l_fp *actual) {
 	if (*expected == *actual) {
 		return true;
 	}
-	printf("Expected: %s (%u.%u) but was: %s (%u.%u)\n",
-		lfptoa(*expected, FRACTION_PREC), lfpuint(*expected),
-		lfpfrac(*expected), lfptoa(*actual, FRACTION_PREC),
-		lfpuint(*actual), lfpfrac(*actual));
+	printf("Expected: 0x%8x.%08x (%u.%010llu) but was: 0x%8x.%08x (%u.%010llu)\n",
+		lfpuint(*expected), lfpfrac(*expected), \
+		lfpuint(*expected), Frac10(*expected), \
+		lfpuint(*actual), lfpfrac(*actual), \
+		lfpuint(*actual), Frac10(*actual));
 	return false;
 }
 



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/a0e5e050dfbdb672459f74bf52562bc8fc50c3b9...bc270426ba6c48f87edc9837da4c3068cfcc2a8d

-- 
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/a0e5e050dfbdb672459f74bf52562bc8fc50c3b9...bc270426ba6c48f87edc9837da4c3068cfcc2a8d
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/20210629/ba16b97e/attachment-0001.htm>


More information about the vc mailing list