[Git][NTPsec/ntpsec][master] 3 commits: Cleanup use of MODE_xxx (mode field in pkt header)

Hal Murray gitlab at mg.gitlab.com
Mon May 4 21:09:01 UTC 2020



Hal Murray pushed to branch master at NTPsec / ntpsec


Commits:
0cd27b56 by Hal Murray at 2020-05-01T10:17:42-07:00
Cleanup use of MODE_xxx (mode field in pkt header)
Drop kludge support for MODE_PASSIVE, aka peer <name>
or equivalent usage in ntpdate like software.

- - - - -
2a8c9d77 by Hal Murray at 2020-05-01T10:17:42-07:00
Fix for inline warnings from libaes_siv
First noticed when Fedora 32 was released with gcc 10.0.1

- - - - -
0afb4a8d by Hal Murray at 2020-05-04T13:56:36-07:00
Add CMAC/HMAC support to libntp/pymodule
So ntpq can authenticate packets using AES

- - - - -


7 changed files:

- include/ntp.h
- include/ntpd.h
- libaes_siv/wscript
- libntp/pymodule.c
- ntpd/ntp_proto.c
- ntpd/ntp_signd.c
- pylib/util.py


Changes:

=====================================
include/ntp.h
=====================================
@@ -350,17 +350,17 @@ struct peer {
 /* Packet Modes
  */
 #define	MODE_UNSPEC	0	/* unspecified (old version) */
-#define	MODE_ACTIVE	1	/* symmetric active mode */
-#define	MODE_PASSIVE	2	/* symmetric passive mode */
+#define	MODE_ACTIVEx	1	/* symmetric active mode */
+#define	MODE_PASSIVEx	2	/* symmetric passive mode */
 #define	MODE_CLIENT	3	/* client mode */
 #define	MODE_SERVER	4	/* server mode */
-#define	MODE_BROADCAST	5	/* broadcast mode */
+#define	MODE_BROADCASTx	5	/* broadcast mode */
 
 /*
  * These can appear in packets
  */
 #define	MODE_CONTROL	6	/* control mode, ntpq*/
-#define	MODE_PRIVATE	7	/* Dead: private mode, was ntpdc */
+#define	MODE_PRIVATEx	7	/* Dead: private mode, was ntpdc */
 /*
  * This is a madeup mode for broadcast client.  No longer used by ntpd.
  */


=====================================
include/ntpd.h
=====================================
@@ -419,8 +419,7 @@ extern struct restriction_data rstrct;
 
 #ifdef ENABLE_MSSNTP
 /* ntp_signd.c */
-extern void send_via_ntp_signd(struct recvbuf *, int, keyid_t, int,
-			       void *);
+extern void send_via_ntp_signd(struct recvbuf *, keyid_t, int, void *);
 #endif
 
 /* ntp_timer.c */


=====================================
libaes_siv/wscript
=====================================
@@ -1,7 +1,8 @@
 def build(ctx):
     # libaes_siv has warnings when built with -Wshadow, so make sure to use
     # -Wno-shadow
-    ctx.env.CFLAGS_cstlib = ['-Wno-shadow']
+    # gcc 10 gives inline warnings, so add no-inline too
+    ctx.env.CFLAGS_cstlib = ['-Wno-shadow', '-Wno-inline']
 
     ctx(
         target="aes_siv",


=====================================
libntp/pymodule.c
=====================================
@@ -4,6 +4,7 @@
  *
  * Python binding for selected libntp library functions
  */
+#define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
 #include "config.h"
@@ -21,6 +22,9 @@
 
 #include "ntp_control.h"
 
+#include "ntp_auth.h"
+#include <openssl/evp.h>
+
 #include "python_compatibility.h"
 
 const char *progname = "libntpc";
@@ -141,6 +145,137 @@ ntpc_step_systime(PyObject *self, PyObject *args)
 	return Py_BuildValue("d", step_systime(full_adjustment, ntp_set_tod));
 }
 
+/* --------------------------------------------------------------- */
+/* Hook for CMAC/HMAC
+ * Not really part of libntp, but this is a handy place to put it.
+ */
+
+/* Slightly older version of OpenSSL */
+/* Similar hack in ssl_init.c and attic/digest-timing.c */
+#ifndef EVP_MD_CTX_new
+#define EVP_MD_CTX_new() EVP_MD_CTX_create()
+#endif
+#ifndef EVP_MD_CTX_reset
+#define EVP_MD_CTX_reset(ctx) EVP_MD_CTX_init(ctx)
+#endif
+
+
+/* xx = ntp.ntpc.checkname(name)
+ * returns None if algorithm name is invalid. */
+
+static PyObject *
+ntpc_checkname(PyObject *self, PyObject *args)
+{
+	const char *name;
+	char upcase[100];
+	const EVP_MD *digest;
+	const EVP_CIPHER *cipher;
+	UNUSED_ARG(self);
+
+	if (!PyArg_ParseTuple(args, "s", &name))
+		return NULL;
+        strlcpy(upcase, name, sizeof(upcase));
+	for (int i=0; upcase[i]!=0; i++) {
+		upcase[i] = toupper(upcase[i]);
+	}
+
+        digest = EVP_get_digestbyname(upcase);
+	if (NULL != digest) {
+		return Py_BuildValue("i", 1);
+        }
+
+        if ((strcmp(upcase, "AES") == 0) || (strcmp(upcase, "AES128CMAC") == 0)) {
+                strlcpy(upcase, "AES-128", sizeof(upcase));
+        }
+        strlcat(upcase, "-CBC", sizeof(upcase));
+	cipher = EVP_get_cipherbyname(upcase);
+	if (NULL != cipher) {
+		int length = EVP_CIPHER_key_length(cipher);
+		return Py_BuildValue("i", length);
+	}
+
+	Py_RETURN_NONE;
+}
+
+
+/* mac = ntp.ntpc.mac(data, key, name) */
+
+static PyObject *
+ntpc_mac(PyObject *self, PyObject *args)
+{
+	UNUSED_ARG(self);
+	uint8_t *data;
+	Py_ssize_t datalen;
+	uint8_t *key;
+	Py_ssize_t keylen;
+	char *name;
+	uint8_t mac[CMAC_MAX_MAC_LENGTH];
+	size_t maclen;
+	char upcase[100];
+	static EVP_MD_CTX *digest_ctx = NULL;
+	static CMAC_CTX *cmac_ctx = NULL;
+	const EVP_MD *digest;
+	const EVP_CIPHER *cipher;
+	int cipherlen;
+	if (!PyArg_ParseTuple(args, "y#y#s",
+			&data, &datalen, &key, &keylen, &name))
+		Py_RETURN_NONE;
+
+        strlcpy(upcase, name, sizeof(upcase));
+	for (int i=0; upcase[i]!=0; i++) {
+		upcase[i] = toupper(upcase[i]);
+	}
+
+        digest = EVP_get_digestbyname(upcase);
+	if (NULL != digest) {
+		/* Old digest case, MD5, SHA1 */
+		unsigned int maclenint;
+		if (NULL == digest_ctx)
+			digest_ctx = EVP_MD_CTX_new();
+		EVP_MD_CTX_reset(digest_ctx);
+		if (!EVP_DigestInit_ex(digest_ctx, digest, NULL))
+			Py_RETURN_NONE;
+		EVP_DigestUpdate(digest_ctx, key, keylen);
+		EVP_DigestUpdate(digest_ctx, data, (unsigned int)datalen);
+		EVP_DigestFinal_ex(digest_ctx, mac, &maclenint);
+		if (MAX_BARE_MAC_LENGTH < maclenint)
+			maclenint = MAX_BARE_MAC_LENGTH;
+		return Py_BuildValue("y#", &mac, maclenint);
+	}
+
+        if ((strcmp(upcase, "AES") == 0) || (strcmp(upcase, "AES128CMAC") == 0)) {
+                strlcpy(upcase, "AES-128", sizeof(upcase));
+        }
+        strlcat(upcase, "-CBC", sizeof(upcase));
+
+	cipher = EVP_get_cipherbyname(upcase);
+	if (NULL == cipher)
+		Py_RETURN_NONE;
+
+	cipherlen = EVP_CIPHER_key_length(cipher);
+	if (cipherlen < keylen) {
+		keylen = cipherlen;		/* truncate */
+	} else if (cipherlen > keylen) {
+		uint8_t newkey[EVP_MAX_KEY_LENGTH];
+		memcpy(newkey, key, keylen);
+		while (cipherlen > keylen)
+			key[keylen++] = 0;	/* pad with 0s */
+		key = newkey;
+	}
+	if (NULL == cmac_ctx)
+		cmac_ctx = CMAC_CTX_new();
+	CMAC_resume(cmac_ctx);
+        if (!CMAC_Init(cmac_ctx, key, keylen, cipher, NULL)) {
+                /* Shouldn't happen.  Does if wrong key_size. */
+		Py_RETURN_NONE;
+        }
+        CMAC_Update(cmac_ctx, data, (unsigned int)datalen);
+        CMAC_Final(cmac_ctx, mac, &maclen);
+        if (MAX_BARE_MAC_LENGTH < maclen)
+                maclen = MAX_BARE_MAC_LENGTH;
+	return Py_BuildValue("y#", &mac, maclen);
+}
+
 /* List of functions defined in the module */
 
 static PyMethodDef ntpc_methods[] = {
@@ -158,6 +293,10 @@ static PyMethodDef ntpc_methods[] = {
      PyDoc_STR("Adjust system time by slewing.")},
     {"step_systime",    ntpc_step_systime,   	METH_VARARGS,
      PyDoc_STR("Adjust system time by stepping.")},
+    {"checkname",       ntpc_checkname,   	METH_VARARGS,
+     PyDoc_STR("Check if name is a valid algorithm name")},
+    {"mac",             ntpc_mac,   		METH_VARARGS,
+     PyDoc_STR("Compute HMAC or CMAC from data, key, and algorithm name")},
     {NULL,		NULL, 0, NULL}		/* sentinel */
 };
 


=====================================
ntpd/ntp_proto.c
=====================================
@@ -239,7 +239,7 @@ double	measured_tick;		/* non-overridable sys_tick (s) */
 static	void	clock_combine	(peer_select *, int, int);
 static	void	clock_select	(void);
 static	void	clock_update	(struct peer *);
-static	void	fast_xmit	(struct recvbuf *, int, auth_info*, int);
+static	void	fast_xmit	(struct recvbuf *, auth_info*, int);
 static	int	local_refid	(struct peer *);
 #ifdef ENABLE_FUZZ
 static	void	measure_precision(const bool);
@@ -290,10 +290,11 @@ is_vn_mode_acceptable(
 	)
 {
 	return rbufp->recv_length >= 1 &&
-	    PKT_VERSION(rbufp->recv_buffer[0]) >= 1 &&
-	    PKT_VERSION(rbufp->recv_buffer[0]) <= 4 &&
-	    PKT_MODE(rbufp->recv_buffer[0]) != MODE_PRIVATE &&
-	    PKT_MODE(rbufp->recv_buffer[0]) != MODE_UNSPEC;
+	    PKT_VERSION(rbufp->recv_buffer[0]) >= NTP_OLDVERSION &&
+	    PKT_VERSION(rbufp->recv_buffer[0]) <= NTP_VERSION &&
+	    ( PKT_MODE(rbufp->recv_buffer[0]) == MODE_CLIENT ||
+	      PKT_MODE(rbufp->recv_buffer[0]) == MODE_SERVER ||
+              PKT_MODE(rbufp->recv_buffer[0]) == MODE_CONTROL);
 }
 
 static bool
@@ -302,7 +303,7 @@ is_control_packet(
 	)
 {
 	return rbufp->recv_length >= 1 &&
-	    PKT_VERSION(rbufp->recv_buffer[0]) <= 4 &&
+	    PKT_VERSION(rbufp->recv_buffer[0]) <= NTP_VERSION &&
 	    PKT_MODE(rbufp->recv_buffer[0]) == MODE_CONTROL;
 }
 
@@ -668,7 +669,7 @@ receive(
 	struct peer *peer = NULL;
 	unsigned short restrict_mask;
 	auth_info* auth = NULL;  /* !NULL if authenticated */
-	int mode, xmode;
+	int mode;
 
 	stat_count.sys_received++;
 
@@ -772,7 +773,6 @@ receive(
 	}
 
 	switch (mode) {
-	    case MODE_ACTIVE:  /* remote site using "peer" in config file */
 	    case MODE_CLIENT:  /* Request for us as a server. */
 		if (rbufp->extens_present
 #ifndef DISABLE_NTS
@@ -784,8 +784,7 @@ receive(
 			maybe_log_junk("EX-REQ", rbufp);
 			break;
 		}
-		xmode = (mode == MODE_ACTIVE) ? MODE_PASSIVE : MODE_SERVER;
-		fast_xmit(rbufp, xmode, auth, restrict_mask);
+		fast_xmit(rbufp, auth, restrict_mask);
 		stat_count.sys_processed++;
 		break;
 	    case MODE_SERVER:  /* Reply to our request to a server. */
@@ -1289,8 +1288,6 @@ peer_clear(
 	peer->nextdate = peer->update = peer->outdate = current_time;
 	if (initializing1) {
 		peer->nextdate += (unsigned long)peer_associations;
-	} else if (MODE_PASSIVE == peer->hmode) {
-		peer->nextdate += (unsigned long)rstrct.ntp_minpkt;
 	} else {
 	    /*
 	     * Randomizing the next poll interval used to be done with
@@ -2222,7 +2219,6 @@ leap_smear_add_offs(l_fp *t) {
 static void
 fast_xmit(
 	struct recvbuf *rbufp,	/* receive packet pointer */
-	int	xmode,		/* receive mode */
 	auth_info *auth,	/* !NULL for authentication */
 	int	flags		/* restrict mask */
 	)
@@ -2251,7 +2247,7 @@ fast_xmit(
 	if (flags & RES_KOD) {
 		stat_count.sys_kodsent++;
 		xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
-		    PKT_VERSION(rbufp->pkt.li_vn_mode), xmode);
+		    PKT_VERSION(rbufp->pkt.li_vn_mode), MODE_SERVER);
 		xpkt.stratum = STRATUM_PKT_UNSPEC;
 		xpkt.ppoll = max(rbufp->pkt.ppoll, rstrct.ntp_minpoll);
 		xpkt.precision = rbufp->pkt.precision;
@@ -2287,7 +2283,7 @@ fast_xmit(
 		 * the transmit/receive times.
 		 */
 		xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_vars.sys_leap,
-		    PKT_VERSION(rbufp->pkt.li_vn_mode), xmode);
+		    PKT_VERSION(rbufp->pkt.li_vn_mode), MODE_SERVER);
 		xpkt.stratum = STRATUM_TO_PKT(sys_vars.sys_stratum);
 		xpkt.ppoll = max(rbufp->pkt.ppoll, rstrct.ntp_minpoll);
 		xpkt.precision = sys_vars.sys_precision;
@@ -2336,7 +2332,7 @@ fast_xmit(
 		keyid_t keyid = 0;
 		if (NULL != auth) keyid = auth->keyid;
 		// FIXME need counter
-		send_via_ntp_signd(rbufp, xmode, keyid, flags, &xpkt);
+		send_via_ntp_signd(rbufp, keyid, flags, &xpkt);
 		return;
 	}
 #endif /* ENABLE_MSSNTP */
@@ -2370,9 +2366,9 @@ fast_xmit(
 	/* Previous versions of this code had separate DPRINT-s so it
 	 * could print the key on the auth case.  That requires separate
 	 * sendpkt-s on each branch or the DPRINT pollutes the timing. */
-	DPRINT(1, ("transmit: at %u %s->%s mode %d len %zu\n",
+	DPRINT(1, ("transmit: at %u %s->%s len %zu\n",
 		   current_time, socktoa(&rbufp->dstadr->sin),
-		   socktoa(&rbufp->recv_srcadr), xmode, sendlen));
+		   socktoa(&rbufp->recv_srcadr), sendlen));
 }
 
 


=====================================
ntpd/ntp_signd.c
=====================================
@@ -121,16 +121,12 @@ recv_packet(int fd, char **buf, uint32_t *len)
 void
 send_via_ntp_signd(
 	struct recvbuf *rbufp,	/* receive packet pointer */
-	int	xmode,
 	keyid_t	xkeyid,
 	int flags,
 	void *xpkt
 	)
 {
 	UNUSED_ARG(flags);
-#ifndef DEBUG
-	UNUSED_ARG(xmode);
-#endif
 
 	/* We are here because it was detected that the client
 	 * sent an all-zero signature, and we therefore know
@@ -220,9 +216,9 @@ send_via_ntp_signd(
 				sendlen = reply_len - offsetof(struct samba_key_out, pkt);
 				xpkt = &samba_reply.pkt;
 				sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, xpkt, sendlen);
-				DPRINT(1, ("transmit ntp_signd packet: at %u %s->%s mode %d keyid %08x len %d\n",
+				DPRINT(1, ("transmit ntp_signd packet: at %u %s->%s keyid %08x len %d\n",
 					   current_time, socktoa(&rbufp->dstadr->sin),
-					   socktoa(&rbufp->recv_srcadr), xmode, xkeyid, sendlen));
+					   socktoa(&rbufp->recv_srcadr), xkeyid, sendlen));
 			}
 		}
 


=====================================
pylib/util.py
=====================================
@@ -1096,7 +1096,7 @@ class PeerSummary:
         if hmode == ntp.magic.MODE_BCLIENTX:
             # broadcastclient or multicastclient
             ptype = 'b'
-        elif hmode == ntp.magic.MODE_BROADCAST:
+        elif hmode == ntp.magic.MODE_BROADCASTx:
             # broadcast or multicast server
             if srcadr.startswith("224."):       # IANA multicast address prefix
                 ptype = 'M'
@@ -1114,9 +1114,9 @@ class PeerSummary:
                 ptype = chr(ntscookies + ord('0'))
             else:
                 ptype = 'u'     # unicast
-        elif hmode == ntp.magic.MODE_ACTIVE:
+        elif hmode == ntp.magic.MODE_ACTIVEx:
             ptype = 's'         # symmetric active
-        elif hmode == ntp.magic.MODE_PASSIVE:
+        elif hmode == ntp.magic.MODE_PASSIVEx:
             ptype = 'S'         # symmetric passive
 
         #



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/574d871ed8aa44f04b6bbad0220773475ebf55db...0afb4a8da0de6c99011dee6baf4580d27c5feee7

-- 
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/574d871ed8aa44f04b6bbad0220773475ebf55db...0afb4a8da0de6c99011dee6baf4580d27c5feee7
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/20200504/d5ccc964/attachment-0001.htm>


More information about the vc mailing list