OpenDNSSEC-signer 2.1.13
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
45static const char* backup_str = "backup";
46
47
52char*
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
76int
77backup_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
103int
104backup_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
120int
121backup_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
137int
138backup_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
157int
158backup_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
174int
175backup_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
191int
192backup_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
208int
209backup_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
225static ldns_rr*
226backup_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;
231backup_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
281static char*
282replace_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
303ods_status
304backup_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
478backup_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
498ods_status
499backup_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
631backup_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
ods_status adapi_add_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:359
ldns_rdf * adapi_get_origin(zone_type *zone)
Definition: adapi.c:78
int adutil_readline_frm_file(FILE *fd, char *line, unsigned int *l, int keep_comments)
Definition: adutil.c:47
#define SE_ADFILE_MAXLINE
Definition: adutil.h:40
ods_status backup_read_namedb(FILE *in, void *zone)
Definition: backup.c:304
int backup_read_uint32_t(FILE *in, uint32_t *v)
Definition: backup.c:209
int backup_read_int(FILE *in, int *v)
Definition: backup.c:175
ods_status backup_read_ixfr(FILE *in, void *zone)
Definition: backup.c:499
int backup_read_rr_type(FILE *in, ldns_rr_type *v)
Definition: backup.c:158
int backup_read_time_t(FILE *in, time_t *v)
Definition: backup.c:121
int backup_read_uint8_t(FILE *in, uint8_t *v)
Definition: backup.c:192
int backup_read_check_str(FILE *in, const char *str)
Definition: backup.c:77
int backup_read_duration(FILE *in, duration_type **v)
Definition: backup.c:138
int backup_read_str(FILE *in, const char **str)
Definition: backup.c:104
char * backup_read_token(FILE *in)
Definition: backup.c:53
void denial_add_rr(denial_type *denial, ldns_rr *rr)
Definition: denial.c:259
void ixfr_purge(ixfr_type *ixfr, char const *zonename)
Definition: ixfr.c:237
void ixfr_del_rr(ixfr_type *ixfr, ldns_rr *rr)
Definition: ixfr.c:131
void ixfr_add_rr(ixfr_type *ixfr, ldns_rr *rr)
Definition: ixfr.c:106
void namedb_diff(namedb_type *db, unsigned is_ixfr, unsigned more_coming)
Definition: namedb.c:811
denial_type * namedb_lookup_denial(namedb_type *db, ldns_rdf *dname)
Definition: namedb.c:424
void rrset_add_rrsig(rrset_type *rrset, ldns_rr *rr, const char *locator, uint32_t flags)
Definition: rrset.c:435
rrset_type * rrset
Definition: denial.h:55
pthread_mutex_t ixfr_lock
Definition: ixfr.h:64
unsigned is_initialized
Definition: namedb.h:57
uint32_t outserial
Definition: namedb.h:55
unsigned needs_signing
Definition: rrset.h:67
uint32_t default_ttl
Definition: zone.h:63
namedb_type * db
Definition: zone.h:79
ixfr_type * ixfr
Definition: zone.h:80
const char * name
Definition: zone.h:69
rrset_type * zone_lookup_rrset(zone_type *zone, ldns_rdf *owner, ldns_rr_type type)
Definition: zone.c:510