From 58ea8fb1dfc8c055a7d4ad74d65e345436ede790 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 7 Dec 2006 05:05:10 +0000 Subject: [PATCH] 2112. [security] Warn if weak RSA exponent is used. [RT #16460] --- CHANGES | 2 + bin/named/server.c | 9 ++++- lib/dns/zone.c | 91 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 93 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index e50b54e808..4f3b273a15 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +2112. [security] Warn if weak RSA exponent is used. [RT #16460] + 2111. [bug] Fix a number of errors reported by Coverity. [RT #16507] diff --git a/bin/named/server.c b/bin/named/server.c index a24a3cfef2..d7d2e3cf29 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.468 2006/12/04 02:38:22 marka Exp $ */ +/* $Id: server.c,v 1.469 2006/12/07 05:05:09 marka Exp $ */ /*! \file */ @@ -348,6 +348,13 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, keystruct.datalen = r.length; keystruct.data = r.base; + if ((keystruct.algorithm == DST_ALG_RSASHA1 || + keystruct.algorithm == DST_ALG_RSAMD5) && + r.length > 1 && r.base[0] == 1 && r.base[1] == 3) + cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, + "trusted key '%s' has a weak exponent", + keynamestr); + CHECK(dns_rdata_fromstruct(NULL, keystruct.common.rdclass, keystruct.common.rdtype, diff --git a/lib/dns/zone.c b/lib/dns/zone.c index fb94c8066c..4e12d88ccd 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.457 2006/07/19 00:53:42 marka Exp $ */ +/* $Id: zone.c,v 1.458 2006/12/07 05:05:10 marka Exp $ */ /*! \file */ @@ -1267,7 +1267,7 @@ zone_gotreadhandle(isc_task_t *task, isc_event_t *event) { options |= DNS_MASTER_CHECKMXFAIL; if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKWILDCARD)) options |= DNS_MASTER_CHECKWILDCARD; - result = dns_master_loadfileinc2(load->zone->masterfile, + result = dns_master_loadfileinc2(load->zone->masterfile, dns_db_origin(load->db), dns_db_origin(load->db), load->zone->rdclass, @@ -1477,7 +1477,7 @@ zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name, if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) { dns_name_format(foundname, altbuf, sizeof altbuf); dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME" - " '%s' (illegal)", ownerbuf, namebuf, + " '%s' (illegal)", ownerbuf, namebuf, altbuf); } return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE); @@ -1579,7 +1579,7 @@ zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name, static isc_boolean_t zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name, - dns_name_t *owner) + dns_name_t *owner) { isc_boolean_t answer = ISC_TRUE; isc_result_t result, tresult; @@ -1812,6 +1812,75 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) { return (ok); } +/* + * OpenSSL verification of RSA keys with exponent 3 is known to be + * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn + * if they are in use. + */ +static void +zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) { + dns_dbnode_t *node = NULL; + dns_dbversion_t *version = NULL; + dns_rdata_dnskey_t dnskey; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_t rdataset; + isc_result_t result; + isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE; + const char *algorithm; + + result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node); + if (result != ISC_R_SUCCESS) + goto cleanup; + + dns_db_currentversion(db, &version); + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey, + dns_rdatatype_none, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) + { + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &dnskey, NULL); + INSIST(result == ISC_R_SUCCESS); + + if ((dnskey.algorithm == DST_ALG_RSASHA1 || + dnskey.algorithm == DST_ALG_RSAMD5) && + dnskey.datalen > 1 && dnskey.data[0] == 1 && + dnskey.data[1] == 3) + { + if (dnskey.algorithm == DST_ALG_RSASHA1) { + logit = !foundrsa; + foundrsa = ISC_TRUE; + algorithm = "RSASHA1"; + } else { + logit = !foundmd5; + foundmd5 = ISC_TRUE; + algorithm = "RSAMD5"; + } + if (logit) + dns_zone_log(zone, ISC_LOG_WARNING, + "weak %s (%u) key found " + "(exponent=3)", algorithm, + dnskey.algorithm); + if (foundrsa && foundmd5) + break; + } + dns_rdata_reset(&rdata); + } + dns_rdataset_disassociate(&rdataset); + + cleanup: + if (node != NULL) + dns_db_detachnode(db, &node); + if (version != NULL) + dns_db_closeversion(db, &version, ISC_FALSE); + +} + static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, isc_result_t result) @@ -2010,6 +2079,12 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, goto cleanup; } + /* + * Check for weak DNSKEY's. + */ + if (zone->type == dns_zone_master) + zone_check_dnskeys(zone, db); + #if 0 /* destroy notification example. */ { @@ -3589,7 +3664,7 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) { */ if (isc_sockaddr_pf(¬ify->dst) == PF_INET6 && IN6_IS_ADDR_V4MAPPED(¬ify->dst.type.sin6.sin6_addr)) { - isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); + isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); notify_log(notify->zone, ISC_LOG_DEBUG(3), "notify: ignoring IPv6 mapped IPV4 address: %s", addrbuf); @@ -4797,7 +4872,7 @@ soa_query(isc_task_t *task, isc_event_t *event) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(keyname, namebuf, sizeof(namebuf)); dns_zone_log(zone, ISC_LOG_ERROR, - "unable to find key: %s", namebuf); + "unable to find key: %s", namebuf); } } if (key == NULL) @@ -5022,7 +5097,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(keyname, namebuf, sizeof(namebuf)); dns_zone_log(zone, ISC_LOG_ERROR, - "unable to find key: %s", namebuf); + "unable to find key: %s", namebuf); } } if (key == NULL) @@ -5109,7 +5184,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { if (message != NULL) dns_message_destroy(&message); unlock: - if (key != NULL) + if (key != NULL) dns_tsigkey_detach(&key); UNLOCK_ZONE(zone); return;