diff -Nru ntp-4.2.6.p5+dfsg/debian/changelog ntp-4.2.6.p5+dfsg/debian/changelog --- ntp-4.2.6.p5+dfsg/debian/changelog 2014-12-20 11:06:29.000000000 +0000 +++ ntp-4.2.6.p5+dfsg/debian/changelog 2015-02-06 14:10:10.000000000 +0000 @@ -1,3 +1,17 @@ +ntp (1:4.2.6.p5+dfsg-3ubuntu2.14.04.2) trusty-security; urgency=medium + + * SECURITY UPDATE: denial of service and possible info leakage via + extension fields + - debian/patches/CVE-2014-9297.patch: properly check lengths in + ntpd/ntp_crypto.c, ntpd/ntp_proto.c. + - CVE-2014-9297 + * SECURITY UPDATE: IPv6 ACL bypass + - debian/patches/CVE-2014-9298.patch: check for spoofed ::1 in + ntpd/ntp_io.c. + - CVE-2014-9298 + + -- Marc Deslauriers Fri, 06 Feb 2015 09:10:10 -0500 + ntp (1:4.2.6.p5+dfsg-3ubuntu2.14.04.1) trusty-security; urgency=medium * SECURITY UPDATE: weak default key in config_auth() diff -Nru ntp-4.2.6.p5+dfsg/debian/patches/CVE-2014-9297.patch ntp-4.2.6.p5+dfsg/debian/patches/CVE-2014-9297.patch --- ntp-4.2.6.p5+dfsg/debian/patches/CVE-2014-9297.patch 1970-01-01 00:00:00.000000000 +0000 +++ ntp-4.2.6.p5+dfsg/debian/patches/CVE-2014-9297.patch 2015-02-06 14:10:02.000000000 +0000 @@ -0,0 +1,371 @@ +Description: fix denial of service and possible info leakage via + extension fields +Origin: upstream, http://bk1.ntp.org/ntp-stable/?PAGE=patch&REV=5492d353ncauuWt_PONxaDhC5Qv_SA +Origin: upstream, http://bk1.ntp.org/ntp-stable/?PAGE=patch&REV=54a7c595jlwS3KmAxBML75HFGLR_pQ +Origin: upstream, http://bk1.ntp.org/ntp-stable/?PAGE=patch&REV=54abb266In81wLNAqIaovtP8f2UmUw +Bug: http://bugs.ntp.org/show_bug.cgi?id=2671 + +Index: ntp-4.2.6.p5+dfsg/ntpd/ntp_crypto.c +=================================================================== +--- ntp-4.2.6.p5+dfsg.orig/ntpd/ntp_crypto.c 2015-02-06 07:58:50.000000000 -0500 ++++ ntp-4.2.6.p5+dfsg/ntpd/ntp_crypto.c 2015-02-06 08:44:08.207402853 -0500 +@@ -109,6 +109,7 @@ + #define TAI_1972 10 /* initial TAI offset (s) */ + #define MAX_LEAP 100 /* max UTC leapseconds (s) */ + #define VALUE_LEN (6 * 4) /* min response field length */ ++#define MAX_VALLEN (65535 - VALUE_LEN) + #define YEAR (60 * 60 * 24 * 365) /* seconds in year */ + + /* +@@ -147,8 +148,8 @@ + */ + static int crypto_verify (struct exten *, struct value *, + struct peer *); +-static int crypto_encrypt (struct exten *, struct value *, +- keyid_t *); ++static int crypto_encrypt (const u_char *, u_int, keyid_t *, ++ struct value *); + static int crypto_alice (struct peer *, struct value *); + static int crypto_alice2 (struct peer *, struct value *); + static int crypto_alice3 (struct peer *, struct value *); +@@ -444,6 +445,12 @@ + tstamp = ntohl(ep->tstamp); + fstamp = ntohl(ep->fstamp); + vallen = ntohl(ep->vallen); ++ /* ++ * Bug 2761: I hope this isn't too early... ++ */ ++ if ( vallen == 0 ++ || len - VALUE_LEN < vallen) ++ return XEVNT_LEN; + } + switch (code) { + +@@ -494,8 +501,9 @@ + rval = XEVNT_ERR; + break; + } ++ INSIST(len >= VALUE_LEN); + if (vallen == 0 || vallen > MAXHOSTNAME || +- len < VALUE_LEN + vallen) { ++ len - VALUE_LEN < vallen) { + rval = XEVNT_LEN; + break; + } +@@ -1162,8 +1170,9 @@ + * choice. + */ + case CRYPTO_CERT | CRYPTO_RESP: +- vallen = ntohl(ep->vallen); +- if (vallen == 0 || vallen > MAXHOSTNAME) { ++ vallen = ntohl(ep->vallen); /* Must be <64k */ ++ if (vallen == 0 || vallen > MAXHOSTNAME || ++ len - VALUE_LEN < vallen) { + rval = XEVNT_LEN; + break; + +@@ -1315,7 +1324,10 @@ + * anything goes wrong. + */ + case CRYPTO_COOK | CRYPTO_RESP: +- if ((opcode & 0xffff) < VALUE_LEN) { ++ vallen = ntohl(ep->vallen); /* Must be <64k */ ++ if ( vallen == 0 ++ || (vallen >= MAX_VALLEN) ++ || (opcode & 0x0000ffff) < VALUE_LEN + vallen) { + rval = XEVNT_LEN; + break; + } +@@ -1323,8 +1335,8 @@ + tcookie = cookie; + else + tcookie = peer->hcookie; +- if ((rval = crypto_encrypt(ep, &vtemp, &tcookie)) == +- XEVNT_OK) { ++ if ((rval = crypto_encrypt((const u_char *)ep->pkt, vallen, &tcookie, &vtemp)) ++ == XEVNT_OK) { + len = crypto_send(fp, &vtemp, start); + value_free(&vtemp); + } +@@ -1464,13 +1476,16 @@ + * up to the next word (4 octets). + */ + vallen = ntohl(ep->vallen); +- if (vallen == 0) ++ if ( vallen == 0 ++ || vallen > MAX_VALLEN) + return (XEVNT_LEN); + + i = (vallen + 3) / 4; + siglen = ntohl(ep->pkt[i++]); +- if (len < VALUE_LEN + ((vallen + 3) / 4) * 4 + ((siglen + 3) / +- 4) * 4) ++ if ( siglen > MAX_VALLEN ++ || len - VALUE_LEN < ((vallen + 3) / 4) * 4 ++ || len - VALUE_LEN - ((vallen + 3) / 4) * 4 ++ < ((siglen + 3) / 4) * 4) + return (XEVNT_LEN); + + /* +@@ -1528,6 +1543,7 @@ + * proventic bit. What a relief. + */ + EVP_VerifyInit(&ctx, peer->digest); ++ /* XXX: the "+ 12" needs to be at least documented... */ + EVP_VerifyUpdate(&ctx, (u_char *)&ep->tstamp, vallen + 12); + if (EVP_VerifyFinal(&ctx, (u_char *)&ep->pkt[i], siglen, + pkey) <= 0) +@@ -1540,34 +1556,31 @@ + + + /* +- * crypto_encrypt - construct encrypted cookie and signature from +- * extension field and cookie ++ * crypto_encrypt - construct vp (encrypted cookie and signature) from ++ * the public key and cookie. + * +- * Returns ++ * Returns: + * XEVNT_OK success + * XEVNT_CKY bad or missing cookie + * XEVNT_PUB bad or missing public key + */ + static int + crypto_encrypt( +- struct exten *ep, /* extension pointer */ +- struct value *vp, /* value pointer */ +- keyid_t *cookie /* server cookie */ ++ const u_char *ptr, /* Public Key */ ++ u_int vallen, /* Length of Public Key */ ++ keyid_t *cookie, /* server cookie */ ++ struct value *vp /* value pointer */ + ) + { + EVP_PKEY *pkey; /* public key */ + EVP_MD_CTX ctx; /* signature context */ + tstamp_t tstamp; /* NTP timestamp */ + u_int32 temp32; +- u_int len; +- u_char *ptr; + + /* + * Extract the public key from the request. + */ +- len = ntohl(ep->vallen); +- ptr = (u_char *)ep->pkt; +- pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ptr, len); ++ pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ptr, vallen); + if (pkey == NULL) { + msyslog(LOG_ERR, "crypto_encrypt: %s", + ERR_error_string(ERR_get_error(), NULL)); +@@ -1581,9 +1594,9 @@ + tstamp = crypto_time(); + vp->tstamp = htonl(tstamp); + vp->fstamp = hostval.tstamp; +- len = EVP_PKEY_size(pkey); +- vp->vallen = htonl(len); +- vp->ptr = emalloc(len); ++ vallen = EVP_PKEY_size(pkey); ++ vp->vallen = htonl(vallen); ++ vp->ptr = emalloc(vallen); + ptr = vp->ptr; + temp32 = htonl(*cookie); + if (RSA_public_encrypt(4, (u_char *)&temp32, ptr, +@@ -1601,8 +1614,8 @@ + vp->sig = emalloc(sign_siglen); + EVP_SignInit(&ctx, sign_digest); + EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12); +- EVP_SignUpdate(&ctx, vp->ptr, len); +- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) ++ EVP_SignUpdate(&ctx, vp->ptr, vallen); ++ if (EVP_SignFinal(&ctx, vp->sig, &vallen, sign_pkey)) + vp->siglen = htonl(sign_siglen); + return (XEVNT_OK); + } +@@ -1673,6 +1686,9 @@ + * call in the protocol module. + * + * Returns extension field pointer (no errors) ++ * ++ * XXX: opcode and len should really be 32-bit quantities and ++ * we should make sure that str is not too big. + */ + struct exten * + crypto_args( +@@ -1685,24 +1701,31 @@ + tstamp_t tstamp; /* NTP timestamp */ + struct exten *ep; /* extension field pointer */ + u_int len; /* extension field length */ ++ size_t slen; + + tstamp = crypto_time(); + len = sizeof(struct exten); +- if (str != NULL) +- len += strlen(str); ++ if (str != NULL) { ++ slen = strlen(str); ++ INSIST(slen < MAX_VALLEN); ++ len += slen; ++ } + ep = emalloc(len); + memset(ep, 0, len); + if (opcode == 0) + return (ep); + ++ REQUIRE(0 == (len & ~0x0000ffff)); ++ REQUIRE(0 == (opcode & ~0xffff0000)); ++ + ep->opcode = htonl(opcode + len); + ep->associd = htonl(associd); + ep->tstamp = htonl(tstamp); + ep->fstamp = hostval.tstamp; + ep->vallen = 0; + if (str != NULL) { +- ep->vallen = htonl(strlen(str)); +- memcpy((char *)ep->pkt, str, strlen(str)); ++ ep->vallen = htonl(slen); ++ memcpy((char *)ep->pkt, str, slen); + } + return (ep); + } +@@ -1715,6 +1738,8 @@ + * Note: it is not polite to send a nonempty signature with zero + * timestamp or a nonzero timestamp with an empty signature, but those + * rules are not enforced here. ++ * ++ * XXX This code won't work on a box with 16-bit ints. + */ + int + crypto_send( +@@ -1730,8 +1755,9 @@ + * Calculate extension field length and check for buffer + * overflow. Leave room for the MAC. + */ +- len = 16; ++ len = 16; /* XXX Document! */ + vallen = ntohl(vp->vallen); ++ INSIST(vallen <= MAX_VALLEN); + len += ((vallen + 3) / 4 + 1) * 4; + siglen = ntohl(vp->siglen); + len += ((siglen + 3) / 4 + 1) * 4; +@@ -1772,6 +1798,7 @@ + } + opcode = ntohl(ep->opcode); + ep->opcode = htonl((opcode & 0xffff0000) | len); ++ ENSURE(len <= MAX_VALLEN); + return (len); + } + +@@ -1807,7 +1834,6 @@ + if (hostval.tstamp == 0) + return; + +- + /* + * Sign public key and timestamps. The filestamp is derived from + * the host key file extension from wherever the file was +@@ -2108,7 +2134,8 @@ + tstamp_t tstamp; /* NTP timestamp */ + BIGNUM *bn, *bk, *r; + u_char *ptr; +- u_int len; ++ u_int len; /* extension field length */ ++ u_int vallen = 0; /* value length */ + + /* + * If the IFF parameters are not valid, something awful +@@ -2123,8 +2150,11 @@ + /* + * Extract r from the challenge. + */ +- len = ntohl(ep->vallen); +- if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) { ++ vallen = ntohl(ep->vallen); ++ len = ntohl(ep->opcode) & 0x0000ffff; ++ if (vallen == 0 || len < VALUE_LEN || len - VALUE_LEN < vallen) ++ return XEVNT_LEN; ++ if ((r = BN_bin2bn((u_char *)ep->pkt, vallen, NULL)) == NULL) { + msyslog(LOG_ERR, "crypto_bob: %s", + ERR_error_string(ERR_get_error(), NULL)); + return (XEVNT_ERR); +@@ -2136,7 +2166,7 @@ + */ + bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new(); + sdsa = DSA_SIG_new(); +- BN_rand(bk, len * 8, -1, 1); /* k */ ++ BN_rand(bk, vallen * 8, -1, 1); /* k */ + BN_mod_mul(bn, dsa->priv_key, r, dsa->q, bctx); /* b r mod q */ + BN_add(bn, bn, bk); + BN_mod(bn, bn, dsa->q, bctx); /* k + b r mod q */ +@@ -2155,30 +2185,37 @@ + * Encode the values in ASN.1 and sign. The filestamp is from + * the local file. + */ +- len = i2d_DSA_SIG(sdsa, NULL); +- if (len == 0) { ++ vallen = i2d_DSA_SIG(sdsa, NULL); ++ if (vallen == 0) { + msyslog(LOG_ERR, "crypto_bob: %s", + ERR_error_string(ERR_get_error(), NULL)); + DSA_SIG_free(sdsa); + return (XEVNT_ERR); + } ++ if (vallen > MAX_VALLEN) { ++ msyslog(LOG_ERR, "crypto_bob: signature is too big: %d", ++ vallen); ++ DSA_SIG_free(sdsa); ++ return (XEVNT_LEN); ++ } + memset(vp, 0, sizeof(struct value)); + tstamp = crypto_time(); + vp->tstamp = htonl(tstamp); + vp->fstamp = htonl(iffkey_info->fstamp); +- vp->vallen = htonl(len); +- ptr = emalloc(len); ++ vp->vallen = htonl(vallen); ++ ptr = emalloc(vallen); + vp->ptr = ptr; + i2d_DSA_SIG(sdsa, &ptr); + DSA_SIG_free(sdsa); + if (tstamp == 0) + return (XEVNT_OK); + ++ /* XXX: more validation to make sure the sign fits... */ + vp->sig = emalloc(sign_siglen); + EVP_SignInit(&ctx, sign_digest); + EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12); +- EVP_SignUpdate(&ctx, vp->ptr, len); +- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) ++ EVP_SignUpdate(&ctx, vp->ptr, vallen); ++ if (EVP_SignFinal(&ctx, vp->sig, &vallen, sign_pkey)) + vp->siglen = htonl(sign_siglen); + return (XEVNT_OK); + } +Index: ntp-4.2.6.p5+dfsg/ntpd/ntp_proto.c +=================================================================== +--- ntp-4.2.6.p5+dfsg.orig/ntpd/ntp_proto.c 2015-02-06 07:58:50.000000000 -0500 ++++ ntp-4.2.6.p5+dfsg/ntpd/ntp_proto.c 2015-02-06 08:32:45.146114360 -0500 +@@ -431,7 +431,7 @@ + */ + authlen = LEN_PKT_NOMAC; + has_mac = rbufp->recv_length - authlen; +- while (has_mac != 0) { ++ while (has_mac > 0) { + u_int32 len; + + if (has_mac % 4 != 0 || has_mac < MIN_MAC_LEN) { +@@ -456,6 +456,14 @@ + } + + /* ++ * If has_mac is < 0 we had a malformed packet. ++ */ ++ if (has_mac < 0) { ++ sys_badlength++; ++ return; /* bad length */ ++ } ++ ++ /* + * If authentication required, a MAC must be present. + */ + if (restrict_mask & RES_DONTTRUST && has_mac == 0) { diff -Nru ntp-4.2.6.p5+dfsg/debian/patches/CVE-2014-9298.patch ntp-4.2.6.p5+dfsg/debian/patches/CVE-2014-9298.patch --- ntp-4.2.6.p5+dfsg/debian/patches/CVE-2014-9298.patch 1970-01-01 00:00:00.000000000 +0000 +++ ntp-4.2.6.p5+dfsg/debian/patches/CVE-2014-9298.patch 2015-02-06 14:10:06.000000000 +0000 @@ -0,0 +1,43 @@ +Description: fix IPv6 ACL bypass +Origin: upstream, http://bk1.ntp.org/ntp-stable/?PAGE=patch&REV=54922b65gDSbE4G7c3JjkuK1Tv33qQ +Origin: upstream, http://bk1.ntp.org/ntp-stable/?PAGE=patch&REV=5492d2879rotbnnuVch_ZC3RAfS8AA +Origin: upstream, http://bk1.ntp.org/ntp-stable/?PAGE=patch&REV=5493f333hALqPcXLR4-76bC6j-16xQ +Origin: upstream, http://bk1.ntp.org/ntp-stable/?PAGE=patch&REV=5496213frLaEz5PHLZVhuYjM7Lalkw +Origin: upstream, http://bk1.ntp.org/ntp-stable/ntpd/ntp_io.c?PAGE=diffs&REV=54a0f621LdfQSkkWKUKN6PaFbH25_Q +Origin: upstream, http://bk1.ntp.org/ntp-stable/?PAGE=patch&REV=54c2228bpOp4_zrX9aGXdMEZJEGzkg +Bug: http://bugs.ntp.org/show_bug.cgi?id=2672 + +Index: ntp-4.2.6.p5+dfsg/ntpd/ntp_io.c +=================================================================== +--- ntp-4.2.6.p5+dfsg.orig/ntpd/ntp_io.c 2011-11-30 21:55:17.000000000 -0500 ++++ ntp-4.2.6.p5+dfsg/ntpd/ntp_io.c 2015-02-06 08:57:54.277845529 -0500 +@@ -3470,6 +3470,29 @@ + fd, buflen, stoa(&rb->recv_srcadr))); + + /* ++ ** Bug 2672: Some OSes (MacOSX and Linux) don't block spoofed ::1 ++ */ ++ ++ if (AF_INET6 == itf->family) { ++ DPRINTF(2, ("Got an IPv6 packet, from <%s> (%d) to <%s> (%d)\n", ++ stoa(&rb->recv_srcadr), ++ IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&rb->recv_srcadr)), ++ stoa(&itf->sin), ++ !IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&itf->sin)) ++ )); ++ ++ if ( IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&rb->recv_srcadr)) ++ && !IN6_IS_ADDR_LOOPBACK(PSOCK_ADDR6(&itf->sin)) ++ ) { ++ packets_dropped++; ++ DPRINTF(2, ("DROPPING that packet\n")); ++ freerecvbuf(rb); ++ return buflen; ++ } ++ DPRINTF(2, ("processing that packet\n")); ++ } ++ ++ /* + * Got one. Mark how and when it got here, + * put it on the full list and do bookkeeping. + */ diff -Nru ntp-4.2.6.p5+dfsg/debian/patches/series ntp-4.2.6.p5+dfsg/debian/patches/series --- ntp-4.2.6.p5+dfsg/debian/patches/series 2014-12-20 11:06:17.000000000 +0000 +++ ntp-4.2.6.p5+dfsg/debian/patches/series 2015-02-06 14:10:06.000000000 +0000 @@ -14,3 +14,5 @@ CVE-2014-9294.patch CVE-2014-9295.patch CVE-2014-9296.patch +CVE-2014-9297.patch +CVE-2014-9298.patch