From bfcdbc13d479a2bb93a0753305b4e4ebad508cda Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Thu, 13 Dec 2018 15:49:58 +0100 Subject: [PATCH] auth: Fallback to sha1 for the signatures cache if md5 is not available --- modules/goraclebackend/soracle.cc | 2 +- pdns/Makefile.am | 5 +- pdns/digests.hh | 81 +++++++++++++++++++++ pdns/dnssecsigner.cc | 14 +++- pdns/md5.hh | 36 --------- pdns/{test-md5_hh.cc => test-digests_hh.cc} | 14 +++- pdns/tsig-tests.cc | 2 +- 7 files changed, 109 insertions(+), 45 deletions(-) create mode 100644 pdns/digests.hh delete mode 100644 pdns/md5.hh rename pdns/{test-md5_hh.cc => test-digests_hh.cc} (60%) diff --git a/modules/goraclebackend/soracle.cc b/modules/goraclebackend/soracle.cc index fdf01caca..5442b174c 100644 --- a/modules/goraclebackend/soracle.cc +++ b/modules/goraclebackend/soracle.cc @@ -29,7 +29,7 @@ #include "pdns/logger.hh" #include "pdns/dns.hh" #include "pdns/namespaces.hh" -#include "pdns/md5.hh" +#include "pdns/digests.hh" static AtomicCounter s_txid; diff --git a/pdns/Makefile.am b/pdns/Makefile.am index 838af8dd0..eddb1f342 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -166,6 +166,7 @@ pdns_server_SOURCES = \ common_startup.cc common_startup.hh \ communicator.cc communicator.hh \ dbdnsseckeeper.cc \ + digests.hh \ distributor.hh \ dns.cc dns.hh \ dns_random.cc dns_random.hh \ @@ -194,7 +195,6 @@ pdns_server_SOURCES = \ lua-base4.cc lua-base4.hh \ lua-auth4.cc lua-auth4.hh \ mastercommunicator.cc \ - md5.hh \ misc.cc misc.hh \ nameserver.cc nameserver.hh \ namespaces.hh \ @@ -822,6 +822,7 @@ tsig_tests_SOURCES = \ arguments.cc \ base32.cc \ base64.cc base64.hh \ + digests.hh \ dns.cc \ dns_random_urandom.cc dns_random.hh \ dnslabeltext.cc \ @@ -1287,6 +1288,7 @@ testrunner_SOURCES = \ test-bindparser_cc.cc \ test-common.hh \ test-dnsrecordcontent.cc \ + test-digests_hh.cc \ test-distributor_hh.cc \ test-dns_random_hh.cc \ test-dnsname_cc.cc \ @@ -1297,7 +1299,6 @@ testrunner_SOURCES = \ test-ixfr_cc.cc \ test-lock_hh.cc \ test-lua_auth4_cc.cc \ - test-md5_hh.cc \ test-misc_hh.cc \ test-nameserver_cc.cc \ test-packetcache_cc.cc \ diff --git a/pdns/digests.hh b/pdns/digests.hh new file mode 100644 index 000000000..8e32acc2d --- /dev/null +++ b/pdns/digests.hh @@ -0,0 +1,81 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +#include +#include + +#include + +inline std::string pdns_hash(const EVP_MD * md, const std::string& input) +{ +#if OPENSSL_VERSION_NUMBER < 0x1010000fL + auto mdctx = std::unique_ptr(EVP_MD_CTX_create(), EVP_MD_CTX_destroy); +#else + auto mdctx = std::unique_ptr(EVP_MD_CTX_new(), EVP_MD_CTX_free); +#endif + if (!mdctx) { + throw std::runtime_error(std::string(EVP_MD_name(md)) + " context initialization failed"); + } + + if (EVP_DigestInit_ex(mdctx.get(), md, nullptr) != 1) { + throw std::runtime_error(std::string(EVP_MD_name(md)) + " EVP initialization failed"); + } + + if (EVP_DigestUpdate(mdctx.get(), input.data(), input.size()) != 1) { + throw std::runtime_error(std::string(EVP_MD_name(md)) + " EVP update failed"); + } + + unsigned int written; + std::string result; + result.resize(EVP_MD_size(md)); + + if (EVP_DigestFinal_ex(mdctx.get(), const_cast(reinterpret_cast(result.c_str())), &written) != 1) { + throw std::runtime_error(std::string(EVP_MD_name(md)) + " EVP final failed"); + } + + if (written != result.size()) { + throw std::runtime_error(std::string(EVP_MD_name(md)) + " EVP final wrote " + std::to_string(written) + ", expected " + std::to_string(result.size())); + } + + return result; +} + +inline std::string pdns_md5sum(const std::string& input) +{ + const auto md = EVP_md5(); + if (md == nullptr) { + throw std::runtime_error("The MD5 digest is not available via the OpenSSL EVP interface"); + } + + return pdns_hash(md, input); +} + +inline std::string pdns_sha1sum(const std::string& input) +{ + const auto md = EVP_sha1(); + if (md == nullptr) { + throw std::runtime_error("The SHA1 digest is not available via the OpenSSL EVP interface"); + } + + return pdns_hash(md, input); +} diff --git a/pdns/dnssecsigner.cc b/pdns/dnssecsigner.cc index 5c563d7ef..22abee7cc 100644 --- a/pdns/dnssecsigner.cc +++ b/pdns/dnssecsigner.cc @@ -25,7 +25,7 @@ #include "dnssecinfra.hh" #include "namespaces.hh" -#include "md5.hh" +#include "digests.hh" #include "dnsseckeeper.hh" #include "dns_random.hh" #include "lock.hh" @@ -41,6 +41,16 @@ static int g_cacheweekno; const static std::set g_KSKSignedQTypes {QType::DNSKEY, QType::CDS, QType::CDNSKEY}; AtomicCounter* g_signatureCount; +static std::string getLookupKey(const std::string& msg) +{ + try { + return pdns_md5sum(msg); + } + catch(const std::runtime_error& e) { + return pdns_sha1sum(msg); + } +} + static void fillOutRRSIG(DNSSECPrivateKey& dpk, const DNSName& signQName, RRSIGRecordContent& rrc, vector >& toSign) { if(!g_signatureCount) @@ -52,7 +62,7 @@ static void fillOutRRSIG(DNSSECPrivateKey& dpk, const DNSName& signQName, RRSIGR rrc.d_algorithm = drc.d_algorithm; string msg=getMessageForRRSET(signQName, rrc, toSign); // this is what we will hash & sign - pair lookup(rc->getPubKeyHash(), pdns_md5sum(msg)); // this hash is a memory saving exercise + pair lookup(rc->getPubKeyHash(), getLookupKey(msg)); // this hash is a memory saving exercise bool doCache=1; if(doCache) diff --git a/pdns/md5.hh b/pdns/md5.hh deleted file mode 100644 index 13f69b1c2..000000000 --- a/pdns/md5.hh +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of PowerDNS or dnsdist. - * Copyright -- PowerDNS.COM B.V. and its contributors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * In addition, for the avoidance of any doubt, permission is granted to - * link this program with OpenSSL and to (re)distribute the binaries - * produced as the result of such linking. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef _MD5_H -#define _MD5_H - -#include -#include -#include - -inline std::string pdns_md5sum(const std::string& input) -{ - unsigned char result[16] = {0}; - MD5(reinterpret_cast(input.c_str()), input.length(), result); - return std::string(result, result + sizeof result); -} - -#endif /* md5.h */ diff --git a/pdns/test-md5_hh.cc b/pdns/test-digests_hh.cc similarity index 60% rename from pdns/test-md5_hh.cc rename to pdns/test-digests_hh.cc index 5d9e90898..c061a8c20 100644 --- a/pdns/test-md5_hh.cc +++ b/pdns/test-digests_hh.cc @@ -6,18 +6,26 @@ #include #include -#include "md5.hh" +#include "digests.hh" #include "misc.hh" using namespace boost; -BOOST_AUTO_TEST_SUITE(test_md5_hh) +BOOST_AUTO_TEST_SUITE(test_digests_hh) BOOST_AUTO_TEST_CASE(test_pdns_md5sum) { std::string result = "a3 24 8c e3 1a 88 a6 40 e6 30 73 98 57 6d 06 9e "; std::string sum = pdns_md5sum("a quick brown fox jumped over the lazy dog"); - + + BOOST_CHECK_EQUAL(makeHexDump(sum), result); +} + +BOOST_AUTO_TEST_CASE(test_pdns_sha1sum) +{ + std::string result = "b9 37 10 0d c9 57 b3 86 d9 cb 77 fc 90 c0 18 22 fd eb 6e 7f "; + std::string sum = pdns_sha1sum("a quick brown fox jumped over the lazy dog"); + BOOST_CHECK_EQUAL(makeHexDump(sum), result); } diff --git a/pdns/tsig-tests.cc b/pdns/tsig-tests.cc index 93900fb25..3a705096c 100644 --- a/pdns/tsig-tests.cc +++ b/pdns/tsig-tests.cc @@ -8,7 +8,7 @@ #include "dnswriter.hh" #include "dnsrecords.hh" #include "statbag.hh" -#include "md5.hh" +#include "digests.hh" #include "base64.hh" #include "dnssecinfra.hh" #include "resolver.hh" -- 2.40.0