OpenDNSSEC-signer 1.2.1

/build/buildd-opendnssec_1.2.1.dfsg-1-ia64-j6OroR/opendnssec-1.2.1.dfsg/signer/src/signer/signconf.c

Go to the documentation of this file.
00001 /*
00002  * $Id: signconf.c 4294 2011-01-13 19:58:29Z jakob $
00003  *
00004  * Copyright (c) 2009 NLNet Labs. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00016  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00019  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00021  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00023  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00025  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  */
00028 
00034 #include "parser/confparser.h"
00035 #include "parser/signconfparser.h"
00036 #include "scheduler/task.h"
00037 #include "signer/backup.h"
00038 #include "signer/se_key.h"
00039 #include "signer/signconf.h"
00040 #include "util/duration.h"
00041 #include "util/file.h"
00042 #include "util/log.h"
00043 #include "util/se_malloc.h"
00044 
00049 signconf_type*
00050 signconf_create(void)
00051 {
00052     signconf_type* sc = (signconf_type*) se_malloc(sizeof(signconf_type));
00053 
00054     /* Signatures */
00055     sc->sig_resign_interval = NULL;
00056     sc->sig_refresh_interval = NULL;
00057     sc->sig_validity_default = NULL;
00058     sc->sig_validity_denial = NULL;
00059     sc->sig_jitter = NULL;
00060     sc->sig_inception_offset = NULL;
00061     /* Denial of existence */
00062     sc->nsec_type = 0;
00063     sc->nsec3_optout = 0;
00064     sc->nsec3_algo = 0;
00065     sc->nsec3_iterations = 0;
00066     sc->nsec3_salt = NULL;
00067     /* Keys */
00068     sc->dnskey_ttl = NULL;
00069     sc->keys = NULL;
00070     /* Source of authority */
00071     sc->soa_ttl = NULL;
00072     sc->soa_min = NULL;
00073     sc->soa_serial = NULL;
00074     /* Other useful information */
00075     sc->last_modified = 0;
00076     sc->audit = 0;
00077 
00078     return sc;
00079 }
00080 
00081 
00086 signconf_type*
00087 signconf_read(const char* filename, time_t last_modified)
00088 {
00089     signconf_type* signconf;
00090     const char* rngfile = ODS_SE_RNGDIR "/signconf.rng";
00091     FILE* scfd = NULL;
00092     time_t st_mtime = 0;
00093 
00094     st_mtime = se_file_lastmodified(filename);
00095     if (st_mtime <= last_modified) {
00096         se_log_debug("signconf file %s is unchanged",
00097             filename?filename:"(null)");
00098         return NULL;
00099     }
00100 
00101     if (parse_file_check(filename, rngfile) != 0) {
00102         se_log_error("unable to parse signconf file %s",
00103             filename?filename:"(null)");
00104         return NULL;
00105     }
00106 
00107     scfd = se_fopen(filename, NULL, "r");
00108     if (scfd) {
00109         signconf = signconf_create();
00110         signconf->filename = se_strdup(filename);
00111         signconf->sig_resign_interval = parse_sc_sig_resign_interval(filename);
00112         signconf->sig_refresh_interval = parse_sc_sig_refresh_interval(filename);
00113         signconf->sig_validity_default = parse_sc_sig_validity_default(filename);
00114         signconf->sig_validity_denial = parse_sc_sig_validity_denial(filename);
00115         signconf->sig_jitter = parse_sc_sig_jitter(filename);
00116         signconf->sig_inception_offset = parse_sc_sig_inception_offset(filename);
00117         signconf->nsec_type = parse_sc_nsec_type(filename);
00118         if (signconf->nsec_type == LDNS_RR_TYPE_NSEC3) {
00119             signconf->nsec3_optout = parse_sc_nsec3_optout(filename);
00120             signconf->nsec3_algo = parse_sc_nsec3_algorithm(filename);
00121             signconf->nsec3_iterations = parse_sc_nsec3_iterations(filename);
00122             signconf->nsec3_salt = parse_sc_nsec3_salt(filename);
00123         }
00124         signconf->keys = parse_sc_keys(filename);
00125         signconf->dnskey_ttl = parse_sc_dnskey_ttl(filename);
00126         signconf->soa_ttl = parse_sc_soa_ttl(filename);
00127         signconf->soa_min = parse_sc_soa_min(filename);
00128         signconf->soa_serial = parse_sc_soa_serial(filename);
00129         signconf->audit = parse_sc_audit(filename);
00130         signconf->last_modified = st_mtime;
00131 
00132         se_fclose(scfd);
00133         return signconf;
00134     }
00135 
00136     se_log_error("unable to read signconf file %s", filename?filename:"(null)");
00137     return NULL;
00138 }
00139 
00140 
00145 signconf_type*
00146 signconf_recover_from_backup(const char* filename)
00147 {
00148     signconf_type* signconf = NULL;
00149     const char* zonename = NULL;
00150     FILE* scfd = NULL;
00151 
00152     scfd = se_fopen(filename, NULL, "r");
00153     if (scfd) {
00154         signconf = signconf_create();
00155 
00156         if (!backup_read_check_str(scfd, ODS_SE_FILE_MAGIC) ||
00157             !backup_read_check_str(scfd, ";name:") ||
00158             !backup_read_str(scfd, &zonename) ||
00159             !backup_read_check_str(scfd, ";filename:") ||
00160             !backup_read_str(scfd, &signconf->filename) ||
00161             !backup_read_check_str(scfd, ";last_modified:") ||
00162             !backup_read_time_t(scfd, &signconf->last_modified) ||
00163             !backup_read_check_str(scfd, ";sig_resign_interval:") ||
00164             !backup_read_duration(scfd, &signconf->sig_resign_interval) ||
00165             !backup_read_check_str(scfd, ";sig_refresh_interval:") ||
00166             !backup_read_duration(scfd, &signconf->sig_refresh_interval) ||
00167             !backup_read_check_str(scfd, ";sig_validity_default:") ||
00168             !backup_read_duration(scfd, &signconf->sig_validity_default) ||
00169             !backup_read_check_str(scfd, ";sig_validity_denial:") ||
00170             !backup_read_duration(scfd, &signconf->sig_validity_denial) ||
00171             !backup_read_check_str(scfd, ";sig_jitter:") ||
00172             !backup_read_duration(scfd, &signconf->sig_jitter) ||
00173             !backup_read_check_str(scfd, ";sig_inception_offset:") ||
00174             !backup_read_duration(scfd, &signconf->sig_inception_offset) ||
00175             !backup_read_check_str(scfd, ";nsec_type:") ||
00176             !backup_read_rr_type(scfd, &signconf->nsec_type) ||
00177             !backup_read_check_str(scfd, ";dnskey_ttl:") ||
00178             !backup_read_duration(scfd, &signconf->dnskey_ttl) ||
00179             !backup_read_check_str(scfd, ";soa_ttl:") ||
00180             !backup_read_duration(scfd, &signconf->soa_ttl) ||
00181             !backup_read_check_str(scfd, ";soa_min:") ||
00182             !backup_read_duration(scfd, &signconf->soa_min) ||
00183             !backup_read_check_str(scfd, ";soa_serial:") ||
00184             !backup_read_str(scfd, &signconf->soa_serial) ||
00185             !backup_read_check_str(scfd, ";audit:") ||
00186             !backup_read_int(scfd, &signconf->audit) ||
00187             !backup_read_check_str(scfd, ODS_SE_FILE_MAGIC))
00188         {
00189             se_log_error("unable to recover signconf backup file %s: corrupt "
00190                 "backup file ", filename?filename:"(null)");
00191             signconf_cleanup(signconf);
00192             signconf = NULL;
00193         }
00194 
00195         if (zonename) {
00196             se_free((void*) zonename);
00197         }
00198         se_fclose(scfd);
00199         return signconf;
00200     }
00201 
00202     se_log_debug("unable to recover signconf backup file %s",
00203         filename?filename:"(null)");
00204     return NULL;
00205 }
00206 
00207 
00212 static void
00213 signconf_backup_duration(FILE* fd, const char* opt, duration_type* duration)
00214 {
00215     char* str = duration2string(duration);
00216     fprintf(fd, ";%s: %s\n", opt, str);
00217     se_free((void*) str);
00218     return;
00219 }
00220 
00221 
00222 
00227 void
00228 signconf_backup(signconf_type* sc)
00229 {
00230     FILE* fd = NULL;
00231     char* filename = NULL;
00232 
00233     se_log_assert(sc);
00234 
00235     filename = se_build_path(sc->name, ".sc", 0);
00236     fd = se_fopen(filename, NULL, "w");
00237     if (fd) {
00238         fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC);
00239         fprintf(fd, ";name: %s\n", sc->name?sc->name:"(null)");
00240         fprintf(fd, ";filename: %s\n", sc->filename?sc->filename:"(null)");
00241         fprintf(fd, ";last_modified: %u\n", (uint32_t) sc->last_modified);
00242 
00243         signconf_backup_duration(fd, "sig_resign_interval",
00244             sc->sig_resign_interval);
00245         signconf_backup_duration(fd, "sig_refresh_interval",
00246             sc->sig_refresh_interval);
00247         signconf_backup_duration(fd, "sig_validity_default",
00248             sc->sig_validity_default);
00249         signconf_backup_duration(fd, "sig_validity_denial",
00250             sc->sig_validity_denial);
00251         signconf_backup_duration(fd, "sig_jitter",
00252             sc->sig_jitter);
00253         signconf_backup_duration(fd, "sig_inception_offset",
00254             sc->sig_inception_offset);
00255 
00256         fprintf(fd, ";nsec_type: %u\n", (unsigned int) sc->nsec_type);
00257 
00258         signconf_backup_duration(fd, "dnskey_ttl", sc->dnskey_ttl);
00261         signconf_backup_duration(fd, "soa_ttl", sc->soa_ttl);
00262         signconf_backup_duration(fd, "soa_min", sc->soa_min);
00263         fprintf(fd, ";soa_serial: %s\n",
00264             sc->soa_serial?sc->soa_serial:"(null)");
00265 
00266         fprintf(fd, ";audit: %i\n", sc->audit);
00267 
00268         fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC);
00269         se_fclose(fd);
00270     } else {
00271         se_log_warning("cannot backup signconf: cannot open file "
00272         "%s for writing", filename?filename:"(null)");
00273     }
00274     se_free((void*) filename);
00275     return;
00276 }
00277 
00278 
00283 static int
00284 signconf_soa_serial_check(const char* serial) {
00285     if (!serial) {
00286         return 1;
00287     }
00288 
00289     if (strlen(serial) == 4 && strncmp(serial, "keep", 4) == 0) {
00290         return 0;
00291     }
00292     if (strlen(serial) == 7 && strncmp(serial, "counter", 7) == 0) {
00293         return 0;
00294     }
00295     if (strlen(serial) == 8 && strncmp(serial, "unixtime", 8) == 0) {
00296         return 0;
00297     }
00298     if (strlen(serial) == 11 && strncmp(serial, "datecounter", 11) == 0) {
00299         return 0;
00300     }
00301     return 1;
00302 }
00303 
00308 int
00309 signconf_check(signconf_type* sc)
00310 {
00311     int ret = 0;
00312 
00313     if (!sc->sig_resign_interval) {
00314         se_log_error("signconf-check: no signature resign interval found");
00315         ret = 1;
00316     }
00317     if (!sc->sig_refresh_interval) {
00318         se_log_error("signconf-check: no signature resign interval found");
00319         ret = 1;
00320     }
00321     if (!sc->sig_validity_default) {
00322         se_log_error("signconf-check: no signature default validity found");
00323         ret = 1;
00324     }
00325     if (!sc->sig_validity_denial) {
00326         se_log_error("signconf-check: no signature denial validity found");
00327         ret = 1;
00328     }
00329     if (!sc->sig_jitter) {
00330         se_log_error("signconf-check: no signature jitter found");
00331         ret = 1;
00332     }
00333     if (!sc->sig_inception_offset) {
00334         se_log_error("signconf-check: no signature inception offset found");
00335         ret = 1;
00336     }
00337     if (sc->nsec_type == LDNS_RR_TYPE_NSEC3) {
00338         if (sc->nsec3_algo == 0) {
00339             se_log_error("signconf-check: no nsec3 algorithm found");
00340             ret = 1;
00341         }
00342         /* iterations */
00343         /* salt */
00344         /* optout */
00345     } else if (sc->nsec_type != LDNS_RR_TYPE_NSEC) {
00346         se_log_error("signconf-check: wrong nsec type %i", sc->nsec_type);
00347         ret = 1;
00348     }
00349     if (!sc->keys || sc->keys->count == 0) {
00350         se_log_error("signconf-check: no keys found");
00351         ret = 1;
00352     }
00353     if (!sc->dnskey_ttl) {
00354         se_log_error("signconf-check: no dnskey ttl found");
00355         ret = 1;
00356     }
00357     if (!sc->soa_ttl) {
00358         se_log_error("signconf-check: no soa ttl found");
00359         ret = 1;
00360     }
00361     if (!sc->soa_min) {
00362         se_log_error("signconf-check: no soa minimum found");
00363         ret = 1;
00364     }
00365     if (signconf_soa_serial_check(sc->soa_serial) != 0) {
00366         se_log_error("signconf-check: wrong soa serial type %s",
00367             sc->soa_serial?sc->soa_serial:"(null)");
00368         ret = 1;
00369     }
00370 
00371     if (!ret) {
00372         se_log_debug("signer configuration settings ok");
00373     }
00374     return ret;
00375 
00376 }
00377 
00378 
00383 int
00384 signconf_compare(signconf_type* a, signconf_type* b, int* update)
00385 {
00386    int new_task = TASK_SIGN;
00387 
00388    se_log_assert(a);
00389    se_log_assert(b);
00390 
00391    if (a->nsec_type != b->nsec_type) {
00392        new_task = TASK_READ;
00393        *update = 1;
00394    } else if (a->nsec_type == LDNS_RR_TYPE_NSEC3) {
00395        if ((se_strcmp(a->nsec3_salt, b->nsec3_salt) != 0) ||
00396            (a->nsec3_algo != b->nsec3_algo) ||
00397            (a->nsec3_iterations != b->nsec3_iterations) ||
00398            (a->nsec3_optout != b->nsec3_optout)) {
00399 
00400            new_task = TASK_READ;
00401            *update = 1;
00402        }
00403    }
00404 
00405    if (duration_compare(a->soa_min, b->soa_min) != 0) {
00406        new_task = TASK_READ;
00407        *update = 1;
00408    }
00409 
00410    if (keylist_compare(a->keys, b->keys) != 0) {
00411        new_task = TASK_READ;
00412    }
00413 
00414    /* not like python: reschedule if resign/refresh differs */
00415    /* this needs review, tasks correct on signconf changes? */
00416 
00417    return new_task;
00418 }
00419 
00424 void
00425 signconf_cleanup(signconf_type* sc)
00426 {
00427     if (sc) {
00428         if (sc->sig_resign_interval) {
00429             duration_cleanup(sc->sig_resign_interval);
00430             sc->sig_resign_interval = NULL;
00431         }
00432         if (sc->sig_refresh_interval) {
00433             duration_cleanup(sc->sig_refresh_interval);
00434             sc->sig_refresh_interval = NULL;
00435         }
00436         if (sc->sig_validity_default) {
00437             duration_cleanup(sc->sig_validity_default);
00438             sc->sig_validity_default = NULL;
00439         }
00440         if (sc->sig_validity_denial) {
00441             duration_cleanup(sc->sig_validity_denial);
00442             sc->sig_validity_denial = NULL;
00443         }
00444         if (sc->sig_jitter) {
00445             duration_cleanup(sc->sig_jitter);
00446             sc->sig_jitter = NULL;
00447         }
00448         if (sc->sig_inception_offset) {
00449             duration_cleanup(sc->sig_inception_offset);
00450             sc->sig_inception_offset = NULL;
00451         }
00452         if (sc->dnskey_ttl) {
00453             duration_cleanup(sc->dnskey_ttl);
00454             sc->dnskey_ttl = NULL;
00455         }
00456         if (sc->soa_ttl) {
00457             duration_cleanup(sc->soa_ttl);
00458             sc->soa_ttl = NULL;
00459         }
00460         if (sc->soa_min) {
00461             duration_cleanup(sc->soa_min);
00462             sc->soa_min = NULL;
00463         }
00464         if (sc->keys) {
00465             keylist_cleanup(sc->keys);
00466             sc->keys = NULL;
00467         }
00468         if (sc->nsec3_salt) {
00469             se_free((void*)sc->nsec3_salt);
00470             sc->nsec3_salt = NULL;
00471         }
00472         if (sc->soa_serial) {
00473             se_free((void*)sc->soa_serial);
00474             sc->soa_serial = NULL;
00475         }
00476         if (sc->filename) {
00477             se_free((void*)sc->filename);
00478             sc->filename = NULL;
00479         }
00480         se_free((void*)sc);
00481     } else {
00482         se_log_warning("cleanup empty signconf");
00483     }
00484 }
00485 
00486 
00491 void
00492 signconf_print(FILE* out, signconf_type* sc, const char* name)
00493 {
00494     char* s = NULL;
00495 
00496     fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00497 
00498     if (sc) {
00499         fprintf(out, "<SignerConfiguration>\n");
00500         fprintf(out, "\t<Zone name=\"%s\">\n", name?name:"(null)");
00501 
00502         /* Signatures */
00503         fprintf(out, "\t\t<Signatures>\n");
00504         s = duration2string(sc->sig_resign_interval);
00505         fprintf(out, "\t\t\t<Resign>%s</Resign>\n", s?s:"(null)");
00506         se_free((void*)s);
00507 
00508         s = duration2string(sc->sig_refresh_interval);
00509         fprintf(out, "\t\t\t<Refresh>%s</Refresh>\n", s?s:"(null)");
00510         se_free((void*)s);
00511 
00512         fprintf(out, "\t\t\t<Validity>\n");
00513 
00514         s = duration2string(sc->sig_validity_default);
00515         fprintf(out, "\t\t\t\t<Default>%s</Default>\n", s?s:"(null)");
00516         se_free((void*)s);
00517 
00518         s = duration2string(sc->sig_validity_denial);
00519         fprintf(out, "\t\t\t\t<Denial>%s</Denial>\n", s?s:"(null)");
00520         se_free((void*)s);
00521 
00522         fprintf(out, "\t\t\t</Validity>\n");
00523 
00524         s = duration2string(sc->sig_jitter);
00525         fprintf(out, "\t\t\t<Jitter>%s</Jitter>\n", s?s:"(null)");
00526         se_free((void*)s);
00527 
00528         s = duration2string(sc->sig_inception_offset);
00529         fprintf(out, "\t\t\t<InceptionOffset>%s</InceptionOffset>\n",
00530             s?s:"(null)");
00531         se_free((void*)s);
00532 
00533         fprintf(out, "\t\t</Signatures>\n");
00534         fprintf(out, "\n");
00535 
00536         /* Denial */
00537         fprintf(out, "\t\t<Denial>\n");
00538         if (sc->nsec_type == LDNS_RR_TYPE_NSEC) {
00539             fprintf(out, "\t\t\t<NSEC />\n");
00540         } else if (sc->nsec_type == LDNS_RR_TYPE_NSEC3) {
00541             fprintf(out, "\t\t\t<NSEC3>\n");
00542             if (sc->nsec3_optout) {
00543                 fprintf(out, "\t\t\t\t<OptOut />\n");
00544             }
00545             fprintf(out, "\t\t\t\t<Hash>\n");
00546             fprintf(out, "\t\t\t\t\t<Algorithm>%i</Algorithm>\n",
00547                 sc->nsec3_algo);
00548             fprintf(out, "\t\t\t\t\t<Iterations>%i</Iterations>\n",
00549                 sc->nsec3_iterations);
00550             fprintf(out, "\t\t\t\t\t<Salt>%s</Salt>\n",
00551                 sc->nsec3_salt?sc->nsec3_salt:"(null)");
00552             fprintf(out, "\t\t\t\t</Hash>\n");
00553             fprintf(out, "\t\t\t</NSEC3>\n");
00554         }
00555         fprintf(out, "\t\t</Denial>\n");
00556         fprintf(out, "\n");
00557 
00558         /* Keys */
00559         fprintf(out, "\t\t<Keys>\n");
00560         s = duration2string(sc->dnskey_ttl);
00561         fprintf(out, "\t\t\t<TTL>%s</TTL>\n", s?s:"(null)");
00562         se_free((void*)s);
00563         fprintf(out, "\n");
00564         keylist_print(out, sc->keys);
00565         fprintf(out, "\t\t</Keys>\n");
00566         fprintf(out, "\n");
00567 
00568         /* SOA */
00569         fprintf(out, "\t\t<SOA>\n");
00570         s = duration2string(sc->soa_ttl);
00571         fprintf(out, "\t\t\t<TTL>%s</TTL>\n", s?s:"(null)");
00572         se_free((void*)s);
00573 
00574         s = duration2string(sc->soa_min);
00575         fprintf(out, "\t\t\t<Minimum>%s</Minimum>\n", s?s:"(null)");
00576         se_free((void*)s);
00577 
00578         fprintf(out, "\t\t\t<Serial>%s</Serial>\n",
00579             sc->soa_serial?sc->soa_serial:"(null)");
00580         fprintf(out, "\t\t</SOA>\n");
00581         fprintf(out, "\n");
00582 
00583         /* Audit */
00584         if (sc->audit) {
00585             fprintf(out, "\t\t<Audit />\n");
00586             fprintf(out, "\n");
00587         }
00588 
00589         fprintf(out, "\t</Zone>\n");
00590         fprintf(out, "</SignerConfiguration>\n");
00591     }
00592 
00593     return;
00594 }