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