OpenDNSSEC-signer  1.3.14
zone.c
Go to the documentation of this file.
1 /*
2  * $Id: zone.c 7124 2013-05-03 09:49:26Z matthijs $
3  *
4  * Copyright (c) 2009 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "adapter/adapi.h"
35 #include "adapter/adapter.h"
36 #include "scheduler/schedule.h"
37 #include "scheduler/task.h"
38 #include "shared/allocator.h"
39 #include "shared/file.h"
40 #include "shared/hsm.h"
41 #include "shared/locks.h"
42 #include "shared/log.h"
43 #include "shared/status.h"
44 #include "shared/util.h"
45 #include "signer/backup.h"
46 #include "signer/nsec3params.h"
47 #include "signer/signconf.h"
48 #include "signer/zone.h"
49 #include "signer/zonedata.h"
50 
51 #include <ldns/ldns.h>
52 
53 static const char* zone_str = "zone";
54 
55 
60 zone_type*
61 zone_create(char* name, ldns_rr_class klass)
62 {
63  allocator_type* allocator = NULL;
64  zone_type* zone = NULL;
65 
66  if (!name || !klass) {
67  ods_log_error("[%s] unable to create zone: no name or class",
68  zone_str);
69  return NULL;
70  }
71 
72  allocator = allocator_create(malloc, free);
73  if (!allocator) {
74  ods_log_error("[%s] unable to create zone %s: create allocator "
75  "failed", zone_str, name);
76  return NULL;
77  }
78  ods_log_assert(allocator);
79 
80  zone = (zone_type*) allocator_alloc(allocator, sizeof(zone_type));
81  if (!zone) {
82  ods_log_error("[%s] unable to create zone %s: allocator failed",
83  zone_str, name);
84  allocator_cleanup(allocator);
85  return NULL;
86  }
87  ods_log_assert(zone);
88 
89  zone->allocator = allocator;
90  /* [start] PS 9218653: Drop trailing dot in domain name */
91  if (strlen(name) > 1 && name[strlen(name)-1] == '.') {
92  name[strlen(name)-1] = '\0';
93  }
94  /* [end] PS 9218653 */
95  zone->name = allocator_strdup(allocator, name);
96  zone->klass = klass;
97 
98  zone->dname = ldns_dname_new_frm_str(name);
99  ldns_dname2canonical(zone->dname);
100  zone->notify_ns = NULL;
101  zone->policy_name = NULL;
102  zone->signconf_filename = NULL;
103 
104  zone->adinbound = NULL;
105  zone->adoutbound = NULL;
106  zone->nsec3params = NULL;
107 
108  zone->just_added = 0;
109  zone->just_updated = 0;
110  zone->tobe_removed = 0;
111  zone->processed = 0;
112  zone->prepared = 0;
113  zone->fetch = 0;
114 
115  zone->zonedata = zonedata_create(zone->allocator);
116  if (!zone->zonedata) {
117  ods_log_error("[%s] unable to create zone %s: create zonedata "
118  "failed", zone_str, name);
119  zone_cleanup(zone);
120  return NULL;
121  }
122 
123  zone->signconf = signconf_create();
124  if (!zone->signconf) {
125  ods_log_error("[%s] unable to create zone %s: create signconf "
126  "failed", zone_str, name);
127  zone_cleanup(zone);
128  return NULL;
129  }
130 
131  zone->stats = stats_create();
132  zone->task = NULL;
133  lock_basic_init(&zone->zone_lock);
134  zone->zone_locked = 0;
135  return zone;
136 }
137 
138 
144 zone_add_rr(zone_type* zone, ldns_rr* rr, int do_stats)
145 {
146  domain_type* domain = NULL;
147  rrset_type* rrset = NULL;
148  ldns_rdf* soa_min = NULL;
149  ldns_rr_type type = LDNS_RR_TYPE_FIRST;
150  uint32_t tmp = 0;
151 
152  if (!rr) {
153  ods_log_error("[%s] unable to add RR: no RR", zone_str);
154  return ODS_STATUS_ASSERT_ERR;
155  }
156  ods_log_assert(rr);
157 
158  if (!zone || !zone->zonedata) {
159  ods_log_error("[%s] unable to add RR: no storage", zone_str);
160  return ODS_STATUS_ASSERT_ERR;
161  }
162  ods_log_assert(zone);
163  ods_log_assert(zone->zonedata);
164 
165  if (!zone->signconf) {
166  ods_log_error("[%s] unable to add RR: no signconf", zone_str);
167  return ODS_STATUS_ASSERT_ERR;
168  }
169  ods_log_assert(zone->signconf);
170 
171  /* in-zone? */
172  if (ldns_dname_compare(zone->dname, ldns_rr_owner(rr)) != 0 &&
173  !ldns_dname_is_subdomain(ldns_rr_owner(rr), zone->dname)) {
174  ods_log_warning("[%s] zone %s contains out-of-zone data, skipping",
175  zone_str, zone->name?zone->name:"(null)");
176  /* ok, just filter */
177  ldns_rr_free(rr);
178  return ODS_STATUS_OK;
179  }
180 
181  /* type specific configuration */
182  type = ldns_rr_get_type(rr);
183  if (type == LDNS_RR_TYPE_DNSKEY && zone->signconf->dnskey_ttl) {
184  tmp = (uint32_t) duration2time(zone->signconf->dnskey_ttl);
185  ods_log_verbose("[%s] zone %s set DNSKEY TTL to %u",
186  zone_str, zone->name?zone->name:"(null)", tmp);
187  ldns_rr_set_ttl(rr, tmp);
188  }
189  if (type == LDNS_RR_TYPE_SOA) {
190  if (zone->signconf->soa_ttl) {
191  tmp = (uint32_t) duration2time(zone->signconf->soa_ttl);
192  ods_log_verbose("[%s] zone %s set SOA TTL to %u",
193  zone_str, zone->name?zone->name:"(null)", tmp);
194  ldns_rr_set_ttl(rr, tmp);
195  }
196  if (zone->signconf->soa_min) {
197  tmp = (uint32_t) duration2time(zone->signconf->soa_min);
198  ods_log_verbose("[%s] zone %s set SOA MINIMUM to %u",
199  zone_str, zone->name?zone->name:"(null)", tmp);
200  soa_min = ldns_rr_set_rdf(rr,
201  ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, tmp),
203  if (soa_min) {
204  ldns_rdf_deep_free(soa_min);
205  } else {
206  ods_log_error("[%s] zone %s failed to replace SOA MINIMUM "
207  "rdata", zone_str, zone->name?zone->name:"(null)");
208  return ODS_STATUS_ASSERT_ERR;
209  }
210  }
211  }
212 
213  /* lookup domain */
214  domain = zonedata_lookup_domain(zone->zonedata, ldns_rr_owner(rr));
215  if (!domain) {
216  /* add domain */
217  domain = domain_create(ldns_rr_owner(rr));
218  if (!domain) {
219  ods_log_error("[%s] unable to add RR: create domain failed",
220  zone_str);
221  return ODS_STATUS_ERR;
222  }
223  if (zonedata_add_domain(zone->zonedata, domain) == NULL) {
224  ods_log_error("[%s] unable to add RR: add domain failed",
225  zone_str);
226  return ODS_STATUS_ERR;
227  }
228  if (ldns_dname_compare(domain->dname, zone->dname) == 0) {
229  domain->dstatus = DOMAIN_STATUS_APEX;
230  }
231  }
232  ods_log_assert(domain);
233 
234  /* lookup RRset */
235  rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr));
236  if (!rrset) {
237  /* add RRset */
238  rrset = rrset_create(ldns_rr_get_type(rr));
239  if (!rrset) {
240  ods_log_error("[%s] unable to add RR: create RRset failed",
241  zone_str);
242  return ODS_STATUS_ERR;
243  }
244  if (domain_add_rrset(domain, rrset) == NULL) {
245  ods_log_error("[%s] unable to add RR: add RRset failed",
246  zone_str);
247  return ODS_STATUS_ERR;
248  }
249  }
250  ods_log_assert(rrset);
251 
252  /* add RR */
253  if (rrset_add_rr(rrset, rr) == NULL) {
254  ods_log_error("[%s] unable to add RR: pend RR failed", zone_str);
255  return ODS_STATUS_ERR;
256  }
257 
258  /* update stats */
259  if (zone->stats && do_stats) {
260  zone->stats->sort_count += 1;
261  }
262  return ODS_STATUS_OK;
263 }
264 
265 
271 zone_del_rr(zone_type* zone, ldns_rr* rr, int do_stats)
272 {
273  domain_type* domain = NULL;
274  rrset_type* rrset = NULL;
275 
276  if (!rr) {
277  ods_log_error("[%s] unable to del RR: no RR", zone_str);
278  return ODS_STATUS_ASSERT_ERR;
279  }
280  ods_log_assert(rr);
281 
282  if (!zone || !zone->zonedata) {
283  ods_log_error("[%s] unable to del RR: no storage", zone_str);
284  return ODS_STATUS_ASSERT_ERR;
285  }
286  ods_log_assert(zone);
287  ods_log_assert(zone->zonedata);
288 
289  /* lookup domain */
290  domain = zonedata_lookup_domain(zone->zonedata, ldns_rr_owner(rr));
291  if (!domain) {
292  /* no domain, no del */
293  ods_log_warning("[%s] unable to del RR: no such domain", zone_str);
294  return ODS_STATUS_UNCHANGED;
295  }
296  ods_log_assert(domain);
297 
298  /* lookup RRset */
299  rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr));
300  if (!rrset) {
301  /* no RRset, no del */
302  ods_log_warning("[%s] unable to del RR: no such RRset", zone_str);
303  return ODS_STATUS_UNCHANGED;
304  }
305  ods_log_assert(rrset);
306 
307  /* del RR */
308  if (rrset_del_rr(rrset, rr, (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY))
309  == NULL) {
310  ods_log_error("[%s] unable to del RR: pend RR failed", zone_str);
311  return ODS_STATUS_ERR;
312  }
313 
314  /* update stats */
315  if (do_stats && zone->stats) {
316  zone->stats->sort_count -= 1;
317  }
318  return ODS_STATUS_OK;
319 }
320 
321 
326 static ods_status
327 dnskey_withdraw(zone_type* zone, ldns_rr_list* del)
328 {
329  ldns_rr* clone = NULL;
330  ods_status status = ODS_STATUS_OK;
331  size_t i = 0;
332 
333  for (i=0; i < ldns_rr_list_rr_count(del); i++) {
334  clone = ldns_rr_clone(ldns_rr_list_rr(del, i));
335  status = zone_del_rr(zone, clone, 0);
336  if (status != ODS_STATUS_OK) {
337  return status;
338  }
339  }
340  return status;
341 }
342 
343 
348 static ods_status
349 nsec3param_withdraw(zone_type* zone, ldns_rr* rr)
350 {
351  ldns_rr* clone = NULL;
352  ods_status status = ODS_STATUS_OK;
353 
354  if (!rr) { /* no nsec3param, nothing to withdraw */
355  return status;
356  }
357  clone = ldns_rr_clone(rr);
358  status = zone_del_rr(zone, clone, 0);
359  if (status != ODS_STATUS_OK) {
360  return status;
361  }
362  return status;
363 }
364 
365 
372 {
373  ods_status status = ODS_STATUS_OK;
374  signconf_type* signconf = NULL;
375  ldns_rr_list* del = NULL;
376  char* datestamp = NULL;
377  uint32_t ustamp;
378  task_id denial_what;
379  task_id keys_what;
380  task_id what;
381 
382  if (!zone) {
383  ods_log_error("[%s] unable to load signconf: no zone", zone_str);
384  return ODS_STATUS_ASSERT_ERR;
385  }
386  ods_log_assert(zone);
387  if (!zone->signconf_filename) {
388  ods_log_warning("[%s] zone %s has no signconf filename, treat as "
389  "insecure?", zone_str, zone->name);
390  return ODS_STATUS_INSECURE;
391  }
393 
394  status = signconf_update(&signconf, zone->signconf_filename,
395  zone->signconf->last_modified);
396  if (status == ODS_STATUS_OK) {
397  if (!signconf) {
398  /* this is unexpected */
399  ods_log_error("[%s] unable to load signconf: zone %s signconf "
400  "%s: storage empty", zone_str, zone->name,
401  zone->signconf_filename);
402  return ODS_STATUS_ASSERT_ERR;
403  }
404  ustamp = time_datestamp(signconf->last_modified, "%Y-%m-%d %T",
405  &datestamp);
406  ods_log_debug("[%s] zone %s signconf file %s is modified since %s",
407  zone_str, zone->name, zone->signconf_filename,
408  datestamp?datestamp:"Unknown");
409  free((void*)datestamp);
410 
411  /* do stuff */
412  del = ldns_rr_list_new();
413  if (!del) {
414  ods_log_error("[%s] unable to load signconf: zone %s "
415  "signconf %s: ldns_rr_list_new() failed",
416  zone_str, zone->name, zone->signconf_filename);
417  return ODS_STATUS_MALLOC_ERR;
418  }
419  denial_what = signconf_compare_denial(zone->signconf, signconf);
420  keys_what = signconf_compare_keys(zone->signconf, signconf, del);
421 
422  /* Key Rollover? */
423  if (keys_what == TASK_READ) {
424  status = dnskey_withdraw(zone, del);
425  }
426  ldns_rr_list_free(del);
427  if (status != ODS_STATUS_OK) {
428  ods_log_error("[%s] unable to load signconf: zone %s "
429  "signconf %s: failed to delete DNSKEY from RRset",
430  zone_str, zone->name, zone->signconf_filename);
432  return status;
433  }
434 
435  /* Denial of Existence Rollover? */
436  if (denial_what == TASK_NSECIFY) {
437  status = ODS_STATUS_OK;
438  if (denial_what == TASK_NSECIFY && zone->nsec3params) {
439  status = nsec3param_withdraw(zone, zone->nsec3params->rr);
440  }
441  if (status != ODS_STATUS_OK) {
442  ods_log_error("[%s] unable to load signconf: zone %s "
443  "signconf %s: failed to delete NSEC3PARAM RRset",
444  zone_str, zone->name, zone->signconf_filename);
446  return status;
447  }
448  /* or NSEC -> NSEC3, or NSEC3 -> NSEC, or NSEC3PARAM changed */
450  zone->nsec3params = NULL;
451  /* all NSEC(3)s become invalid */
455  }
456 
457  /* all ok, switch to new signconf */
458  if (keys_what != TASK_NONE) {
459  what = keys_what;
460  } else {
461  what = denial_what;
462  }
463  if (what == TASK_NONE) { /* no major changes, continue signing */
464  what = TASK_SIGN;
465  }
466  *tbs = what;
467  ods_log_debug("[%s] tbs for zone %s set to: %s", zone_str,
468  zone->name, task_what2str(*tbs));
469  signconf_cleanup(zone->signconf);
470  ods_log_debug("[%s] zone %s switch to new signconf", zone_str,
471  zone->name);
472  zone->signconf = signconf;
473  signconf_log(zone->signconf, zone->name);
474  zone->zonedata->default_ttl =
475  (uint32_t) duration2time(zone->signconf->soa_min);
476  } else if (status == ODS_STATUS_UNCHANGED) {
477  *tbs = TASK_READ;
478  ods_log_debug("[%s] tbs for zone %s set to: %s", zone_str,
479  zone->name, task_what2str(*tbs));
480  ustamp = time_datestamp(zone->signconf->last_modified,
481  "%Y-%m-%d %T", &datestamp);
482  ods_log_verbose("[%s] zone %s signconf file %s is unchanged since "
483  "%s", zone_str, zone->name, zone->signconf_filename,
484  datestamp?datestamp:"Unknown");
485  free((void*)datestamp);
486  } else {
487  ods_log_error("[%s] unable to load signconf: zone %s signconf %s: "
488  "%s", zone_str, zone->name, zone->signconf_filename,
489  ods_status2str(status));
490  }
491  return status;
492 }
493 
494 
500 zone_publish_dnskeys(zone_type* zone, int recover)
501 {
502  hsm_ctx_t* ctx = NULL;
503  key_type* key = NULL;
504  uint32_t ttl = 0;
505  size_t count = 0;
506  ods_status status = ODS_STATUS_OK;
507  ldns_rr* dnskey = NULL;
508  int do_publish = 0;
509 
510  if (!zone) {
511  ods_log_error("[%s] unable to publish dnskeys: no zone", zone_str);
512  return ODS_STATUS_ASSERT_ERR;
513  }
514  ods_log_assert(zone);
515 
516  if (!zone->signconf) {
517  ods_log_error("[%s] unable to publish dnskeys zone %s: no signconf",
518  zone_str, zone->name);
519  return ODS_STATUS_ASSERT_ERR;
520  }
521  ods_log_assert(zone->signconf);
522 
523  if (!zone->signconf->keys) {
524  ods_log_error("[%s] unable to publish dnskeys zone %s: no keys",
525  zone_str, zone->name);
526  return ODS_STATUS_ASSERT_ERR;
527  }
528  ods_log_assert(zone->signconf->keys);
529 
530  if (!zone->zonedata) {
531  ods_log_error("[%s] unable to publish dnskeys zone %s: no zonedata",
532  zone_str, zone->name);
533  return ODS_STATUS_ASSERT_ERR;
534  }
535  ods_log_assert(zone->zonedata);
536 
537  ttl = zone->zonedata->default_ttl;
538  if (zone->signconf->dnskey_ttl) {
539  ttl = (uint32_t) duration2time(zone->signconf->dnskey_ttl);
540  }
541 
542  /* check connection here? */
543  ctx = hsm_create_context();
544  if (ctx == NULL) {
545  ods_log_error("[%s] unable to publish dnskeys for zone %s: error "
546  "creating libhsm context", zone_str, zone->name);
547  return ODS_STATUS_HSM_ERR;
548  }
549 
550  key = zone->signconf->keys->first_key;
551  for (count=0; count < zone->signconf->keys->count; count++) {
552  if (key->publish) {
553  do_publish = 0;
554  if (!key->dnskey) {
555  do_publish = 1;
556  }
557 
558  status = lhsm_get_key(ctx, zone->dname, key);
559  if (status != ODS_STATUS_OK) {
560  ods_log_error("[%s] unable to publish dnskeys zone %s: "
561  "error creating DNSKEY for key %s", zone_str,
562  zone->name, key->locator?key->locator:"(null)");
563  break;
564  }
565  ods_log_assert(key->dnskey);
566 
567  if (recover) {
568  dnskey = ldns_rr_clone(key->dnskey);
569  status = zone_add_rr(zone, dnskey, 0);
570  } else if (do_publish) {
571  ldns_rr_set_ttl(key->dnskey, ttl);
572  ldns_rr_set_class(key->dnskey, zone->klass);
573  ldns_rr2canonical(key->dnskey);
574  dnskey = ldns_rr_clone(key->dnskey);
575  status = zone_add_rr(zone, dnskey, 0);
576  } else {
577  status = ODS_STATUS_OK;
578  }
579 
580  if (status != ODS_STATUS_OK) {
581  ods_log_error("[%s] unable to publish dnskeys zone %s: "
582  "error adding DNSKEY[%u] for key %s", zone_str,
583  zone->name, ldns_calc_keytag(dnskey),
584  key->locator?key->locator:"(null)");
585  break;
586  }
587  }
588  key = key->next;
589  }
590 
591  if (status != ODS_STATUS_OK) {
593  }
594 
595  hsm_destroy_context(ctx);
596  ctx = NULL;
597  return status;
598 }
599 
600 
606 zone_prepare_nsec3(zone_type* zone, int recover)
607 {
608  ldns_rr* nsec3params_rr = NULL;
609  ods_status status = ODS_STATUS_OK;
610  int doe_rollover = 0;
611 
612  if (!zone) {
613  ods_log_error("[%s] unable to prepare NSEC3: no zone", zone_str);
614  return ODS_STATUS_ASSERT_ERR;
615  }
616  ods_log_assert(zone);
617 
618  if (!zone->signconf) {
619  ods_log_error("[%s] unable to prepare NSEC3: no signconf", zone_str);
620  return ODS_STATUS_ASSERT_ERR;
621  }
622  ods_log_assert(zone->signconf);
623 
624  if (zone->signconf->nsec_type != LDNS_RR_TYPE_NSEC3) {
625  /* no preparations needed */
626  return ODS_STATUS_OK;
627  }
628 
629  if (!zone->nsec3params) {
630  ods_log_debug("[%s] prepare NSEC3 for zone %s", zone_str, zone->name);
631 
633  (uint8_t) zone->signconf->nsec3_algo,
634  (uint8_t) zone->signconf->nsec3_optout,
635  (uint16_t) zone->signconf->nsec3_iterations,
636  zone->signconf->nsec3_salt);
637  doe_rollover = 1;
638  }
639  if (!zone->nsec3params) {
640  ods_log_error("[%s] unable to prepare zone %s for NSEC3: failed "
641  "to create NSEC3 parameters", zone_str, zone->name);
642  return ODS_STATUS_MALLOC_ERR;
643  }
645 
646  if (recover) {
647  nsec3params_rr = ldns_rr_clone(zone->nsec3params->rr);
648  status = zone_add_rr(zone, nsec3params_rr, 0);
649  } else if (doe_rollover) {
650  nsec3params_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS);
651  if (!nsec3params_rr) {
652  ods_log_error("[%s] unable to prepare zone %s for NSEC3: failed "
653  "to create NSEC3PARAM RR", zone_str, zone->name);
655  zone->nsec3params = NULL;
656  return ODS_STATUS_MALLOC_ERR;
657  }
658  ods_log_assert(nsec3params_rr);
659 
660  ldns_rr_set_class(nsec3params_rr, zone->klass);
661  ldns_rr_set_ttl(nsec3params_rr, 0);
662  ldns_rr_set_owner(nsec3params_rr, ldns_rdf_clone(zone->dname));
663  ldns_nsec3_add_param_rdfs(nsec3params_rr,
664  zone->nsec3params->algorithm, 0,
665  zone->nsec3params->iterations,
666  zone->nsec3params->salt_len,
667  zone->nsec3params->salt_data);
672  ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3params_rr, 1)), 7, 0);
673 
674  ldns_rr2canonical(nsec3params_rr);
675  zone->nsec3params->rr = ldns_rr_clone(nsec3params_rr);
676  status = zone_add_rr(zone, nsec3params_rr, 0);
677  }
678 
679  if (status != ODS_STATUS_OK) {
680  ods_log_error("[%s] unable to add NSEC3PARAM RR to zone %s",
681  zone_str, zone->name);
683  zone->nsec3params = NULL;
684  ldns_rr_free(nsec3params_rr);
685  }
686  /* previous nsec3params is already withdrawn during load signconf */
687 
688  return status;
689 }
690 
691 
698 {
699  char* filename = NULL;
700  FILE* fd = NULL;
701 
702  ods_log_assert(zone);
703  ods_log_assert(zone->zonedata);
704  ods_log_assert(zone->signconf);
705 
706  filename = ods_build_path(zone->name, ".backup", 0, 1);
707  fd = ods_fopen(filename, NULL, "w");
708  free((void*)filename);
709 
710  if (fd) {
711  fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC);
713  fprintf(fd, ";;Zone: name %s class %i ttl %u inbound %u internal "
714  "%u outbound %u\n",
715  zone->name?zone->name:"(null)",
716  (int) zone->klass,
717  (unsigned) zone->zonedata->default_ttl,
718  (unsigned) zone->zonedata->inbound_serial,
719  (unsigned) zone->zonedata->internal_serial,
720  (unsigned) zone->zonedata->outbound_serial);
722  if (zone->task) {
723  task_backup(fd, (task_type*) zone->task);
724  }
726  signconf_backup(fd, zone->signconf);
727  fprintf(fd, ";;\n");
729  if (zone->nsec3params) {
731  zone->signconf->nsec3_algo,
732  zone->signconf->nsec3_optout,
733  zone->signconf->nsec3_iterations,
734  zone->signconf->nsec3_salt,
735  zone->nsec3params->rr);
736  }
738  keylist_backup(fd, zone->signconf->keys);
740  zonedata_backup(fd, zone->zonedata);
742  fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC);
743  ods_fclose(fd);
744  } else {
745  return ODS_STATUS_FOPEN_ERR;
746  }
747  return ODS_STATUS_OK;
748 }
749 
750 
757 {
758  char* filename = NULL;
759  FILE* fd = NULL;
760  const char* token = NULL;
761  ods_status status = ODS_STATUS_OK;
762  /* zone part */
763  int klass = 0;
764  uint32_t ttl = 0;
765  uint32_t inbound = 0;
766  uint32_t internal = 0;
767  uint32_t outbound = 0;
768  /* task part */
769  task_type* task = NULL;
770  time_t when = 0;
771  time_t backoff = 0;
772  int what = 0;
773  int interrupt = 0;
774  int halted = 0;
775  int flush = 0;
776  /* signconf part */
777  time_t lastmod = 0;
778  /* nsec3params part */
779  const char* salt = NULL;
780  ldns_rr* nsec3params_rr = NULL;
781  nsec3params_type* nsec3params = NULL;
782  /* keys part */
783  key_type* key = NULL;
784  /* zonedata part */
785  int fetch = 0;
786 
787  ods_log_assert(zone);
788  ods_log_assert(zone->signconf);
789  ods_log_assert(zone->zonedata);
790 
791  filename = ods_build_path(zone->name, ".backup", 0, 1);
792  fd = ods_fopen(filename, NULL, "r");
793  free((void*)filename);
794  if (fd) {
795  /* start recovery */
796  if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC) ||
797  /* zone part */
798  !backup_read_check_str(fd, ";;Zone:") ||
799  !backup_read_check_str(fd, "name") ||
800  !backup_read_check_str(fd, zone->name) ||
801  !backup_read_check_str(fd, "class") ||
802  !backup_read_int(fd, &klass) ||
803  !backup_read_check_str(fd, "ttl") ||
804  !backup_read_uint32_t(fd, &ttl) ||
805  !backup_read_check_str(fd, "inbound") ||
806  !backup_read_uint32_t(fd, &inbound) ||
807  !backup_read_check_str(fd, "internal") ||
808  !backup_read_uint32_t(fd, &internal) ||
809  !backup_read_check_str(fd, "outbound") ||
810  !backup_read_uint32_t(fd, &outbound) ||
811  /* task part */
812  !backup_read_check_str(fd, ";;Task:") ||
813  !backup_read_check_str(fd, "when") ||
814  !backup_read_time_t(fd, &when) ||
815  !backup_read_check_str(fd, "what") ||
816  !backup_read_int(fd, &what) ||
817  !backup_read_check_str(fd, "interrupt") ||
818  !backup_read_int(fd, &interrupt) ||
819  !backup_read_check_str(fd, "halted") ||
820  !backup_read_int(fd, &halted) ||
821  !backup_read_check_str(fd, "backoff") ||
822  !backup_read_time_t(fd, &backoff) ||
823  !backup_read_check_str(fd, "flush") ||
824  !backup_read_int(fd, &flush) ||
825  /* signconf part */
826  !backup_read_check_str(fd, ";;Signconf:") ||
827  !backup_read_check_str(fd, "lastmod") ||
828  !backup_read_time_t(fd, &lastmod) ||
829  !backup_read_check_str(fd, "resign") ||
831  &zone->signconf->sig_resign_interval) ||
832  !backup_read_check_str(fd, "refresh") ||
834  &zone->signconf->sig_refresh_interval) ||
835  !backup_read_check_str(fd, "valid") ||
837  &zone->signconf->sig_validity_default) ||
838  !backup_read_check_str(fd, "denial") ||
840  &zone->signconf->sig_validity_denial) ||
841  !backup_read_check_str(fd, "jitter") ||
842  !backup_read_duration(fd, &zone->signconf->sig_jitter) ||
843  !backup_read_check_str(fd, "offset") ||
845  &zone->signconf->sig_inception_offset) ||
846  !backup_read_check_str(fd, "nsec") ||
847  !backup_read_rr_type(fd, &zone->signconf->nsec_type) ||
848  !backup_read_check_str(fd, "dnskeyttl") ||
849  !backup_read_duration(fd, &zone->signconf->dnskey_ttl) ||
850  !backup_read_check_str(fd, "soattl") ||
851  !backup_read_duration(fd, &zone->signconf->soa_ttl) ||
852  !backup_read_check_str(fd, "soamin") ||
853  !backup_read_duration(fd, &zone->signconf->soa_min) ||
854  !backup_read_check_str(fd, "serial") ||
855  !backup_read_str(fd, &zone->signconf->soa_serial) ||
856  !backup_read_check_str(fd, "audit") ||
857  !backup_read_int(fd, &zone->signconf->audit) ||
858  !backup_read_check_str(fd, ";;")) {
859  goto recover_error;
860  }
861  /* nsec3params part */
862  if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) {
863  if (!backup_read_check_str(fd, ";;Nsec3parameters:") ||
864  !backup_read_check_str(fd, "salt") ||
865  !backup_read_str(fd, &salt) ||
866  !backup_read_check_str(fd, "algorithm") ||
867  !backup_read_uint32_t(fd, &zone->signconf->nsec3_algo) ||
868  !backup_read_check_str(fd, "optout") ||
869  !backup_read_int(fd, &zone->signconf->nsec3_optout) ||
870  !backup_read_check_str(fd, "iterations") ||
872  &zone->signconf->nsec3_iterations) ||
873  ldns_rr_new_frm_fp(&nsec3params_rr, fd, NULL, NULL, NULL) ||
874  !backup_read_check_str(fd, ";;Nsec3done") ||
875  !backup_read_check_str(fd, ";;")) {
876  goto recover_error;
877  }
878  }
879  /* keys part */
880  zone->signconf->keys = keylist_create(zone->signconf->allocator);
881  while (backup_read_str(fd, &token)) {
882  if (ods_strcmp(token, ";;Key:") == 0) {
883  key = key_recover(fd, zone->signconf->allocator);
884  if (!key || keylist_push(zone->signconf->keys, key) !=
885  ODS_STATUS_OK) {
886  goto recover_error;
887  }
888  key = NULL;
889  } else if (ods_strcmp(token, ";;") == 0) {
890  /* keylist done */
891  free((void*) token);
892  token = NULL;
893  break;
894  } else {
895  /* keylist corrupted */
896  goto recover_error;
897  }
898  free((void*) token);
899  token = NULL;
900  }
901  /* zonedata part */
902  filename = ods_build_path(zone->name, ".inbound", 0, 1);
903  status = adbackup_read(zone, filename);
904  free((void*)filename);
905  if (status != ODS_STATUS_OK) {
906  goto recover_error;
907  }
908 
909  zone->klass = (ldns_rr_class) klass;
910  zone->zonedata->default_ttl = ttl;
911  zone->zonedata->inbound_serial = inbound;
912  zone->zonedata->internal_serial = internal;
913  zone->zonedata->outbound_serial = outbound;
915  zone->signconf->allocator, salt);
916  free((void*) salt);
917  salt = NULL;
918  task = task_create((task_id) what, when, zone->name, (void*) zone);
919  if (!task) {
920  goto recover_error;
921  }
922  if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) {
923  nsec3params = nsec3params_create(zone->signconf->nsec3_algo,
924  zone->signconf->nsec3_optout,
925  zone->signconf->nsec3_iterations,
926  zone->signconf->nsec3_salt);
927  if (!nsec3params) {
928  goto recover_error;
929  }
930  nsec3params->rr = nsec3params_rr;
931  zone->nsec3params = nsec3params;
932  }
933  zone->task = (void*) task;
934  zone->signconf->last_modified = lastmod;
935 
941  status = zone_publish_dnskeys(zone, 1);
942  if (status != ODS_STATUS_OK) {
943  zone->task = NULL;
944  zone->nsec3params = NULL;
945  goto recover_error;
946  }
947  status = zone_prepare_nsec3(zone, 1);
948  if (status != ODS_STATUS_OK) {
949  zone->task = NULL;
950  zone->nsec3params = NULL;
951  goto recover_error;
952  }
953  status = zonedata_commit(zone->zonedata);
954  if (status != ODS_STATUS_OK) {
955  zone->task = NULL;
956  zone->nsec3params = NULL;
957  goto recover_error;
958  }
959  status = zonedata_entize(zone->zonedata, zone->dname);
960  if (status != ODS_STATUS_OK) {
961  zone->task = NULL;
962  zone->nsec3params = NULL;
963  goto recover_error;
964  }
965  status = zonedata_recover(zone->zonedata, fd);
966  if (status != ODS_STATUS_OK) {
967  zone->task = NULL;
968  zone->nsec3params = NULL;
969  goto recover_error;
970  }
971  ods_fclose(fd);
972 
973  /* all ok */
974  zone->zonedata->initialized = 1;
975  zone->prepared = 1;
976  if (zone->stats) {
979  stats_clear(zone->stats);
981  zone->stats->stats_locked = 0;
982  }
983  return ODS_STATUS_OK;
984  } else {
985  /* backwards compatible backup recovery (serial) */
986  filename = ods_build_path(zone->name, ".state", 0, 1);
987  fd = ods_fopen(filename, NULL, "r");
988  free((void*)filename);
989  if (fd) {
990  if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1) ||
991  !backup_read_check_str(fd, ";name:") ||
992  !backup_read_check_str(fd, zone->name) ||
993  !backup_read_check_str(fd, ";class:") ||
994  !backup_read_int(fd, &klass) ||
995  !backup_read_check_str(fd, ";fetch:") ||
996  !backup_read_int(fd, &fetch) ||
997  !backup_read_check_str(fd, ";default_ttl:") ||
998  !backup_read_uint32_t(fd, &ttl) ||
999  !backup_read_check_str(fd, ";inbound_serial:") ||
1000  !backup_read_uint32_t(fd, &inbound) ||
1001  !backup_read_check_str(fd, ";internal_serial:") ||
1002  !backup_read_uint32_t(fd, &internal) ||
1003  !backup_read_check_str(fd, ";outbound_serial:") ||
1004  !backup_read_uint32_t(fd, &outbound) ||
1005  !backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1))
1006  {
1007  goto recover_error;
1008  }
1009  zone->klass = (ldns_rr_class) klass;
1010  zone->zonedata->default_ttl = ttl;
1011  zone->zonedata->inbound_serial = inbound;
1012  zone->zonedata->internal_serial = internal;
1013  zone->zonedata->outbound_serial = outbound;
1014  /* all ok */
1015  zone->zonedata->initialized = 1;
1016  zone->prepared = 1;
1017  if (zone->stats) {
1018  lock_basic_lock(&zone->stats->stats_lock);
1020  stats_clear(zone->stats);
1022  zone->stats->stats_locked = 0;
1023  }
1024  return ODS_STATUS_UNCHANGED;
1025  }
1026  ods_fclose(fd);
1027  }
1028 
1029  return ODS_STATUS_UNCHANGED;
1030 
1031 recover_error:
1032  ods_log_error("[%s] unable to recover zone %s: corrupted file",
1033  zone_str, zone->name);
1034  ods_fclose(fd);
1035 
1036  /* signconf cleanup */
1037  signconf_cleanup(zone->signconf);
1038  zone->signconf = signconf_create();
1039  ods_log_assert(zone->signconf);
1040 
1041  /* task cleanup */
1042  task_cleanup(task);
1043  task = NULL;
1044 
1045  /* nsec3params cleanup */
1046  free((void*)salt);
1047  salt = NULL;
1048 
1049  ldns_rr_free(nsec3params_rr);
1050  nsec3params_rr = NULL;
1051  if (nsec3params) {
1052  nsec3params->rr = NULL;
1053  }
1054  nsec3params_cleanup(nsec3params);
1055  nsec3params = NULL;
1056 
1057  /* zonedata cleanup */
1058  zonedata_cleanup(zone->zonedata);
1059  zone->zonedata = zonedata_create(zone->allocator);
1060  ods_log_assert(zone->zonedata);
1061  /* do keep serial information */
1062  zone->zonedata->inbound_serial = inbound;
1063  zone->zonedata->internal_serial = internal;
1064  zone->zonedata->outbound_serial = outbound;
1065  zone->zonedata->initialized = 1;
1066 
1067  if (zone->stats) {
1068  lock_basic_lock(&zone->stats->stats_lock);
1070  stats_clear(zone->stats);
1072  zone->stats->stats_locked = 0;
1073  }
1074  return ODS_STATUS_ERR;
1075 }
1076 
1077 
1082 void
1084 {
1085  const char* str;
1086  adapter_type* adtmp = NULL;
1087 
1088  if (!z1 || !z2) {
1089  return;
1090  }
1091 
1092  /* policy name */
1093  if (ods_strcmp(z2->policy_name, z1->policy_name) != 0) {
1094  if (z2->policy_name) {
1095  str = strdup(z2->policy_name);
1096  if (!str) {
1097  ods_log_error("[%s] failed to merge policy %s name to zone "
1098  "%s", zone_str, z2->policy_name, z1->name);
1099  } else {
1100  free((void*)z1->policy_name);
1101  z1->policy_name = str;
1102  z1->just_updated = 1;
1103  }
1104  } else {
1105  free((void*)z1->policy_name);
1106  z1->policy_name = NULL;
1107  z1->just_updated = 1;
1108  }
1109  }
1110 
1111  /* signconf filename */
1112  if (ods_strcmp(z2->signconf_filename, z1->signconf_filename) != 0) {
1113  if (z2->signconf_filename) {
1114  str = strdup(z2->signconf_filename);
1115  if (!str) {
1116  ods_log_error("[%s] failed to merge signconf filename %s to "
1117  "zone %s", zone_str, z2->policy_name, z1->name);
1118  } else {
1119  free((void*)z1->signconf_filename);
1120  z1->signconf_filename = str;
1121  z1->just_updated = 1;
1122  }
1123  } else {
1124  free((void*)z1->signconf_filename);
1125  z1->signconf_filename = NULL;
1126  z1->just_updated = 1;
1127  }
1128  }
1129 
1130  /* adapters */
1131  if (adapter_compare(z2->adinbound, z1->adinbound) != 0) {
1132  adtmp = z2->adinbound;
1133  z2->adinbound = z1->adinbound;
1134  z1->adinbound = adtmp;
1135  adtmp = NULL;
1136  }
1137  if (adapter_compare(z2->adoutbound, z1->adoutbound) != 0) {
1138  adtmp = z2->adoutbound;
1139  z2->adoutbound = z1->adoutbound;
1140  z1->adoutbound = adtmp;
1141  adtmp = NULL;
1142  }
1143  return;
1144 }
1145 
1146 
1151 ods_status
1153 {
1154  ods_status status = ODS_STATUS_OK;
1155  domain_type* domain = NULL;
1156  rrset_type* rrset = NULL;
1157  ldns_rdf* serial = NULL;
1158 
1159  if (!zone) {
1160  ods_log_error("[%s] unable to update serial: no zone",
1161  zone_str);
1162  return ODS_STATUS_ASSERT_ERR;
1163  }
1164  ods_log_assert(zone);
1165 
1166  if (!zone->signconf) {
1167  ods_log_error("[%s] unable to update serial: no signconf",
1168  zone_str);
1169  return ODS_STATUS_ASSERT_ERR;
1170  }
1171  ods_log_assert(zone->signconf);
1172 
1173  if (!zone->zonedata) {
1174  ods_log_error("[%s] unable to update serial: no zonedata",
1175  zone_str);
1176  return ODS_STATUS_ASSERT_ERR;
1177  }
1178  ods_log_assert(zone->zonedata);
1179 
1180  status = zonedata_update_serial(zone->zonedata, zone->signconf);
1181  if (status != ODS_STATUS_OK) {
1182  ods_log_error("[%s] unable to update serial: failed to increment",
1183  zone_str);
1184  return status;
1185  }
1186 
1187  /* lookup domain */
1188  domain = zonedata_lookup_domain(zone->zonedata, zone->dname);
1189  if (!domain) {
1190  ods_log_error("[%s] unable to update serial: apex not found",
1191  zone_str);
1192  return ODS_STATUS_ERR;
1193  }
1194  ods_log_assert(domain);
1195 
1196  /* lookup RRset */
1197  rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA);
1198  if (!rrset) {
1199  ods_log_error("[%s] unable to update serial: SOA RRset not found",
1200  zone_str);
1201  return ODS_STATUS_ERR;
1202  }
1203  ods_log_assert(rrset);
1204  ods_log_assert(rrset->rr_type == LDNS_RR_TYPE_SOA);
1205 
1206  if (rrset->rrs && rrset->rrs->rr) {
1207  serial = ldns_rr_set_rdf(rrset->rrs->rr,
1208  ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
1210  if (serial) {
1211  if (ldns_rdf2native_int32(serial) !=
1212  zone->zonedata->internal_serial) {
1213  rrset->needs_signing = 1;
1214  }
1215  ldns_rdf_deep_free(serial);
1216  } else {
1217  ods_log_error("[%s] unable to update serial: failed to replace "
1218  "SOA SERIAL rdata", zone_str);
1219  return ODS_STATUS_ERR;
1220  }
1221  }
1222  return ODS_STATUS_OK;
1223 }
1224 
1225 
1230 ods_status
1231 zone_print(FILE* fd, zone_type* zone)
1232 {
1233  if (fd && zone && zone->zonedata) {
1234  return zonedata_print(fd, zone->zonedata);
1235  }
1236  return ODS_STATUS_ASSERT_ERR;
1237 }
1238 
1239 
1244 ods_status
1246 {
1247  if (zone && zone->zonedata && zone->adinbound) {
1248  return zonedata_examine(zone->zonedata, zone->dname,
1249  zone->adinbound->type);
1250  }
1251  return ODS_STATUS_ASSERT_ERR;
1252 }
1253 
1254 
1259 void
1261 {
1262  allocator_type* allocator;
1263  lock_basic_type zone_lock;
1264 
1265  if (!zone) {
1266  return;
1267  }
1268 
1269  allocator = zone->allocator;
1270  zone_lock = zone->zone_lock;
1271 
1272  ldns_rdf_deep_free(zone->dname);
1273  adapter_cleanup(zone->adinbound);
1274  adapter_cleanup(zone->adoutbound);
1275  zonedata_cleanup(zone->zonedata);
1276  signconf_cleanup(zone->signconf);
1278  stats_cleanup(zone->stats);
1279  allocator_deallocate(allocator, (void*) zone->notify_ns);
1280  allocator_deallocate(allocator, (void*) zone->policy_name);
1281  allocator_deallocate(allocator, (void*) zone->signconf_filename);
1282  allocator_deallocate(allocator, (void*) zone->name);
1283  allocator_deallocate(allocator, (void*) zone);
1284  allocator_cleanup(allocator);
1285  lock_basic_destroy(&zone_lock);
1286  return;
1287 }