[Git][NTPsec/ntpsec][buildtest] 6 commits: Ensure that the python scripts actually get compiled

Ian Bruene gitlab at mg.gitlab.com
Sat Dec 2 17:45:37 UTC 2017


Ian Bruene pushed to branch buildtest at NTPsec / ntpsec


Commits:
41be3c20 by Matt Selsky at 2017-11-28T13:53:23+00:00
Ensure that the python scripts actually get compiled

This ensures that we byte-compile the python scripts (as well as the python
libraries so that we catch syntax errors during the build, instead of at
run-time.

Fixes Gitlab issue #413

- - - - -
8459d15f by Richard Laager at 2017-11-30T13:38:20+00:00
systemd: Do not restart

It is important to specify -g on the command line to allow NTP to
correct the clock on boot.  However, if Restart=yes is set, a malicious
(or broken) server could send the incorrect time, trip the panic
threshold, and when ntpd restarts, serve it the incorrect time (which
would be accepted).

See page 16 here:
http://events.linuxfoundation.org/sites/events/files/slides/vangundy-ntp-security.pdf

This can probably be done by a MITM attacker too, making this
essentially the same as CVE-2015-5300.

- - - - -
f02d60ec by Gary E. Miller at 2017-11-30T19:54:18-08:00
ntpviz: fix odd UTF-8 error in Python 2

Not sure what broke this, something somewhat recent, and not on
all Python 2 hosts.

- - - - -
f030489e by NHOrus at 2017-12-02T05:12:19+00:00
C99 allows inline declaration in for loops

- - - - -
3c7787ff by Matt Selsky at 2017-12-02T00:53:11-05:00
Fix removal of ".py" suffix from python scripts

string.rstrip() and string.replace() do very different things.

- - - - -
4d54f91a by Ian Bruene at 2017-12-02T17:44:19+00:00
Updated waf to 1.9.14, added python tests to build script

- - - - -


20 changed files:

- etc/ntpd.service
- libntp/macencrypt.c
- ntpclients/ntpdig → ntpclients/ntpdig.py
- ntpclients/ntpkeygen → ntpclients/ntpkeygen.py
- ntpclients/ntploggps → ntpclients/ntploggps.py
- ntpclients/ntplogtemp → ntpclients/ntplogtemp.py
- ntpclients/ntpmon → ntpclients/ntpmon.py
- ntpclients/ntpq → ntpclients/ntpq.py
- ntpclients/ntpsnmpd → ntpclients/ntpsnmpd.py
- ntpclients/ntpsweep → ntpclients/ntpsweep.py
- ntpclients/ntptrace → ntpclients/ntptrace.py
- ntpclients/ntpviz → ntpclients/ntpviz.py
- ntpclients/ntpwait → ntpclients/ntpwait.py
- ntpd/ntp_io.c
- ntpd/ntp_proto.c
- ntpd/refclock_neoclock.c
- ntpd/refclock_oncore.c
- tests/wscript
- waf
- wscript


Changes:

=====================================
etc/ntpd.service
=====================================
--- a/etc/ntpd.service
+++ b/etc/ntpd.service
@@ -11,7 +11,11 @@ Conflicts=systemd-timesyncd.service
 Type=forking
 PrivateTmp=true
 ExecStart=/usr/sbin/ntpd -g -N -u ntp:ntp
-Restart=always
+# Specifying -g on the command line allows ntpd to make large adjustments to
+# the clock on boot.  However, if Restart=yes is set, a malicious (or broken)
+# server could send the incorrect time, trip the panic threshold, and when
+# ntpd restarts, serve it the incorrect time (which would be accepted).
+Restart=no
 
 [Install]
 WantedBy=multi-user.target


=====================================
libntp/macencrypt.c
=====================================
--- a/libntp/macencrypt.c
+++ b/libntp/macencrypt.c
@@ -28,9 +28,8 @@ static bool ctmemeq(const void *s1, const void *s2, size_t n) {
 	const uint8_t *a = s1;
 	const uint8_t *b = s2;
 	uint8_t accum = 0;
-        size_t i;
 
-	for(i=0; i<n; i++) {
+	for(size_t i = 0; i < n; i++) {
 		accum |= a[i] ^ b[i];
 	}
 


=====================================
ntpclients/ntpdig → ntpclients/ntpdig.py
=====================================


=====================================
ntpclients/ntpkeygen → ntpclients/ntpkeygen.py
=====================================


=====================================
ntpclients/ntploggps → ntpclients/ntploggps.py
=====================================


=====================================
ntpclients/ntplogtemp → ntpclients/ntplogtemp.py
=====================================


=====================================
ntpclients/ntpmon → ntpclients/ntpmon.py
=====================================


=====================================
ntpclients/ntpq → ntpclients/ntpq.py
=====================================


=====================================
ntpclients/ntpsnmpd → ntpclients/ntpsnmpd.py
=====================================


=====================================
ntpclients/ntpsweep → ntpclients/ntpsweep.py
=====================================


=====================================
ntpclients/ntptrace → ntpclients/ntptrace.py
=====================================


=====================================
ntpclients/ntpviz → ntpclients/ntpviz.py
=====================================
--- a/ntpclients/ntpviz
+++ b/ntpclients/ntpviz.py
@@ -58,6 +58,11 @@ ntpviz: can't find the Python argparse module
 
 if sys.version_info[0] == 2:
     import codecs
+    import sys  
+
+    # force UTF-8 strings, otherwise some systems crash on micro.
+    reload(sys)  
+    sys.setdefaultencoding('utf8')
     def open(file, mode='r', buffering=-1, encoding=None, errors=None):
         return codecs.open(filename=file, mode=mode, encoding=encoding,
             errors=errors, buffering=buffering)


=====================================
ntpclients/ntpwait → ntpclients/ntpwait.py
=====================================


=====================================
ntpd/ntp_io.c
=====================================
--- a/ntpd/ntp_io.c
+++ b/ntpd/ntp_io.c
@@ -461,12 +461,11 @@ sockaddr_dump(const sockaddr_u *psau)
 	/* Limit the size of the sockaddr_in6 hex dump */
 	const int maxsize = min(32, sizeof(psau->sa6));
 	const uint8_t *	cp;
-	int		i;
 
 	/* XXX: Should we limit maxsize based on psau->saX.sin_family? */
 	cp = (const void *)&psau->sa6;
 
-	for(i = 0; i < maxsize; i++) {
+	for(int i = 0; i < maxsize; i++) {
 		printf("%02x", *cp++);
 		if (!((i + 1) % 4))
 			printf(" ");


=====================================
ntpd/ntp_proto.c
=====================================
--- a/ntpd/ntp_proto.c
+++ b/ntpd/ntp_proto.c
@@ -246,10 +246,9 @@ free_packet(
 	struct parsed_pkt *pkt
 	)
 {
-	size_t i;
 	if(pkt == NULL) { return; };
 	if(pkt->extensions != NULL) {
-		for(i = 0; i < pkt->num_extensions; i++) {
+		for(size_t i = 0; i < pkt->num_extensions; i++) {
 			free(pkt->extensions[i].body);
 			pkt->extensions[i].body = NULL;
 		}
@@ -309,7 +308,6 @@ parse_packet(
 		/* Count and validate extensions */
 		size_t ext_count = 0;
 		size_t extlen = 0;
-		size_t i;
 		while(bufptr <= recv_buf + recv_length - 28) {
 			extlen = ntp_be16dec(bufptr + 2);
 			if(extlen % 4 != 0 || extlen < 16) {
@@ -331,7 +329,7 @@ parse_packet(
 
 		/* Copy extensions */
 		bufptr = recv_buf + LEN_PKT_NOMAC;
-		for(i = 0; i < ext_count; i++) {
+		for(size_t i = 0; i < ext_count; i++) {
 			pkt->extensions[i].type = ntp_be16dec(bufptr);
 			pkt->extensions[i].len = ntp_be16dec(bufptr + 2) - 4;
 			pkt->extensions[i].body =


=====================================
ntpd/refclock_neoclock.c
=====================================
--- a/ntpd/refclock_neoclock.c
+++ b/ntpd/refclock_neoclock.c
@@ -137,9 +137,6 @@ neoclock4x_start(int unit,
   char dev[20];
   int sl232;
   struct termios termsettings;
-#if !defined(NEOCLOCK4X_FIRMWARE)
-  int tries;
-#endif
 
   (void) snprintf(dev, sizeof(dev)-1, "/dev/neoclock4x-%d", unit);
 
@@ -293,7 +290,7 @@ neoclock4x_start(int unit,
   return false;
 #endif
 #else
-  for(tries=0; tries < 5; tries++)
+  for(int tries = 0; tries < 5; tries++)
     {
       NLOG(NLOG_CLOCKINFO)
 	msyslog(LOG_INFO, "REFCLOCK: NeoClock4X(%d): checking NeoClock4X firmware version (%d/5)", unit, tries);
@@ -389,7 +386,6 @@ neoclock4x_receive(struct recvbuf *rbufp)
   unsigned long calc_utc;
   int day;
   int month;	/* ddd conversion */
-  int c;
   int dsec;
   unsigned char calc_chksum;
   int recv_chksum;
@@ -422,7 +418,7 @@ neoclock4x_receive(struct recvbuf *rbufp)
 
   /* calculate checksum */
   calc_chksum = 0;
-  for(c=0; c < NEOCLOCK4X_OFFSET_CRC; c++)
+  for(int c = 0; c < NEOCLOCK4X_OFFSET_CRC; c++)
     {
       calc_chksum += pp->a_lastcode[c];
     }
@@ -725,10 +721,9 @@ neol_hexatoi_len(const char str[],
 		 int maxlen)
 {
   int hexdigit;
-  int i;
   int n = 0;
 
-  for(i=0; isxdigit((unsigned char)str[i]) && i < maxlen; i++)
+  for(int i = 0; isxdigit((unsigned char)str[i]) && i < maxlen; i++)
     {
       hexdigit = isdigit((unsigned char)str[i]) ? toupper((unsigned char)str[i]) - '0' : toupper((unsigned char)str[i]) - 'A' + 10;
       n = 16 * n + hexdigit;
@@ -743,10 +738,9 @@ neol_atoi_len(const char str[],
 		  int maxlen)
 {
   int digit;
-  int i;
   int n = 0;
 
-  for(i=0; isdigit((unsigned char)str[i]) && i < maxlen; i++)
+  for(int i = 0; isdigit((unsigned char)str[i]) && i < maxlen; i++)
     {
       digit = str[i] - '0';
       n = 10 * n + digit;


=====================================
ntpd/refclock_oncore.c
=====================================
--- a/ntpd/refclock_oncore.c
+++ b/ntpd/refclock_oncore.c
@@ -1497,7 +1497,7 @@ oncore_consume(
 
 		/* Ok, we have a header now */
 		l = sizeof(oncore_messages)/sizeof(oncore_messages[0]) -1;
-		for(m=0; m<l; m++)
+		for(m = 0; m < l; m++)
 			if (!strncmp(oncore_messages[m].flag, (char *)(rcvbuf+2), (size_t) 2))
 				break;
 		if (m == l) {
@@ -1883,7 +1883,6 @@ oncore_msg_any(
 	UNUSED_ARG(len);
 	UNUSED_ARG(idx);
 #else
-	int i;
 	const char *fmt = oncore_messages[idx].fmt;
 	const char *p;
 	char *q;
@@ -1899,7 +1898,7 @@ oncore_msg_any(
 		if (!*fmt) {
 			snprintf(Msg, sizeof(Msg), ">>@@%c%c ", buf[2],
 				 buf[3]);
-			for(i = 2; i < len && i < 2400 ; i++) {
+			for(int i = 2; i < len && i < 2400 ; i++) {
 				snprintf(Msg2, sizeof(Msg2), "%02x",
 					 buf[i]);
 				strlcat(Msg, Msg2, sizeof(Msg));


=====================================
tests/wscript
=====================================
--- a/tests/wscript
+++ b/tests/wscript
@@ -1,8 +1,10 @@
+import os
 from waflib import Utils  # pylint: disable=import-error
 
 def build(ctx):
     srcnode = ctx.srcnode.abspath()
     testsrc = ctx.srcnode.make_node('tests')
+    pylib = ctx.srcnode.make_node('pylib')
     testpylib = testsrc.make_node('pylib')
     testpysrc = testpylib.ant_glob('*.py')
 
@@ -114,12 +116,43 @@ def build(ctx):
 
     testpylib.get_bld().mkdir()
 
+    pypath = pylib.get_bld()
+    linkpath = ctx.bldnode.make_node("tests/pylib/ntp")
+    if (not linkpath.exists()) or os.readlink(linkpath.abspath()):
+        try:
+            os.remove(linkpath.abspath())
+        except OSError:
+            pass
+        os.symlink(pypath.abspath(), linkpath.abspath())
+
+    ctx(
+        features="pytest",
+        pytest_source="pylib/test_util.py",
+        pytest_paths=pypath,
+		ut_str="${PYTHON} ${SRC}"
+    )
+    ctx(
+        features="pytest",
+        pytest_source="pylib/test_agentx.py",
+        pytest_paths=pypath,
+		ut_str="${PYTHON} ${SRC}"
+    )
+    ctx(
+        features="pytest",
+        pytest_source="pylib/test_packet.py",
+        pytest_paths=pypath,
+		ut_str="${PYTHON} ${SRC}"
+    )
+    ctx(
+        features="pytest",
+        pytest_source="pylib/test_statfiles.py",
+        pytest_paths=pypath,
+		ut_str="${PYTHON} ${SRC}"
+    )
+
     ctx(
         features="subst",
         source=testpysrc,
         target=[x.get_bld() for x in testpysrc],
         chmod=Utils.O755,
     )
-
-    # ctx.exec_command("%s/tests/pylib/test_statfiles.py" % srcnode)
-    # ctx.exec_command("%s/tests/pylib/test_util.py" % srcnode)


=====================================
waf
=====================================
The diff for this file was not included because it is too large.

=====================================
wscript
=====================================
--- a/wscript
+++ b/wscript
@@ -16,6 +16,7 @@ from waflib.Context import BOTH
 from waflib.Errors import WafError
 from waflib.Logs import pprint
 from waflib.Tools import waf_unit_test
+from waflib.extras import pytest
 
 # Avoid writing .pyc files in wafhelpers/
 sys.dont_write_bytecode = True
@@ -91,6 +92,7 @@ def configure(ctx):
     ctx.run_build_cls = 'check'
     ctx.load('waf', tooldir='wafhelpers/')
     ctx.load('waf_unit_test')
+    ctx.load('pytest')
     ctx.load('gnu_dirs')
 
     with open("VERSION", "r") as f:
@@ -1039,17 +1041,17 @@ def afterparty(ctx):
 
 
 python_scripts = [
-    "ntpclients/ntploggps",
-    "ntpclients/ntpdig",
-    "ntpclients/ntpkeygen",
-    "ntpclients/ntpmon",
-    "ntpclients/ntpq",
-    "ntpclients/ntpsweep",
-    "ntpclients/ntptrace",
-    "ntpclients/ntpviz",
-    "ntpclients/ntpwait",
-    "ntpclients/ntplogtemp",
-    "ntpclients/ntpsnmpd",
+    "ntpclients/ntploggps.py",
+    "ntpclients/ntpdig.py",
+    "ntpclients/ntpkeygen.py",
+    "ntpclients/ntpmon.py",
+    "ntpclients/ntpq.py",
+    "ntpclients/ntpsweep.py",
+    "ntpclients/ntptrace.py",
+    "ntpclients/ntpviz.py",
+    "ntpclients/ntpwait.py",
+    "ntpclients/ntplogtemp.py",
+    "ntpclients/ntpsnmpd.py",
 ]
 
 
@@ -1087,12 +1089,18 @@ def build(ctx):
     ctx.recurse("attic")
     ctx.recurse("tests")
 
+    # Make sure the python scripts actually get compiled
+    ctx(
+        features="py",
+        source=python_scripts,
+    )
+
     scripts = ["ntpclients/ntpleapfetch"] + python_scripts
 
     ctx(
         features="subst",
         source=scripts,
-        target=scripts,
+        target=[x.replace('.py', '') for x in scripts],
         chmod=Utils.O755,
         install_path='${BINDIR}',
     )



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/16ea62cece62580c36e45c1434ff488030817084...4d54f91a69925012862947786b8f07144018272b

---
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/16ea62cece62580c36e45c1434ff488030817084...4d54f91a69925012862947786b8f07144018272b
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/20171202/d4dba11b/attachment.html>


More information about the vc mailing list