From: Harlan Stenn Date: Mon, 27 Nov 2017 09:58:16 +0000 (+0000) Subject: Merge psp-deb1.ntp.org:/home/stenn/ntp-stable X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8acd781fa7fe7d30d8078d9ea235131c0e6ea703;p=thirdparty%2Fntp.git Merge psp-deb1.ntp.org:/home/stenn/ntp-stable into psp-deb1.ntp.org:/net/nfs1/nfs/home/stenn/ntp-stable-aes128cmac bk: 5a1be1b8kiy67hpyZMFoekD1Vbm-sQ --- 8acd781fa7fe7d30d8078d9ea235131c0e6ea703 diff --cc ChangeLog index add12209e,ae2fd1954..7b0301db4 --- a/ChangeLog +++ b/ChangeLog @@@ -1,53 -1,7 +1,54 @@@ --- -* AES-128-CMAC support +* [Bug 3441] Validate the assumption that AF_UNSPEC is 0. stenn@ntp.org +* [Bug 3439] When running multiple commands / hosts in ntpq... + - applied patch by ggarvey +* [Bug 3438] Negative values and values > 999 days in... + - applied patch by ggarvey (with minor mods) +* [Bug 3437] ntpd tries to open socket with AF_UNSPEC domain + - applied patch (with mods) by Miroslav Lichvar +* [Bug 3435] anchor NTP era alignment +* [Bug 3430] ntpq dumps core (SIGSEGV) for "keytype md2" + - fixed several issues with hash algos in ntpd, sntp, ntpq, + ntpdc and the test suites +* [Bug 3424] Trimble Thunderbolt 1024 week millenium bug + - initial patch by Daniel Pouzzner +* [Bug 3423] QNX adjtime() implementation error checking is + wrong +* [Bug 3417] ntpq ifstats packet counters can be negative + made IFSTATS counter quantities unsigned +* [Bug 3411] problem about SIGN(6) packet handling for ntp-4.2.8p10 + - raised receive buffer size to 1200 +* [Bug 3408] refclock_jjy.c: Avoid a wrong report of the coverity static + analysis tool. +* [Bug 3399] NTP: linker error in 4.2.8p10 during Linux cross-compilation + - initial patch by timeflies@mail2tor.com +* [Bug 3398] tests fail with core dump + - patch contributed by Alexander Bluhm +* [Bug 3397] ctl_putstr() asserts that data fits in its buffer + rework of formatting & data transfer stuff in 'ntp_control.c' + avoids unecessary buffers and size limitations. +* [Bug 3394] Leap second deletion does not work on ntpd clients + - fixed handling of dynamic deletion w/o leap file +* [Bug 3391] ntpd segfaults on startup due to small warmup thread stack size + - increased mimimum stack size to 32kB +* [Bug 3367] Faulty LinuxPPS NMEA clock support in 4.2.8 + - reverted handling of PPS kernel consumer to 4.2.6 behavior +* [Bug 3365] Updates driver40(-ja).html and miscopt.html * [Bug 3358] Spurious KoD log messages in .INIT. phase. HStenn. +* [Bug 3016] wrong error position reported for bad ":config pool" + - fixed location counter & ntpq output +* [Bug 2737] Wrong phone number listed for USNO. ntp-bugs@bodosom.net, + perlinger@ntp.org +* [Bug 2557] Fix Thunderbolt init. ntp-bugs@bodosom.net, perlinger@ntp. +* [Bug 948] Trustedkey config directive leaks memory. +* Use strlcpy() to copy strings, not memcpy(). HStenn. +* Typos. HStenn. +* test_ntp_scanner_LDADD needs ntpd/ntp_io.o. HStenn. +* refclock_jjy.c: Add missing "%s" to an msyslog() call. HStenn. +* Build ntpq and libntpq.a with NTP_HARD_*FLAGS. perlinger@ntp.org +* Fix bug in the override portion of the compiler hardening macro. HStenn. ++* AES-128-CMAC support --- (4.2.8p10) 2017/03/21 Released by Harlan Stenn diff --cc libntp/a_md5encrypt.c index eef9515f9,b7bb83145..7ec7e57f2 --- a/libntp/a_md5encrypt.c +++ b/libntp/a_md5encrypt.c @@@ -44,12 -125,16 +125,16 @@@ MD5authencrypt EVP_DigestUpdate(ctx, key, cache_secretsize); EVP_DigestUpdate(ctx, (u_char *)pkt, length); EVP_DigestFinal(ctx, digest, &len); + #endif EVP_MD_CTX_free(ctx); + #ifdef OPENSSL + } + #endif /* 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 (len > MAX_MDG_LEN) + len = MAX_MDG_LEN; + memmove((u_char *)pkt + length + KEY_MAC_LEN, digest, len); + return (len + KEY_MAC_LEN); } @@@ -77,21 -162,100 +162,100 @@@ MD5authdecrypt * 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); + #ifdef OPENSSL + /* Check if CMAC key type specific code required */ + if (cache_type == NID_cmac) { + CMAC_CTX * ctx; + + + if (debug) { + fprintf(stderr, "%s:%d:%s():%s:nid\n", + __FILE__, __LINE__, __func__, CMAC); + } + + if (!(ctx = CMAC_CTX_new())) { + fprintf(stderr, "MAC decrypt: CMAC %s CTX new failed.\n", CMAC); + msyslog(LOG_ERR, "MAC decrypt: CMAC %s CTX new failed.", CMAC); + len = 0; + } else + if (!CMAC_Init(ctx, key, (u_int)AES_128_KEY_SIZE, + EVP_aes_128_cbc(), NULL)) { + fprintf(stderr, "MAC decrypt: CMAC %s Init failed.\n", CMAC); + msyslog(LOG_ERR, "MAC decrypt: CMAC %s Init failed.", CMAC); + len = 0; + } else + if (!CMAC_Update(ctx, (u_char *)pkt, (u_int)length)) { + fprintf(stderr, "MAC decrypt: CMAC %s Update failed.\n", CMAC); + msyslog(LOG_ERR, "MAC decrypt: CMAC %s Update failed.", CMAC); + len = 0; + } else + if (!CMAC_Final(ctx, digest, &len)) { + fprintf(stderr, "MAC decrypt: CMAC %s Final failed.\n", CMAC); + msyslog(LOG_ERR, "MAC decrypt: CMAC %s Final failed.", CMAC); + len = 0; + } + + CMAC_CTX_cleanup(ctx); + } else { /* generic MAC handling */ + #endif + EVP_MD_CTX * ctx; + + if (!(ctx = EVP_MD_CTX_new())) { + fprintf(stderr, "MAC decrypt: MAC %s Digest CTX new failed.\n", + OBJ_nid2sn(type)); + msyslog(LOG_ERR, "MAC decrypt: MAC %s Digest CTX new failed.", + OBJ_nid2sn(type)); + len = 0; + } + #ifdef OPENSSL /* OpenSSL 1 supports return codes 0 fail, 1 okay */ + else + if (!EVP_DigestInit(ctx, EVP_get_digestbynid(type))) { + fprintf(stderr, "MAC decrypt: MAC %s Digest Init failed.\n", + OBJ_nid2sn(type)); + msyslog(LOG_ERR, "MAC decrypt: MAC %s Digest Init failed.", + OBJ_nid2sn(type)); + len = 0; + } else + if (!EVP_DigestUpdate(ctx, key, (u_int)cache_secretsize)) { + fprintf(stderr, "MAC decrypt: MAC %s Digest Update key failed.\n", + OBJ_nid2sn(type)); + msyslog(LOG_ERR, "MAC decrypt: MAC %s Digest Update key failed.", + OBJ_nid2sn(type)); + len = 0; + } else + if (!EVP_DigestUpdate(ctx, (u_char *)pkt, (u_int)length)) { + fprintf(stderr, "MAC decrypt: MAC %s Digest Update data failed.\n", + OBJ_nid2sn(type)); + msyslog(LOG_ERR, "MAC decrypt: MAC %s Digest Update data failed.", + OBJ_nid2sn(type)); + len = 0; + } else + if (!EVP_DigestFinal(ctx, digest, &len)) { + fprintf(stderr, "MAC decrypt: MAC %s Digest Final failed.\n", + OBJ_nid2sn(type)); + msyslog(LOG_ERR, "MAC decrypt: MAC %s Digest Final failed.", + OBJ_nid2sn(type)); + len = 0; + } + #else /* !OPENSSL */ + 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, (u_int)length); + EVP_DigestFinal(ctx, digest, &len); + #endif + EVP_MD_CTX_free(ctx); + #ifdef OPENSSL } - EVP_DigestUpdate(ctx, key, cache_secretsize); - EVP_DigestUpdate(ctx, (u_char *)pkt, length); - EVP_DigestFinal(ctx, digest, &len); - EVP_MD_CTX_free(ctx); + #endif /* 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 (len > MAX_MDG_LEN) + len = MAX_MDG_LEN; + if (size != (size_t)len + KEY_MAC_LEN) { msyslog(LOG_ERR, "MAC decrypt: MAC length error"); return (0); diff --cc libntp/ssl_init.c index a3c163b34,71f2eda04..2dc3ea841 --- a/libntp/ssl_init.c +++ b/libntp/ssl_init.c @@@ -94,55 -100,90 +100,93 @@@ keytype_from_text { int key_type; u_int digest_len; - - /*----------------------------------------------------------- */ -#ifdef OPENSSL - const u_long max_digest_len = MAX_MAC_LEN - sizeof(keyid_t); +#ifdef OPENSSL /* --*-- OpenSSL code --*-- */ - /*----------------------------------------------------------- */ - 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' or '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' use NID_md5 to be consistent with past - * behavior. ++ * 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); + } - md = EVP_get_digestbyname(upcased); - if (NULL == md && !strcmp(upcased, "M")) - md = EVP_get_digestbyname("MD5"); - if (NULL == md) - return 0; + key_type = OBJ_sn2nid(upcased); - key_type = EVP_MD_type(md); - digest_len = EVP_MD_size(md); + if (!key_type && !strncmp(CMAC, upcased, strlen(CMAC) + 1)) { + key_type = NID_cmac; - /*----------------------------------------------------------- */ - #else /* --*-- NON-SSL CODE --*-- */ - /*----------------------------------------------------------- */ + if (debug) { + fprintf(stderr, "%s:%d:%s():%s:key\n", + __FILE__, __LINE__, __func__, CMAC); + } + } + #else + - if ('m' == tolower((unsigned char)text[0])) - key_type = NID_md5; - else - return 0; + key_type = 0; + #endif - digest_len = 16; + if (!key_type && 'm' == tolower((unsigned char)text[0])) { + key_type = NID_md5; + } - /*----------------------------------------------------------- */ - #endif /* --*-- NON-SSL CODE --*-- */ - /*----------------------------------------------------------- */ + if (!key_type) { + return 0; + } - if (pdigest_len) + if (NULL != pdigest_len) { + #ifdef OPENSSL + const EVP_MD * md = EVP_get_digestbynid(key_type); + + digest_len = (md) ? EVP_MD_size(md) : 0; + + 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 is not supported by OpenSSL\n", + keytype_name(key_type)); + msyslog(LOG_ERR, + "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 = MD5_LENGTH; + #endif *pdigest_len = digest_len; + } + return key_type; } diff --cc ntpq/ntpq.c index c8a9f8e8e,3c3764e50..fa35b69ec --- a/ntpq/ntpq.c +++ b/ntpq/ntpq.c @@@ -3590,73 -3597,191 +3603,197 @@@ ntpq_custom_opt_handler * Obtain list of digest names */ +#if defined(OPENSSL) && !defined(HAVE_EVP_MD_DO_ALL_SORTED) +# if defined(_MSC_VER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +# define HAVE_EVP_MD_DO_ALL_SORTED +# endif +#endif + #ifdef OPENSSL # ifdef HAVE_EVP_MD_DO_ALL_SORTED + # define K_PER_LINE 8 + # define K_NL_PFX_STR "\n " + # define K_DELIM_STR ", " + struct hstate { char *list; const char **seen; int idx; }; - #define K_PER_LINE 8 - #define K_NL_PFX_STR "\n " - #define K_DELIM_STR ", " - static void list_md_fn(const EVP_MD *m, const char *from, const char *to, void *arg ) + + + static void + list_md_fn(const EVP_MD *m, const char *from, const char *to, void *arg) { - size_t len, n; - const char *name, *cp, **seen; + size_t len, n, digest_len; + const char *name, **seen; struct hstate *hstate = arg; - if (!m) - return; /* Ignore aliases */ + /* m is MD obj, from is name or alias, to is base name for alias */ + if (!m || !from || to) { + return; /* Ignore aliases */ + } + + /* Discard MACs that NTP won't accept. */ + /* Keep this consistent with keytype_from_text() in ssl_init.c. */ + if (EVP_MD_size(m) > (MAX_MAC_LEN - sizeof(keyid_t))) { + return; + } - /* There are duplicates. Discard if name has been seen. - * - * Names are capitalized in 'keytype_from_text()' in ssl_init.c; we - * have to make sure we do compare case-insensitive when checking - * for dupes... - */ name = EVP_MD_name(m); - len = strlen(name) + 1; - for (seen = hstate->seen; *seen; seen++) - if (!strcasecmp(*seen, name)) - return; - - /* Discard MACs that NTP won't accept. - * Keep this consistent with keytype_from_text() in ssl_init.c, - * which is done most easily by using it... - */ - if (keytype_from_text(name, &digest_len) == 0) + + /* Lowercase names aren't accepted by keytype_from_text in ssl_init.c */ + + for (cp = name; *cp; cp++) { + if (islower((unsigned char)*cp)) { + return; + } + } + + len = (cp - name) + 1; + + /* There are duplicates. Discard if name has been seen. */ + + for (seen = hstate->seen; *seen; seen++) { + if (!strcmp(*seen, name)) { return; + } + } n = (seen - hstate->seen) + 2; hstate->seen = erealloc(hstate->seen, n * sizeof(*seen)); hstate->seen[n-2] = name; hstate->seen[n-1] = NULL; - if (hstate->list != NULL) - len += strlen(hstate->list); - len += (hstate->idx >= K_PER_LINE)? strlen(K_NL_PFX_STR): strlen(K_DELIM_STR); + if (hstate->list != NULL) { + len += strlen(hstate->list); + } + + len += (hstate->idx >= K_PER_LINE) + ? strlen(K_NL_PFX_STR) + : strlen(K_DELIM_STR); if (hstate->list == NULL) { - hstate->list = (char *)emalloc(len); - hstate->list[0] = '\0'; - hstate->list = (char *)emalloc(len); ++ hstate->list = (char *)emalloc(len); + hstate->list[0] = '\0'; } else { - hstate->list = (char *)erealloc(hstate->list, len); + hstate->list = (char *)erealloc(hstate->list, len); } - + sprintf(hstate->list + strlen(hstate->list), "%s%s", - ((hstate->idx >= K_PER_LINE)? K_NL_PFX_STR : K_DELIM_STR), + ((hstate->idx >= K_PER_LINE) ? K_NL_PFX_STR : K_DELIM_STR), name); - if (hstate->idx >= K_PER_LINE) - hstate->idx = 1; - else - hstate->idx++; + + if (hstate->idx >= K_PER_LINE) { + hstate->idx = 1; + } else { + hstate->idx++; + } + } + + + /* Insert CMAC into SSL digests list */ + static char * + insert_cmac(char *list) + { + int insert; + size_t len; + + + /* If list empty, we need to insert CMAC on new line */ + insert = (!list || !*list); + + if (insert) { + len = strlen(K_NL_PFX_STR) + strlen(CMAC); + list = (char *)erealloc(list, len + 1); + sprintf(list, "%s%s", K_NL_PFX_STR, CMAC); + } else { /* List not empty */ + /* Check if CMAC already in list - future proofing */ + const char *cmac_sn; + char *cmac_p; + + cmac_sn = OBJ_nid2sn(NID_cmac); + cmac_p = list; + insert = cmac_sn != NULL && *cmac_sn != '\0'; + + /* CMAC in list if found, followed by nul char or ',' */ + while (insert && NULL != (cmac_p = strstr(cmac_p, cmac_sn))) { + cmac_p += strlen(cmac_sn); + /* Still need to insert if not nul and not ',' */ + insert = *cmac_p && ',' != *cmac_p; + } + + /* Find proper insertion point */ + if (insert) { + char *last_nl; + char *point; + char *delim; + int found; + + /* Default to start if list empty */ + found = 0; + delim = list; + len = strlen(list); + + /* While new lines */ + while (delim < list + len && *delim && + !strncmp(K_NL_PFX_STR, delim, strlen(K_NL_PFX_STR))) { + point = delim + strlen(K_NL_PFX_STR); + + /* While digest names on line */ + while (point < list + len && *point) { + /* Another digest after on same or next line? */ + delim = strstr( point, K_DELIM_STR); + last_nl = strstr( point, K_NL_PFX_STR); + + /* No - end of list */ + if (!delim && !last_nl) { + delim = list + len; + } else + /* New line and no delim or before delim? */ + if (last_nl && (!delim || last_nl < delim)) { + delim = last_nl; + } + + /* Found insertion point where CMAC before entry? */ + if (strncmp(CMAC, point, delim - point) < 0) { + found = 1; + break; + } + + if (delim < list + len && *delim && + !strncmp(K_DELIM_STR, delim, strlen(K_DELIM_STR))) { + point += strlen(K_DELIM_STR); + } else { + break; + } + } /* While digest names on line */ + } /* While new lines */ + + /* If found in list */ + if (found) { + /* insert cmac and delim */ + /* Space for list could move - save offset */ + ptrdiff_t p_offset = point - list; + len += strlen(CMAC) + strlen(K_DELIM_STR); + list = (char *)erealloc(list, len + 1); + point = list + p_offset; + /* move to handle src/dest overlap */ + memmove(point + strlen(CMAC) + strlen(K_DELIM_STR), + point, strlen(point) + 1); + strncpy(point, CMAC, strlen(CMAC)); + strncpy(point + strlen(CMAC), K_DELIM_STR, strlen(K_DELIM_STR)); + } else { /* End of list */ + /* append delim and cmac */ + len += strlen(K_DELIM_STR) + strlen(CMAC); + list = (char *)erealloc(list, len + 1); + strcpy(list + strlen(list), K_DELIM_STR); + strcpy(list + strlen(list), CMAC); + } + } /* insert */ + } /* List not empty */ + + return list; } # endif #endif diff --cc sntp/crypto.c index 1158b3cac,a0275ff47..04e34e9e8 --- a/sntp/crypto.c +++ b/sntp/crypto.c @@@ -139,10 -220,11 +222,12 @@@ auth_init if (octothorpe) *octothorpe = '\0'; act = emalloc(sizeof(*act)); - scan_cnt = sscanf(kbuf, "%d %19s %128s", &act->key_id, act->typen, keystring); + /* keep width 15 = sizeof struct key.type - 1 synced */ + scan_cnt = sscanf(kbuf, "%d %15s %128s", + &act->key_id, act->type, keystring); if (scan_cnt == 3) { int len = strlen(keystring); + goodline = 1; /* assume best for now */ if (len <= 20) { act->key_len = len; memcpy(act->key_seq, keystring, len + 1);