1 /* 2 * This file is part of PowerDNS or dnsdist. 3 * Copyright -- PowerDNS.COM B.V. and its contributors 4 * 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. 8 * 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. 12 * 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. 17 * 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. 21 */ 22 #pragma once 23 #include <string> 24 #include <string.h> 25 #include <vector> 26 #include <boost/logic/tribool.hpp> 27 #include <boost/multi_index_container.hpp> 28 #include <boost/multi_index/hashed_index.hpp> 29 #include <boost/multi_index/ordered_index.hpp> 30 #include <boost/tuple/tuple_comparison.hpp> 31 #include <boost/multi_index/key_extractors.hpp> 32 #include <boost/multi_index/sequenced_index.hpp> 33 #include "dnssecinfra.hh" 34 #include "dnsrecords.hh" 35 #include "ueberbackend.hh" 36 #include "lock.hh" 37 38 using namespace ::boost::multi_index; 39 40 class DNSSECKeeper : public boost::noncopyable 41 { 42 public: 43 enum keytype_t { KSK, ZSK, CSK }; 44 enum keyalgorithm_t : uint8_t { 45 RSAMD5=1, 46 DH=2, 47 DSA=3, 48 RSASHA1=5, 49 DSANSEC3SHA1=6, 50 RSASHA1NSEC3SHA1=7, 51 RSASHA256=8, 52 RSASHA512=10, 53 ECCGOST=12, 54 ECDSA256=13, 55 ECDSA384=14, 56 ED25519=15, 57 ED448=16 58 }; 59 60 enum dsdigestalgorithm_t : uint8_t { 61 DIGEST_SHA1=1, 62 DIGEST_SHA256=2, 63 DIGEST_GOST=3, 64 DIGEST_SHA384=4 65 }; 66 67 struct KeyMetaData 68 { 69 string fname; 70 unsigned int id; 71 bool active; 72 keytype_t keyType; 73 bool hasSEPBit; 74 bool published; 75 }; 76 typedef std::pair<DNSSECPrivateKey, KeyMetaData> keymeta_t; 77 typedef std::vector<keymeta_t > keyset_t; 78 keyTypeToString(const keytype_t & keyType)79 static string keyTypeToString(const keytype_t &keyType) 80 { 81 switch(keyType) { 82 case DNSSECKeeper::KSK: 83 return("KSK"); 84 case DNSSECKeeper::ZSK: 85 return("ZSK"); 86 case DNSSECKeeper::CSK: 87 return("CSK"); 88 default: 89 return("UNKNOWN"); 90 } 91 } 92 93 /* 94 * Returns the algorithm number based on the mnemonic (or old PowerDNS value of) a string. 95 * See https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml for the mapping 96 */ shorthand2algorithm(const string & algorithm)97 static int shorthand2algorithm(const string &algorithm) 98 { 99 if (pdns_iequals(algorithm, "rsamd5")) return RSAMD5; 100 if (pdns_iequals(algorithm, "dh")) return DH; 101 if (pdns_iequals(algorithm, "dsa")) return DSA; 102 if (pdns_iequals(algorithm, "rsasha1")) return RSASHA1; 103 if (pdns_iequals(algorithm, "dsa-nsec3-sha1")) return DSANSEC3SHA1; 104 if (pdns_iequals(algorithm, "rsasha1-nsec3-sha1")) return RSASHA1NSEC3SHA1; 105 if (pdns_iequals(algorithm, "rsasha256")) return RSASHA256; 106 if (pdns_iequals(algorithm, "rsasha512")) return RSASHA512; 107 if (pdns_iequals(algorithm, "ecc-gost")) return ECCGOST; 108 if (pdns_iequals(algorithm, "gost")) return ECCGOST; 109 if (pdns_iequals(algorithm, "ecdsa256")) return ECDSA256; 110 if (pdns_iequals(algorithm, "ecdsap256sha256")) return ECDSA256; 111 if (pdns_iequals(algorithm, "ecdsa384")) return ECDSA384; 112 if (pdns_iequals(algorithm, "ecdsap384sha384")) return ECDSA384; 113 if (pdns_iequals(algorithm, "ed25519")) return ED25519; 114 if (pdns_iequals(algorithm, "ed448")) return ED448; 115 if (pdns_iequals(algorithm, "indirect")) return 252; 116 if (pdns_iequals(algorithm, "privatedns")) return 253; 117 if (pdns_iequals(algorithm, "privateoid")) return 254; 118 return -1; 119 } 120 121 /* 122 * Returns the mnemonic from https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml 123 */ algorithm2name(uint8_t algo)124 static string algorithm2name(uint8_t algo) { 125 switch(algo) { 126 case 0: 127 case 4: 128 case 9: 129 case 11: 130 return "Reserved"; 131 case RSAMD5: 132 return "RSAMD5"; 133 case DH: 134 return "DH"; 135 case DSA: 136 return "DSA"; 137 case RSASHA1: 138 return "RSASHA1"; 139 case DSANSEC3SHA1: 140 return "DSA-NSEC3-SHA1"; 141 case RSASHA1NSEC3SHA1: 142 return "RSASHA1-NSEC3-SHA1"; 143 case RSASHA256: 144 return "RSASHA256"; 145 case RSASHA512: 146 return "RSASHA512"; 147 case ECCGOST: 148 return "ECC-GOST"; 149 case ECDSA256: 150 return "ECDSAP256SHA256"; 151 case ECDSA384: 152 return "ECDSAP384SHA384"; 153 case ED25519: 154 return "ED25519"; 155 case ED448: 156 return "ED448"; 157 case 252: 158 return "INDIRECT"; 159 case 253: 160 return "PRIVATEDNS"; 161 case 254: 162 return "PRIVATEOID"; 163 default: 164 return "Unallocated/Reserved"; 165 } 166 } 167 168 private: 169 UeberBackend* d_keymetadb; 170 bool d_ourDB; 171 172 public: DNSSECKeeper()173 DNSSECKeeper() : d_keymetadb( new UeberBackend("key-only")), d_ourDB(true) 174 { 175 176 } 177 DNSSECKeeper(UeberBackend * db)178 DNSSECKeeper(UeberBackend* db) : d_keymetadb(db), d_ourDB(false) 179 { 180 } 181 ~DNSSECKeeper()182 ~DNSSECKeeper() 183 { 184 if(d_ourDB) 185 delete d_keymetadb; 186 } 187 188 static uint64_t dbdnssecCacheSizes(const std::string& str); 189 static void clearAllCaches(); 190 static bool clearKeyCache(const DNSName& name); 191 static bool clearMetaCache(const DNSName& name); 192 static void clearCaches(const DNSName& name); 193 194 bool doesDNSSEC(); 195 bool isSecuredZone(const DNSName& zone, bool useCache=true); 196 keyset_t getEntryPoints(const DNSName& zname); 197 keyset_t getKeys(const DNSName& zone, bool useCache = true); 198 DNSSECPrivateKey getKeyById(const DNSName& zone, unsigned int id); 199 bool addKey(const DNSName& zname, bool setSEPBit, int algorithm, int64_t& id, int bits=0, bool active=true, bool published=true); 200 bool addKey(const DNSName& zname, const DNSSECPrivateKey& dpk, int64_t& id, bool active=true, bool published=true); 201 bool removeKey(const DNSName& zname, unsigned int id); 202 bool activateKey(const DNSName& zname, unsigned int id); 203 bool deactivateKey(const DNSName& zname, unsigned int id); 204 bool publishKey(const DNSName& zname, unsigned int id); 205 bool unpublishKey(const DNSName& zname, unsigned int id); 206 bool checkKeys(const DNSName& zname, vector<string>* errorMessages = nullptr); 207 208 bool getNSEC3PARAM(const DNSName& zname, NSEC3PARAMRecordContent* n3p=0, bool* narrow=0, bool useCache=true); 209 bool checkNSEC3PARAM(const NSEC3PARAMRecordContent& ns3p, string& msg); 210 bool setNSEC3PARAM(const DNSName& zname, const NSEC3PARAMRecordContent& n3p, const bool& narrow=false); 211 bool unsetNSEC3PARAM(const DNSName& zname); 212 void getPreRRSIGs(UeberBackend& db, vector<DNSZoneRecord>& rrs, uint32_t signTTL); 213 bool isPresigned(const DNSName& zname, bool useCache=true); 214 bool setPresigned(const DNSName& zname); 215 bool unsetPresigned(const DNSName& zname); 216 bool setPublishCDNSKEY(const DNSName& zname, bool deleteAlg); 217 void getPublishCDNSKEY(const DNSName& zname, std::string& value); 218 bool unsetPublishCDNSKEY(const DNSName& zname); 219 bool setPublishCDS(const DNSName& zname, const string& digestAlgos); 220 void getPublishCDS(const DNSName& zname, std::string& value); 221 bool unsetPublishCDS(const DNSName& zname); 222 223 bool TSIGGrantsAccess(const DNSName& zone, const DNSName& keyname); 224 bool getTSIGForAccess(const DNSName& zone, const ComboAddress& master, DNSName* keyname); 225 startTransaction(const DNSName & zone,int zone_id)226 void startTransaction(const DNSName& zone, int zone_id) 227 { 228 (*d_keymetadb->backends.begin())->startTransaction(zone, zone_id); 229 } 230 commitTransaction()231 void commitTransaction() 232 { 233 (*d_keymetadb->backends.begin())->commitTransaction(); 234 } 235 236 void getFromMetaOrDefault(const DNSName& zname, const std::string& key, std::string& value, const std::string& defaultvalue); 237 bool getFromMeta(const DNSName& zname, const std::string& key, std::string& value); 238 void getSoaEdit(const DNSName& zname, std::string& value, bool useCache=true); 239 bool unSecureZone(const DNSName& zone, std::string& error, std::string& info); 240 bool rectifyZone(const DNSName& zone, std::string& error, std::string& info, bool doTransaction); 241 242 static void setMaxEntries(size_t maxEntries); 243 244 typedef std::map<std::string, std::vector<std::string> > METAValues; 245 private: 246 bool getFromMetaNoCache(const DNSName& name, const std::string& kind, std::string& value); 247 248 int64_t d_metaCacheCleanAction{0}; 249 bool d_metaUpdate{false}; 250 251 struct KeyCacheEntry 252 { 253 typedef vector<DNSSECKeeper::keymeta_t> keys_t; 254 getTTDDNSSECKeeper::KeyCacheEntry255 uint32_t getTTD() const 256 { 257 return d_ttd; 258 } 259 260 DNSName d_domain; 261 mutable keys_t d_keys; 262 unsigned int d_ttd; 263 }; 264 265 struct METACacheEntry 266 { getTTDDNSSECKeeper::METACacheEntry267 time_t getTTD() const 268 { 269 return d_ttd; 270 } 271 272 DNSName d_domain; 273 mutable METAValues d_value; 274 time_t d_ttd; 275 }; 276 277 struct KeyCacheTag{}; 278 struct CompositeTag{}; 279 struct SequencedTag{}; 280 281 typedef multi_index_container< 282 KeyCacheEntry, 283 indexed_by< 284 hashed_unique<tag<KeyCacheTag>,member<KeyCacheEntry, DNSName, &KeyCacheEntry::d_domain> >, 285 sequenced<tag<SequencedTag>> 286 > 287 > keycache_t; 288 289 typedef multi_index_container< 290 METACacheEntry, 291 indexed_by< 292 ordered_unique<member<METACacheEntry, DNSName, &METACacheEntry::d_domain> >, 293 sequenced<tag<SequencedTag>> 294 > 295 > metacache_t; 296 297 void cleanup(); 298 299 static keycache_t s_keycache; 300 static metacache_t s_metacache; 301 static int64_t s_metaCacheCleanActions; 302 static ReadWriteLock s_metacachelock; 303 static ReadWriteLock s_keycachelock; 304 static AtomicCounter s_ops; 305 static time_t s_last_prune; 306 static size_t s_maxEntries; 307 308 public: preRemoval(const KeyCacheEntry &)309 void preRemoval(const KeyCacheEntry&) 310 { 311 } preRemoval(const METACacheEntry &)312 void preRemoval(const METACacheEntry&) 313 { 314 } 315 }; 316 317 class DNSPacket; 318 uint32_t localtime_format_YYYYMMDDSS(time_t t, uint32_t seq); 319 // for SOA-EDIT 320 uint32_t calculateEditSOA(uint32_t old_serial, DNSSECKeeper& dk, const DNSName& zonename); 321 uint32_t calculateEditSOA(uint32_t old_serial, const string& kind, const DNSName& zonename); 322 // for SOA-EDIT-DNSUPDATE/API 323 bool increaseSOARecord(DNSResourceRecord& dr, const string& increaseKind, const string& editKind); 324 bool makeIncreasedSOARecord(SOAData& sd, const string& increaseKind, const string& editKind, DNSResourceRecord& rrout); 325 DNSZoneRecord makeEditedDNSZRFromSOAData(DNSSECKeeper& dk, const SOAData& sd, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER); 326