|
|
063937 |
diff -up ntp-4.2.6p5/ntpd/ntp_crypto.c.cve-2015-7691_7692_7702 ntp-4.2.6p5/ntpd/ntp_crypto.c
|
|
|
063937 |
--- ntp-4.2.6p5/ntpd/ntp_crypto.c.cve-2015-7691_7692_7702 2015-10-22 13:05:34.696482937 +0200
|
|
|
063937 |
+++ ntp-4.2.6p5/ntpd/ntp_crypto.c 2015-10-22 13:14:12.473848919 +0200
|
|
|
063937 |
@@ -170,6 +170,7 @@ static void cert_free (struct cert_info
|
|
|
063937 |
static struct pkey_info *crypto_key (char *, char *, sockaddr_u *);
|
|
|
063937 |
static void bighash (BIGNUM *, BIGNUM *);
|
|
|
063937 |
static struct cert_info *crypto_cert (char *);
|
|
|
063937 |
+static u_int exten_payload_size(const struct exten *);
|
|
|
063937 |
|
|
|
063937 |
#ifdef SYS_WINNT
|
|
|
063937 |
int
|
|
|
063937 |
@@ -389,7 +390,7 @@ crypto_recv(
|
|
|
063937 |
struct autokey *ap, *bp; /* autokey pointer */
|
|
|
063937 |
struct exten *ep, *fp; /* extension pointers */
|
|
|
063937 |
struct cert_info *xinfo; /* certificate info pointer */
|
|
|
063937 |
- int has_mac; /* length of MAC field */
|
|
|
063937 |
+ int macbytes; /* length of MAC field, signed by intention */
|
|
|
063937 |
int authlen; /* offset of MAC field */
|
|
|
063937 |
associd_t associd; /* association ID */
|
|
|
063937 |
tstamp_t tstamp = 0; /* timestamp */
|
|
|
063937 |
@@ -417,7 +418,11 @@ crypto_recv(
|
|
|
063937 |
*/
|
|
|
063937 |
authlen = LEN_PKT_NOMAC;
|
|
|
063937 |
hismode = (int)PKT_MODE((&rbufp->recv_pkt)->li_vn_mode);
|
|
|
063937 |
- while ((has_mac = rbufp->recv_length - authlen) > MAX_MAC_LEN) {
|
|
|
063937 |
+ while ((macbytes = rbufp->recv_length - authlen) > (int)MAX_MAC_LEN) {
|
|
|
063937 |
+ /* We can be reasonably sure that we can read at least
|
|
|
063937 |
+ * the opcode and the size field here. More stringent
|
|
|
063937 |
+ * checks follow up shortly.
|
|
|
063937 |
+ */
|
|
|
063937 |
pkt = (u_int32 *)&rbufp->recv_pkt + authlen / 4;
|
|
|
063937 |
ep = (struct exten *)pkt;
|
|
|
063937 |
code = ntohl(ep->opcode) & 0xffff0000;
|
|
|
063937 |
@@ -441,6 +446,18 @@ crypto_recv(
|
|
|
063937 |
code |= CRYPTO_ERROR;
|
|
|
063937 |
}
|
|
|
063937 |
|
|
|
063937 |
+ /* Check if the declared size fits into the remaining
|
|
|
063937 |
+ * buffer.
|
|
|
063937 |
+ */
|
|
|
063937 |
+ if (len > macbytes) {
|
|
|
063937 |
+ DPRINTF(1, ("crypto_recv: possible attack detected, associd %d\n",
|
|
|
063937 |
+ associd));
|
|
|
063937 |
+ return XEVNT_LEN;
|
|
|
063937 |
+ }
|
|
|
063937 |
+
|
|
|
063937 |
+ /* Check if the paylod of the extension fits into the
|
|
|
063937 |
+ * declared frame.
|
|
|
063937 |
+ */
|
|
|
063937 |
if (len >= VALUE_LEN) {
|
|
|
063937 |
tstamp = ntohl(ep->tstamp);
|
|
|
063937 |
fstamp = ntohl(ep->fstamp);
|
|
|
063937 |
@@ -1170,9 +1187,8 @@ crypto_xmit(
|
|
|
063937 |
* choice.
|
|
|
063937 |
*/
|
|
|
063937 |
case CRYPTO_CERT | CRYPTO_RESP:
|
|
|
063937 |
- vallen = ntohl(ep->vallen); /* Must be <64k */
|
|
|
063937 |
- if (vallen == 0 || vallen > MAXHOSTNAME ||
|
|
|
063937 |
- len - VALUE_LEN < vallen) {
|
|
|
063937 |
+ vallen = exten_payload_size(ep); /* Must be <64k */
|
|
|
063937 |
+ if (vallen == 0 || vallen >= sizeof(certname) ) {
|
|
|
063937 |
rval = XEVNT_LEN;
|
|
|
063937 |
break;
|
|
|
063937 |
} else {
|
|
|
063937 |
@@ -2134,8 +2150,7 @@ crypto_bob(
|
|
|
063937 |
tstamp_t tstamp; /* NTP timestamp */
|
|
|
063937 |
BIGNUM *bn, *bk, *r;
|
|
|
063937 |
u_char *ptr;
|
|
|
063937 |
- u_int len; /* extension field length */
|
|
|
063937 |
- u_int vallen = 0; /* value length */
|
|
|
063937 |
+ u_int len; /* extension field value length */
|
|
|
063937 |
|
|
|
063937 |
/*
|
|
|
063937 |
* If the IFF parameters are not valid, something awful
|
|
|
063937 |
@@ -2150,11 +2165,10 @@ crypto_bob(
|
|
|
063937 |
/*
|
|
|
063937 |
* Extract r from the challenge.
|
|
|
063937 |
*/
|
|
|
063937 |
- vallen = ntohl(ep->vallen);
|
|
|
063937 |
- len = ntohl(ep->opcode) & 0x0000ffff;
|
|
|
063937 |
- if (vallen == 0 || len < VALUE_LEN || len - VALUE_LEN < vallen)
|
|
|
063937 |
- return XEVNT_LEN;
|
|
|
063937 |
- if ((r = BN_bin2bn((u_char *)ep->pkt, vallen, NULL)) == NULL) {
|
|
|
063937 |
+ len = exten_payload_size(ep);
|
|
|
063937 |
+ if (len == 0 || len > MAX_VALLEN)
|
|
|
063937 |
+ return (XEVNT_LEN);
|
|
|
063937 |
+ if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
|
|
|
063937 |
msyslog(LOG_ERR, "crypto_bob: %s",
|
|
|
063937 |
ERR_error_string(ERR_get_error(), NULL));
|
|
|
063937 |
return (XEVNT_ERR);
|
|
|
063937 |
@@ -2166,7 +2180,7 @@ crypto_bob(
|
|
|
063937 |
*/
|
|
|
063937 |
bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new();
|
|
|
063937 |
sdsa = DSA_SIG_new();
|
|
|
063937 |
- BN_rand(bk, vallen * 8, -1, 1); /* k */
|
|
|
063937 |
+ BN_rand(bk, len * 8, -1, 1); /* k */
|
|
|
063937 |
BN_mod_mul(bn, dsa->priv_key, r, dsa->q, bctx); /* b r mod q */
|
|
|
063937 |
BN_add(bn, bn, bk);
|
|
|
063937 |
BN_mod(bn, bn, dsa->q, bctx); /* k + b r mod q */
|
|
|
063937 |
@@ -2185,16 +2199,16 @@ crypto_bob(
|
|
|
063937 |
* Encode the values in ASN.1 and sign. The filestamp is from
|
|
|
063937 |
* the local file.
|
|
|
063937 |
*/
|
|
|
063937 |
- vallen = i2d_DSA_SIG(sdsa, NULL);
|
|
|
063937 |
- if (vallen == 0) {
|
|
|
063937 |
+ len = i2d_DSA_SIG(sdsa, NULL);
|
|
|
063937 |
+ if (len == 0) {
|
|
|
063937 |
msyslog(LOG_ERR, "crypto_bob: %s",
|
|
|
063937 |
ERR_error_string(ERR_get_error(), NULL));
|
|
|
063937 |
DSA_SIG_free(sdsa);
|
|
|
063937 |
return (XEVNT_ERR);
|
|
|
063937 |
}
|
|
|
063937 |
- if (vallen > MAX_VALLEN) {
|
|
|
063937 |
- msyslog(LOG_ERR, "crypto_bob: signature is too big: %d",
|
|
|
063937 |
- vallen);
|
|
|
063937 |
+ if (len > MAX_VALLEN) {
|
|
|
063937 |
+ msyslog(LOG_ERR, "crypto_bob: signature is too big: %u",
|
|
|
063937 |
+ len);
|
|
|
063937 |
DSA_SIG_free(sdsa);
|
|
|
063937 |
return (XEVNT_LEN);
|
|
|
063937 |
}
|
|
|
063937 |
@@ -2202,8 +2216,8 @@ crypto_bob(
|
|
|
063937 |
tstamp = crypto_time();
|
|
|
063937 |
vp->tstamp = htonl(tstamp);
|
|
|
063937 |
vp->fstamp = htonl(iffkey_info->fstamp);
|
|
|
063937 |
- vp->vallen = htonl(vallen);
|
|
|
063937 |
- ptr = emalloc(vallen);
|
|
|
063937 |
+ vp->vallen = htonl(len);
|
|
|
063937 |
+ ptr = emalloc(len);
|
|
|
063937 |
vp->ptr = ptr;
|
|
|
063937 |
i2d_DSA_SIG(sdsa, &ptr);
|
|
|
063937 |
DSA_SIG_free(sdsa);
|
|
|
063937 |
@@ -2214,9 +2228,9 @@ crypto_bob(
|
|
|
063937 |
vp->sig = emalloc(sign_siglen);
|
|
|
063937 |
EVP_SignInit(&ctx, sign_digest);
|
|
|
063937 |
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
|
|
|
063937 |
- EVP_SignUpdate(&ctx, vp->ptr, vallen);
|
|
|
063937 |
- if (EVP_SignFinal(&ctx, vp->sig, &vallen, sign_pkey))
|
|
|
063937 |
- vp->siglen = htonl(sign_siglen);
|
|
|
063937 |
+ EVP_SignUpdate(&ctx, vp->ptr, len);
|
|
|
063937 |
+ if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
|
|
|
063937 |
+ vp->siglen = htonl(len);
|
|
|
063937 |
return (XEVNT_OK);
|
|
|
063937 |
}
|
|
|
063937 |
|
|
|
063937 |
@@ -2462,7 +2476,9 @@ crypto_bob2(
|
|
|
063937 |
/*
|
|
|
063937 |
* Extract r from the challenge.
|
|
|
063937 |
*/
|
|
|
063937 |
- len = ntohl(ep->vallen);
|
|
|
063937 |
+ len = exten_payload_size(ep);
|
|
|
063937 |
+ if (len == 0 || len > MAX_VALLEN)
|
|
|
063937 |
+ return (XEVNT_LEN);
|
|
|
063937 |
if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
|
|
|
063937 |
msyslog(LOG_ERR, "crypto_bob2: %s",
|
|
|
063937 |
ERR_error_string(ERR_get_error(), NULL));
|
|
|
063937 |
@@ -2787,7 +2803,9 @@ crypto_bob3(
|
|
|
063937 |
/*
|
|
|
063937 |
* Extract r from the challenge.
|
|
|
063937 |
*/
|
|
|
063937 |
- len = ntohl(ep->vallen);
|
|
|
063937 |
+ len = exten_payload_size(ep);
|
|
|
063937 |
+ if (len == 0 || len > MAX_VALLEN)
|
|
|
063937 |
+ return (XEVNT_LEN);
|
|
|
063937 |
if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
|
|
|
063937 |
msyslog(LOG_ERR, "crypto_bob3: %s",
|
|
|
063937 |
ERR_error_string(ERR_get_error(), NULL));
|
|
|
063937 |
@@ -3002,8 +3020,11 @@ cert_sign(
|
|
|
063937 |
if (tstamp == 0)
|
|
|
063937 |
return (XEVNT_TSP);
|
|
|
063937 |
|
|
|
063937 |
+ len = exten_payload_size(ep);
|
|
|
063937 |
+ if (len == 0 || len > MAX_VALLEN)
|
|
|
063937 |
+ return (XEVNT_LEN);
|
|
|
063937 |
ptr = (u_char *)ep->pkt;
|
|
|
063937 |
- if ((req = d2i_X509(NULL, &ptr, ntohl(ep->vallen))) == NULL) {
|
|
|
063937 |
+ if ((req = d2i_X509(NULL, &ptr, len)) == NULL) {
|
|
|
063937 |
msyslog(LOG_ERR, "cert_sign: %s",
|
|
|
063937 |
ERR_error_string(ERR_get_error(), NULL));
|
|
|
063937 |
return (XEVNT_CRT);
|
|
|
063937 |
@@ -3968,6 +3989,36 @@ crypto_config(
|
|
|
063937 |
break;
|
|
|
063937 |
}
|
|
|
063937 |
}
|
|
|
063937 |
+
|
|
|
063937 |
+/*
|
|
|
063937 |
+ * Get payload size (internal value length) of an extension packet. If
|
|
|
063937 |
+ * the inner value length does not match the outer packet length (that
|
|
|
063937 |
+ * is, the value would end behind the frame given by the opcode/size
|
|
|
063937 |
+ * field) the function will efectively return UINT_MAX. If the frame is
|
|
|
063937 |
+ * too short to holda variable-sized value, the return value is zero.
|
|
|
063937 |
+ */
|
|
|
063937 |
+static u_int
|
|
|
063937 |
+exten_payload_size(
|
|
|
063937 |
+ const struct exten * ep)
|
|
|
063937 |
+{
|
|
|
063937 |
+ typedef const u_char *BPTR;
|
|
|
063937 |
+
|
|
|
063937 |
+ size_t extn_size;
|
|
|
063937 |
+ size_t data_size;
|
|
|
063937 |
+ size_t head_size;
|
|
|
063937 |
+
|
|
|
063937 |
+ data_size = 0;
|
|
|
063937 |
+ if (NULL != ep) {
|
|
|
063937 |
+ head_size = (BPTR)(&ep->vallen + 1) - (BPTR)ep;
|
|
|
063937 |
+ extn_size = (uint16_t)(ntohl(ep->opcode) & 0x0000ffff);
|
|
|
063937 |
+ if (extn_size >= head_size) {
|
|
|
063937 |
+ data_size = (uint32_t)ntohl(ep->vallen);
|
|
|
063937 |
+ if (data_size > extn_size - head_size)
|
|
|
063937 |
+ data_size = ~(size_t)0u;
|
|
|
063937 |
+ }
|
|
|
063937 |
+ }
|
|
|
063937 |
+ return (u_int)data_size;
|
|
|
063937 |
+}
|
|
|
063937 |
# else
|
|
|
063937 |
int ntp_crypto_bs_pubkey;
|
|
|
063937 |
# endif /* OPENSSL */
|