[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