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
27 /**
28 * Recover from backup.
29 *
30 */
31
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
48 /**
49 * Read token from backup file.
50 *
51 */
52 char*
backup_read_token(FILE * in)53 backup_read_token(FILE* in)
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
72 /**
73 * Read and match a string from backup file.
74 *
75 */
76 int
backup_read_check_str(FILE * in,const char * str)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
99 /**
100 * Read a string from backup file.
101 *
102 */
103 int
backup_read_str(FILE * in,const char ** str)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
116 /**
117 * Read time from backup file.
118 *
119 */
120 int
backup_read_time_t(FILE * in,time_t * v)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
133 /**
134 * Read duration from backup file.
135 *
136 */
137 int
backup_read_duration(FILE * in,duration_type ** v)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
153 /**
154 * Read rr type from backup file.
155 *
156 */
157 int
backup_read_rr_type(FILE * in,ldns_rr_type * v)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
170 /**
171 * Read integer from backup file.
172 *
173 */
174 int
backup_read_int(FILE * in,int * v)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
187 /**
188 * Read 8bit unsigned integer from backup file.
189 *
190 */
191 int
backup_read_uint8_t(FILE * in,uint8_t * v)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
204 /**
205 * Read 32bit unsigned integer from backup file.
206 *
207 */
208 int
backup_read_uint32_t(FILE * in,uint32_t * v)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
221 /**
222 * Read the next RR from the backup file.
223 *
224 */
225 static ldns_rr*
backup_read_rr(FILE * in,zone_type * zone,char * line,ldns_rdf ** orig,ldns_rdf ** prev,ldns_status * status,unsigned int * l)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
277 /**
278 * Get locator from string.
279 *
280 */
281 static char*
replace_space_with_nul(char * str)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
299 /**
300 * Read namedb from backup file.
301 *
302 */
303 ods_status
backup_read_namedb(FILE * in,void * zone)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
493 /**
494 * Read ixfr journal from file.
495 *
496 *
497 */
498 ods_status
backup_read_ixfr(FILE * in,void * zone)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
643