diff options
author | gordon <gordon@FreeBSD.org> | 2018-03-07 05:58:24 +0000 |
---|---|---|
committer | gordon <gordon@FreeBSD.org> | 2018-03-07 05:58:24 +0000 |
commit | 5f0a95d4d67b9661a44d76f8be22183785af0814 (patch) | |
tree | d12a586453bbbc83e599e0e2311907acb6e2e467 /contrib/ntp/libntp | |
parent | 722c1ce56e86ad17ed56adee959f19b00bc1ca93 (diff) | |
download | FreeBSD-src-5f0a95d4d67b9661a44d76f8be22183785af0814.zip FreeBSD-src-5f0a95d4d67b9661a44d76f8be22183785af0814.tar.gz |
Fix multiple vulnerabilities in ntp. [SA-18:02.ntp]
Approved by: so
Security: FreeBSD-SA-18:02.ntp
Security: CVE-2018-7182
Security: CVE-2018-7170
Security: CVE-2018-7184
Security: CVE-2018-7185
Security: CVE-2018-7183
Diffstat (limited to 'contrib/ntp/libntp')
-rw-r--r-- | contrib/ntp/libntp/Makefile.in | 1 | ||||
-rw-r--r-- | contrib/ntp/libntp/a_md5encrypt.c | 248 | ||||
-rw-r--r-- | contrib/ntp/libntp/adjtime.c | 4 | ||||
-rw-r--r-- | contrib/ntp/libntp/authkeys.c | 126 | ||||
-rw-r--r-- | contrib/ntp/libntp/authreadkeys.c | 52 | ||||
-rw-r--r-- | contrib/ntp/libntp/libssl_compat.c | 5 | ||||
-rw-r--r-- | contrib/ntp/libntp/ntp_calendar.c | 109 | ||||
-rw-r--r-- | contrib/ntp/libntp/ssl_init.c | 114 | ||||
-rw-r--r-- | contrib/ntp/libntp/statestr.c | 284 | ||||
-rw-r--r-- | contrib/ntp/libntp/systime.c | 338 | ||||
-rw-r--r-- | contrib/ntp/libntp/work_thread.c | 2 |
11 files changed, 914 insertions, 369 deletions
diff --git a/contrib/ntp/libntp/Makefile.in b/contrib/ntp/libntp/Makefile.in index 25718b9..2bef787 100644 --- a/contrib/ntp/libntp/Makefile.in +++ b/contrib/ntp/libntp/Makefile.in @@ -101,6 +101,7 @@ am__aclocal_m4_deps = $(top_srcdir)/sntp/libopts/m4/libopts.m4 \ $(top_srcdir)/sntp/m4/ltsugar.m4 \ $(top_srcdir)/sntp/m4/ltversion.m4 \ $(top_srcdir)/sntp/m4/lt~obsolete.m4 \ + $(top_srcdir)/sntp/m4/ntp_af_unspec.m4 \ $(top_srcdir)/sntp/m4/ntp_cacheversion.m4 \ $(top_srcdir)/sntp/m4/ntp_compiler.m4 \ $(top_srcdir)/sntp/m4/ntp_crosscompile.m4 \ diff --git a/contrib/ntp/libntp/a_md5encrypt.c b/contrib/ntp/libntp/a_md5encrypt.c index 7394d0d..7dc7e7e 100644 --- a/contrib/ntp/libntp/a_md5encrypt.c +++ b/contrib/ntp/libntp/a_md5encrypt.c @@ -11,6 +11,177 @@ #include "ntp.h" #include "ntp_md5.h" /* provides OpenSSL digest API */ #include "isc/string.h" + +#ifdef OPENSSL +# include "openssl/cmac.h" +# define CMAC "AES128CMAC" +# define AES_128_KEY_SIZE 16 +#endif + +typedef struct { + const void * buf; + size_t len; +} robuffT; + +typedef struct { + void * buf; + size_t len; +} rwbuffT; + +#ifdef OPENSSL +static size_t +cmac_ctx_size( + CMAC_CTX * ctx) +{ + size_t mlen = 0; + + if (ctx) { + EVP_CIPHER_CTX * cctx; + if (NULL != (cctx = CMAC_CTX_get0_cipher_ctx (ctx))) + mlen = EVP_CIPHER_CTX_block_size(cctx); + } + return mlen; +} +#endif /*OPENSSL*/ + +static size_t +make_mac( + const rwbuffT * digest, + int ktype, + const robuffT * key, + const robuffT * msg) +{ + /* + * Compute digest of key concatenated with packet. Note: the + * key type and digest type have been verified when the key + * was created. + */ + size_t retlen = 0; + +#ifdef OPENSSL + + INIT_SSL(); + + /* Check if CMAC key type specific code required */ + if (ktype == NID_cmac) { + CMAC_CTX * ctx = NULL; + void const * keyptr = key->buf; + u_char keybuf[AES_128_KEY_SIZE]; + + /* adjust key size (zero padded buffer) if necessary */ + if (AES_128_KEY_SIZE > key->len) { + memcpy(keybuf, keyptr, key->len); + memset((keybuf + key->len), 0, + (AES_128_KEY_SIZE - key->len)); + keyptr = keybuf; + } + + if (NULL == (ctx = CMAC_CTX_new())) { + msyslog(LOG_ERR, "MAC encrypt: CMAC %s CTX new failed.", CMAC); + goto cmac_fail; + } + if (!CMAC_Init(ctx, keyptr, AES_128_KEY_SIZE, EVP_aes_128_cbc(), NULL)) { + msyslog(LOG_ERR, "MAC encrypt: CMAC %s Init failed.", CMAC); + goto cmac_fail; + } + if (cmac_ctx_size(ctx) > digest->len) { + msyslog(LOG_ERR, "MAC encrypt: CMAC %s buf too small.", CMAC); + goto cmac_fail; + } + if (!CMAC_Update(ctx, msg->buf, msg->len)) { + msyslog(LOG_ERR, "MAC encrypt: CMAC %s Update failed.", CMAC); + goto cmac_fail; + } + if (!CMAC_Final(ctx, digest->buf, &retlen)) { + msyslog(LOG_ERR, "MAC encrypt: CMAC %s Final failed.", CMAC); + retlen = 0; + } + cmac_fail: + if (ctx) + CMAC_CTX_cleanup(ctx); + } + else { /* generic MAC handling */ + EVP_MD_CTX * ctx = EVP_MD_CTX_new(); + u_int uilen = 0; + + if ( ! ctx) { + msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest CTX new failed.", + OBJ_nid2sn(ktype)); + goto mac_fail; + } + + #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW + /* make sure MD5 is allowd */ + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + #endif + /* [Bug 3457] DON'T use plain EVP_DigestInit! It would + * kill the flags! */ + if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(ktype), NULL)) { + msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Init failed.", + OBJ_nid2sn(ktype)); + goto mac_fail; + } + if ((size_t)EVP_MD_CTX_size(ctx) > digest->len) { + msyslog(LOG_ERR, "MAC encrypt: MAC %s buf too small.", + OBJ_nid2sn(ktype)); + goto mac_fail; + } + if (!EVP_DigestUpdate(ctx, key->buf, (u_int)key->len)) { + msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Update key failed.", + OBJ_nid2sn(ktype)); + goto mac_fail; + } + if (!EVP_DigestUpdate(ctx, msg->buf, (u_int)msg->len)) { + msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Update data failed.", + OBJ_nid2sn(ktype)); + goto mac_fail; + } + if (!EVP_DigestFinal(ctx, digest->buf, &uilen)) { + msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Final failed.", + OBJ_nid2sn(ktype)); + uilen = 0; + } + mac_fail: + retlen = (size_t)uilen; + + if (ctx) + EVP_MD_CTX_free(ctx); + } + +#else /* !OPENSSL follows */ + + if (ktype == NID_md5) + { + EVP_MD_CTX * ctx = EVP_MD_CTX_new(); + uint uilen = 0; + + if (digest->len < 16) { + msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 buf too small."); + } + else if ( ! ctx) { + msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 Digest CTX new failed."); + } + else { + EVP_DigestInit(ctx, EVP_get_digestbynid(ktype)); + EVP_DigestUpdate(ctx, key->buf, key->len); + EVP_DigestUpdate(ctx, msg->buf, msg->len); + EVP_DigestFinal(ctx, digest->buf, &uilen); + } + if (ctx) + EVP_MD_CTX_free(ctx); + retlen = (size_t)uilen; + } + else + { + msyslog(LOG_ERR, "MAC encrypt: invalid key type %d" , ktype); + } + +#endif /* !OPENSSL */ + + return retlen; +} + + /* * MD5authencrypt - generate message digest * @@ -20,36 +191,23 @@ size_t MD5authencrypt( int type, /* hash algorithm */ const u_char * key, /* key pointer */ + size_t klen, /* key length */ u_int32 * pkt, /* packet pointer */ size_t length /* packet length */ ) { u_char digest[EVP_MAX_MD_SIZE]; - u_int len; - EVP_MD_CTX *ctx; + rwbuffT digb = { digest, sizeof(digest) }; + robuffT keyb = { key, klen }; + robuffT msgb = { pkt, length }; + size_t dlen = 0; - /* - * Compute digest of key concatenated with packet. Note: the - * key type and digest type have been verified when the key - * was creaded. - */ - INIT_SSL(); - ctx = EVP_MD_CTX_new(); - if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) { - msyslog(LOG_ERR, - "MAC encrypt: digest init failed"); - EVP_MD_CTX_free(ctx); - return (0); - } - EVP_DigestUpdate(ctx, key, cache_secretsize); - EVP_DigestUpdate(ctx, (u_char *)pkt, length); - EVP_DigestFinal(ctx, digest, &len); - EVP_MD_CTX_free(ctx); + dlen = make_mac(&digb, type, &keyb, &msgb); /* If the MAC is longer than the MAX then truncate it. */ - if (len > MAX_MAC_LEN - 4) - len = MAX_MAC_LEN - 4; - memmove((u_char *)pkt + length + 4, digest, len); - return (len + 4); + if (dlen > MAX_MDG_LEN) + dlen = MAX_MDG_LEN; + memcpy((u_char *)pkt + length + KEY_MAC_LEN, digest, dlen); + return (dlen + KEY_MAC_LEN); } @@ -62,41 +220,30 @@ int MD5authdecrypt( int type, /* hash algorithm */ const u_char * key, /* key pointer */ + size_t klen, /* key length */ u_int32 * pkt, /* packet pointer */ size_t length, /* packet length */ size_t size /* MAC size */ ) { u_char digest[EVP_MAX_MD_SIZE]; - u_int len; - EVP_MD_CTX *ctx; + rwbuffT digb = { digest, sizeof(digest) }; + robuffT keyb = { key, klen }; + robuffT msgb = { pkt, length }; + size_t dlen = 0; - /* - * Compute digest of key concatenated with packet. Note: the - * key type and digest type have been verified when the key - * was created. - */ - INIT_SSL(); - ctx = EVP_MD_CTX_new(); - if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) { - msyslog(LOG_ERR, - "MAC decrypt: digest init failed"); - EVP_MD_CTX_free(ctx); - return (0); - } - EVP_DigestUpdate(ctx, key, cache_secretsize); - EVP_DigestUpdate(ctx, (u_char *)pkt, length); - EVP_DigestFinal(ctx, digest, &len); - EVP_MD_CTX_free(ctx); + dlen = make_mac(&digb, type, &keyb, &msgb); + /* If the MAC is longer than the MAX then truncate it. */ - if (len > MAX_MAC_LEN - 4) - len = MAX_MAC_LEN - 4; - if (size != (size_t)len + 4) { + if (dlen > MAX_MDG_LEN) + dlen = MAX_MDG_LEN; + if (size != (size_t)dlen + KEY_MAC_LEN) { msyslog(LOG_ERR, "MAC decrypt: MAC length error"); return (0); } - return !isc_tsmemcmp(digest, (u_char *)pkt + length + 4, len); + return !isc_tsmemcmp(digest, + (u_char *)pkt + length + KEY_MAC_LEN, dlen); } /* @@ -108,7 +255,7 @@ MD5authdecrypt( u_int32 addr2refid(sockaddr_u *addr) { - u_char digest[20]; + u_char digest[EVP_MAX_MD_SIZE]; u_int32 addr_refid; EVP_MD_CTX *ctx; u_int len; @@ -119,11 +266,12 @@ addr2refid(sockaddr_u *addr) INIT_SSL(); ctx = EVP_MD_CTX_new(); - EVP_MD_CTX_init(ctx); -#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW +# ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW /* MD5 is not used as a crypto hash here. */ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); -#endif +# endif + /* [Bug 3457] DON'T use plain EVP_DigestInit! It would kill the + * flags! */ if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) { msyslog(LOG_ERR, "MD5 init failed"); diff --git a/contrib/ntp/libntp/adjtime.c b/contrib/ntp/libntp/adjtime.c index a8e6580..b536cc5 100644 --- a/contrib/ntp/libntp/adjtime.c +++ b/contrib/ntp/libntp/adjtime.c @@ -314,7 +314,7 @@ adjtime (struct timeval *delta, struct timeval *olddelta) /* * Get the current clock period (nanoseconds) */ - if (ClockPeriod (CLOCK_REALTIME, 0, &period, 0) < 0) + if (ClockPeriod (CLOCK_REALTIME, 0, &period, 0) == -1) return -1; /* @@ -354,7 +354,7 @@ adjtime (struct timeval *delta, struct timeval *olddelta) adj.tick_count = 0; } - if (ClockAdjust (CLOCK_REALTIME, &adj, &oldadj) < 0) + if (ClockAdjust (CLOCK_REALTIME, &adj, &oldadj) == -1) return -1; /* diff --git a/contrib/ntp/libntp/authkeys.c b/contrib/ntp/libntp/authkeys.c index b2ff410..7c1cbb0 100644 --- a/contrib/ntp/libntp/authkeys.c +++ b/contrib/ntp/libntp/authkeys.c @@ -114,13 +114,16 @@ KeyAccT *cache_keyacclist; /* key access list */ KeyAccT* keyacc_new_push( KeyAccT * head, - const sockaddr_u * addr + const sockaddr_u * addr, + unsigned int subnetbits ) { KeyAccT * node = emalloc(sizeof(KeyAccT)); memcpy(&node->addr, addr, sizeof(sockaddr_u)); + node->subnetbits = subnetbits; node->next = head; + return node; } @@ -165,7 +168,8 @@ keyacc_contains( { if (head) { do { - if (SOCK_EQ(&head->addr, addr)) + if (keyacc_amatch(&head->addr, addr, + head->subnetbits)) return TRUE; } while (NULL != (head = head->next)); return FALSE; @@ -174,6 +178,98 @@ keyacc_contains( } } +#if CHAR_BIT != 8 +# error "don't know how to handle bytes with that bit size" +#endif + +/* ----------------------------------------------------------------- */ +/* check two addresses for a match, taking a prefix length into account + * when doing the compare. + * + * The ISC lib contains a similar function with not entirely specified + * semantics, so it seemed somewhat cleaner to do this from scratch. + * + * Note 1: It *is* assumed that the addresses are stored in network byte + * order, that is, most significant byte first! + * + * Note 2: "no address" compares unequal to all other addresses, even to + * itself. This has the same semantics as NaNs have for floats: *any* + * relational or equality operation involving a NaN returns FALSE, even + * equality with itself. "no address" is either a NULL pointer argument + * or an address of type AF_UNSPEC. + */ +int/*BOOL*/ +keyacc_amatch( + const sockaddr_u * a1, + const sockaddr_u * a2, + unsigned int mbits + ) +{ + const uint8_t * pm1; + const uint8_t * pm2; + uint8_t msk; + unsigned int len; + + /* 1st check: If any address is not an address, it's inequal. */ + if ( !a1 || (AF_UNSPEC == AF(a1)) || + !a2 || (AF_UNSPEC == AF(a2)) ) + return FALSE; + + /* We could check pointers for equality here and shortcut the + * other checks if we find object identity. But that use case is + * too rare to care for it. + */ + + /* 2nd check: Address families must be the same. */ + if (AF(a1) != AF(a2)) + return FALSE; + + /* type check: address family determines buffer & size */ + switch (AF(a1)) { + case AF_INET: + /* IPv4 is easy: clamp size, get byte pointers */ + if (mbits > sizeof(NSRCADR(a1)) * 8) + mbits = sizeof(NSRCADR(a1)) * 8; + pm1 = (const void*)&NSRCADR(a1); + pm2 = (const void*)&NSRCADR(a2); + break; + + case AF_INET6: + /* IPv6 is slightly different: Both scopes must match, + * too, before we even consider doing a match! + */ + if ( ! SCOPE_EQ(a1, a2)) + return FALSE; + if (mbits > sizeof(NSRCADR6(a1)) * 8) + mbits = sizeof(NSRCADR6(a1)) * 8; + pm1 = (const void*)&NSRCADR6(a1); + pm2 = (const void*)&NSRCADR6(a2); + break; + + default: + /* don't know how to compare that!?! */ + return FALSE; + } + + /* Split bit length into byte length and partial byte mask. + * Note that the byte mask extends from the MSB of a byte down, + * and that zero shift (--> mbits % 8 == 0) results in an + * all-zero mask. + */ + msk = 0xFFu ^ (0xFFu >> (mbits & 7)); + len = mbits >> 3; + + /* 3rd check: Do memcmp() over full bytes, if any */ + if (len && memcmp(pm1, pm2, len)) + return FALSE; + + /* 4th check: compare last incomplete byte, if any */ + if (msk && ((pm1[len] ^ pm2[len]) & msk)) + return FALSE; + + /* If none of the above failed, we're successfully through. */ + return TRUE; +} /* * init_auth - initialize internal data @@ -316,6 +412,10 @@ auth_log2(size_t x) return (u_short)r; } +int/*BOOL*/ +ipaddr_match_masked(const sockaddr_u *,const sockaddr_u *, + unsigned int mbits); + static void authcache_flush_id( keyid_t id @@ -617,20 +717,19 @@ authistrusted( { symkey * sk; - /* That specific key was already used to authenticate the - * packet. Therefore, the key *must* exist... There's a chance - * that is not trusted, though. - */ if (keyno == cache_keyid) { return (KEY_TRUSTED & cache_flags) && keyacc_contains(cache_keyacclist, sau, TRUE); - } else { + } + + if (NULL != (sk = auth_findkey(keyno))) { authkeyuncached++; - sk = auth_findkey(keyno); - INSIST(NULL != sk); return (KEY_TRUSTED & sk->flags) && keyacc_contains(sk->keyacclist, sau, TRUE); } + + authkeynotfound++; + return FALSE; } /* Note: There are two locations below where 'strncpy()' is used. While @@ -795,7 +894,9 @@ authencrypt( return 0; } - return MD5authencrypt(cache_type, cache_secret, pkt, length); + return MD5authencrypt(cache_type, + cache_secret, cache_secretsize, + pkt, length); } @@ -822,6 +923,7 @@ authdecrypt( return FALSE; } - return MD5authdecrypt(cache_type, cache_secret, pkt, length, - size); + return MD5authdecrypt(cache_type, + cache_secret, cache_secretsize, + pkt, length, size); } diff --git a/contrib/ntp/libntp/authreadkeys.c b/contrib/ntp/libntp/authreadkeys.c index e9273ad..bd98ab2 100644 --- a/contrib/ntp/libntp/authreadkeys.c +++ b/contrib/ntp/libntp/authreadkeys.c @@ -5,8 +5,8 @@ #include <stdio.h> #include <ctype.h> -#include "ntpd.h" /* Only for DPRINTF */ -#include "ntp_fp.h" +//#include "ntpd.h" /* Only for DPRINTF */ +//#include "ntp_fp.h" #include "ntp.h" #include "ntp_syslog.h" #include "ntp_stdlib.h" @@ -148,6 +148,7 @@ authreadkeys( u_int nerr; KeyDataT *list = NULL; KeyDataT *next = NULL; + /* * Open file. Complain and return if it can't be opened. */ @@ -220,7 +221,8 @@ authreadkeys( log_maybe(NULL, "authreadkeys: invalid type for key %d", keyno); - } else if (EVP_get_digestbynid(keytype) == NULL) { + } else if (NID_cmac != keytype && + EVP_get_digestbynid(keytype) == NULL) { log_maybe(NULL, "authreadkeys: no algorithm for key %d", keyno); @@ -295,28 +297,62 @@ authreadkeys( } token = nexttok(&line); - DPRINTF(0, ("authreadkeys: full access list <%s>\n", (token) ? token : "NULL")); if (token != NULL) { /* A comma-separated IP access list */ char *tp = token; while (tp) { char *i; + char *snp; /* subnet text pointer */ + unsigned int snbits; sockaddr_u addr; i = strchr(tp, (int)','); - if (i) + if (i) { *i = '\0'; - DPRINTF(0, ("authreadkeys: access list: <%s>\n", tp)); + } + snp = strchr(tp, (int)'/'); + if (snp) { + char *sp; + + *snp++ = '\0'; + snbits = 0; + sp = snp; + + while (*sp != '\0') { + if (!isdigit((unsigned char)*sp)) + break; + if (snbits > 1000) + break; /* overflow */ + snbits = 10 * snbits + (*sp++ - '0'); /* ascii dependent */ + } + if (*sp != '\0') { + log_maybe(&nerr, + "authreadkeys: Invalid character in subnet specification for <%s/%s> in key %d", + sp, snp, keyno); + goto nextip; + } + } else { + snbits = UINT_MAX; + } if (is_ip_address(tp, AF_UNSPEC, &addr)) { - next->keyacclist = keyacc_new_push( - next->keyacclist, &addr); + /* Make sure that snbits is valid for addr */ + if ((snbits < UINT_MAX) && + ( (IS_IPV4(&addr) && snbits > 32) || + (IS_IPV6(&addr) && snbits > 128))) { + log_maybe(NULL, + "authreadkeys: excessive subnet mask <%s/%s> for key %d", + tp, snp, keyno); + } + next->keyacclist = keyacc_new_push( + next->keyacclist, &addr, snbits); } else { log_maybe(&nerr, "authreadkeys: invalid IP address <%s> for key %d", tp, keyno); } + nextip: if (i) { tp = i + 1; } else { diff --git a/contrib/ntp/libntp/libssl_compat.c b/contrib/ntp/libntp/libssl_compat.c index afe4d07..5527682 100644 --- a/contrib/ntp/libntp/libssl_compat.c +++ b/contrib/ntp/libntp/libssl_compat.c @@ -74,7 +74,10 @@ sslshimBN_GENCB_free( EVP_MD_CTX* sslshim_EVP_MD_CTX_new(void) { - return calloc(1, sizeof(EVP_MD_CTX)); + EVP_MD_CTX * ctx; + if (NULL != (ctx = calloc(1, sizeof(EVP_MD_CTX)))) + EVP_MD_CTX_init(ctx); + return ctx; } void diff --git a/contrib/ntp/libntp/ntp_calendar.c b/contrib/ntp/libntp/ntp_calendar.c index 4bfb0e7..a550d5d 100644 --- a/contrib/ntp/libntp/ntp_calendar.c +++ b/contrib/ntp/libntp/ntp_calendar.c @@ -1825,4 +1825,113 @@ isocal_date_to_ntp( return isocal_date_to_ntp64(id).d_s.lo; } +/* + * ==================================================================== + * 'basedate' support functions + * ==================================================================== + */ + +static int32_t s_baseday = NTP_TO_UNIX_DAYS; + +int32_t +basedate_eval_buildstamp(void) +{ + struct calendar jd; + int32_t ed; + + if (!ntpcal_get_build_date(&jd)) + return NTP_TO_UNIX_DAYS; + + /* The time zone of the build stamp is unspecified; we remove + * one day to provide a certain slack. And in case somebody + * fiddled with the system clock, we make sure we do not go + * before the UNIX epoch (1970-01-01). It's probably not possible + * to do this to the clock on most systems, but there are other + * ways to tweak the build stamp. + */ + jd.monthday -= 1; + ed = ntpcal_date_to_rd(&jd) - DAY_NTP_STARTS; + return (ed < NTP_TO_UNIX_DAYS) ? NTP_TO_UNIX_DAYS : ed; +} + +int32_t +basedate_eval_string( + const char * str + ) +{ + u_short y,m,d; + u_long ned; + int rc, nc; + size_t sl; + + sl = strlen(str); + rc = sscanf(str, "%4hu-%2hu-%2hu%n", &y, &m, &d, &nc); + if (rc == 3 && (size_t)nc == sl) { + if (m >= 1 && m <= 12 && d >= 1 && d <= 31) + return ntpcal_edate_to_eradays(y-1, m-1, d) + - DAY_NTP_STARTS; + goto buildstamp; + } + + rc = scanf(str, "%lu%n", &ned, &nc); + if (rc == 1 && (size_t)nc == sl) { + if (ned <= INT32_MAX) + return (int32_t)ned; + goto buildstamp; + } + + buildstamp: + msyslog(LOG_WARNING, + "basedate string \"%s\" invalid, build date substituted!", + str); + return basedate_eval_buildstamp(); +} + +uint32_t +basedate_get_day(void) +{ + return s_baseday; +} + +int32_t +basedate_set_day( + int32_t day + ) +{ + struct calendar jd; + int32_t retv; + + if (day < NTP_TO_UNIX_DAYS) { + msyslog(LOG_WARNING, + "baseday_set_day: invalid day (%lu), UNIX epoch substituted", + (unsigned long)day); + day = NTP_TO_UNIX_DAYS; + } + retv = s_baseday; + s_baseday = day; + ntpcal_rd_to_date(&jd, day + DAY_NTP_STARTS); + msyslog(LOG_INFO, "basedate set to %04hu-%02hu-%02hu", + jd.year, (u_short)jd.month, (u_short)jd.monthday); + return retv; +} + +time_t +basedate_get_eracenter(void) +{ + time_t retv; + retv = (time_t)(s_baseday - NTP_TO_UNIX_DAYS); + retv *= SECSPERDAY; + retv += (UINT32_C(1) << 31); + return retv; +} + +time_t +basedate_get_erabase(void) +{ + time_t retv; + retv = (time_t)(s_baseday - NTP_TO_UNIX_DAYS); + retv *= SECSPERDAY; + return retv; +} + /* -*-EOF-*- */ diff --git a/contrib/ntp/libntp/ssl_init.c b/contrib/ntp/libntp/ssl_init.c index bebf6e1..96d9d08 100644 --- a/contrib/ntp/libntp/ssl_init.c +++ b/contrib/ntp/libntp/ssl_init.c @@ -5,7 +5,7 @@ * Moved from ntpd/ntp_crypto.c crypto_setup() */ #ifdef HAVE_CONFIG_H -#include <config.h> +# include <config.h> #endif #include <ctype.h> #include <ntp.h> @@ -13,11 +13,15 @@ #include <lib_strbuf.h> #ifdef OPENSSL -#include "openssl/crypto.h" -#include "openssl/err.h" -#include "openssl/evp.h" -#include "openssl/opensslv.h" -#include "libssl_compat.h" +# include "openssl/cmac.h" +# include "openssl/crypto.h" +# include "openssl/err.h" +# include "openssl/evp.h" +# include "openssl/opensslv.h" +# include "libssl_compat.h" + +# define CMAC_LENGTH 16 +# define CMAC "AES128CMAC" int ssl_init_done; @@ -26,8 +30,9 @@ int ssl_init_done; static void atexit_ssl_cleanup(void) { - if (!ssl_init_done) + if (!ssl_init_done) { return; + } ssl_init_done = FALSE; EVP_cleanup(); @@ -63,7 +68,7 @@ void ssl_check_version(void) { u_long v; - + v = OpenSSL_version_num(); if ((v ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) { msyslog(LOG_WARNING, @@ -77,6 +82,8 @@ ssl_check_version(void) INIT_SSL(); } +#else /* !OPENSSL */ +# define MD5_LENGTH 16 #endif /* OPENSSL */ @@ -88,61 +95,95 @@ ssl_check_version(void) */ int keytype_from_text( - const char *text, - size_t *pdigest_len + const char * text, + size_t * pdigest_len ) { int key_type; u_int digest_len; -#ifdef OPENSSL +#ifdef OPENSSL /* --*-- OpenSSL code --*-- */ const u_long max_digest_len = MAX_MAC_LEN - sizeof(keyid_t); - u_char digest[EVP_MAX_MD_SIZE]; char * upcased; char * pch; + EVP_MD const * md; /* * OpenSSL digest short names are capitalized, so uppercase the * digest name before passing to OBJ_sn2nid(). If it is not - * recognized but begins with 'M' use NID_md5 to be consistent - * with past behavior. + * recognized but matches our CMAC string use NID_cmac, or if + * it begins with 'M' or 'm' use NID_md5 to be consistent with + * past behavior. */ INIT_SSL(); + + /* get name in uppercase */ LIB_GETBUF(upcased); strlcpy(upcased, text, LIB_BUFLENGTH); - for (pch = upcased; '\0' != *pch; pch++) + + for (pch = upcased; '\0' != *pch; pch++) { *pch = (char)toupper((unsigned char)*pch); + } + key_type = OBJ_sn2nid(upcased); + + if (!key_type && !strncmp(CMAC, upcased, strlen(CMAC) + 1)) { + key_type = NID_cmac; + + if (debug) { + fprintf(stderr, "%s:%d:%s():%s:key\n", + __FILE__, __LINE__, __func__, CMAC); + } + } #else + key_type = 0; #endif - if (!key_type && 'm' == tolower((unsigned char)text[0])) + if (!key_type && 'm' == tolower((unsigned char)text[0])) { key_type = NID_md5; + } - if (!key_type) + if (!key_type) { return 0; + } if (NULL != pdigest_len) { #ifdef OPENSSL - EVP_MD_CTX *ctx; + md = EVP_get_digestbynid(key_type); + digest_len = (md) ? EVP_MD_size(md) : 0; - ctx = EVP_MD_CTX_new(); - EVP_DigestInit(ctx, EVP_get_digestbynid(key_type)); - EVP_DigestFinal(ctx, digest, &digest_len); - EVP_MD_CTX_free(ctx); - if (digest_len > max_digest_len) { + if (!md || digest_len <= 0) { + if (key_type == NID_cmac) { + digest_len = CMAC_LENGTH; + + if (debug) { + fprintf(stderr, "%s:%d:%s():%s:len\n", + __FILE__, __LINE__, __func__, CMAC); + } + } else { fprintf(stderr, - "key type %s %u octet digests are too big, max %lu\n", - keytype_name(key_type), digest_len, - max_digest_len); + "key type %s is not supported by OpenSSL\n", + keytype_name(key_type)); msyslog(LOG_ERR, - "key type %s %u octet digests are too big, max %lu", - keytype_name(key_type), digest_len, - max_digest_len); + "key type %s is not supported by OpenSSL\n", + keytype_name(key_type)); return 0; + } + } + + if (digest_len > max_digest_len) { + fprintf(stderr, + "key type %s %u octet digests are too big, max %lu\n", + keytype_name(key_type), digest_len, + max_digest_len); + msyslog(LOG_ERR, + "key type %s %u octet digests are too big, max %lu", + keytype_name(key_type), digest_len, + max_digest_len); + return 0; } #else - digest_len = 16; + digest_len = MD5_LENGTH; #endif *pdigest_len = digest_len; } @@ -167,8 +208,18 @@ keytype_name( #ifdef OPENSSL INIT_SSL(); name = OBJ_nid2sn(nid); - if (NULL == name) + + if (NID_cmac == nid) { + name = CMAC; + + if (debug) { + fprintf(stderr, "%s:%d:%s():%s:nid\n", + __FILE__, __LINE__, __func__, CMAC); + } + } else + if (NULL == name) { name = unknown_type; + } #else /* !OPENSSL follows */ if (NID_md5 == nid) name = "MD5"; @@ -203,3 +254,4 @@ getpass_keytype( return getpass(pass_prompt); } + diff --git a/contrib/ntp/libntp/statestr.c b/contrib/ntp/libntp/statestr.c index b8fa53c..d135222 100644 --- a/contrib/ntp/libntp/statestr.c +++ b/contrib/ntp/libntp/statestr.c @@ -22,64 +22,65 @@ */ struct codestring { int code; - const char * const string; + const char * const string1; + const char * const string0; }; /* * Leap status (leap) */ static const struct codestring leap_codes[] = { - { LEAP_NOWARNING, "leap_none" }, - { LEAP_ADDSECOND, "leap_add_sec" }, - { LEAP_DELSECOND, "leap_del_sec" }, - { LEAP_NOTINSYNC, "leap_alarm" }, - { -1, "leap" } + { LEAP_NOWARNING, "leap_none", 0 }, + { LEAP_ADDSECOND, "leap_add_sec", 0 }, + { LEAP_DELSECOND, "leap_del_sec", 0 }, + { LEAP_NOTINSYNC, "leap_alarm", 0 }, + { -1, "leap", 0 } }; /* * Clock source status (sync) */ static const struct codestring sync_codes[] = { - { CTL_SST_TS_UNSPEC, "sync_unspec" }, - { CTL_SST_TS_ATOM, "sync_pps" }, - { CTL_SST_TS_LF, "sync_lf_radio" }, - { CTL_SST_TS_HF, "sync_hf_radio" }, - { CTL_SST_TS_UHF, "sync_uhf_radio" }, - { CTL_SST_TS_LOCAL, "sync_local" }, - { CTL_SST_TS_NTP, "sync_ntp" }, - { CTL_SST_TS_UDPTIME, "sync_other" }, - { CTL_SST_TS_WRSTWTCH, "sync_wristwatch" }, - { CTL_SST_TS_TELEPHONE, "sync_telephone" }, - { -1, "sync" } + { CTL_SST_TS_UNSPEC, "sync_unspec", 0 }, + { CTL_SST_TS_ATOM, "sync_pps", 0 }, + { CTL_SST_TS_LF, "sync_lf_radio", 0 }, + { CTL_SST_TS_HF, "sync_hf_radio", 0 }, + { CTL_SST_TS_UHF, "sync_uhf_radio", 0 }, + { CTL_SST_TS_LOCAL, "sync_local", 0 }, + { CTL_SST_TS_NTP, "sync_ntp", 0 }, + { CTL_SST_TS_UDPTIME, "sync_other", 0 }, + { CTL_SST_TS_WRSTWTCH, "sync_wristwatch", 0 }, + { CTL_SST_TS_TELEPHONE, "sync_telephone", 0 }, + { -1, "sync", 0 } }; /* * Peer selection status (sel) */ static const struct codestring select_codes[] = { - { CTL_PST_SEL_REJECT, "sel_reject" }, - { CTL_PST_SEL_SANE, "sel_falsetick" }, - { CTL_PST_SEL_CORRECT, "sel_excess" }, - { CTL_PST_SEL_SELCAND, "sel_outlier" }, - { CTL_PST_SEL_SYNCCAND, "sel_candidate" }, - { CTL_PST_SEL_EXCESS, "sel_backup" }, - { CTL_PST_SEL_SYSPEER, "sel_sys.peer" }, - { CTL_PST_SEL_PPS, "sel_pps.peer" }, - { -1, "sel" } + { CTL_PST_SEL_REJECT, "sel_reject", 0 }, + { CTL_PST_SEL_SANE, "sel_falsetick", 0 }, + { CTL_PST_SEL_CORRECT, "sel_excess", 0 }, + { CTL_PST_SEL_SELCAND, "sel_outlier", 0 }, + { CTL_PST_SEL_SYNCCAND, "sel_candidate", 0 }, + { CTL_PST_SEL_EXCESS, "sel_backup", 0 }, + { CTL_PST_SEL_SYSPEER, "sel_sys.peer", 0 }, + { CTL_PST_SEL_PPS, "sel_pps.peer", 0 }, + { -1, "sel", 0 } }; /* * Clock status (clk) */ static const struct codestring clock_codes[] = { - { CTL_CLK_OKAY, "clk_unspec" }, - { CTL_CLK_NOREPLY, "clk_no_reply" }, - { CTL_CLK_BADFORMAT, "clk_bad_format" }, - { CTL_CLK_FAULT, "clk_fault" }, - { CTL_CLK_PROPAGATION, "clk_bad_signal" }, - { CTL_CLK_BADDATE, "clk_bad_date" }, - { CTL_CLK_BADTIME, "clk_bad_time" }, - { -1, "clk" } + { CTL_CLK_OKAY, "clk_unspec", 0 }, + { CTL_CLK_NOREPLY, "clk_no_reply", 0 }, + { CTL_CLK_BADFORMAT, "clk_bad_format", 0 }, + { CTL_CLK_FAULT, "clk_fault", 0 }, + { CTL_CLK_PROPAGATION, "clk_bad_signal", 0 }, + { CTL_CLK_BADDATE, "clk_bad_date", 0 }, + { CTL_CLK_BADTIME, "clk_bad_time", 0 }, + { -1, "clk", 0 } }; @@ -88,20 +89,20 @@ static const struct codestring clock_codes[] = { * Flash bits -- see ntpq.c tstflags & tstflagnames */ static const struct codestring flash_codes[] = { - { TEST1, "pkt_dup" }, - { TEST2, "pkt_bogus" }, - { TEST3, "pkt_unsync" }, - { TEST4, "pkt_denied" }, - { TEST5, "pkt_auth" }, - { TEST6, "pkt_stratum" }, - { TEST7, "pkt_header" }, - { TEST8, "pkt_autokey" }, - { TEST9, "pkt_crypto" }, - { TEST10, "peer_stratum" }, - { TEST11, "peer_dist" }, - { TEST12, "peer_loop" }, - { TEST13, "peer_unreach" }, - { -1, "flash" } + { TEST1, "pkt_dup", 0 }, + { TEST2, "pkt_bogus", 0 }, + { TEST3, "pkt_unsync", 0 }, + { TEST4, "pkt_denied", 0 }, + { TEST5, "pkt_auth", 0 }, + { TEST6, "pkt_stratum", 0 }, + { TEST7, "pkt_header", 0 }, + { TEST8, "pkt_autokey", 0 }, + { TEST9, "pkt_crypto", 0 }, + { TEST10, "peer_stratum", 0 }, + { TEST11, "peer_dist", 0 }, + { TEST12, "peer_loop", 0 }, + { TEST13, "peer_unreach", 0 }, + { -1, "flash", 0 } }; #endif @@ -110,56 +111,56 @@ static const struct codestring flash_codes[] = { * System events (sys) */ static const struct codestring sys_codes[] = { - { EVNT_UNSPEC, "unspecified" }, - { EVNT_NSET, "freq_not_set" }, - { EVNT_FSET, "freq_set" }, - { EVNT_SPIK, "spike_detect" }, - { EVNT_FREQ, "freq_mode" }, - { EVNT_SYNC, "clock_sync" }, - { EVNT_SYSRESTART, "restart" }, - { EVNT_SYSFAULT, "panic_stop" }, - { EVNT_NOPEER, "no_sys_peer" }, - { EVNT_ARMED, "leap_armed" }, - { EVNT_DISARMED, "leap_disarmed" }, - { EVNT_LEAP, "leap_event" }, - { EVNT_CLOCKRESET, "clock_step" }, - { EVNT_KERN, "kern" }, - { EVNT_TAI, "TAI" }, - { EVNT_LEAPVAL, "stale_leapsecond_values" }, - { -1, "" } + { EVNT_UNSPEC, "unspecified", 0 }, + { EVNT_NSET, "freq_not_set", 0 }, + { EVNT_FSET, "freq_set", 0 }, + { EVNT_SPIK, "spike_detect", 0 }, + { EVNT_FREQ, "freq_mode", 0 }, + { EVNT_SYNC, "clock_sync", 0 }, + { EVNT_SYSRESTART, "restart", 0 }, + { EVNT_SYSFAULT, "panic_stop", 0 }, + { EVNT_NOPEER, "no_sys_peer", 0 }, + { EVNT_ARMED, "leap_armed", 0 }, + { EVNT_DISARMED, "leap_disarmed", 0 }, + { EVNT_LEAP, "leap_event", 0 }, + { EVNT_CLOCKRESET, "clock_step", 0 }, + { EVNT_KERN, "kern", 0 }, + { EVNT_TAI, "TAI", 0 }, + { EVNT_LEAPVAL, "stale_leapsecond_values", 0 }, + { -1, "", 0 } }; /* * Peer events (peer) */ static const struct codestring peer_codes[] = { - { PEVNT_MOBIL & ~PEER_EVENT, "mobilize" }, - { PEVNT_DEMOBIL & ~PEER_EVENT, "demobilize" }, - { PEVNT_UNREACH & ~PEER_EVENT, "unreachable" }, - { PEVNT_REACH & ~PEER_EVENT, "reachable" }, - { PEVNT_RESTART & ~PEER_EVENT, "restart" }, - { PEVNT_REPLY & ~PEER_EVENT, "no_reply" }, - { PEVNT_RATE & ~PEER_EVENT, "rate_exceeded" }, - { PEVNT_DENY & ~PEER_EVENT, "access_denied" }, - { PEVNT_ARMED & ~PEER_EVENT, "leap_armed" }, - { PEVNT_NEWPEER & ~PEER_EVENT, "sys_peer" }, - { PEVNT_CLOCK & ~PEER_EVENT, "clock_event" }, - { PEVNT_AUTH & ~PEER_EVENT, "bad_auth" }, - { PEVNT_POPCORN & ~PEER_EVENT, "popcorn" }, - { PEVNT_XLEAVE & ~PEER_EVENT, "interleave_mode" }, - { PEVNT_XERR & ~PEER_EVENT, "interleave_error" }, - { -1, "" } + { PEVNT_MOBIL & ~PEER_EVENT, "mobilize", 0 }, + { PEVNT_DEMOBIL & ~PEER_EVENT, "demobilize", 0 }, + { PEVNT_UNREACH & ~PEER_EVENT, "unreachable", 0 }, + { PEVNT_REACH & ~PEER_EVENT, "reachable", 0 }, + { PEVNT_RESTART & ~PEER_EVENT, "restart", 0 }, + { PEVNT_REPLY & ~PEER_EVENT, "no_reply", 0 }, + { PEVNT_RATE & ~PEER_EVENT, "rate_exceeded", 0 }, + { PEVNT_DENY & ~PEER_EVENT, "access_denied", 0 }, + { PEVNT_ARMED & ~PEER_EVENT, "leap_armed", 0 }, + { PEVNT_NEWPEER & ~PEER_EVENT, "sys_peer", 0 }, + { PEVNT_CLOCK & ~PEER_EVENT, "clock_event", 0 }, + { PEVNT_AUTH & ~PEER_EVENT, "bad_auth", 0 }, + { PEVNT_POPCORN & ~PEER_EVENT, "popcorn", 0 }, + { PEVNT_XLEAVE & ~PEER_EVENT, "interleave_mode", 0 }, + { PEVNT_XERR & ~PEER_EVENT, "interleave_error", 0 }, + { -1, "", 0 } }; /* * Peer status bits */ static const struct codestring peer_st_bits[] = { - { CTL_PST_CONFIG, "conf" }, - { CTL_PST_AUTHENABLE, "authenb" }, - { CTL_PST_AUTHENTIC, "auth" }, - { CTL_PST_REACH, "reach" }, - { CTL_PST_BCAST, "bcast" }, + { CTL_PST_CONFIG, "conf", 0 }, + { CTL_PST_AUTHENABLE, "authenb", 0 }, + { CTL_PST_AUTHENTIC, "auth", 0 }, + { CTL_PST_REACH, "reach", 0 }, + { CTL_PST_BCAST, "bcast", 0 }, /* not used with getcode(), no terminating entry needed */ }; @@ -167,9 +168,9 @@ static const struct codestring peer_st_bits[] = { * Restriction match bits */ static const struct codestring res_match_bits[] = { - { RESM_NTPONLY, "ntpport" }, - { RESM_INTERFACE, "interface" }, - { RESM_SOURCE, "source" }, + { RESM_NTPONLY, "ntpport", 0 }, + { RESM_INTERFACE, "interface", 0 }, + { RESM_SOURCE, "source", 0 }, /* not used with getcode(), no terminating entry needed */ }; @@ -177,18 +178,19 @@ static const struct codestring res_match_bits[] = { * Restriction access bits */ static const struct codestring res_access_bits[] = { - { RES_IGNORE, "ignore" }, - { RES_DONTSERVE, "noserve" }, - { RES_DONTTRUST, "notrust" }, - { RES_NOQUERY, "noquery" }, - { RES_NOMODIFY, "nomodify" }, - { RES_NOPEER, "nopeer" }, - { RES_NOTRAP, "notrap" }, - { RES_LPTRAP, "lptrap" }, - { RES_LIMITED, "limited" }, - { RES_VERSION, "version" }, - { RES_KOD, "kod" }, - { RES_FLAKE, "flake" }, + { RES_IGNORE, "ignore", 0 }, + { RES_DONTSERVE, "noserve", "serve" }, + { RES_DONTTRUST, "notrust", "trust" }, + { RES_NOQUERY, "noquery", "query" }, + { RES_NOMODIFY, "nomodify", 0 }, + { RES_NOPEER, "nopeer", "peer" }, + { RES_NOEPEER, "noepeer", "epeer" }, + { RES_NOTRAP, "notrap", "trap" }, + { RES_LPTRAP, "lptrap", 0 }, + { RES_LIMITED, "limited", 0 }, + { RES_VERSION, "version", 0 }, + { RES_KOD, "kod", 0 }, + { RES_FLAKE, "flake", 0 }, /* not used with getcode(), no terminating entry needed */ }; @@ -197,23 +199,23 @@ static const struct codestring res_access_bits[] = { * Crypto events (cryp) */ static const struct codestring crypto_codes[] = { - { XEVNT_OK & ~CRPT_EVENT, "success" }, - { XEVNT_LEN & ~CRPT_EVENT, "bad_field_format_or_length" }, - { XEVNT_TSP & ~CRPT_EVENT, "bad_timestamp" }, - { XEVNT_FSP & ~CRPT_EVENT, "bad_filestamp" }, - { XEVNT_PUB & ~CRPT_EVENT, "bad_or_missing_public_key" }, - { XEVNT_MD & ~CRPT_EVENT, "unsupported_digest_type" }, - { XEVNT_KEY & ~CRPT_EVENT, "unsupported_identity_type" }, - { XEVNT_SGL & ~CRPT_EVENT, "bad_signature_length" }, - { XEVNT_SIG & ~CRPT_EVENT, "signature_not_verified" }, - { XEVNT_VFY & ~CRPT_EVENT, "certificate_not_verified" }, - { XEVNT_PER & ~CRPT_EVENT, "host_certificate_expired" }, - { XEVNT_CKY & ~CRPT_EVENT, "bad_or_missing_cookie" }, - { XEVNT_DAT & ~CRPT_EVENT, "bad_or_missing_leapseconds" }, - { XEVNT_CRT & ~CRPT_EVENT, "bad_or_missing_certificate" }, - { XEVNT_ID & ~CRPT_EVENT, "bad_or_missing_group key" }, - { XEVNT_ERR & ~CRPT_EVENT, "protocol_error" }, - { -1, "" } + { XEVNT_OK & ~CRPT_EVENT, "success", 0 }, + { XEVNT_LEN & ~CRPT_EVENT, "bad_field_format_or_length", 0 }, + { XEVNT_TSP & ~CRPT_EVENT, "bad_timestamp", 0 }, + { XEVNT_FSP & ~CRPT_EVENT, "bad_filestamp", 0 }, + { XEVNT_PUB & ~CRPT_EVENT, "bad_or_missing_public_key", 0 }, + { XEVNT_MD & ~CRPT_EVENT, "unsupported_digest_type", 0 }, + { XEVNT_KEY & ~CRPT_EVENT, "unsupported_identity_type", 0 }, + { XEVNT_SGL & ~CRPT_EVENT, "bad_signature_length", 0 }, + { XEVNT_SIG & ~CRPT_EVENT, "signature_not_verified", 0 }, + { XEVNT_VFY & ~CRPT_EVENT, "certificate_not_verified", 0 }, + { XEVNT_PER & ~CRPT_EVENT, "host_certificate_expired", 0 }, + { XEVNT_CKY & ~CRPT_EVENT, "bad_or_missing_cookie", 0 }, + { XEVNT_DAT & ~CRPT_EVENT, "bad_or_missing_leapseconds", 0 }, + { XEVNT_CRT & ~CRPT_EVENT, "bad_or_missing_certificate", 0 }, + { XEVNT_ID & ~CRPT_EVENT, "bad_or_missing_group key", 0 }, + { XEVNT_ERR & ~CRPT_EVENT, "protocol_error", 0 }, + { -1, "", 0 } }; #endif /* AUTOKEY */ @@ -223,52 +225,52 @@ static const struct codestring crypto_codes[] = { */ static const struct codestring k_st_bits[] = { # ifdef STA_PLL - { STA_PLL, "pll" }, + { STA_PLL, "pll", 0 }, # endif # ifdef STA_PPSFREQ - { STA_PPSFREQ, "ppsfreq" }, + { STA_PPSFREQ, "ppsfreq", 0 }, # endif # ifdef STA_PPSTIME - { STA_PPSTIME, "ppstime" }, + { STA_PPSTIME, "ppstime", 0 }, # endif # ifdef STA_FLL - { STA_FLL, "fll" }, + { STA_FLL, "fll", 0 }, # endif # ifdef STA_INS - { STA_INS, "ins" }, + { STA_INS, "ins", 0 }, # endif # ifdef STA_DEL - { STA_DEL, "del" }, + { STA_DEL, "del", 0 }, # endif # ifdef STA_UNSYNC - { STA_UNSYNC, "unsync" }, + { STA_UNSYNC, "unsync", 0 }, # endif # ifdef STA_FREQHOLD - { STA_FREQHOLD, "freqhold" }, + { STA_FREQHOLD, "freqhold", 0 }, # endif # ifdef STA_PPSSIGNAL - { STA_PPSSIGNAL, "ppssignal" }, + { STA_PPSSIGNAL, "ppssignal", 0 }, # endif # ifdef STA_PPSJITTER - { STA_PPSJITTER, "ppsjitter" }, + { STA_PPSJITTER, "ppsjitter", 0 }, # endif # ifdef STA_PPSWANDER - { STA_PPSWANDER, "ppswander" }, + { STA_PPSWANDER, "ppswander", 0 }, # endif # ifdef STA_PPSERROR - { STA_PPSERROR, "ppserror" }, + { STA_PPSERROR, "ppserror", 0 }, # endif # ifdef STA_CLOCKERR - { STA_CLOCKERR, "clockerr" }, + { STA_CLOCKERR, "clockerr", 0 }, # endif # ifdef STA_NANO - { STA_NANO, "nano" }, + { STA_NANO, "nano", 0 }, # endif # ifdef STA_MODE - { STA_MODE, "mode=fll" }, + { STA_MODE, "mode=fll", 0 }, # endif # ifdef STA_CLK - { STA_CLK, "src=B" }, + { STA_CLK, "src=B", 0 }, # endif /* not used with getcode(), no terminating entry needed */ }; @@ -292,12 +294,12 @@ getcode( while (codetab->code != -1) { if (codetab->code == code) - return codetab->string; + return codetab->string1; codetab++; } LIB_GETBUF(buf); - snprintf(buf, LIB_BUFLENGTH, "%s_%d", codetab->string, code); + snprintf(buf, LIB_BUFLENGTH, "%s_%d", codetab->string1, code); return buf; } @@ -354,10 +356,18 @@ decode_bitflags( sep = ""; for (b = 0; b < tab_ct; b++) { + const char * flagstr; + if (tab[b].code & bits) { + flagstr = tab[b].string1; + } else { + flagstr = tab[b].string0; + } + + if (flagstr) { size_t avail = lim - pch; rc = snprintf(pch, avail, "%s%s", sep, - tab[b].string); + flagstr); if ((size_t)rc >= avail) goto toosmall; pch += rc; diff --git a/contrib/ntp/libntp/systime.c b/contrib/ntp/libntp/systime.c index 29f1e86..8e70897 100644 --- a/contrib/ntp/libntp/systime.c +++ b/contrib/ntp/libntp/systime.c @@ -5,8 +5,10 @@ * */ #include <config.h> +#include <math.h> #include "ntp.h" +#include "ntpd.h" #include "ntp_syslog.h" #include "ntp_stdlib.h" #include "ntp_random.h" @@ -14,6 +16,7 @@ #include "timevalops.h" #include "timespecops.h" #include "ntp_calendar.h" +#include "lib_strbuf.h" #ifdef HAVE_SYS_PARAM_H # include <sys/param.h> @@ -28,6 +31,9 @@ int allow_panic = FALSE; /* allow panic correction (-g) */ int enable_panic_check = TRUE; /* Can we check allow_panic's state? */ +u_long sys_lamport; /* Lamport violation */ +u_long sys_tsrounding; /* timestamp rounding errors */ + #ifndef USE_COMPILETIME_PIVOT # define USE_COMPILETIME_PIVOT 1 #endif @@ -110,7 +116,10 @@ set_sys_fuzz( sys_fuzz = fuzz_val; INSIST(sys_fuzz >= 0); INSIST(sys_fuzz <= 1.0); - sys_fuzz_nsec = (long)(sys_fuzz * 1e9 + 0.5); + /* [Bug 3450] ensure nsec fuzz >= sys_fuzz to reduce chance of + * short-falling fuzz advance + */ + sys_fuzz_nsec = (long)ceil(sys_fuzz * 1e9); } @@ -168,13 +177,10 @@ get_systime( static struct timespec ts_last; /* last sampled os time */ static struct timespec ts_prev; /* prior os time */ static l_fp lfp_prev; /* prior result */ - static double dfuzz_prev; /* prior fuzz */ struct timespec ts; /* seconds and nanoseconds */ struct timespec ts_min; /* earliest permissible */ struct timespec ts_lam; /* lamport fictional increment */ - struct timespec ts_prev_log; /* for msyslog only */ double dfuzz; - double ddelta; l_fp result; l_fp lfpfuzz; l_fp lfpdelta; @@ -191,8 +197,10 @@ get_systime( * introduce small steps backward. It should not be an issue on * systems where get_ostime() results in a true syscall.) */ - if (cmp_tspec(add_tspec_ns(ts, 50000000), ts_last) < 0) + if (cmp_tspec(add_tspec_ns(ts, 50000000), ts_last) < 0) { lamport_violated = 1; + sys_lamport++; + } ts_last = ts; /* @@ -216,21 +224,16 @@ get_systime( if (!lamport_violated) ts = ts_min; } - ts_prev_log = ts_prev; ts_prev = ts; - } else { - /* - * Quiet "ts_prev_log.tv_sec may be used uninitialized" - * warning from x86 gcc 4.5.2. - */ - ZERO(ts_prev_log); } /* convert from timespec to l_fp fixed-point */ result = tspec_stamp_to_lfp(ts); /* - * Add in the fuzz. + * Add in the fuzz. 'ntp_random()' returns [0..2**31-1] so we + * must scale up the result by 2.0 to cover the full fractional + * range. */ dfuzz = ntp_random() * 2. / FRAC * sys_fuzz; DTOLFP(dfuzz, &lfpfuzz); @@ -240,30 +243,34 @@ get_systime( * Ensure result is strictly greater than prior result (ignoring * sys_residual's effect for now) once sys_fuzz has been * determined. + * + * [Bug 3450] Rounding errors and time slew can lead to a + * violation of the expected postcondition. This is bound to + * happen from time to time (depending on state of the random + * generator, the current slew and the closeness of system time + * stamps drawn) and does not warrant a syslog entry. Instead it + * makes much more sense to ensure the postcondition and hop + * along silently. */ if (!USING_SIGIO()) { - if (!L_ISZERO(&lfp_prev) && !lamport_violated) { - if (!L_ISGTU(&result, &lfp_prev) && - sys_fuzz > 0.) { - msyslog(LOG_ERR, "ts_prev %s ts_min %s", - tspectoa(ts_prev_log), - tspectoa(ts_min)); - msyslog(LOG_ERR, "ts %s", tspectoa(ts)); - msyslog(LOG_ERR, "sys_fuzz %ld nsec, prior fuzz %.9f", - sys_fuzz_nsec, dfuzz_prev); - msyslog(LOG_ERR, "this fuzz %.9f", - dfuzz); - lfpdelta = lfp_prev; - L_SUB(&lfpdelta, &result); - LFPTOD(&lfpdelta, ddelta); - msyslog(LOG_ERR, - "prev get_systime 0x%x.%08x is %.9f later than 0x%x.%08x", - lfp_prev.l_ui, lfp_prev.l_uf, - ddelta, result.l_ui, result.l_uf); + if ( !L_ISZERO(&lfp_prev) + && !lamport_violated + && (sys_fuzz > 0.0) + ) { + lfpdelta = result; + L_SUB(&lfpdelta, &lfp_prev); + L_SUBUF(&lfpdelta, 1); + if (lfpdelta.l_i < 0) + { + L_NEG(&lfpdelta); + DPRINTF(1, ("get_systime: postcond failed by %s secs, fixed\n", + lfptoa(&lfpdelta, 9))); + result = lfp_prev; + L_ADDUF(&result, 1); + sys_tsrounding++; } } lfp_prev = result; - dfuzz_prev = dfuzz; if (lamport_violated) lamport_violated = FALSE; } @@ -362,105 +369,16 @@ adj_systime( } #endif - /* - * step_systime - step the system clock. + * helper to keep utmp/wtmp up to date */ - -int -step_systime( - double step +static void +update_uwtmp( + struct timeval timetv, + struct timeval tvlast ) { - time_t pivot; /* for ntp era unfolding */ - struct timeval timetv, tvlast, tvdiff; - struct timespec timets; - struct calendar jd; - l_fp fp_ofs, fp_sys; /* offset and target system time in FP */ - - /* - * Get pivot time for NTP era unfolding. Since we don't step - * very often, we can afford to do the whole calculation from - * scratch. And we're not in the time-critical path yet. - */ -#if SIZEOF_TIME_T > 4 - /* - * This code makes sure the resulting time stamp for the new - * system time is in the 2^32 seconds starting at 1970-01-01, - * 00:00:00 UTC. - */ - pivot = 0x80000000; -#if USE_COMPILETIME_PIVOT - /* - * Add the compile time minus 10 years to get a possible target - * area of (compile time - 10 years) to (compile time + 126 - * years). This should be sufficient for a given binary of - * NTPD. - */ - if (ntpcal_get_build_date(&jd)) { - jd.year -= 10; - pivot += ntpcal_date_to_time(&jd); - } else { - msyslog(LOG_ERR, - "step-systime: assume 1970-01-01 as build date"); - } -#else - UNUSED_LOCAL(jd); -#endif /* USE_COMPILETIME_PIVOT */ -#else - UNUSED_LOCAL(jd); - /* This makes sure the resulting time stamp is on or after - * 1969-12-31/23:59:59 UTC and gives us additional two years, - * from the change of NTP era in 2036 to the UNIX rollover in - * 2038. (Minus one second, but that won't hurt.) We *really* - * need a longer 'time_t' after that! Or a different baseline, - * but that would cause other serious trouble, too. - */ - pivot = 0x7FFFFFFF; -#endif - - /* get the complete jump distance as l_fp */ - DTOLFP(sys_residual, &fp_sys); - DTOLFP(step, &fp_ofs); - L_ADD(&fp_ofs, &fp_sys); - - /* ---> time-critical path starts ---> */ - - /* get the current time as l_fp (without fuzz) and as struct timeval */ - get_ostime(&timets); - fp_sys = tspec_stamp_to_lfp(timets); - tvlast.tv_sec = timets.tv_sec; - tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; - - /* get the target time as l_fp */ - L_ADD(&fp_sys, &fp_ofs); - - /* unfold the new system time */ - timetv = lfp_stamp_to_tval(fp_sys, &pivot); - - /* now set new system time */ - if (ntp_set_tod(&timetv, NULL) != 0) { - msyslog(LOG_ERR, "step-systime: %m"); - if (enable_panic_check && allow_panic) { - msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); - } - return FALSE; - } - - /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ - - sys_residual = 0; - lamport_violated = (step < 0); - if (step_callback) - (*step_callback)(); - -#ifdef NEED_HPUX_ADJTIME - /* - * CHECKME: is this correct when called by ntpdate????? - */ - _clear_adjtime(); -#endif - + struct timeval tvdiff; /* * FreeBSD, for example, has: * struct utmp { @@ -589,6 +507,83 @@ step_systime( #endif /* UPDATE_WTMPX */ } +} + +/* + * step_systime - step the system clock. + */ + +int +step_systime( + double step + ) +{ + time_t pivot; /* for ntp era unfolding */ + struct timeval timetv, tvlast; + struct timespec timets; + l_fp fp_ofs, fp_sys; /* offset and target system time in FP */ + + /* + * Get pivot time for NTP era unfolding. Since we don't step + * very often, we can afford to do the whole calculation from + * scratch. And we're not in the time-critical path yet. + */ +#if SIZEOF_TIME_T > 4 + pivot = basedate_get_eracenter(); +#else + /* This makes sure the resulting time stamp is on or after + * 1969-12-31/23:59:59 UTC and gives us additional two years, + * from the change of NTP era in 2036 to the UNIX rollover in + * 2038. (Minus one second, but that won't hurt.) We *really* + * need a longer 'time_t' after that! Or a different baseline, + * but that would cause other serious trouble, too. + */ + pivot = 0x7FFFFFFF; +#endif + + /* get the complete jump distance as l_fp */ + DTOLFP(sys_residual, &fp_sys); + DTOLFP(step, &fp_ofs); + L_ADD(&fp_ofs, &fp_sys); + + /* ---> time-critical path starts ---> */ + + /* get the current time as l_fp (without fuzz) and as struct timeval */ + get_ostime(&timets); + fp_sys = tspec_stamp_to_lfp(timets); + tvlast.tv_sec = timets.tv_sec; + tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; + + /* get the target time as l_fp */ + L_ADD(&fp_sys, &fp_ofs); + + /* unfold the new system time */ + timetv = lfp_stamp_to_tval(fp_sys, &pivot); + + /* now set new system time */ + if (ntp_set_tod(&timetv, NULL) != 0) { + msyslog(LOG_ERR, "step-systime: %m"); + if (enable_panic_check && allow_panic) { + msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); + } + return FALSE; + } + + /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ + + sys_residual = 0; + lamport_violated = (step < 0); + if (step_callback) + (*step_callback)(); + +#ifdef NEED_HPUX_ADJTIME + /* + * CHECKME: is this correct when called by ntpdate????? + */ + _clear_adjtime(); +#endif + + update_uwtmp(timetv, tvlast); if (enable_panic_check && allow_panic) { msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); INSIST(!allow_panic); @@ -596,4 +591,93 @@ step_systime( return TRUE; } +static const char * +tv_fmt_libbuf( + const struct timeval * ptv + ) +{ + char * retv; + vint64 secs; + ntpcal_split dds; + struct calendar jd; + + secs = time_to_vint64(&ptv->tv_sec); + dds = ntpcal_daysplit(&secs); + ntpcal_daysplit_to_date(&jd, &dds, DAY_UNIX_STARTS); + LIB_GETBUF(retv); + snprintf(retv, LIB_BUFLENGTH, + "%04hu-%02hu-%02hu/%02hu:%02hu:%02hu.%06u", + jd.year, (u_short)jd.month, (u_short)jd.monthday, + (u_short)jd.hour, (u_short)jd.minute, (u_short)jd.second, + (u_int)ptv->tv_usec); + return retv; +} + + +int /*BOOL*/ +clamp_systime(void) +{ +#if SIZEOF_TIME_T > 4 + + struct timeval timetv, tvlast; + struct timespec timets; + uint32_t tdiff; + + + timetv.tv_sec = basedate_get_erabase(); + + /* ---> time-critical path starts ---> */ + + /* get the current time as l_fp (without fuzz) and as struct timeval */ + get_ostime(&timets); + tvlast.tv_sec = timets.tv_sec; + tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; + if (tvlast.tv_usec >= 1000000) { + tvlast.tv_usec -= 1000000; + tvlast.tv_sec += 1; + } + timetv.tv_usec = tvlast.tv_usec; + + tdiff = (uint32_t)(tvlast.tv_sec & UINT32_MAX) - + (uint32_t)(timetv.tv_sec & UINT32_MAX); + timetv.tv_sec += tdiff; + if (timetv.tv_sec != tvlast.tv_sec) { + /* now set new system time */ + if (ntp_set_tod(&timetv, NULL) != 0) { + msyslog(LOG_ERR, "clamp-systime: %m"); + return FALSE; + } + } else { + msyslog(LOG_INFO, + "clamp-systime: clock (%s) in allowed range", + tv_fmt_libbuf(&timetv)); + return FALSE; + } + + /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ + + sys_residual = 0; + lamport_violated = (timetv.tv_sec < tvlast.tv_sec); + if (step_callback) + (*step_callback)(); + +# ifdef NEED_HPUX_ADJTIME + /* + * CHECKME: is this correct when called by ntpdate????? + */ + _clear_adjtime(); +# endif + + update_uwtmp(timetv, tvlast); + msyslog(LOG_WARNING, + "clamp-systime: clock stepped from %s to %s!", + tv_fmt_libbuf(&tvlast), tv_fmt_libbuf(&timetv)); + return TRUE; + +#else + + return 0; +#endif +} + #endif /* !SIM */ diff --git a/contrib/ntp/libntp/work_thread.c b/contrib/ntp/libntp/work_thread.c index 82f6064..433290c 100644 --- a/contrib/ntp/libntp/work_thread.c +++ b/contrib/ntp/libntp/work_thread.c @@ -27,7 +27,7 @@ #define CHILD_GONE_RESP CHILD_EXIT_REQ /* Queue size increments: * The request queue grows a bit faster than the response queue -- the - * deamon can push requests and pull results faster on avarage than the + * daemon can push requests and pull results faster on avarage than the * worker can process requests and push results... If this really pays * off is debatable. */ |