root/trunk/pdns/pdns/dbdnsseckeeper.cc @ 1878

Revision 1878, 7.5 KB (checked in by ahu, 2 years ago)

oops, put the NSEC3NARROW item in the NSEC3PARAM cache

Line 
1/*
2    PowerDNS Versatile Database Driven Nameserver
3    Copyright (C) 2001 - 2011  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 as
7    published by the Free Software Foundation
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17*/
18
19#include "dnsseckeeper.hh"
20#include "dnssecinfra.hh"
21#include "ueberbackend.hh"
22#include "statbag.hh"
23#include <iostream>
24#include <boost/foreach.hpp>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <fstream>
28#include <boost/algorithm/string.hpp>
29#include <boost/format.hpp>
30#include <boost/assign/std/vector.hpp> // for 'operator+=()'
31#include <boost/assign/list_inserter.hpp>
32
33
34using namespace boost::assign;
35using namespace std;
36using namespace boost;
37
38DNSSECKeeper::keycache_t DNSSECKeeper::s_keycache;
39DNSSECKeeper::nseccache_t DNSSECKeeper::s_nseccache;
40pthread_mutex_t DNSSECKeeper::s_nseccachelock = PTHREAD_MUTEX_INITIALIZER;
41pthread_mutex_t DNSSECKeeper::s_keycachelock = PTHREAD_MUTEX_INITIALIZER;
42
43bool DNSSECKeeper::haveActiveKSKFor(const std::string& zone) 
44{
45  {
46    Lock l(&s_keycachelock);
47    keycache_t::const_iterator iter = s_keycache.find(zone);
48    if(iter != s_keycache.end() && iter->d_ttd > time(0)) { 
49      if(iter->d_keys.empty())
50        return false;
51      else
52        return true;
53    }
54    else
55      ; 
56  }
57  keyset_t keys = getKeys(zone, true);
58 
59  BOOST_FOREACH(keyset_t::value_type& val, keys) {
60    if(val.second.active) {
61      return true;
62    }
63  }
64  return false;
65}
66
67
68void DNSSECKeeper::addKey(const std::string& name, bool keyOrZone, int algorithm, int bits, bool active)
69{
70  if(!bits)
71    bits = keyOrZone ? 2048 : 1024;
72  DNSSECPrivateKey dpk;
73  dpk.d_key.create(bits); 
74  dpk.d_algorithm = algorithm;
75  dpk.d_flags = keyOrZone ? 257 : 256;
76  addKey(name, dpk, active);
77}
78
79void DNSSECKeeper::addKey(const std::string& name, const DNSSECPrivateKey& dpk, bool active)
80{
81  DNSBackend::KeyData kd;
82  kd.flags = dpk.d_flags; // the dpk doesn't get stored, only they key part
83  kd.active = active;
84  kd.content = dpk.d_key.convertToISC(dpk.d_algorithm);
85 // now store it
86  d_db.addDomainKey(name, kd);
87}
88
89
90static bool keyCompareByKindAndID(const DNSSECKeeper::keyset_t::value_type& a, const DNSSECKeeper::keyset_t::value_type& b)
91{
92  return make_pair(!a.second.keyOrZone, a.second.id) <
93         make_pair(!b.second.keyOrZone, b.second.id);
94}
95
96DNSSECPrivateKey DNSSECKeeper::getKeyById(const std::string& zname, unsigned int id)
97{ 
98  vector<DNSBackend::KeyData> keys;
99  d_db.getDomainKeys(zname, 0, keys);
100  BOOST_FOREACH(const DNSBackend::KeyData& kd, keys) {
101    if(kd.id != id) 
102      continue;
103   
104    DNSSECPrivateKey dpk;
105    DNSKEYRecordContent dkrc = getRSAKeyFromISCString(&dpk.d_key.getContext(), kd.content);
106    dpk.d_flags = kd.flags;
107    dpk.d_algorithm = dkrc.d_algorithm;
108   
109    if(dpk.d_algorithm == 5 && getNSEC3PARAM(zname)) {
110      dpk.d_algorithm += 2;
111    }
112   
113    return dpk;   
114  }
115  throw runtime_error("Can't find a key with id "+lexical_cast<string>(id)+" for zone '"+zname+"'");
116}
117
118
119void DNSSECKeeper::removeKey(const std::string& zname, unsigned int id)
120{
121  d_db.removeDomainKey(zname, id);
122}
123
124void DNSSECKeeper::deactivateKey(const std::string& zname, unsigned int id)
125{
126  d_db.deactivateDomainKey(zname, id);
127}
128
129void DNSSECKeeper::activateKey(const std::string& zname, unsigned int id)
130{
131  d_db.activateDomainKey(zname, id);
132}
133
134bool DNSSECKeeper::getNSEC3PARAM(const std::string& zname, NSEC3PARAMRecordContent* ns3p, bool* narrow)
135{
136  time_t now = time(0);
137  {
138    Lock l(&s_nseccachelock); 
139   
140    nseccache_t::const_iterator iter = s_nseccache.find(zname);
141    if(iter != s_nseccache.end() && iter->d_ttd > now)
142    {
143      if(iter->d_nsec3param.empty()) // this says: no NSEC3
144        return false;
145       
146      if(ns3p) {
147        NSEC3PARAMRecordContent* tmp=dynamic_cast<NSEC3PARAMRecordContent*>(DNSRecordContent::mastermake(QType::NSEC3PARAM, 1, iter->d_nsec3param));
148        *ns3p = *tmp;
149        delete tmp;
150      }
151      if(narrow)
152        *narrow = iter->d_narrow;
153      return true;
154    }
155  }
156  vector<string> meta;
157  d_db.getDomainMetadata(zname, "NSEC3PARAM", meta);
158 
159  NSECCacheEntry nce;
160  nce.d_domain=zname;
161  nce.d_ttd = now+60;
162 
163  if(meta.empty()) {
164    nce.d_nsec3param.clear(); // store 'no nsec3'
165    nce.d_narrow = false;
166    Lock l(&s_nseccachelock);
167    replacing_insert(s_nseccache, nce);
168   
169    return false;
170  }
171  nce.d_nsec3param = *meta.begin();
172 
173  meta.clear();
174  d_db.getDomainMetadata(zname, "NSEC3NARROW", meta);
175  nce.d_narrow = !meta.empty() && meta[1]=="1";
176 
177  if(narrow) {
178    *narrow=nce.d_narrow;
179  }
180 
181  if(ns3p) {
182    string descr = nce.d_nsec3param;
183    reportAllTypes();
184    NSEC3PARAMRecordContent* tmp=dynamic_cast<NSEC3PARAMRecordContent*>(DNSRecordContent::mastermake(QType::NSEC3PARAM, 1, descr));
185    if(!tmp) {
186      cerr<<"descr: '"<<descr<<"'\n";
187      return false;
188    }
189    *ns3p = *tmp;
190    delete tmp;
191  }
192  Lock l(&s_nseccachelock);
193  replacing_insert(s_nseccache, nce);
194 
195  return true;
196}
197
198void DNSSECKeeper::setNSEC3PARAM(const std::string& zname, const NSEC3PARAMRecordContent& ns3p, const bool& narrow)
199{
200  string descr = ns3p.getZoneRepresentation();
201  vector<string> meta;
202  meta.push_back(descr);
203  d_db.setDomainMetadata(zname, "NSEC3PARAM", meta);
204 
205  meta.clear();
206  if(narrow)
207    meta.push_back("1");
208  d_db.setDomainMetadata(zname, "NSEC3NARROW", meta);
209}
210
211void DNSSECKeeper::unsetNSEC3PARAM(const std::string& zname)
212{
213  d_db.setDomainMetadata(zname, "NSEC3PARAM", vector<string>());
214}
215
216
217DNSSECKeeper::keyset_t DNSSECKeeper::getKeys(const std::string& zone, boost::tribool allOrKeyOrZone) 
218{
219  time_t now = time(0);
220  {
221    Lock l(&s_keycachelock);
222    keycache_t::const_iterator iter = s_keycache.find(zone);
223   
224    if(iter != s_keycache.end() && iter->d_ttd > now) { 
225      keyset_t ret;
226      BOOST_FOREACH(const keyset_t::value_type& value, iter->d_keys) {
227        if(boost::indeterminate(allOrKeyOrZone) || allOrKeyOrZone == value.second.keyOrZone)
228          ret.push_back(value);
229      }
230      return ret;
231    }
232  }
233 
234  keyset_t retkeyset, allkeyset;
235  vector<UeberBackend::KeyData> dbkeyset;
236 
237  d_db.getDomainKeys(zone, 0, dbkeyset);
238 
239  BOOST_FOREACH(UeberBackend::KeyData& kd, dbkeyset) 
240  {
241    DNSSECPrivateKey dpk;
242
243    DNSKEYRecordContent dkrc=getRSAKeyFromISCString(&dpk.d_key.getContext(), kd.content);
244    dpk.d_flags = kd.flags;
245    dpk.d_algorithm = dkrc.d_algorithm;
246    if(dpk.d_algorithm == 5 && getNSEC3PARAM(zone))
247      dpk.d_algorithm+=2;
248   
249    KeyMetaData kmd;
250
251    kmd.active = kd.active;
252    kmd.keyOrZone = (kd.flags == 257);
253    kmd.id = kd.id;
254   
255    if(boost::indeterminate(allOrKeyOrZone) || allOrKeyOrZone == kmd.keyOrZone)
256      retkeyset.push_back(make_pair(dpk, kmd));
257    allkeyset.push_back(make_pair(dpk, kmd));
258  }
259  sort(retkeyset.begin(), retkeyset.end(), keyCompareByKindAndID);
260  sort(allkeyset.begin(), allkeyset.end(), keyCompareByKindAndID);
261  Lock l(&s_keycachelock);
262 
263  KeyCacheEntry kce;
264  kce.d_domain=zone;
265  kce.d_keys = allkeyset;
266  kce.d_ttd = now + 30;
267  replacing_insert(s_keycache, kce);
268 
269  return retkeyset;
270}
271
272void DNSSECKeeper::secureZone(const std::string& name, int algorithm)
273{
274  addKey(name, true, algorithm);
275}
Note: See TracBrowser for help on using the browser.