2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <boost/logic/tribool.hpp>
27 #include <boost/multi_index_container.hpp>
28 #include <boost/multi_index/ordered_index.hpp>
29 #include <boost/tuple/tuple_comparison.hpp>
30 #include <boost/multi_index/key_extractors.hpp>
31 #include <boost/multi_index/sequenced_index.hpp>
32 #include "dnssecinfra.hh"
33 #include "dnsrecords.hh"
34 #include "ueberbackend.hh"
36 using namespace ::boost::multi_index;
38 class DNSSECKeeper : public boost::noncopyable
41 enum keytype_t { KSK, ZSK, CSK };
42 enum keyalgorithm_t : uint8_t {
58 enum dsdigestalgorithm_t : uint8_t {
73 typedef std::pair<DNSSECPrivateKey, KeyMetaData> keymeta_t;
74 typedef std::vector<keymeta_t > keyset_t;
76 static string keyTypeToString(const keytype_t &keyType)
79 case DNSSECKeeper::KSK:
81 case DNSSECKeeper::ZSK:
83 case DNSSECKeeper::CSK:
91 * Returns the algorithm number based on the mnemonic (or old PowerDNS value of) a string.
92 * See https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml for the mapping
94 static int shorthand2algorithm(const string &algorithm)
96 if (pdns_iequals(algorithm, "rsamd5")) return RSAMD5;
97 if (pdns_iequals(algorithm, "dh")) return DH;
98 if (pdns_iequals(algorithm, "dsa")) return DSA;
99 if (pdns_iequals(algorithm, "rsasha1")) return RSASHA1;
100 if (pdns_iequals(algorithm, "dsa-nsec3-sha1")) return DSANSEC3SHA1;
101 if (pdns_iequals(algorithm, "rsasha1-nsec3-sha1")) return RSASHA1NSEC3SHA1;
102 if (pdns_iequals(algorithm, "rsasha256")) return RSASHA256;
103 if (pdns_iequals(algorithm, "rsasha512")) return RSASHA512;
104 if (pdns_iequals(algorithm, "ecc-gost")) return ECCGOST;
105 if (pdns_iequals(algorithm, "gost")) return ECCGOST;
106 if (pdns_iequals(algorithm, "ecdsa256")) return ECDSA256;
107 if (pdns_iequals(algorithm, "ecdsap256sha256")) return ECDSA256;
108 if (pdns_iequals(algorithm, "ecdsa384")) return ECDSA384;
109 if (pdns_iequals(algorithm, "ecdsap384sha384")) return ECDSA384;
110 if (pdns_iequals(algorithm, "ed25519")) return ED25519;
111 if (pdns_iequals(algorithm, "ed448")) return ED448;
112 if (pdns_iequals(algorithm, "indirect")) return 252;
113 if (pdns_iequals(algorithm, "privatedns")) return 253;
114 if (pdns_iequals(algorithm, "privateoid")) return 254;
119 * Returns the mnemonic from https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
121 static string algorithm2name(uint8_t algo) {
137 return "DSA-NSEC3-SHA1";
138 case RSASHA1NSEC3SHA1:
139 return "RSASHA1-NSEC3-SHA1";
147 return "ECDSAP256SHA256";
149 return "ECDSAP384SHA384";
161 return "Unallocated/Reserved";
166 UeberBackend* d_keymetadb;
170 DNSSECKeeper() : d_keymetadb( new UeberBackend("key-only")), d_ourDB(true)
175 DNSSECKeeper(UeberBackend* db) : d_keymetadb(db), d_ourDB(false)
185 static uint64_t dbdnssecCacheSizes(const std::string& str);
186 static void clearAllCaches();
187 static void clearCaches(const DNSName& name);
190 bool isSecuredZone(const DNSName& zone);
191 keyset_t getEntryPoints(const DNSName& zname);
192 keyset_t getKeys(const DNSName& zone, bool useCache = true);
193 DNSSECPrivateKey getKeyById(const DNSName& zone, unsigned int id);
194 bool addKey(const DNSName& zname, bool setSEPBit, int algorithm, int64_t& id, int bits=0, bool active=true);
195 bool addKey(const DNSName& zname, const DNSSECPrivateKey& dpk, int64_t& id, bool active=true);
196 bool removeKey(const DNSName& zname, unsigned int id);
197 bool activateKey(const DNSName& zname, unsigned int id);
198 bool deactivateKey(const DNSName& zname, unsigned int id);
199 bool checkKeys(const DNSName& zname, vector<string>* errorMessages = nullptr);
201 bool getNSEC3PARAM(const DNSName& zname, NSEC3PARAMRecordContent* n3p=0, bool* narrow=0);
202 bool checkNSEC3PARAM(const NSEC3PARAMRecordContent& ns3p, string& msg);
203 bool setNSEC3PARAM(const DNSName& zname, const NSEC3PARAMRecordContent& n3p, const bool& narrow=false);
204 bool unsetNSEC3PARAM(const DNSName& zname);
205 bool getPreRRSIGs(UeberBackend& db, const DNSName& signer, const DNSName& qname, const DNSName& wildcardname, const QType& qtype, DNSResourceRecord::Place, vector<DNSZoneRecord>& rrsigs, uint32_t signTTL);
206 bool isPresigned(const DNSName& zname);
207 bool setPresigned(const DNSName& zname);
208 bool unsetPresigned(const DNSName& zname);
209 bool setPublishCDNSKEY(const DNSName& zname);
210 bool unsetPublishCDNSKEY(const DNSName& zname);
211 bool setPublishCDS(const DNSName& zname, const string& digestAlgos);
212 bool unsetPublishCDS(const DNSName& zname);
214 bool TSIGGrantsAccess(const DNSName& zone, const DNSName& keyname);
215 bool getTSIGForAccess(const DNSName& zone, const ComboAddress& master, DNSName* keyname);
217 void startTransaction(const DNSName& zone, int zone_id)
219 (*d_keymetadb->backends.begin())->startTransaction(zone, zone_id);
222 void commitTransaction()
224 (*d_keymetadb->backends.begin())->commitTransaction();
227 void getFromMeta(const DNSName& zname, const std::string& key, std::string& value);
228 void getSoaEdit(const DNSName& zname, std::string& value);
229 bool unSecureZone(const DNSName& zone, std::string& error, std::string& info);
230 bool rectifyZone(const DNSName& zone, std::string& error, std::string& info, bool doTransaction);
236 typedef vector<DNSSECKeeper::keymeta_t> keys_t;
238 uint32_t getTTD() const
244 mutable keys_t d_keys;
248 struct METACacheEntry
250 uint32_t getTTD() const
256 mutable std::string d_key, d_value;
261 struct KeyCacheTag{};
262 struct CompositeTag{};
263 struct SequencedTag{};
265 typedef multi_index_container<
268 ordered_unique<tag<KeyCacheTag>,member<KeyCacheEntry, DNSName, &KeyCacheEntry::d_domain> >,
269 sequenced<tag<SequencedTag>>
272 typedef multi_index_container<
275 ordered_unique<tag<CompositeTag>,
278 member<METACacheEntry, DNSName, &METACacheEntry::d_domain> ,
279 member<METACacheEntry, std::string, &METACacheEntry::d_key>
280 >, composite_key_compare<std::less<DNSName>, CIStringCompare> >,
281 sequenced<tag<SequencedTag>>
287 static keycache_t s_keycache;
288 static metacache_t s_metacache;
289 static pthread_rwlock_t s_metacachelock;
290 static pthread_rwlock_t s_keycachelock;
291 static AtomicCounter s_ops;
292 static time_t s_last_prune;
295 void preRemoval(const KeyCacheEntry&)
298 void preRemoval(const METACacheEntry&)
304 uint32_t localtime_format_YYYYMMDDSS(time_t t, uint32_t seq);
306 uint32_t calculateEditSOA(uint32_t old_serial, DNSSECKeeper& dk, const DNSName& zonename);
307 uint32_t calculateEditSOA(uint32_t old_serial, const string& kind, const DNSName& zonename);
308 // for SOA-EDIT-DNSUPDATE/API
309 bool increaseSOARecord(DNSResourceRecord& dr, const string& increaseKind, const string& editKind);
310 bool makeIncreasedSOARecord(SOAData& sd, const string& increaseKind, const string& editKind, DNSResourceRecord& rrout);
311 DNSZoneRecord makeEditedDNSZRFromSOAData(DNSSECKeeper& dk, const SOAData& sd, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER);