]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/backends/bind/binddnssec.cc
add OpenSSL exception to PowerDNS, Netherlabs, van Dijk and Hubert copyrights
[thirdparty/pdns.git] / pdns / backends / bind / binddnssec.cc
CommitLineData
2717b8b3
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002-2012 PowerDNS.COM BV
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
f782fe38
MH
8
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
2717b8b3
BH
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 St, Fifth Floor, Boston, MA 02110-1301 USA
21*/
22#include "bindbackend2.hh"
2717b8b3
BH
23#include "dnsrecords.hh"
24#include "bind-dnssec.schema.sqlite3.sql.h"
fbe72b7a 25#include <boost/foreach.hpp>
9ca633e6 26#include "config.h"
e237ea04 27#include "pdns/arguments.hh"
2717b8b3 28
9ca633e6
BH
29#ifndef HAVE_SQLITE3
30void Bind2Backend::setupDNSSEC()
32869e14 31{
f5033922
PD
32 if(!getArg("dnssec-db").empty())
33 throw runtime_error("bind-dnssec-db requires building PowerDNS with SQLite3");
32869e14 34}
9ca633e6
BH
35
36void Bind2Backend::createDNSSECDB(const string& fname)
37{}
38
9bd2f6f4
PD
39bool Bind2Backend::doesDNSSEC()
40{ return false; }
41
9ca633e6
BH
42bool Bind2Backend::getNSEC3PARAM(const std::string& zname, NSEC3PARAMRecordContent* ns3p)
43{ return false; }
44
45bool Bind2Backend::getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta)
46{ return false; }
47
48bool Bind2Backend::setDomainMetadata(const string& name, const std::string& kind, const std::vector<std::string>& meta)
49{ return false; }
50
51bool Bind2Backend::getDomainKeys(const string& name, unsigned int kind, std::vector<KeyData>& keys)
52{ return false; }
53
54bool Bind2Backend::removeDomainKey(const string& name, unsigned int id)
55{ return false; }
56
57int Bind2Backend::addDomainKey(const string& name, const KeyData& key)
58{ return false; }
59
60bool Bind2Backend::activateDomainKey(const string& name, unsigned int id)
61{ return false; }
62
63bool Bind2Backend::deactivateDomainKey(const string& name, unsigned int id)
64{ return false; }
65
66bool Bind2Backend::getTSIGKey(const string& name, string* algorithm, string* content)
67{ return false; }
7e5b2860
AT
68
69bool Bind2Backend::setTSIGKey(const string& name, const string& algorithm, const string& content)
70{ return false; }
71
72bool Bind2Backend::deleteTSIGKey(const string& name)
73{ return false; }
74
75bool Bind2Backend::getTSIGKeys(std::vector< struct TSIGKey > &keys)
76{ return false; }
9ca633e6
BH
77#else
78
32869e14 79#include "pdns/ssqlite3.hh"
2717b8b3
BH
80void Bind2Backend::setupDNSSEC()
81{
82 // cerr<<"Settting up dnssec db.. "<<getArg("dnssec-db") <<endl;
83 if(getArg("dnssec-db").empty())
84 return;
85 try {
86 d_dnssecdb = shared_ptr<SSQLite3>(new SSQLite3(getArg("dnssec-db")));
87 }
88 catch(SSqlException& se) {
89 // this error is meant to kill the server dead - it makes no sense to continue..
90 throw runtime_error("Error opening DNSSEC database in BIND backend: "+se.txtReason());
91 }
c507b822
PD
92
93 d_dnssecdb->setLog(::arg().mustDo("query-logging"));
2717b8b3
BH
94}
95
96void Bind2Backend::createDNSSECDB(const string& fname)
97{
2717b8b3 98 try {
fbe72b7a
BH
99 SSQLite3 db(fname, true); // create=ok
100 vector<string> statements;
101 stringtok(statements, sqlCreate, ";");
102 BOOST_FOREACH(const string& statement, statements)
103 db.doCommand(statement);
2717b8b3
BH
104 }
105 catch(SSqlException& se) {
3f81d239 106 throw PDNSException("Error creating database in BIND backend: "+se.txtReason());
2717b8b3
BH
107 }
108}
109
9bd2f6f4
PD
110bool Bind2Backend::doesDNSSEC()
111{
112 return true;
113}
2717b8b3
BH
114
115bool Bind2Backend::getNSEC3PARAM(const std::string& zname, NSEC3PARAMRecordContent* ns3p)
116{
117 string value;
2717b8b3
BH
118 vector<string> meta;
119 getDomainMetadata(zname, "NSEC3PARAM", meta);
120 if(!meta.empty())
121 value=*meta.begin();
122
123 if(value.empty()) { // "no NSEC3"
124 return false;
125 }
126
127 if(ns3p) {
128 NSEC3PARAMRecordContent* tmp=dynamic_cast<NSEC3PARAMRecordContent*>(DNSRecordContent::mastermake(QType::NSEC3PARAM, 1, value));
129 *ns3p = *tmp;
130 delete tmp;
131 }
132 return true;
133}
134
135bool Bind2Backend::getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta)
136{
137 if(!d_dnssecdb)
138 return false;
139
140 // cerr<<"Asked to get metadata for zone '"<<name<<"'|"<<kind<<"\n";
141
142 boost::format fmt("select content from domainmetadata where domain='%s' and kind='%s'");
143 try {
144 d_dnssecdb->doQuery((fmt % d_dnssecdb->escape(name) % d_dnssecdb->escape(kind)).str());
145
146 vector<string> row;
147 while(d_dnssecdb->getRow(row)) {
148 meta.push_back(row[0]);
149 }
150 }
151 catch(SSqlException& se) {
3f81d239 152 throw PDNSException("Error accessing DNSSEC database in BIND backend: "+se.txtReason());
2717b8b3
BH
153 }
154 return true;
155}
156
157bool Bind2Backend::setDomainMetadata(const string& name, const std::string& kind, const std::vector<std::string>& meta)
158{
159 if(!d_dnssecdb)
160 return false;
161
162 boost::format fmt("delete from domainmetadata where domain='%s' and kind='%s'");
163 boost::format fmt2("insert into domainmetadata (domain, kind, content) values ('%s','%s', '%s')");
164 try {
165 d_dnssecdb->doCommand((fmt % d_dnssecdb->escape(name) % d_dnssecdb->escape(kind)).str());
166 if(!meta.empty())
167 d_dnssecdb->doCommand((fmt2 % d_dnssecdb->escape(name) % d_dnssecdb->escape(kind) % d_dnssecdb->escape(meta.begin()->c_str())).str());
168 }
169 catch(SSqlException& se) {
3f81d239 170 throw PDNSException("Error accessing DNSSEC database in BIND backend: "+se.txtReason());
2717b8b3
BH
171 }
172 return true;
173
174}
175
176bool Bind2Backend::getDomainKeys(const string& name, unsigned int kind, std::vector<KeyData>& keys)
177{
178 // cerr<<"Asked to get keys for zone '"<<name<<"'\n";
179 if(!d_dnssecdb)
180 return false;
181 boost::format fmt("select id,flags, active, content from cryptokeys where domain='%s'");
182 try {
183 d_dnssecdb->doQuery((fmt % d_dnssecdb->escape(name)).str());
184 KeyData kd;
185 vector<string> row;
186 while(d_dnssecdb->getRow(row)) {
187 kd.id = atoi(row[0].c_str());
188 kd.flags = atoi(row[1].c_str());
189 kd.active = atoi(row[2].c_str());
190 kd.content = row[3];
191 keys.push_back(kd);
192 }
193 }
194 catch(SSqlException& se) {
3f81d239 195 throw PDNSException("Error accessing DNSSEC database in BIND backend: "+se.txtReason());
2717b8b3
BH
196 }
197
198 return true;
199}
200
201bool Bind2Backend::removeDomainKey(const string& name, unsigned int id)
202{
203 if(!d_dnssecdb)
204 return false;
205
206 cerr<<"Asked to remove key "<<id<<" in zone '"<<name<<"'\n";
207
208 boost::format fmt("delete from cryptokeys where domain='%s' and id=%d");
209 try {
210 d_dnssecdb->doCommand((fmt % d_dnssecdb->escape(name) % id).str());
211 }
212 catch(SSqlException& se) {
213 cerr<<se.txtReason() <<endl;
214 }
215
216 return true;
217}
218
219int Bind2Backend::addDomainKey(const string& name, const KeyData& key)
220{
221 if(!d_dnssecdb)
222 return false;
223
224 //cerr<<"Asked to add a key to zone '"<<name<<"'\n";
225
226 boost::format fmt("insert into cryptokeys (domain, flags, active, content) values ('%s', %d, %d, '%s')");
227 try {
228 d_dnssecdb->doCommand((fmt % d_dnssecdb->escape(name) % key.flags % key.active % d_dnssecdb->escape(key.content)).str());
229 }
230 catch(SSqlException& se) {
3f81d239 231 throw PDNSException("Error accessing DNSSEC database in BIND backend: "+se.txtReason());
2717b8b3
BH
232 }
233
234 return true;
235}
236
237bool Bind2Backend::activateDomainKey(const string& name, unsigned int id)
238{
239 // cerr<<"Asked to activate key "<<id<<" inzone '"<<name<<"'\n";
240 if(!d_dnssecdb)
241 return false;
242
243 boost::format fmt("update cryptokeys set active=1 where domain='%s' and id=%d");
244 try {
245 d_dnssecdb->doCommand((fmt % d_dnssecdb->escape(name) % id).str());
246 }
247 catch(SSqlException& se) {
3f81d239 248 throw PDNSException("Error accessing DNSSEC database in BIND backend: "+se.txtReason());
2717b8b3
BH
249 }
250
251 return true;
252}
253
254bool Bind2Backend::deactivateDomainKey(const string& name, unsigned int id)
255{
256 // cerr<<"Asked to deactivate key "<<id<<" inzone '"<<name<<"'\n";
257 if(!d_dnssecdb)
258 return false;
259
260 boost::format fmt("update cryptokeys set active=0 where domain='%s' and id=%d");
261 try {
262 d_dnssecdb->doCommand((fmt % d_dnssecdb->escape(name) % id).str());
263 }
264 catch(SSqlException& se) {
3f81d239 265 throw PDNSException("Error accessing DNSSEC database in BIND backend: "+se.txtReason());
2717b8b3
BH
266 }
267
268 return true;
269}
270
271bool Bind2Backend::getTSIGKey(const string& name, string* algorithm, string* content)
272{
273 if(!d_dnssecdb)
274 return false;
275 boost::format fmt("select algorithm, secret from tsigkeys where name='%s'");
276
277 try {
278 d_dnssecdb->doQuery( (fmt % d_dnssecdb->escape(name)).str());
279 }
280 catch (SSqlException &e) {
3f81d239 281 throw PDNSException("BindBackend unable to retrieve named TSIG key: "+e.txtReason());
2717b8b3
BH
282 }
283
284 SSql::row_t row;
285
286 content->clear();
287 while(d_dnssecdb->getRow(row)) {
288 *algorithm = row[0];
289 *content=row[1];
290 }
291
292 return !content->empty();
293
294}
7e5b2860
AT
295
296bool Bind2Backend::setTSIGKey(const string& name, const string& algorithm, const string& content)
297{
298 if(!d_dnssecdb)
299 return false;
1fc07025 300 boost::format fmt("replace into tsigkeys (name,algorithm,secret) values('%s', '%s', '%s')");
7e5b2860
AT
301 try {
302 d_dnssecdb->doCommand( (fmt % d_dnssecdb->escape(name) % d_dnssecdb->escape(algorithm) % d_dnssecdb->escape(content)).str() );
303 }
304 catch (SSqlException &e) {
a56bc64d 305 throw PDNSException("BindBackend unable to retrieve named TSIG key: "+e.txtReason());
7e5b2860
AT
306 }
307
308 return true;
309}
310
311bool Bind2Backend::deleteTSIGKey(const string& name)
312{
313 if(!d_dnssecdb)
314 return false;
315 boost::format fmt("delete from tsigkeys where name='%s'");
316
317 try {
1fc07025 318 d_dnssecdb->doCommand( (fmt % d_dnssecdb->escape(name)).str() );
7e5b2860
AT
319 }
320 catch (SSqlException &e) {
a56bc64d 321 throw PDNSException("BindBackend unable to retrieve named TSIG key: "+e.txtReason());
7e5b2860
AT
322 }
323
324 return true;
325}
326
327bool Bind2Backend::getTSIGKeys(std::vector< struct TSIGKey > &keys)
328{
329 if(!d_dnssecdb)
330 return false;
331
332 try {
333 d_dnssecdb->doQuery( "select name,algorithm,secret from tsigkeys" );
334 }
335 catch (SSqlException &e) {
a56bc64d 336 throw PDNSException("GSQLBackend unable to retrieve named TSIG key: "+e.txtReason());
7e5b2860
AT
337 }
338
339 SSql::row_t row;
340
341 while(d_dnssecdb->getRow(row)) {
342 struct TSIGKey key;
343 key.name = row[0];
344 key.algorithm = row[1];
345 key.key = row[2];
1fc07025 346 keys.push_back(key);
7e5b2860
AT
347 }
348
1fc07025 349 return !keys.empty();
7e5b2860
AT
350}
351
352
9ca633e6 353#endif