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