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