OpenDNSSEC-signer  1.4.3
backup.c
Go to the documentation of this file.
1 /*
2  * $Id: tools.c 3817 2010-08-27 08:43:00Z matthijs $
3  *
4  * Copyright (c) 2006-2010 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 "config.h"
35 #include "adapter/adapi.h"
36 #include "adapter/adutil.h"
37 #include "shared/duration.h"
38 #include "shared/file.h"
39 #include "shared/log.h"
40 #include "shared/status.h"
41 #include "shared/util.h"
42 #include "signer/backup.h"
43 #include "signer/zone.h"
44 
45 #include <ldns/ldns.h>
46 
47 static const char* backup_str = "backup";
48 
49 
54 char*
56 {
57  static char buf[4000];
58  buf[sizeof(buf)-1]=0;
59 
60  while (1) {
61  if (fscanf(in, "%3990s", buf) != 1) {
62  return 0;
63  }
64  if (buf[0] != '#') {
65  return buf;
66  }
67  if (!fgets(buf, sizeof(buf), in)) {
68  return 0;
69  }
70  }
71  return 0;
72 }
73 
78 int
79 backup_read_check_str(FILE* in, const char* str)
80 {
81  char *p = backup_read_token(in);
82  if (!p) {
83  ods_log_debug("[%s] cannot read check string \'%s\'", backup_str, str);
84  return 0;
85  }
86  if (ods_strcmp(p, str) != 0) {
87  ods_log_debug("[%s] \'%s\' does not match \'%s\'", backup_str, p, str);
88  return 0;
89  }
90  return 1;
91 }
92 
93 
98 int
99 backup_read_str(FILE* in, const char** str)
100 {
101  char *p = backup_read_token(in);
102  if (!p) {
103  ods_log_debug("[%s] cannot read string", backup_str);
104  return 0;
105  }
106  *str = strdup(p);
107  return 1;
108 }
109 
110 
115 int
116 backup_read_time_t(FILE* in, time_t* v)
117 {
118  char* p = backup_read_token(in);
119  if (!p) {
120  ods_log_debug("[%s] cannot read time", backup_str);
121  return 0;
122  }
123  *v=atol(p);
124  return 1;
125 }
126 
127 
132 int
134 {
135  char* p = backup_read_token(in);
136  if (!p) {
137  ods_log_debug("[%s] cannot read duration", backup_str);
138  return 0;
139  }
140  *v=duration_create_from_string((const char*) p);
141  return 1;
142 }
143 
144 
149 int
150 backup_read_rr_type(FILE* in, ldns_rr_type* v)
151 {
152  char* p = backup_read_token(in);
153  if (!p) {
154  ods_log_debug("[%s] cannot read rr type", backup_str);
155  return 0;
156  }
157  *v=(ldns_rr_type) atoi(p);
158  return 1;
159 }
160 
161 
166 int
167 backup_read_int(FILE* in, int* v)
168 {
169  char* p = backup_read_token(in);
170  if (!p) {
171  ods_log_debug("[%s] cannot read integer", backup_str);
172  return 0;
173  }
174  *v=atoi(p);
175  return 1;
176 }
177 
178 
183 int
184 backup_read_size_t(FILE* in, size_t* v)
185 {
186  char* p = backup_read_token(in);
187  if (!p) {
188  ods_log_debug("[%s] cannot read size_t", backup_str);
189  return 0;
190  }
191  *v=(size_t)atoi(p);
192  return 1;
193 }
194 
195 
200 int
201 backup_read_uint8_t(FILE* in, uint8_t* v)
202 {
203  char* p = backup_read_token(in);
204  if (!p) {
205  ods_log_debug("[%s] cannot read uint8_t", backup_str);
206  return 0;
207  }
208  *v= (uint8_t)atoi(p);
209  return 1;
210 }
211 
212 
217 int
218 backup_read_uint16_t(FILE* in, uint16_t* v)
219 {
220  char* p = backup_read_token(in);
221  if (!p) {
222  ods_log_debug("[%s] cannot read uint16_t", backup_str);
223  return 0;
224  }
225  *v= (uint16_t)atoi(p);
226  return 1;
227 }
228 
229 
234 int
235 backup_read_uint32_t(FILE* in, uint32_t* v)
236 {
237  char* p = backup_read_token(in);
238  if (!p) {
239  ods_log_debug("[%s] cannot read uint32_t", backup_str);
240  return 0;
241  }
242  *v= (uint32_t)atol(p);
243  return 1;
244 }
245 
246 
251 static ldns_rr*
252 backup_read_rr(FILE* in, zone_type* zone, char* line, ldns_rdf** orig,
253  ldns_rdf** prev, ldns_status* status, unsigned int* l)
254 {
255  ldns_rr* rr = NULL;
256  int len = 0;
257 backup_read_line:
258  len = adutil_readline_frm_file(in, line, l, 1);
259  if (len >= 0) {
260  switch (line[0]) {
261  case ';':
262  /* done */
263  *status = LDNS_STATUS_OK;
264  return NULL;
265  break;
266  case '\n':
267  case '\0':
268  goto backup_read_line; /* perhaps next line is rr */
269  break;
270  /* let's hope its a RR */
271  default:
272  *status = ldns_rr_new_frm_str(&rr, line, zone->default_ttl,
273  *orig, prev);
274  if (*status == LDNS_STATUS_OK) {
275  return rr;
276  } else if (*status == LDNS_STATUS_SYNTAX_EMPTY) {
277  if (rr) {
278  ldns_rr_free(rr);
279  rr = NULL;
280  }
281  *status = LDNS_STATUS_OK;
282  goto backup_read_line; /* perhaps next line is rr */
283  break;
284  } else {
285  ods_log_error("[%s] error parsing RR #%i (%s): %s",
286  backup_str, l&&*l?*l:0,
287  ldns_get_errorstr_by_id(*status), line);
288  if (rr) {
289  ldns_rr_free(rr);
290  rr = NULL;
291  }
292  return NULL;
293  }
294  break;
295  }
296  }
297  /* -1, EOF */
298  *status = LDNS_STATUS_OK;
299  return NULL;
300 }
301 
302 
307 static char*
308 replace_space_with_nul(char* str)
309 {
310  int i = 0;
311  if (!str) {
312  return NULL;
313  }
314  i = strlen(str);
315  while (i>0) {
316  --i;
317  if (str[i] == ' ') {
318  str[i] = '\0';
319  }
320  }
321  return strdup(str);
322 }
323 
324 
330 backup_read_namedb(FILE* in, void* zone)
331 {
332  zone_type* z = (zone_type*) zone;
333  denial_type* denial = NULL;
334  rrset_type* rrset = NULL;
335  ods_status result = ODS_STATUS_OK;
336  ldns_rr_type type_covered;
337  ldns_rr* rr = NULL;
338  ldns_rdf* prev = NULL;
339  ldns_rdf* orig = NULL;
340  ldns_rdf* dname = NULL;
341  ldns_status status = LDNS_STATUS_OK;
342  char line[SE_ADFILE_MAXLINE];
343  char* str = NULL;
344  char* locator = NULL;
345  uint32_t flags = 0;
346  unsigned int l = 0;
347 
348  ods_log_assert(in);
349  ods_log_assert(z);
350 
351  /* $ORIGIN <zone name> */
352  dname = adapi_get_origin(z);
353  if (!dname) {
354  ods_log_error("[%s] error getting default value for $ORIGIN",
355  backup_str);
356  return ODS_STATUS_ERR;
357  }
358  orig = ldns_rdf_clone(dname);
359  if (!orig) {
360  ods_log_error("[%s] error setting default value for $ORIGIN",
361  backup_str);
362  return ODS_STATUS_ERR;
363  }
364  /* read RRs */
365  ods_log_debug("[%s] read RRs %s", backup_str, z->name);
366  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
367  != NULL) {
368  /* check status */
369  if (status != LDNS_STATUS_OK) {
370  ods_log_error("[%s] error reading RR #%i (%s): %s",
371  backup_str, l, ldns_get_errorstr_by_id(status), line);
372  result = ODS_STATUS_ERR;
373  goto backup_namedb_done;
374  }
375  /* add to the database */
376  result = adapi_add_rr(z, rr, 1);
377  if (result == ODS_STATUS_UNCHANGED) {
378  ods_log_debug("[%s] skipping RR #%i (duplicate): %s",
379  backup_str, l, line);
380  ldns_rr_free(rr);
381  rr = NULL;
382  result = ODS_STATUS_OK;
383  continue;
384  } else if (result != ODS_STATUS_OK) {
385  ods_log_error("[%s] error adding RR #%i: %s",
386  backup_str, l, line);
387  ldns_rr_free(rr);
388  rr = NULL;
389  goto backup_namedb_done;
390  }
391  }
392  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
393  ods_log_error("[%s] error reading RR #%i (%s): %s",
394  backup_str, l, ldns_get_errorstr_by_id(status), line);
395  result = ODS_STATUS_ERR;
396  goto backup_namedb_done;
397  }
398  namedb_diff(z->db, 0, 0);
399 
400  /* read NSEC(3)s */
401  ods_log_debug("[%s] read NSEC(3)s %s", backup_str, z->name);
402  l = 0;
403  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
404  != NULL) {
405  /* check status */
406  if (status != LDNS_STATUS_OK) {
407  ods_log_error("[%s] error reading NSEC(3) #%i (%s): %s",
408  backup_str, l, ldns_get_errorstr_by_id(status), line);
409  result = ODS_STATUS_ERR;
410  goto backup_namedb_done;
411  }
412  if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_NSEC &&
413  ldns_rr_get_type(rr) != LDNS_RR_TYPE_NSEC3) {
414  ods_log_error("[%s] error NSEC(3) #%i is not NSEC(3): %s",
415  backup_str, l, line);
416  ldns_rr_free(rr);
417  rr = NULL;
418  result = ODS_STATUS_ERR;
419  goto backup_namedb_done;
420  }
421  /* add to the denial chain */
422  denial = namedb_lookup_denial(z->db, ldns_rr_owner(rr));
423  if (!denial) {
424  ods_log_error("[%s] error adding NSEC(3) #%i: %s",
425  backup_str, l, line);
426  ldns_rr_free(rr);
427  rr = NULL;
428  result = ODS_STATUS_ERR;
429  goto backup_namedb_done;
430  }
431  denial_add_rr(denial, rr);
432  }
433  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
434  ods_log_error("[%s] error reading NSEC(3) #%i (%s): %s",
435  backup_str, l, ldns_get_errorstr_by_id(status), line);
436  result = ODS_STATUS_ERR;
437  goto backup_namedb_done;
438  }
439 
440  /* read RRSIGs */
441  ods_log_debug("[%s] read RRSIGs %s", backup_str, z->name);
442  l = 0;
443  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
444  != NULL) {
445  /* check status */
446  if (status != LDNS_STATUS_OK) {
447  ods_log_error("[%s] error reading RRSIG #%i (%s): %s",
448  backup_str, l, ldns_get_errorstr_by_id(status), line);
449  result = ODS_STATUS_ERR;
450  goto backup_namedb_done;
451  }
452  if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
453  ods_log_error("[%s] error RRSIG #%i is not RRSIG: %s",
454  backup_str, l, line);
455  ldns_rr_free(rr);
456  rr = NULL;
457  result = ODS_STATUS_ERR;
458  goto backup_namedb_done;
459  }
460  /* read locator and flags */
461  str = strstr(line, "flags");
462  if (str) {
463  flags = (uint32_t) atoi(str+6);
464  }
465  str = strstr(line, "locator");
466  if (str) {
467  locator = replace_space_with_nul(str+8);
468  }
469  /* add signatures */
470  type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
471  if (type_covered == LDNS_RR_TYPE_NSEC ||
472  type_covered == LDNS_RR_TYPE_NSEC3) {
473  denial = namedb_lookup_denial(z->db, ldns_rr_owner(rr));
474  if (!denial) {
475  ods_log_error("[%s] error restoring RRSIG #%i (%s): %s",
476  backup_str, l, ldns_get_errorstr_by_id(status), line);
477  ldns_rr_free(rr);
478  rr = NULL;
479  result = ODS_STATUS_ERR;
480  goto backup_namedb_done;
481  }
482  rrset = denial->rrset;
483  } else {
484  rrset = zone_lookup_rrset(z, ldns_rr_owner(rr), type_covered);
485  }
486  if (!rrset || !rrset_add_rrsig(rrset, rr, locator, flags)) {
487  ods_log_error("[%s] error restoring RRSIG #%i (%s): %s",
488  backup_str, l, ldns_get_errorstr_by_id(status), line);
489  ldns_rr_free(rr);
490  rr = NULL;
491  result = ODS_STATUS_ERR;
492  goto backup_namedb_done;
493  } else {
494  rrset->needs_signing = 0;
495  }
496  }
497  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
498  ods_log_error("[%s] error reading RRSIG #%i (%s): %s",
499  backup_str, l, ldns_get_errorstr_by_id(status), line);
500  result = ODS_STATUS_ERR;
501  }
502 
503 backup_namedb_done:
504  if (orig) {
505  ldns_rdf_deep_free(orig);
506  orig = NULL;
507  }
508  if (prev) {
509  ldns_rdf_deep_free(prev);
510  prev = NULL;
511  }
512  return result;
513 }
514 
515 
522 backup_read_ixfr(FILE* in, void* zone)
523 {
524  zone_type* z = (zone_type*) zone;
525  ods_status result = ODS_STATUS_OK;
526  ldns_rr* rr = NULL;
527  ldns_rdf* prev = NULL;
528  ldns_rdf* orig = NULL;
529  ldns_rdf* dname = NULL;
530  ldns_status status = LDNS_STATUS_OK;
531  char line[SE_ADFILE_MAXLINE];
532  uint32_t serial = 0;
533  unsigned l = 0;
534  unsigned first_soa = 0;
535  unsigned del_mode = 0;
536 
537  ods_log_assert(in);
538  ods_log_assert(z);
539 
540  /* $ORIGIN <zone name> */
541  dname = adapi_get_origin(z);
542  if (!dname) {
543  ods_log_error("[%s] error getting default value for $ORIGIN",
544  backup_str);
545  return ODS_STATUS_ERR;
546  }
547  orig = ldns_rdf_clone(dname);
548  if (!orig) {
549  ods_log_error("[%s] error setting default value for $ORIGIN",
550  backup_str);
551  return ODS_STATUS_ERR;
552  }
553  /* read RRs */
554  while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
555  != NULL) {
556  /* check status */
557  if (status != LDNS_STATUS_OK) {
558  ods_log_error("[%s] error reading RR #%i (%s): %s",
559  backup_str, l, ldns_get_errorstr_by_id(status), line);
560  result = ODS_STATUS_ERR;
561  goto backup_ixfr_done;
562  }
563  if (first_soa == 2) {
564  ods_log_error("[%s] bad ixfr journal: trailing RRs after final "
565  "SOA", backup_str);
566  ldns_rr_free(rr);
567  rr = NULL;
568  result = ODS_STATUS_ERR;
569  goto backup_ixfr_done;
570  }
571  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
572  serial = ldns_rdf2native_int32(
573  ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
574  if (!first_soa) {
575  ods_log_debug("[%s] ixfr first SOA: %s", backup_str,
576  ldns_rr2str(rr));
577  /* first SOA */
578  ldns_rr_free(rr);
579  rr = NULL;
580  if (z->db->outserial != serial) {
581  ods_log_error("[%s] bad ixfr journal: first SOA wrong "
582  "serial (was %u, expected %u)", backup_str,
583  serial, z->db->outserial);
584  result = ODS_STATUS_ERR;
585  goto backup_ixfr_done;
586  }
587  first_soa = 1;
588  continue;
589  }
590  ods_log_assert(first_soa);
591  if (!del_mode) {
592  if (z->db->outserial == serial) {
593  /* final SOA */
594  ods_log_debug("[%s] ixfr final SOA: %s", backup_str,
595  ldns_rr2str(rr));
596  ldns_rr_free(rr);
597  rr = NULL;
598  result = ODS_STATUS_OK;
599  first_soa = 2;
600  continue;
601  } else {
602  ods_log_debug("[%s] new part SOA: %s", backup_str,
603  ldns_rr2str(rr));
605  ixfr_purge(z->ixfr);
607  }
608  } else {
609  ods_log_debug("[%s] second part SOA: %s", backup_str,
610  ldns_rr2str(rr));
611  }
612  del_mode = !del_mode;
613  }
614  /* ixfr add or del rr */
615  if (!first_soa) {
616  ods_log_error("[%s] bad ixfr journal: first RR not SOA",
617  backup_str);
618  ldns_rr_free(rr);
619  rr = NULL;
620  result = ODS_STATUS_ERR;
621  goto backup_ixfr_done;
622  }
623  ods_log_assert(first_soa);
625  if (del_mode) {
626  ods_log_debug("[%s] -IXFR: %s", backup_str, ldns_rr2str(rr));
627  ixfr_del_rr(z->ixfr, rr);
628  } else {
629  ods_log_debug("[%s] +IXFR: %s", backup_str, ldns_rr2str(rr));
630  ixfr_add_rr(z->ixfr, rr);
631  }
633  }
634  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
635  ods_log_error("[%s] error reading RR #%i (%s): %s",
636  backup_str, l, ldns_get_errorstr_by_id(status), line);
637  result = ODS_STATUS_ERR;
638  }
639 
640 backup_ixfr_done:
641  if (orig) {
642  ldns_rdf_deep_free(orig);
643  orig = NULL;
644  }
645  if (prev) {
646  ldns_rdf_deep_free(prev);
647  prev = NULL;
648  }
649  return result;
650 }
651 
uint32_t default_ttl
Definition: zone.h:72
int backup_read_str(FILE *in, const char **str)
Definition: backup.c:99
rrset_type * rrset
Definition: denial.h:56
char * backup_read_token(FILE *in)
Definition: backup.c:55
int backup_read_uint8_t(FILE *in, uint8_t *v)
Definition: backup.c:201
void ods_log_debug(const char *format,...)
Definition: log.c:272
int backup_read_duration(FILE *in, duration_type **v)
Definition: backup.c:133
void ixfr_add_rr(ixfr_type *ixfr, ldns_rr *rr)
Definition: ixfr.c:132
int backup_read_rr_type(FILE *in, ldns_rr_type *v)
Definition: backup.c:150
void ixfr_del_rr(ixfr_type *ixfr, ldns_rr *rr)
Definition: ixfr.c:163
int backup_read_uint16_t(FILE *in, uint16_t *v)
Definition: backup.c:218
int backup_read_time_t(FILE *in, time_t *v)
Definition: backup.c:116
enum ods_enum_status ods_status
Definition: status.h:91
void ods_log_error(const char *format,...)
Definition: log.c:336
uint32_t outserial
Definition: namedb.h:55
rrsig_type * rrset_add_rrsig(rrset_type *rrset, ldns_rr *rr, const char *locator, uint32_t flags)
Definition: rrset.c:402
#define SE_SOA_RDATA_SERIAL
Definition: util.h:49
int ods_strcmp(const char *s1, const char *s2)
Definition: file.c:317
int backup_read_int(FILE *in, int *v)
Definition: backup.c:167
void namedb_diff(namedb_type *db, unsigned is_ixfr, unsigned more_coming)
Definition: namedb.c:821
ods_status backup_read_ixfr(FILE *in, void *zone)
Definition: backup.c:522
ods_status backup_read_namedb(FILE *in, void *zone)
Definition: backup.c:330
#define lock_basic_lock(lock)
Definition: locks.h:93
namedb_type * db
Definition: zone.h:88
ixfr_type * ixfr
Definition: zone.h:89
unsigned needs_signing
Definition: rrset.h:83
ldns_rdf * adapi_get_origin(zone_type *zone)
Definition: adapi.c:81
void denial_add_rr(denial_type *denial, ldns_rr *rr)
Definition: denial.c:265
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:542
ods_status adapi_add_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:358
const char * name
Definition: zone.h:78
#define SE_ADFILE_MAXLINE
Definition: adutil.h:42
int backup_read_size_t(FILE *in, size_t *v)
Definition: backup.c:184
int backup_read_check_str(FILE *in, const char *str)
Definition: backup.c:79
int adutil_readline_frm_file(FILE *fd, char *line, unsigned int *l, int keep_comments)
Definition: adutil.c:84
void ixfr_purge(ixfr_type *ixfr)
Definition: ixfr.c:277
#define ods_log_assert(x)
Definition: log.h:156
duration_type * duration_create_from_string(const char *str)
Definition: duration.c:125
#define lock_basic_unlock(lock)
Definition: locks.h:94
denial_type * namedb_lookup_denial(namedb_type *db, ldns_rdf *dname)
Definition: namedb.c:431
int backup_read_uint32_t(FILE *in, uint32_t *v)
Definition: backup.c:235