From 36014b2690d5b6a3474e8ea46c9361198e9ab402 Mon Sep 17 00:00:00 2001 From: delphij Date: Wed, 2 Nov 2016 07:24:34 +0000 Subject: [PATCH] Fix BIND remote Denial of Service vulnerability. [SA-16:34] Fix OpenSSL remote DoS vulnerability. [SA-16:35] Security: FreeBSD-SA-16:34.bind Security: FreeBSD-SA-16:35.openssl Approved by: so git-svn-id: svn://svn.freebsd.org/base/releng/9.3@308205 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- UPDATING | 7 ++++ contrib/bind9/lib/dns/resolver.c | 69 ++++++++++++++++++++++---------- crypto/openssl/ssl/d1_pkt.c | 15 +++++++ crypto/openssl/ssl/s3_pkt.c | 15 +++++++ crypto/openssl/ssl/ssl.h | 1 + crypto/openssl/ssl/ssl3.h | 2 + crypto/openssl/ssl/ssl_locl.h | 2 + sys/conf/newvers.sh | 2 +- 8 files changed, 90 insertions(+), 23 deletions(-) diff --git a/UPDATING b/UPDATING index 610e9a0ae..639ab76bb 100644 --- a/UPDATING +++ b/UPDATING @@ -11,6 +11,13 @@ handbook: Items affecting the ports and packages system can be found in /usr/ports/UPDATING. Please read that file before running portupgrade. +20161102 p50 FreeBSD-SA-16:34.bind + FreeBSD-SA-16:35.openssl + + Fix BIND remote Denial of Service vulnerability. [SA-16:34] + + Fix OpenSSL remote DoS vulnerability. [SA-16:35] + 20161025 p49 FreeBSD-SA-16:15.sysarch [revised] Fix incorrect argument validation in sysarch(2). [SA-16:15] diff --git a/contrib/bind9/lib/dns/resolver.c b/contrib/bind9/lib/dns/resolver.c index 75fabab5a..f882e4fd9 100644 --- a/contrib/bind9/lib/dns/resolver.c +++ b/contrib/bind9/lib/dns/resolver.c @@ -524,7 +524,9 @@ valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name, valarg->addrinfo = addrinfo; if (!ISC_LIST_EMPTY(fctx->validators)) - INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0); + valoptions |= DNS_VALIDATOR_DEFER; + else + valoptions &= ~DNS_VALIDATOR_DEFER; result = dns_validator_create(fctx->res->view, name, type, rdataset, sigrdataset, fctx->rmessage, @@ -4849,13 +4851,6 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, rdataset, sigrdataset, valoptions, task); - /* - * Defer any further validations. - * This prevents multiple validators - * from manipulating fctx->rmessage - * simultaneously. - */ - valoptions |= DNS_VALIDATOR_DEFER; } } else if (CHAINING(rdataset)) { if (rdataset->type == dns_rdatatype_cname) @@ -4961,6 +4956,11 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, eresult == DNS_R_NCACHENXRRSET); } event->result = eresult; + if (adbp != NULL && *adbp != NULL) { + if (anodep != NULL && *anodep != NULL) + dns_db_detachnode(*adbp, anodep); + dns_db_detach(adbp); + } dns_db_attach(fctx->cache, adbp); dns_db_transfernode(fctx->cache, &node, anodep); clone_results(fctx); @@ -5208,6 +5208,11 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, fctx->attributes |= FCTX_ATTR_HAVEANSWER; if (event != NULL) { event->result = eresult; + if (adbp != NULL && *adbp != NULL) { + if (anodep != NULL && *anodep != NULL) + dns_db_detachnode(*adbp, anodep); + dns_db_detach(adbp); + } dns_db_attach(fctx->cache, adbp); dns_db_transfernode(fctx->cache, &node, anodep); clone_results(fctx); @@ -6016,13 +6021,15 @@ static isc_result_t answer_response(fetchctx_t *fctx) { isc_result_t result; dns_message_t *message; - dns_name_t *name, *dname = NULL, *qname, tname, *ns_name; + dns_name_t *name, *dname = NULL, *qname, *dqname, tname, *ns_name; + dns_name_t *cname = NULL; dns_rdataset_t *rdataset, *ns_rdataset; isc_boolean_t done, external, chaining, aa, found, want_chaining; - isc_boolean_t have_answer, found_cname, found_type, wanted_chaining; + isc_boolean_t have_answer, found_cname, found_dname, found_type; + isc_boolean_t wanted_chaining; unsigned int aflag; dns_rdatatype_t type; - dns_fixedname_t fdname, fqname; + dns_fixedname_t fdname, fqname, fqdname; dns_view_t *view; FCTXTRACE("answer_response"); @@ -6036,6 +6043,7 @@ answer_response(fetchctx_t *fctx) { done = ISC_FALSE; found_cname = ISC_FALSE; + found_dname = ISC_FALSE; found_type = ISC_FALSE; chaining = ISC_FALSE; have_answer = ISC_FALSE; @@ -6045,12 +6053,13 @@ answer_response(fetchctx_t *fctx) { aa = ISC_TRUE; else aa = ISC_FALSE; - qname = &fctx->name; + dqname = qname = &fctx->name; type = fctx->type; view = fctx->res->view; + dns_fixedname_init(&fqdname); result = dns_message_firstname(message, DNS_SECTION_ANSWER); while (!done && result == ISC_R_SUCCESS) { - dns_namereln_t namereln; + dns_namereln_t namereln, dnamereln; int order; unsigned int nlabels; @@ -6058,6 +6067,8 @@ answer_response(fetchctx_t *fctx) { dns_message_currentname(message, DNS_SECTION_ANSWER, &name); external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain)); namereln = dns_name_fullcompare(qname, name, &order, &nlabels); + dnamereln = dns_name_fullcompare(dqname, name, &order, + &nlabels); if (namereln == dns_namereln_equal) { wanted_chaining = ISC_FALSE; for (rdataset = ISC_LIST_HEAD(name->list); @@ -6152,7 +6163,7 @@ answer_response(fetchctx_t *fctx) { } } else if (rdataset->type == dns_rdatatype_rrsig && rdataset->covers == - dns_rdatatype_cname + dns_rdatatype_cname && !found_type) { /* * We're looking for something else, @@ -6182,11 +6193,18 @@ answer_response(fetchctx_t *fctx) { * a CNAME or DNAME). */ INSIST(!external); - if (aflag == - DNS_RDATASETATTR_ANSWER) { + if ((rdataset->type != + dns_rdatatype_cname) || + !found_dname || + (aflag == + DNS_RDATASETATTR_ANSWER)) + { have_answer = ISC_TRUE; + if (rdataset->type == + dns_rdatatype_cname) + cname = name; name->attributes |= - DNS_NAMEATTR_ANSWER; + DNS_NAMEATTR_ANSWER; } rdataset->attributes |= aflag; if (aa) @@ -6280,11 +6298,11 @@ answer_response(fetchctx_t *fctx) { return (DNS_R_FORMERR); } - if (namereln != dns_namereln_subdomain) { + if (dnamereln != dns_namereln_subdomain) { char qbuf[DNS_NAME_FORMATSIZE]; char obuf[DNS_NAME_FORMATSIZE]; - dns_name_format(qname, qbuf, + dns_name_format(dqname, qbuf, sizeof(qbuf)); dns_name_format(name, obuf, sizeof(obuf)); @@ -6299,7 +6317,7 @@ answer_response(fetchctx_t *fctx) { want_chaining = ISC_TRUE; POST(want_chaining); aflag = DNS_RDATASETATTR_ANSWER; - result = dname_target(rdataset, qname, + result = dname_target(rdataset, dqname, nlabels, &fdname); if (result == ISC_R_NOSPACE) { /* @@ -6316,10 +6334,13 @@ answer_response(fetchctx_t *fctx) { dname = dns_fixedname_name(&fdname); if (!is_answertarget_allowed(view, - qname, rdataset->type, - dname, &fctx->domain)) { + dqname, rdataset->type, + dname, &fctx->domain)) + { return (DNS_R_SERVFAIL); } + dqname = dns_fixedname_name(&fqdname); + dns_name_copy(dname, dqname, NULL); } else { /* * We've found a signature that @@ -6344,6 +6365,10 @@ answer_response(fetchctx_t *fctx) { INSIST(!external); if (aflag == DNS_RDATASETATTR_ANSWER) { have_answer = ISC_TRUE; + found_dname = ISC_TRUE; + if (cname != NULL) + cname->attributes &= + ~DNS_NAMEATTR_ANSWER; name->attributes |= DNS_NAMEATTR_ANSWER; } diff --git a/crypto/openssl/ssl/d1_pkt.c b/crypto/openssl/ssl/d1_pkt.c index 034a4fa25..9a5b14582 100644 --- a/crypto/openssl/ssl/d1_pkt.c +++ b/crypto/openssl/ssl/d1_pkt.c @@ -820,6 +820,13 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) goto start; } + /* + * Reset the count of consecutive warning alerts if we've got a non-empty + * record that isn't an alert. + */ + if (rr->type != SSL3_RT_ALERT && rr->length != 0) + s->s3->alert_count = 0; + /* we now have a packet which can be read and processed */ if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, @@ -1043,6 +1050,14 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) if (alert_level == 1) { /* warning */ s->s3->warn_alert = alert_descr; + + s->s3->alert_count++; + if (s->s3->alert_count == MAX_WARN_ALERT_COUNT) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS); + goto f_err; + } + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { s->shutdown |= SSL_RECEIVED_SHUTDOWN; return (0); diff --git a/crypto/openssl/ssl/s3_pkt.c b/crypto/openssl/ssl/s3_pkt.c index ca0ef7064..8a9c92e6f 100644 --- a/crypto/openssl/ssl/s3_pkt.c +++ b/crypto/openssl/ssl/s3_pkt.c @@ -922,6 +922,13 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) return (ret); } + /* + * Reset the count of consecutive warning alerts if we've got a non-empty + * record that isn't an alert. + */ + if (rr->type != SSL3_RT_ALERT && rr->length != 0) + s->s3->alert_count = 0; + /* we now have a packet which can be read and processed */ if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, @@ -1121,6 +1128,14 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) if (alert_level == 1) { /* warning */ s->s3->warn_alert = alert_descr; + + s->s3->alert_count++; + if (s->s3->alert_count == MAX_WARN_ALERT_COUNT) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS); + goto f_err; + } + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { s->shutdown |= SSL_RECEIVED_SHUTDOWN; return (0); diff --git a/crypto/openssl/ssl/ssl.h b/crypto/openssl/ssl/ssl.h index 0c2a30320..b6aa2cdab 100644 --- a/crypto/openssl/ssl/ssl.h +++ b/crypto/openssl/ssl/ssl.h @@ -2195,6 +2195,7 @@ void ERR_load_SSL_strings(void); # define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110 # define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232 # define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 227 +# define SSL_R_TOO_MANY_WARN_ALERTS 409 # define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233 # define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 234 # define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 235 diff --git a/crypto/openssl/ssl/ssl3.h b/crypto/openssl/ssl/ssl3.h index 761a0e20b..eda992fce 100644 --- a/crypto/openssl/ssl/ssl3.h +++ b/crypto/openssl/ssl/ssl3.h @@ -491,6 +491,8 @@ typedef struct ssl3_state_st { char is_probably_safari; # endif /* !OPENSSL_NO_EC */ # endif /* !OPENSSL_NO_TLSEXT */ + /* Count of the number of consecutive warning alerts received */ + unsigned int alert_count; } SSL3_STATE; /* SSLv3 */ diff --git a/crypto/openssl/ssl/ssl_locl.h b/crypto/openssl/ssl/ssl_locl.h index 31a9cecca..ecb0814f3 100644 --- a/crypto/openssl/ssl/ssl_locl.h +++ b/crypto/openssl/ssl/ssl_locl.h @@ -247,6 +247,8 @@ # define DEC32(a) ((a)=((a)-1)&0xffffffffL) # define MAX_MAC_SIZE 20 /* up from 16 for SSLv3 */ +# define MAX_WARN_ALERT_COUNT 5 + /* * Define the Bitmasks for SSL_CIPHER.algorithms. * This bits are used packed as dense as possible. If new methods/ciphers diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index 2c161870a..5398221d4 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="9.3" -BRANCH="RELEASE-p49" +BRANCH="RELEASE-p50" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi -- 2.42.0