OpenDNSSEC-signer  1.4.5
backup.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006-2010 NLNet Labs. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
32 #include "config.h"
33 #include "adapter/adapi.h"
34 #include "adapter/adutil.h"
35 #include "shared/duration.h"
36 #include "shared/file.h"
37 #include "shared/log.h"
38 #include "shared/status.h"
39 #include "shared/util.h"
40 #include "signer/backup.h"
41 #include "signer/zone.h"
42 
43 #include <ldns/ldns.h>
44 
45 static const char* backup_str = "backup";
46 
47 
52 char*
54 {
55  static char buf[4000];
56  buf[sizeof(buf)-1]=0;
57 
58  while (1) {
59  if (fscanf(in, "%3990s", buf) != 1) {
60  return 0;
61  }
62  if (buf[0] != '#') {
63  return buf;
64  }
65  if (!fgets(buf, sizeof(buf), in)) {
66  return 0;
67  }
68  }
69  return 0;
70 }
71 
76 int
77 backup_read_check_str(FILE* in, const char* str)
78 {
79  char *p = backup_read_token(in);
80  if (!p) {
81  ods_log_debug("[%s] cannot read check string \'%s\'", backup_str, str);
82  return 0;
83  }
84  if (ods_strcmp(p, str) != 0) {
85  ods_log_debug("[%s] \'%s\' does not match \'%s\'", backup_str, p, str);
86  return 0;
87  }
88  return 1;
89 }
90 
91 
96 int
97 backup_read_str(FILE* in, const char** str)
98 {
99  char *p = backup_read_token(in);
100  if (!p) {
101  ods_log_debug("[%s] cannot read string", backup_str);
102  return 0;
103  }
104  *str = strdup(p);
105  return 1;
106 }
107 
108 
113 int
114 backup_read_time_t(FILE* in, time_t* v)
115 {
116  char* p = backup_read_token(in);
117  if (!p) {
118  ods_log_debug("[%s] cannot read time", backup_str);
119  return 0;
120  }
121  *v=atol(p);
122  return 1;
123 }
124 
125 
130 int
132 {
133  char* p = backup_read_token(in);
134  if (!p) {
135  ods_log_debug("[%s] cannot read duration", backup_str);
136  return 0;
137  }
138  *v=duration_create_from_string((const char*) p);
139  return 1;
140 }
141 
142 
147 int
148 backup_read_rr_type(FILE* in, ldns_rr_type* v)
149 {
150  char* p = backup_read_token(in);
151  if (!p) {
152  ods_log_debug("[%s] cannot read rr type", backup_str);
153  return 0;
154  }
155  *v=(ldns_rr_type) atoi(p);
156  return 1;
157 }
158 
159 
164 int
165 backup_read_int(FILE* in, int* v)
166 {
167  char* p = backup_read_token(in);
168  if (!p) {
169  ods_log_debug("[%s] cannot read integer", backup_str);
170  return 0;
171  }
172  *v=atoi(p);
173  return 1;
174 }
175 
176 
181 int
182 backup_read_size_t(FILE* in, size_t* v)
183 {
184  char* p = backup_read_token(in);
185  if (!p) {
186  ods_log_debug("[%s] cannot read size_t", backup_str);
187  return 0;
188  }
189  *v=(size_t)atoi(p);
190  return 1;
191 }
192 
193 
198 int
199 backup_read_uint8_t(FILE* in, uint8_t* v)
200 {
201  char* p = backup_read_token(in);
202  if (!p) {
203  ods_log_debug("[%s] cannot read uint8_t", backup_str);
204  return 0;
205  }
206  *v= (uint8_t)atoi(p);
207  return 1;
208 }
209 
210 
215 int
216 backup_read_uint16_t(FILE* in, uint16_t* v)
217 {
218  char* p = backup_read_token(in);
219  if (!p) {
220  ods_log_debug("[%s] cannot read uint16_t", backup_str);
221  return 0;
222  }
223  *v= (uint16_t)atoi(p);
224  return 1;
225 }
226 
227 
232 int
233 backup_read_uint32_t(FILE* in, uint32_t* v)
234 {
235  char* p = backup_read_token(in);
236  if (!p) {
237  ods_log_debug("[%s] cannot read uint32_t", backup_str);
238  return 0;
239  }
240  *v= (uint32_t)atol(p);
241  return 1;
242 }
243 
244 
249 static ldns_rr*
250 backup_read_rr(FILE* in, zone_type* zone, char* line, ldns_rdf** orig,
251  ldns_rdf** prev, ldns_status* status, unsigned int* l)
252 {
253  ldns_rr* rr = NULL;
254  int len = 0;
255 backup_read_line:
256  len = adutil_readline_frm_file(in, line, l, 1);
257  if (len >= 0) {
258  switch (line[0]) {
259  case ';':
260  /* done */
261  *status = LDNS_STATUS_OK;
262  return NULL;
263  break;
264  case '\n':
265  case '\0':
266  goto backup_read_line; /* perhaps next line is rr */
267  break;
268  /* let's hope its a RR */
269  default:
270  *status = ldns_rr_new_frm_str(&rr, line, zone->default_ttl,
271  *orig, prev);
272  if (*status == LDNS_STATUS_OK) {
273  return rr;
274  } else if (*status == LDNS_STATUS_SYNTAX_EMPTY) {
275  if (rr) {
276  ldns_rr_free(rr);
277  rr = NULL;
278  }
279  *status = LDNS_STATUS_OK;
280  goto backup_read_line; /* perhaps next line is rr */
281  break;
282  } else {
283  ods_log_error("[%s] error parsing RR #%i (%s): %s",
284  backup_str, l&&*l?*l:0,
285  ldns_get_errorstr_by_id(*status), line);
286  if (rr) {
287  ldns_rr_free(rr);
288  rr = NULL;
289  }
290  return NULL;
291  }
292  break;
293  }
294  }
295  /* -1, EOF */
296  *status = LDNS_STATUS_OK;
297  return NULL;
298 }
299 
300 
305 static char*
306 replace_space_with_nul(char* str)
307 {
308  int i = 0;
309  if (!str) {
310  return NULL;
311  }
312  i = strlen(str);
313  while (i>0) {
314  --i;
315  if (str[i] == ' ') {
316  str[i] = '\0';
317  }
318  }
319  return strdup(str);
320 }
321 
322 
328 backup_read_namedb(FILE* in, void* zone)
329 {
330  zone_type* z = (zone_type*) zone;
331  denial_type* denial = NULL;
332  rrset_type* rrset = NULL;
333  ods_status result = ODS_STATUS_OK;
334  ldns_rr_type type_covered;
335  ldns_rr* rr = NULL;
336  ldns_rdf* prev = NULL;
337  ldns_rdf* orig = NULL;
338  ldns_rdf* dname = NULL;
339  ldns_status status = LDNS_STATUS_OK;
340  char line[SE_ADFILE_MAXLINE];
341  char* str = NULL;
342  char* locator = NULL;
343  uint32_t flags = 0;
344  unsigned int l = 0;
345 
346  ods_log_assert(in);
347  ods_log_assert(z);
348 
349  /* $ORIGIN <zone name> */
350  dname = adapi_get_origin(z);
351  if (!dname) {
352  ods_log_error("[%s] error getting default value for $ORIGIN",
353  backup_str);
354  return ODS_STATUS_ERR;
355  }
356  orig = ldns_rdf_clone(dname);
357  if (!orig) {
358  ods_log_error("[%s] error setting default value for $ORIGIN",
359  backup_str);
360  return ODS_STATUS_ERR;
361  }
362  /* read RRs */
363  ods_log_debug("[%s] read RRs %s", backup_str, z->name);
364  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
365  != NULL) {
366  /* check status */
367  if (status != LDNS_STATUS_OK) {
368  ods_log_error("[%s] error reading RR #%i (%s): %s",
369  backup_str, l, ldns_get_errorstr_by_id(status), line);
370  result = ODS_STATUS_ERR;
371  goto backup_namedb_done;
372  }
373  /* add to the database */
374  result = adapi_add_rr(z, rr, 1);
375  if (result == ODS_STATUS_UNCHANGED) {
376  ods_log_debug("[%s] skipping RR #%i (duplicate): %s",
377  backup_str, l, line);
378  ldns_rr_free(rr);
379  rr = NULL;
380  result = ODS_STATUS_OK;
381  continue;
382  } else if (result != ODS_STATUS_OK) {
383  ods_log_error("[%s] error adding RR #%i: %s",
384  backup_str, l, line);
385  ldns_rr_free(rr);
386  rr = NULL;
387  goto backup_namedb_done;
388  }
389  }
390  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
391  ods_log_error("[%s] error reading RR #%i (%s): %s",
392  backup_str, l, ldns_get_errorstr_by_id(status), line);
393  result = ODS_STATUS_ERR;
394  goto backup_namedb_done;
395  }
396  namedb_diff(z->db, 0, 0);
397 
398  /* read NSEC(3)s */
399  ods_log_debug("[%s] read NSEC(3)s %s", backup_str, z->name);
400  l = 0;
401  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
402  != NULL) {
403  /* check status */
404  if (status != LDNS_STATUS_OK) {
405  ods_log_error("[%s] error reading NSEC(3) #%i (%s): %s",
406  backup_str, l, ldns_get_errorstr_by_id(status), line);
407  result = ODS_STATUS_ERR;
408  goto backup_namedb_done;
409  }
410  if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_NSEC &&
411  ldns_rr_get_type(rr) != LDNS_RR_TYPE_NSEC3) {
412  ods_log_error("[%s] error NSEC(3) #%i is not NSEC(3): %s",
413  backup_str, l, line);
414  ldns_rr_free(rr);
415  rr = NULL;
416  result = ODS_STATUS_ERR;
417  goto backup_namedb_done;
418  }
419  /* add to the denial chain */
420  denial = namedb_lookup_denial(z->db, ldns_rr_owner(rr));
421  if (!denial) {
422  ods_log_error("[%s] error adding NSEC(3) #%i: %s",
423  backup_str, l, line);
424  ldns_rr_free(rr);
425  rr = NULL;
426  result = ODS_STATUS_ERR;
427  goto backup_namedb_done;
428  }
429  denial_add_rr(denial, rr);
430  }
431  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
432  ods_log_error("[%s] error reading NSEC(3) #%i (%s): %s",
433  backup_str, l, ldns_get_errorstr_by_id(status), line);
434  result = ODS_STATUS_ERR;
435  goto backup_namedb_done;
436  }
437 
438  /* read RRSIGs */
439  ods_log_debug("[%s] read RRSIGs %s", backup_str, z->name);
440  l = 0;
441  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
442  != NULL) {
443  /* check status */
444  if (status != LDNS_STATUS_OK) {
445  ods_log_error("[%s] error reading RRSIG #%i (%s): %s",
446  backup_str, l, ldns_get_errorstr_by_id(status), line);
447  result = ODS_STATUS_ERR;
448  goto backup_namedb_done;
449  }
450  if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
451  ods_log_error("[%s] error RRSIG #%i is not RRSIG: %s",
452  backup_str, l, line);
453  ldns_rr_free(rr);
454  rr = NULL;
455  result = ODS_STATUS_ERR;
456  goto backup_namedb_done;
457  }
458  /* read locator and flags */
459  str = strstr(line, "flags");
460  if (str) {
461  flags = (uint32_t) atoi(str+6);
462  }
463  str = strstr(line, "locator");
464  if (str) {
465  locator = replace_space_with_nul(str+8);
466  }
467  /* add signatures */
468  type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
469  if (type_covered == LDNS_RR_TYPE_NSEC ||
470  type_covered == LDNS_RR_TYPE_NSEC3) {
471  denial = namedb_lookup_denial(z->db, ldns_rr_owner(rr));
472  if (!denial) {
473  ods_log_error("[%s] error restoring RRSIG #%i (%s): %s",
474  backup_str, l, ldns_get_errorstr_by_id(status), line);
475  ldns_rr_free(rr);
476  rr = NULL;
477  result = ODS_STATUS_ERR;
478  goto backup_namedb_done;
479  }
480  rrset = denial->rrset;
481  } else {
482  rrset = zone_lookup_rrset(z, ldns_rr_owner(rr), type_covered);
483  }
484  if (!rrset || !rrset_add_rrsig(rrset, rr, locator, flags)) {
485  ods_log_error("[%s] error restoring RRSIG #%i (%s): %s",
486  backup_str, l, ldns_get_errorstr_by_id(status), line);
487  ldns_rr_free(rr);
488  rr = NULL;
489  result = ODS_STATUS_ERR;
490  goto backup_namedb_done;
491  } else {
492  rrset->needs_signing = 0;
493  }
494  }
495  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
496  ods_log_error("[%s] error reading RRSIG #%i (%s): %s",
497  backup_str, l, ldns_get_errorstr_by_id(status), line);
498  result = ODS_STATUS_ERR;
499  }
500 
501 backup_namedb_done:
502  if (orig) {
503  ldns_rdf_deep_free(orig);
504  orig = NULL;
505  }
506  if (prev) {
507  ldns_rdf_deep_free(prev);
508  prev = NULL;
509  }
510  return result;
511 }
512 
513 
520 backup_read_ixfr(FILE* in, void* zone)
521 {
522  zone_type* z = (zone_type*) zone;
523  ods_status result = ODS_STATUS_OK;
524  ldns_rr* rr = NULL;
525  ldns_rdf* prev = NULL;
526  ldns_rdf* orig = NULL;
527  ldns_rdf* dname = NULL;
528  ldns_status status = LDNS_STATUS_OK;
529  char line[SE_ADFILE_MAXLINE];
530  uint32_t serial = 0;
531  unsigned l = 0;
532  unsigned first_soa = 0;
533  unsigned del_mode = 0;
534 
535  ods_log_assert(in);
536  ods_log_assert(z);
537 
538  /* $ORIGIN <zone name> */
539  dname = adapi_get_origin(z);
540  if (!dname) {
541  ods_log_error("[%s] error getting default value for $ORIGIN",
542  backup_str);
543  return ODS_STATUS_ERR;
544  }
545  orig = ldns_rdf_clone(dname);
546  if (!orig) {
547  ods_log_error("[%s] error setting default value for $ORIGIN",
548  backup_str);
549  return ODS_STATUS_ERR;
550  }
551  /* read RRs */
552  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
553  != NULL) {
554  /* check status */
555  if (status != LDNS_STATUS_OK) {
556  ods_log_error("[%s] error reading RR #%i (%s): %s",
557  backup_str, l, ldns_get_errorstr_by_id(status), line);
558  result = ODS_STATUS_ERR;
559  goto backup_ixfr_done;
560  }
561  if (first_soa == 2) {
562  ods_log_error("[%s] bad ixfr journal: trailing RRs after final "
563  "SOA", backup_str);
564  ldns_rr_free(rr);
565  rr = NULL;
566  result = ODS_STATUS_ERR;
567  goto backup_ixfr_done;
568  }
569  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
570  serial = ldns_rdf2native_int32(
571  ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
572  if (!first_soa) {
573  ods_log_debug("[%s] ixfr first SOA: %s", backup_str,
574  ldns_rr2str(rr));
575  /* first SOA */
576  ldns_rr_free(rr);
577  rr = NULL;
578  if (z->db->outserial != serial) {
579  ods_log_error("[%s] bad ixfr journal: first SOA wrong "
580  "serial (was %u, expected %u)", backup_str,
581  serial, z->db->outserial);
582  result = ODS_STATUS_ERR;
583  goto backup_ixfr_done;
584  }
585  first_soa = 1;
586  continue;
587  }
588  ods_log_assert(first_soa);
589  if (!del_mode) {
590  if (z->db->outserial == serial) {
591  /* final SOA */
592  ods_log_debug("[%s] ixfr final SOA: %s", backup_str,
593  ldns_rr2str(rr));
594  ldns_rr_free(rr);
595  rr = NULL;
596  result = ODS_STATUS_OK;
597  first_soa = 2;
598  continue;
599  } else {
600  ods_log_debug("[%s] new part SOA: %s", backup_str,
601  ldns_rr2str(rr));
603  ixfr_purge(z->ixfr);
605  }
606  } else {
607  ods_log_debug("[%s] second part SOA: %s", backup_str,
608  ldns_rr2str(rr));
609  }
610  del_mode = !del_mode;
611  }
612  /* ixfr add or del rr */
613  if (!first_soa) {
614  ods_log_error("[%s] bad ixfr journal: first RR not SOA",
615  backup_str);
616  ldns_rr_free(rr);
617  rr = NULL;
618  result = ODS_STATUS_ERR;
619  goto backup_ixfr_done;
620  }
621  ods_log_assert(first_soa);
623  if (del_mode) {
624  ods_log_debug("[%s] -IXFR: %s", backup_str, ldns_rr2str(rr));
625  ixfr_del_rr(z->ixfr, rr);
626  } else {
627  ods_log_debug("[%s] +IXFR: %s", backup_str, ldns_rr2str(rr));
628  ixfr_add_rr(z->ixfr, rr);
629  }
631  }
632  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
633  ods_log_error("[%s] error reading RR #%i (%s): %s",
634  backup_str, l, ldns_get_errorstr_by_id(status), line);
635  result = ODS_STATUS_ERR;
636  }
637 
638 backup_ixfr_done:
639  if (orig) {
640  ldns_rdf_deep_free(orig);
641  orig = NULL;
642  }
643  if (prev) {
644  ldns_rdf_deep_free(prev);
645  prev = NULL;
646  }
647  return result;
648 }
649 
uint32_t default_ttl
Definition: zone.h:70
int backup_read_str(FILE *in, const char **str)
Definition: backup.c:97
rrset_type * rrset
Definition: denial.h:54
char * backup_read_token(FILE *in)
Definition: backup.c:53
int backup_read_uint8_t(FILE *in, uint8_t *v)
Definition: backup.c:199
void ods_log_debug(const char *format,...)
Definition: log.c:270
int backup_read_duration(FILE *in, duration_type **v)
Definition: backup.c:131
void ixfr_add_rr(ixfr_type *ixfr, ldns_rr *rr)
Definition: ixfr.c:130
int backup_read_rr_type(FILE *in, ldns_rr_type *v)
Definition: backup.c:148
void ixfr_del_rr(ixfr_type *ixfr, ldns_rr *rr)
Definition: ixfr.c:161
int backup_read_uint16_t(FILE *in, uint16_t *v)
Definition: backup.c:216
int backup_read_time_t(FILE *in, time_t *v)
Definition: backup.c:114
enum ods_enum_status ods_status
Definition: status.h:90
void ods_log_error(const char *format,...)
Definition: log.c:334
uint32_t outserial
Definition: namedb.h:53
rrsig_type * rrset_add_rrsig(rrset_type *rrset, ldns_rr *rr, const char *locator, uint32_t flags)
Definition: rrset.c:400
#define SE_SOA_RDATA_SERIAL
Definition: util.h:47
int ods_strcmp(const char *s1, const char *s2)
Definition: file.c:315
int backup_read_int(FILE *in, int *v)
Definition: backup.c:165
void namedb_diff(namedb_type *db, unsigned is_ixfr, unsigned more_coming)
Definition: namedb.c:819
ods_status backup_read_ixfr(FILE *in, void *zone)
Definition: backup.c:520
ods_status backup_read_namedb(FILE *in, void *zone)
Definition: backup.c:328
#define lock_basic_lock(lock)
Definition: locks.h:91
namedb_type * db
Definition: zone.h:86
ixfr_type * ixfr
Definition: zone.h:87
unsigned needs_signing
Definition: rrset.h:81
ldns_rdf * adapi_get_origin(zone_type *zone)
Definition: adapi.c:79
void denial_add_rr(denial_type *denial, ldns_rr *rr)
Definition: denial.c:263
lock_basic_type ixfr_lock
Definition: ixfr.h:62
rrset_type * zone_lookup_rrset(zone_type *zone, ldns_rdf *owner, ldns_rr_type type)
Definition: zone.c:545
ods_status adapi_add_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:356
const char * name
Definition: zone.h:76
#define SE_ADFILE_MAXLINE
Definition: adutil.h:40
int backup_read_size_t(FILE *in, size_t *v)
Definition: backup.c:182
int backup_read_check_str(FILE *in, const char *str)
Definition: backup.c:77
int adutil_readline_frm_file(FILE *fd, char *line, unsigned int *l, int keep_comments)
Definition: adutil.c:82
void ixfr_purge(ixfr_type *ixfr)
Definition: ixfr.c:275
#define ods_log_assert(x)
Definition: log.h:154
duration_type * duration_create_from_string(const char *str)
Definition: duration.c:123
#define lock_basic_unlock(lock)
Definition: locks.h:92
denial_type * namedb_lookup_denial(namedb_type *db, ldns_rdf *dname)
Definition: namedb.c:429
int backup_read_uint32_t(FILE *in, uint32_t *v)
Definition: backup.c:233