OpenDNSSEC-signer  2.0.3
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 "duration.h"
36 #include "file.h"
37 #include "log.h"
38 #include "status.h"
39 #include "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  if (!strcmp(p, "rfc5011") && !strcmp(str, "keytag")) {
86  return 1;
87  }
88  if (!strcmp(p, "jitter") && !strcmp(str, "keyset")) {
89  fseek(in, -7, SEEK_CUR);
90  return 1;
91  }
92 
93  ods_log_debug("[%s] \'%s\' does not match \'%s\'", backup_str, p, str);
94  return 0;
95  }
96  return 1;
97 }
98 
99 
104 int
105 backup_read_str(FILE* in, const char** str)
106 {
107  char *p = backup_read_token(in);
108  if (!p) {
109  ods_log_debug("[%s] cannot read string", backup_str);
110  return 0;
111  }
112  *str = strdup(p);
113  return 1;
114 }
115 
116 
121 int
122 backup_read_time_t(FILE* in, time_t* v)
123 {
124  char* p = backup_read_token(in);
125  if (!p) {
126  ods_log_debug("[%s] cannot read time", backup_str);
127  return 0;
128  }
129  *v=atol(p);
130  return 1;
131 }
132 
133 
138 int
139 backup_read_duration(FILE* in, duration_type** v)
140 {
141  char* p = backup_read_token(in);
142  if (!p) {
143  ods_log_debug("[%s] cannot read duration", backup_str);
144  return 0;
145  }
146  if (!strcmp(p, "jitter")) {
147  fseek(in, -7, SEEK_CUR);
148  return 1;
149  }
150  *v=duration_create_from_string((const char*) p);
151  return 1;
152 }
153 
154 
159 int
160 backup_read_rr_type(FILE* in, ldns_rr_type* v)
161 {
162  char* p = backup_read_token(in);
163  if (!p) {
164  ods_log_debug("[%s] cannot read rr type", backup_str);
165  return 0;
166  }
167  *v=(ldns_rr_type) atoi(p);
168  return 1;
169 }
170 
171 
176 int
177 backup_read_int(FILE* in, int* v)
178 {
179  char* p = backup_read_token(in);
180  if (!p) {
181  ods_log_debug("[%s] cannot read integer", backup_str);
182  return 0;
183  }
184  *v=atoi(p);
185  return 1;
186 }
187 
188 
193 int
194 backup_read_uint8_t(FILE* in, uint8_t* v)
195 {
196  char* p = backup_read_token(in);
197  if (!p) {
198  ods_log_debug("[%s] cannot read uint8_t", backup_str);
199  return 0;
200  }
201  *v= (uint8_t)atoi(p);
202  return 1;
203 }
204 
205 
210 int
211 backup_read_uint32_t(FILE* in, uint32_t* v)
212 {
213  char* p = backup_read_token(in);
214  if (!p) {
215  ods_log_debug("[%s] cannot read uint32_t", backup_str);
216  return 0;
217  }
218  *v= (uint32_t)atol(p);
219  return 1;
220 }
221 
222 
227 static ldns_rr*
228 backup_read_rr(FILE* in, zone_type* zone, char* line, ldns_rdf** orig,
229  ldns_rdf** prev, ldns_status* status, unsigned int* l)
230 {
231  ldns_rr* rr = NULL;
232  int len = 0;
233 backup_read_line:
234  len = adutil_readline_frm_file(in, line, l, 1);
235  if (len >= 0) {
236  switch (line[0]) {
237  case ';':
238  /* done */
239  *status = LDNS_STATUS_OK;
240  return NULL;
241  break;
242  case '\n':
243  case '\0':
244  goto backup_read_line; /* perhaps next line is rr */
245  break;
246  /* let's hope its a RR */
247  default:
248  *status = ldns_rr_new_frm_str(&rr, line, zone->default_ttl,
249  *orig, prev);
250  if (*status == LDNS_STATUS_OK) {
251  return rr;
252  } else if (*status == LDNS_STATUS_SYNTAX_EMPTY) {
253  if (rr) {
254  ldns_rr_free(rr);
255  rr = NULL;
256  }
257  *status = LDNS_STATUS_OK;
258  goto backup_read_line; /* perhaps next line is rr */
259  break;
260  } else {
261  ods_log_error("[%s] error parsing RR #%i (%s): %s",
262  backup_str, l&&*l?*l:0,
263  ldns_get_errorstr_by_id(*status), line);
264  if (rr) {
265  ldns_rr_free(rr);
266  rr = NULL;
267  }
268  return NULL;
269  }
270  break;
271  }
272  }
273  /* -1, EOF */
274  *status = LDNS_STATUS_OK;
275  return NULL;
276 }
277 
278 
283 static char*
284 replace_space_with_nul(char* str)
285 {
286  int i = 0;
287  if (!str) {
288  return NULL;
289  }
290  i = strlen(str);
291  while (i>0) {
292  --i;
293  if (str[i] == ' ') {
294  str[i] = '\0';
295  }
296  }
297  return strdup(str);
298 }
299 
300 
305 ods_status
306 backup_read_namedb(FILE* in, void* zone)
307 {
308  zone_type* z = (zone_type*) zone;
309  denial_type* denial = NULL;
310  rrset_type* rrset = NULL;
311  ods_status result = ODS_STATUS_OK;
312  ldns_rr_type type_covered;
313  ldns_rr* rr = NULL;
314  ldns_rdf* prev = NULL;
315  ldns_rdf* orig = NULL;
316  ldns_rdf* dname = NULL;
317  ldns_status status = LDNS_STATUS_OK;
318  char line[SE_ADFILE_MAXLINE];
319  char* str = NULL;
320  char* locator = NULL;
321  uint32_t flags = 0;
322  unsigned int l = 0;
323 
324  ods_log_assert(in);
325  ods_log_assert(z);
326 
327  /* $ORIGIN <zone name> */
328  dname = adapi_get_origin(z);
329  if (!dname) {
330  ods_log_error("[%s] error getting default value for $ORIGIN",
331  backup_str);
332  return ODS_STATUS_ERR;
333  }
334  orig = ldns_rdf_clone(dname);
335  if (!orig) {
336  ods_log_error("[%s] error setting default value for $ORIGIN",
337  backup_str);
338  return ODS_STATUS_ERR;
339  }
340  /* read RRs */
341  ods_log_debug("[%s] read RRs %s", backup_str, z->name);
342  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
343  != NULL) {
344  /* check status */
345  if (status != LDNS_STATUS_OK) {
346  ods_log_error("[%s] error reading RR #%i (%s): %s",
347  backup_str, l, ldns_get_errorstr_by_id(status), line);
348  result = ODS_STATUS_ERR;
349  goto backup_namedb_done;
350  }
351  /* add to the database */
352  result = adapi_add_rr(z, rr, 1);
353  if (result == ODS_STATUS_UNCHANGED) {
354  ods_log_debug("[%s] skipping RR #%i (duplicate): %s",
355  backup_str, l, line);
356  ldns_rr_free(rr);
357  rr = NULL;
358  result = ODS_STATUS_OK;
359  continue;
360  } else if (result != ODS_STATUS_OK) {
361  ods_log_error("[%s] error adding RR #%i: %s",
362  backup_str, l, line);
363  ldns_rr_free(rr);
364  rr = NULL;
365  goto backup_namedb_done;
366  }
367  }
368  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
369  ods_log_error("[%s] error reading RR #%i (%s): %s",
370  backup_str, l, ldns_get_errorstr_by_id(status), line);
371  result = ODS_STATUS_ERR;
372  goto backup_namedb_done;
373  }
374  namedb_diff(z->db, 0, 0);
375 
376  /* read NSEC(3)s */
377  ods_log_debug("[%s] read NSEC(3)s %s", backup_str, z->name);
378  l = 0;
379  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
380  != NULL) {
381  /* check status */
382  if (status != LDNS_STATUS_OK) {
383  ods_log_error("[%s] error reading NSEC(3) #%i (%s): %s",
384  backup_str, l, ldns_get_errorstr_by_id(status), line);
385  result = ODS_STATUS_ERR;
386  goto backup_namedb_done;
387  }
388  if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_NSEC &&
389  ldns_rr_get_type(rr) != LDNS_RR_TYPE_NSEC3) {
390  ods_log_error("[%s] error NSEC(3) #%i is not NSEC(3): %s",
391  backup_str, l, line);
392  ldns_rr_free(rr);
393  rr = NULL;
394  result = ODS_STATUS_ERR;
395  goto backup_namedb_done;
396  }
397  /* add to the denial chain */
398  denial = namedb_lookup_denial(z->db, ldns_rr_owner(rr));
399  if (!denial) {
400  ods_log_error("[%s] error adding NSEC(3) #%i: %s",
401  backup_str, l, line);
402  ldns_rr_free(rr);
403  rr = NULL;
404  result = ODS_STATUS_ERR;
405  goto backup_namedb_done;
406  }
407  denial_add_rr(denial, rr);
408  }
409  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
410  ods_log_error("[%s] error reading NSEC(3) #%i (%s): %s",
411  backup_str, l, ldns_get_errorstr_by_id(status), line);
412  result = ODS_STATUS_ERR;
413  goto backup_namedb_done;
414  }
415 
416  /* read RRSIGs */
417  ods_log_debug("[%s] read RRSIGs %s", backup_str, z->name);
418  l = 0;
419  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
420  != NULL) {
421  /* check status */
422  if (status != LDNS_STATUS_OK) {
423  ods_log_error("[%s] error reading RRSIG #%i (%s): %s",
424  backup_str, l, ldns_get_errorstr_by_id(status), line);
425  result = ODS_STATUS_ERR;
426  goto backup_namedb_done;
427  }
428  if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
429  ods_log_error("[%s] error RRSIG #%i is not RRSIG: %s",
430  backup_str, l, line);
431  ldns_rr_free(rr);
432  rr = NULL;
433  result = ODS_STATUS_ERR;
434  goto backup_namedb_done;
435  }
436  /* read locator and flags */
437  str = strstr(line, "flags");
438  if (str) {
439  flags = (uint32_t) atoi(str+6);
440  }
441  str = strstr(line, "locator");
442  if (str) {
443  locator = replace_space_with_nul(str+8);
444  }
445  /* add signatures */
446  type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
447  if (type_covered == LDNS_RR_TYPE_NSEC ||
448  type_covered == LDNS_RR_TYPE_NSEC3) {
449  denial = namedb_lookup_denial(z->db, ldns_rr_owner(rr));
450  if (!denial) {
451  ods_log_error("[%s] error restoring RRSIG #%i (%s): %s",
452  backup_str, l, ldns_get_errorstr_by_id(status), line);
453  ldns_rr_free(rr);
454  rr = NULL;
455  result = ODS_STATUS_ERR;
456  goto backup_namedb_done;
457  }
458  rrset = denial->rrset;
459  } else {
460  rrset = zone_lookup_rrset(z, ldns_rr_owner(rr), type_covered);
461  }
462  if (!rrset) {
463  ods_log_error("[%s] error restoring RRSIG #%i (%s): %s",
464  backup_str, l, ldns_get_errorstr_by_id(status), line);
465  ldns_rr_free(rr);
466  rr = NULL;
467  result = ODS_STATUS_ERR;
468  goto backup_namedb_done;
469  }
470  rrset_add_rrsig(rrset, rr, locator, flags);
471  locator = NULL; /* Locator is owned by rrset now */
472  rrset->needs_signing = 0;
473  }
474  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
475  ods_log_error("[%s] error reading RRSIG #%i (%s): %s",
476  backup_str, l, ldns_get_errorstr_by_id(status), line);
477  result = ODS_STATUS_ERR;
478  }
479 
480 backup_namedb_done:
481  if (orig) {
482  ldns_rdf_deep_free(orig);
483  orig = NULL;
484  }
485  if (prev) {
486  ldns_rdf_deep_free(prev);
487  prev = NULL;
488  }
489  free(locator); /* if everything went well this is NULL. otherwise
490  clean up. */
491  return result;
492 }
493 
494 
500 ods_status
501 backup_read_ixfr(FILE* in, void* zone)
502 {
503  zone_type* z = (zone_type*) zone;
504  ods_status result = ODS_STATUS_OK;
505  ldns_rr* rr = NULL;
506  ldns_rdf* prev = NULL;
507  ldns_rdf* orig = NULL;
508  ldns_rdf* dname = NULL;
509  ldns_status status = LDNS_STATUS_OK;
510  char line[SE_ADFILE_MAXLINE];
511  uint32_t serial = 0;
512  unsigned l = 0;
513  unsigned first_soa = 0;
514  unsigned del_mode = 0;
515 
516  ods_log_assert(in);
517  ods_log_assert(z);
518 
519  /* $ORIGIN <zone name> */
520  dname = adapi_get_origin(z);
521  if (!dname) {
522  ods_log_error("[%s] error getting default value for $ORIGIN",
523  backup_str);
524  return ODS_STATUS_ERR;
525  }
526  orig = ldns_rdf_clone(dname);
527  if (!orig) {
528  ods_log_error("[%s] error setting default value for $ORIGIN",
529  backup_str);
530  return ODS_STATUS_ERR;
531  }
532  /* read RRs */
533  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
534  != NULL) {
535  /* check status */
536  if (status != LDNS_STATUS_OK) {
537  ods_log_error("[%s] error reading RR #%i (%s): %s",
538  backup_str, l, ldns_get_errorstr_by_id(status), line);
539  result = ODS_STATUS_ERR;
540  goto backup_ixfr_done;
541  }
542  if (first_soa == 2) {
543  ods_log_error("[%s] bad ixfr journal: trailing RRs after final "
544  "SOA", backup_str);
545  ldns_rr_free(rr);
546  rr = NULL;
547  result = ODS_STATUS_ERR;
548  goto backup_ixfr_done;
549  }
550  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
551  serial = ldns_rdf2native_int32(
552  ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
553  if (!first_soa) {
554  ods_log_debug("[%s] ixfr first SOA: %s", backup_str,
555  ldns_rr2str(rr));
556  /* first SOA */
557  ldns_rr_free(rr);
558  rr = NULL;
559  if (z->db->outserial != serial) {
560  ods_log_error("[%s] bad ixfr journal: first SOA wrong "
561  "serial (was %u, expected %u)", backup_str,
562  serial, z->db->outserial);
563  result = ODS_STATUS_ERR;
564  goto backup_ixfr_done;
565  }
566  first_soa = 1;
567  continue;
568  }
569  ods_log_assert(first_soa);
570  if (!del_mode) {
571  if (z->db->outserial == serial) {
572  /* final SOA */
573  ods_log_debug("[%s] ixfr final SOA: %s", backup_str,
574  ldns_rr2str(rr));
575  ldns_rr_free(rr);
576  rr = NULL;
577  result = ODS_STATUS_OK;
578  first_soa = 2;
579  continue;
580  } else {
581  ods_log_debug("[%s] new part SOA: %s", backup_str,
582  ldns_rr2str(rr));
583  lock_basic_lock(&z->ixfr->ixfr_lock);
584  ixfr_purge(z->ixfr);
585  lock_basic_unlock(&z->ixfr->ixfr_lock);
586  }
587  } else {
588  ods_log_debug("[%s] second part SOA: %s", backup_str,
589  ldns_rr2str(rr));
590  }
591  del_mode = !del_mode;
592  }
593  /* ixfr add or del rr */
594  if (!first_soa) {
595  ods_log_error("[%s] bad ixfr journal: first RR not SOA",
596  backup_str);
597  ldns_rr_free(rr);
598  rr = NULL;
599  result = ODS_STATUS_ERR;
600  goto backup_ixfr_done;
601  }
602  ods_log_assert(first_soa);
603  lock_basic_lock(&z->ixfr->ixfr_lock);
604  if (del_mode) {
605  ods_log_deeebug("[%s] -IXFR: %s", backup_str, ldns_rr2str(rr));
606  ixfr_del_rr(z->ixfr, rr);
607  } else {
608  ods_log_deeebug("[%s] +IXFR: %s", backup_str, ldns_rr2str(rr));
609  ixfr_add_rr(z->ixfr, rr);
610  }
611  lock_basic_unlock(&z->ixfr->ixfr_lock);
612  }
613  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
614  ods_log_error("[%s] error reading RR #%i (%s): %s",
615  backup_str, l, ldns_get_errorstr_by_id(status), line);
616  result = ODS_STATUS_ERR;
617  }
618 
619 backup_ixfr_done:
620  if (orig) {
621  ldns_rdf_deep_free(orig);
622  orig = NULL;
623  }
624  if (prev) {
625  ldns_rdf_deep_free(prev);
626  prev = NULL;
627  }
628  return result;
629 }
630 
uint32_t default_ttl
Definition: zone.h:61
int backup_read_str(FILE *in, const char **str)
Definition: backup.c:105
rrset_type * rrset
Definition: denial.h:55
char * backup_read_token(FILE *in)
Definition: backup.c:53
int backup_read_uint8_t(FILE *in, uint8_t *v)
Definition: backup.c:194
void rrset_add_rrsig(rrset_type *rrset, ldns_rr *rr, const char *locator, uint32_t flags)
Definition: rrset.c:416
int backup_read_duration(FILE *in, duration_type **v)
Definition: backup.c:139
void ixfr_add_rr(ixfr_type *ixfr, ldns_rr *rr)
Definition: ixfr.c:121
int backup_read_rr_type(FILE *in, ldns_rr_type *v)
Definition: backup.c:160
void ixfr_del_rr(ixfr_type *ixfr, ldns_rr *rr)
Definition: ixfr.c:151
int backup_read_time_t(FILE *in, time_t *v)
Definition: backup.c:122
uint32_t outserial
Definition: namedb.h:55
int backup_read_int(FILE *in, int *v)
Definition: backup.c:177
void namedb_diff(namedb_type *db, unsigned is_ixfr, unsigned more_coming)
Definition: namedb.c:812
ods_status backup_read_ixfr(FILE *in, void *zone)
Definition: backup.c:501
ods_status backup_read_namedb(FILE *in, void *zone)
Definition: backup.c:306
namedb_type * db
Definition: zone.h:77
ixfr_type * ixfr
Definition: zone.h:78
unsigned needs_signing
Definition: rrset.h:67
ldns_rdf * adapi_get_origin(zone_type *zone)
Definition: adapi.c:78
void denial_add_rr(denial_type *denial, ldns_rr *rr)
Definition: denial.c:259
lock_basic_type ixfr_lock
Definition: ixfr.h:64
rrset_type * zone_lookup_rrset(zone_type *zone, ldns_rdf *owner, ldns_rr_type type)
Definition: zone.c:557
ods_status adapi_add_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:360
const char * name
Definition: zone.h:67
#define SE_ADFILE_MAXLINE
Definition: adutil.h:40
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:47
void ixfr_purge(ixfr_type *ixfr)
Definition: ixfr.c:262
denial_type * namedb_lookup_denial(namedb_type *db, ldns_rdf *dname)
Definition: namedb.c:425
int backup_read_uint32_t(FILE *in, uint32_t *v)
Definition: backup.c:211