diff -Naur validns-0.8/afsdb.c validns-0.8_git20160720/afsdb.c --- validns-0.8/afsdb.c 2014-02-11 15:46:27.000000000 -0500 +++ validns-0.8_git20160720/afsdb.c 2016-02-04 09:14:15.000000000 -0500 @@ -21,7 +21,7 @@ { struct rr_afsdb *rr = getmem(sizeof(*rr)); - rr->subtype = extract_integer(&s, "AFSDB subtype"); + rr->subtype = extract_integer(&s, "AFSDB subtype", NULL); if (rr->subtype < 0) return NULL; diff -Naur validns-0.8/cert.c validns-0.8_git20160720/cert.c --- validns-0.8/cert.c 2014-02-11 15:46:12.000000000 -0500 +++ validns-0.8_git20160720/cert.c 2016-02-04 09:14:15.000000000 -0500 @@ -30,7 +30,7 @@ char *str_type; if (isdigit(**s)) { - type = extract_integer(s, what); + type = extract_integer(s, what, NULL); if (type >= 1 && type <= 8) return type; if (type == 253 || type == 254) @@ -84,14 +84,14 @@ if (cert_type < 0) return NULL; rr->type = cert_type; - key_tag = extract_integer(&s, "key tag"); + key_tag = extract_integer(&s, "key tag", NULL); if (key_tag < 0) return NULL; if (key_tag > 65535) return bitch("bad key tag"); rr->key_tag = key_tag; if (isdigit(*s)) { - alg = extract_integer(&s, "algorithm"); + alg = extract_integer(&s, "algorithm", NULL); if (alg < 0) return NULL; if (alg > 255) return bitch("bad algorithm"); if (alg != 0) { /* 0 is just fine */ diff -Naur validns-0.8/common.h validns-0.8_git20160720/common.h --- validns-0.8/common.h 2014-02-11 15:45:02.000000000 -0500 +++ validns-0.8_git20160720/common.h 2016-02-04 09:14:15.000000000 -0500 @@ -9,19 +9,37 @@ #ifndef _COMMON_H_ #define _COMMON_H_ 1 +struct generate_template_piece; +struct generate_template_piece +{ + char *constant_string; + struct generate_template_piece *next; +}; + +#define LINEBUFSZ 2048 + struct file_info { struct file_info *next; FILE *file; int line; int paren_mode; - char buf[2048]; + char buf[LINEBUFSZ]; + char *current_origin; + + int generate_cur; + int generate_lim; + char *generate_type; + struct generate_template_piece *generate_lhs; + struct generate_template_piece *generate_rhs; + + /* must be last struct member */ char name[0]; }; extern struct file_info *file_info; -#define N_POLICY_CHECKS 9 +#define N_POLICY_CHECKS 10 #define POLICY_SINGLE_NS 0 #define POLICY_CNAME_OTHER_DATA 1 @@ -32,6 +50,7 @@ #define POLICY_DNAME 6 #define POLICY_DNSKEY 7 #define POLICY_TLSA_HOST 8 +#define POLICY_KSK_EXISTS 9 #define MAX_TIMES_TO_CHECK 32 @@ -55,11 +74,13 @@ int summary; int verbose; char *include_path; - char *current_origin; + int include_path_specified; + char *first_origin; int n_times_to_check; uint32_t times_to_check[MAX_TIMES_TO_CHECK]; char policy_checks[N_POLICY_CHECKS]; int n_threads; + int soa_minttl_as_default_ttl; } opt; int exit_code; long default_ttl; diff -Naur validns-0.8/dlv.c validns-0.8_git20160720/dlv.c --- validns-0.8/dlv.c 2014-02-11 15:46:32.000000000 -0500 +++ validns-0.8_git20160720/dlv.c 2016-02-04 09:14:15.000000000 -0500 @@ -22,7 +22,7 @@ struct rr_dlv *rr = getmem(sizeof(*rr)); int key_tag, algorithm, digest_type; - key_tag = extract_integer(&s, "key tag"); + key_tag = extract_integer(&s, "key tag", NULL); if (key_tag < 0) return NULL; rr->key_tag = key_tag; @@ -30,7 +30,7 @@ if (algorithm == ALG_UNSUPPORTED) return NULL; rr->algorithm = algorithm; - digest_type = extract_integer(&s, "digest type"); + digest_type = extract_integer(&s, "digest type", NULL); if (digest_type < 0) return NULL; rr->digest_type = digest_type; diff -Naur validns-0.8/dnskey.c validns-0.8_git20160720/dnskey.c --- validns-0.8/dnskey.c 2014-02-11 15:45:11.000000000 -0500 +++ validns-0.8_git20160720/dnskey.c 2016-02-04 09:14:15.000000000 -0500 @@ -20,6 +20,8 @@ #include "carp.h" #include "rr.h" +static struct rr_dnskey *all_dns_keys = NULL; + static struct rr* dnskey_parse(char *name, long ttl, int type, char *s) { struct rr_dnskey *rr = getmem(sizeof(*rr)); @@ -27,10 +29,11 @@ int flags, proto, algorithm; unsigned int ac; int i; + static struct rr *result; - flags = extract_integer(&s, "flags"); + flags = extract_integer(&s, "flags", NULL); if (flags < 0) return NULL; - if (flags & 0xfefe) + if (flags & 0xfe7e) return bitch("reserved flags bits are set"); if (flags & 0x0001 && !(flags & 0x0100)) return bitch("SEP bit is set but Zone Key bit is unset"); @@ -38,7 +41,7 @@ /* TODO validate that `name` is the name of the zone if flags have Zone Key bit set */ - proto = extract_integer(&s, "protocol"); + proto = extract_integer(&s, "protocol", NULL); if (proto < 0) return NULL; if (proto != 3) return bitch("bad protocol value"); @@ -68,11 +71,17 @@ rr->pkey_built = 0; rr->pkey = NULL; + rr->key_type = KEY_TYPE_UNUSED; if (*s) { return bitch("garbage after valid DNSKEY data"); } - return store_record(type, name, ttl, rr); + result = store_record(type, name, ttl, rr); + if (result) { + rr->next_key = all_dns_keys; + all_dns_keys = rr; + } + return result; } static char* dnskey_human(struct rr *rrv) @@ -187,3 +196,18 @@ return rr->pkey ? 1 : 0; } +void +dnskey_ksk_policy_check(void) +{ + struct rr_dnskey *rr = all_dns_keys; + int ksk_found = 0; + + while (rr) { + if (rr->key_type == KEY_TYPE_KSK) + ksk_found = 1; + rr = rr->next_key; + } + if (!ksk_found) + moan(all_dns_keys->rr.file_name, all_dns_keys->rr.line, "No KSK found"); +} + diff -Naur validns-0.8/ds.c validns-0.8_git20160720/ds.c --- validns-0.8/ds.c 2014-02-11 15:44:59.000000000 -0500 +++ validns-0.8_git20160720/ds.c 2016-02-04 09:14:15.000000000 -0500 @@ -22,7 +22,7 @@ struct rr_ds *rr = getmem(sizeof(*rr)); int key_tag, algorithm, digest_type; - key_tag = extract_integer(&s, "key tag"); + key_tag = extract_integer(&s, "key tag", NULL); if (key_tag < 0) return NULL; rr->key_tag = key_tag; @@ -30,7 +30,7 @@ if (algorithm == ALG_UNSUPPORTED) return NULL; rr->algorithm = algorithm; - digest_type = extract_integer(&s, "digest type"); + digest_type = extract_integer(&s, "digest type", NULL); if (digest_type < 0) return NULL; rr->digest_type = digest_type; diff -Naur validns-0.8/ipseckey.c validns-0.8_git20160720/ipseckey.c --- validns-0.8/ipseckey.c 2014-02-11 15:46:25.000000000 -0500 +++ validns-0.8_git20160720/ipseckey.c 2016-02-04 09:14:15.000000000 -0500 @@ -24,15 +24,15 @@ struct rr_ipseckey *rr = getmem(sizeof(*rr)); int i; - rr->precedence = i = extract_integer(&s, "precedence"); + rr->precedence = i = extract_integer(&s, "precedence", NULL); if (i < 0) return NULL; if (i >= 256) return bitch("precedence range is not valid"); - rr->gateway_type = i = extract_integer(&s, "gateway type"); + rr->gateway_type = i = extract_integer(&s, "gateway type", NULL); if (i < 0) return NULL; if (i > 3) return bitch("gateway type is not valid"); - rr->algorithm = i = extract_integer(&s, "algorithm"); + rr->algorithm = i = extract_integer(&s, "algorithm", NULL); if (i < 0) return NULL; if (i > 2) return bitch("algorithm is not valid"); diff -Naur validns-0.8/kx.c validns-0.8_git20160720/kx.c --- validns-0.8/kx.c 2014-02-11 15:46:36.000000000 -0500 +++ validns-0.8_git20160720/kx.c 2016-02-04 09:14:15.000000000 -0500 @@ -21,7 +21,7 @@ { struct rr_kx *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "KX preference"); + rr->preference = extract_integer(&s, "KX preference", NULL); if (rr->preference < 0) return NULL; diff -Naur validns-0.8/l32.c validns-0.8_git20160720/l32.c --- validns-0.8/l32.c 2014-02-11 15:46:17.000000000 -0500 +++ validns-0.8_git20160720/l32.c 2016-02-04 09:14:15.000000000 -0500 @@ -23,7 +23,7 @@ struct in_addr ipv4_like; int preference; - rr->preference = preference = extract_integer(&s, "L32 preference"); + rr->preference = preference = extract_integer(&s, "L32 preference", NULL); if (preference < 0) return NULL; if (extract_ipv4(&s, "Locator32", &ipv4_like) <= 0) diff -Naur validns-0.8/l64.c validns-0.8_git20160720/l64.c --- validns-0.8/l64.c 2014-02-11 15:46:18.000000000 -0500 +++ validns-0.8_git20160720/l64.c 2016-02-04 09:14:15.000000000 -0500 @@ -22,7 +22,7 @@ struct rr_l64 *rr = getmem(sizeof(*rr)); int preference; - rr->preference = preference = extract_integer(&s, "L64 preference"); + rr->preference = preference = extract_integer(&s, "L64 preference", NULL); if (preference < 0) return NULL; if (extract_u64(&s, "Locator64", &rr->locator64) < 0) diff -Naur validns-0.8/loc.c validns-0.8_git20160720/loc.c --- validns-0.8/loc.c 2014-02-11 15:45:16.000000000 -0500 +++ validns-0.8_git20160720/loc.c 2016-02-04 09:14:15.000000000 -0500 @@ -56,7 +56,7 @@ rr->version = 0; /* latitude block */ - i = extract_integer(&s, "degrees latitude"); + i = extract_integer(&s, "degrees latitude", NULL); if (i < 0) return NULL; if (i > 90) @@ -65,7 +65,7 @@ min = 0; sec = 0; if (isdigit(*s)) { - i = extract_integer(&s, "minutes latitude"); + i = extract_integer(&s, "minutes latitude", NULL); if (i < 0) return NULL; if (i > 59) @@ -96,7 +96,7 @@ if (!s) return NULL; /* longitude block */ - i = extract_integer(&s, "degrees longitude"); + i = extract_integer(&s, "degrees longitude", NULL); if (i < 0) return NULL; if (i > 180) @@ -105,7 +105,7 @@ min = 0; sec = 0; if (isdigit(*s)) { - i = extract_integer(&s, "minutes longitude"); + i = extract_integer(&s, "minutes longitude", NULL); if (i < 0) return NULL; if (i > 59) diff -Naur validns-0.8/lp.c validns-0.8_git20160720/lp.c --- validns-0.8/lp.c 2014-02-11 15:45:55.000000000 -0500 +++ validns-0.8_git20160720/lp.c 2016-02-04 09:14:15.000000000 -0500 @@ -23,7 +23,7 @@ struct rr_lp *rr = getmem(sizeof(*rr)); int preference; - rr->preference = preference = extract_integer(&s, "LP preference"); + rr->preference = preference = extract_integer(&s, "LP preference", NULL); if (preference < 0) return NULL; rr->fqdn = extract_name(&s, "LP fqdn", 0); diff -Naur validns-0.8/main.c validns-0.8_git20160720/main.c --- validns-0.8/main.c 2014-02-11 15:47:10.000000000 -0500 +++ validns-0.8_git20160720/main.c 2016-02-04 09:14:15.000000000 -0500 @@ -17,6 +17,7 @@ #include #include #include +#include #include "common.h" #include "carp.h" @@ -27,8 +28,80 @@ struct globals G; struct file_info *file_info = NULL; -int -read_zone_file(void); +int read_zone_file(void); +void open_zone_file(char *fname); + +static void +concat_generate_template(char *buf, int bufsz, int val, struct generate_template_piece *t) +{ + char sval[40]; + + while (t) { + if (t->constant_string) { + mystrlcat(buf, t->constant_string, bufsz); + } else { + snprintf(sval, 40, "%d", val); + mystrlcat(buf, sval, bufsz); + } + t = t->next; + } +} + +static struct generate_template_piece * +free_generate_template(struct generate_template_piece *t) +{ + struct generate_template_piece *n; + while (t) { + n = t->next; + free(t); + t = n; + } + return NULL; +} + +static void +create_generate_template_piece(struct generate_template_piece **generate_template, char *s) +{ + if (s && *s == 0) + return; + + struct generate_template_piece *p = malloc(sizeof(struct generate_template_piece)); + + p->constant_string = s; + p->next = NULL; + + if (*generate_template) { + struct generate_template_piece *t = *generate_template; + while (t->next) + t = t->next; + t->next = p; + } else { + *generate_template = p; + } +} + +static struct generate_template_piece * +prepare_generate_template(char *t) +{ + char *s = t; + struct generate_template_piece *r = NULL; + + while (1) { + while (*t && *t != '$') t++; + if (!*t) { + create_generate_template_piece(&r, s); + break; + } else { + *t = 0; + create_generate_template_piece(&r, s); + create_generate_template_piece(&r, NULL); + t++; + s = t; + } + } + + return r; +} static char *process_directive(char *s) { @@ -48,7 +121,7 @@ if (*s) { return bitch("garbage after valid $ORIGIN directive"); } - G.opt.current_origin = o; + file_info->current_origin = o; if (G.opt.verbose) { fprintf(stderr, "-> %s:%d: ", file_info->name, file_info->line); fprintf(stderr, "origin is now %s\n", o); @@ -71,14 +144,80 @@ fprintf(stderr, "-> %s:%d: ", file_info->name, file_info->line); fprintf(stderr, "default ttl is now %ld\n", G.default_ttl); } + } else if (*(s+1) == 'G' && strncmp(s, "$GENERATE", 9) == 0) { + int from, to; + char *lhs, *rdtype; + + s += 9; + if (!isspace(*s)) { + if (isalnum(*s)) goto unrecognized_directive; + return bitch("bad $GENERATE format"); + } + s = skip_white_space(s); + + from = extract_integer(&s, "generate-from", "-"); + if (from < 0) + return NULL; + if (*s != '-') + return bitch("'-' between generate-from and generate-to is expected"); + s++; + to = extract_integer(&s, "generate-to", "-"); + if (to < 0) + return NULL; + + if (*s == '/') + return bitch("generate-step is unsupported for now"); + + lhs = extract_name(&s, "generate-lhs", KEEP_CAPITALIZATION | DOLLAR_OK_IN_NAMES); + if (!lhs) + return NULL; + + if (*s == '{') + return bitch("{offset,width,type} is unsupported for now"); + + rdtype = extract_label(&s, "type", NULL); + if (!rdtype) + return NULL; + + file_info->generate_cur = from; + file_info->generate_lim = to; + file_info->generate_type = rdtype; + file_info->generate_lhs = prepare_generate_template(lhs); + file_info->generate_rhs = prepare_generate_template(quickstrdup(s)); + + return s; } else if (*(s+1) == 'I' && strncmp(s, "$INCLUDE", 8) == 0) { + char *p, *f; + char c; s += 8; if (!isspace(*s)) { if (isalnum(*s)) goto unrecognized_directive; return bitch("bad $INCLUDE format"); } s = skip_white_space(s); - return bitch("XXX include support is not implemented"); + p = s; + while (*s && !isspace(*s) && *s != ';') + s++; + c = *s; + *s = '\0'; + if (!*p) { + return bitch("$INCLUDE directive with empty file name"); + } + f = quickstrdup_temp(p); + *s = c; + s = skip_white_space(s); + + if (*s) { + return bitch("garbage after valid $INCLUDE directive"); + } + if (*f == '/') { + open_zone_file(f); + } else { + char buf[1024]; + + snprintf(buf, 1024, "%s/%s", G.opt.include_path, f); + open_zone_file(buf); + } } else { unrecognized_directive: s = d-1; @@ -89,6 +228,39 @@ return s; } +char * +read_zone_line(void) +{ + char *r; + + if (file_info->generate_lhs) { + if (file_info->generate_cur <= file_info->generate_lim) { + file_info->buf[0] = 0; + concat_generate_template(file_info->buf, LINEBUFSZ, file_info->generate_cur, file_info->generate_lhs); + mystrlcat(file_info->buf, " ", LINEBUFSZ); + mystrlcat(file_info->buf, file_info->generate_type, LINEBUFSZ); + mystrlcat(file_info->buf, " ", LINEBUFSZ); + concat_generate_template(file_info->buf, LINEBUFSZ, file_info->generate_cur, file_info->generate_rhs); + file_info->generate_cur++; + return file_info->buf; + } else { + /* Done with this $GENERATE */ + file_info->generate_cur = 0; + file_info->generate_lim = 0; + file_info->generate_type = NULL; + file_info->generate_lhs = NULL; + free_generate_template(file_info->generate_lhs); + free_generate_template(file_info->generate_rhs); + file_info->generate_rhs = NULL; + } + } + + r = fgets(file_info->buf, LINEBUFSZ, file_info->file); + if (r) + file_info->line++; + return r; +} + int read_zone_file(void) { @@ -96,9 +268,8 @@ char *name = NULL, *class, *rdtype; long ttl = -1; while (file_info) { - while (fgets(file_info->buf, 2048, file_info->file)) { + while (read_zone_line()) { freeall_temp(); - file_info->line++; file_info->paren_mode = 0; rdtype = NULL; if (empty_line_or_comment(file_info->buf)) @@ -179,23 +350,36 @@ if (ttl < 0) { ttl = G.default_ttl; } - if (ttl < 0) { - bitch("ttl not specified and default is not known"); - continue; - } { int is_generic; int type = str2rdtype(rdtype, &is_generic); + struct rr *rr; + if (type <= 0) continue; + + if (ttl < 0 && !(G.opt.soa_minttl_as_default_ttl && type == T_SOA)) { + bitch("ttl not specified and default is not known"); + continue; + } + if (is_generic) - rr_parse_any(name, ttl, type, s); + rr = rr_parse_any(name, ttl, type, s); else if (type > T_MAX) - rr_parse_any(name, ttl, type, s); + rr = rr_parse_any(name, ttl, type, s); else if (rr_methods[type].rr_parse) - rr_methods[type].rr_parse(name, ttl, type, s); + rr = rr_methods[type].rr_parse(name, ttl, type, s); else - rr_parse_any(name, ttl, type, s); + rr = rr_parse_any(name, ttl, type, s); + + if (type == T_SOA && ttl < 0 && rr) { + struct rr_soa *soa = (struct rr_soa *) rr; + soa->rr.ttl = G.default_ttl = soa->minimum; + if (G.opt.verbose) { + fprintf(stderr, "-> %s:%d: ", file_info->name, file_info->line); + fprintf(stderr, "no ttl specified; using SOA MINTTL (%ld) instead\n", G.default_ttl); + } + } } } if (ferror(file_info->file)) @@ -216,6 +400,9 @@ fname = "stdin"; } else { f = fopen(fname, "r"); + if (!file_info && !G.opt.include_path_specified) { + G.opt.include_path = quickstrdup(dirname(quickstrdup_temp(fname))); + } } if (!f) croak(1, "open %s", fname); @@ -226,6 +413,11 @@ new_file_info->file = f; new_file_info->line = 0; strcpy(new_file_info->name, fname); + if (file_info) { + new_file_info->current_origin = file_info->current_origin; + } else { + new_file_info->current_origin = G.opt.first_origin; + } file_info = new_file_info; } @@ -248,6 +440,8 @@ fprintf(stderr, "\t\t\tmx-alias\n"); fprintf(stderr, "\t\t\tns-alias\n"); fprintf(stderr, "\t\t\trp-txt-exists\n"); + fprintf(stderr, "\t\t\ttlsa-host\n"); + fprintf(stderr, "\t\t\tksk-exists\n"); fprintf(stderr, "\t\t\tall\n"); fprintf(stderr, "\t-n N\t\tuse N worker threads\n"); @@ -273,6 +467,7 @@ G.default_ttl = -1; /* XXX orly? */ G.opt.times_to_check[0] = time(NULL); G.opt.n_times_to_check = 0; + G.opt.include_path = "."; for (i = 0; i <= T_MAX; i++) { rr_methods[i] = unknown_methods; @@ -328,7 +523,7 @@ struct timeval start, stop; initialize_globals(); - while ((o = getopt(argc, argv, "fhqsvI:z:t:p:n:")) != -1) { + while ((o = getopt(argc, argv, "fhMqsvI:z:t:p:n:")) != -1) { switch(o) { case 'h': usage(NULL); @@ -336,6 +531,9 @@ case 'f': G.opt.die_on_first_error = 1; break; + case 'M': + G.opt.soa_minttl_as_default_ttl = 1; + break; case 'q': G.opt.no_output = 1; break; @@ -369,19 +567,22 @@ G.opt.policy_checks[POLICY_RP_TXT_EXISTS] = 1; } else if (strcmp(optarg, "tlsa-host") == 0) { G.opt.policy_checks[POLICY_TLSA_HOST] = 1; + } else if (strcmp(optarg, "ksk-exists") == 0) { + G.opt.policy_checks[POLICY_KSK_EXISTS] = 1; } else { usage("unknown policy name"); } break; case 'I': G.opt.include_path = optarg; + G.opt.include_path_specified = 1; break; case 'z': if (strlen(optarg) && *(optarg+strlen(optarg)-1) == '.') { - G.opt.current_origin = optarg; + G.opt.first_origin = optarg; } else if (strlen(optarg)) { - G.opt.current_origin = getmem(strlen(optarg)+2); - strcpy(mystpcpy(G.opt.current_origin, optarg), "."); + G.opt.first_origin = getmem(strlen(optarg)+2); + strcpy(mystpcpy(G.opt.first_origin, optarg), "."); } else { usage("origin must not be empty"); } @@ -417,6 +618,9 @@ if (first_nsec3) nsec3_validate(&first_nsec3->rr); perform_remaining_nsec3checks(); } + if (G.dnssec_active && G.opt.policy_checks[POLICY_KSK_EXISTS]) { + dnskey_ksk_policy_check(); + } gettimeofday(&stop, NULL); if (G.opt.summary) { printf("records found: %d\n", G.stats.rr_count); diff -Naur validns-0.8/mx.c validns-0.8_git20160720/mx.c --- validns-0.8/mx.c 2014-02-11 15:45:19.000000000 -0500 +++ validns-0.8_git20160720/mx.c 2016-02-04 09:14:15.000000000 -0500 @@ -21,7 +21,7 @@ { struct rr_mx *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "MX preference"); + rr->preference = extract_integer(&s, "MX preference", NULL); if (rr->preference < 0) return NULL; /* XXX preference range check */ diff -Naur validns-0.8/naptr.c validns-0.8_git20160720/naptr.c --- validns-0.8/naptr.c 2014-02-11 15:45:22.000000000 -0500 +++ validns-0.8_git20160720/naptr.c 2016-02-04 09:14:15.000000000 -0500 @@ -24,14 +24,14 @@ int i; struct binary_data text; - i = extract_integer(&s, "order"); + i = extract_integer(&s, "order", NULL); if (i < 0) return NULL; if (i >= 65536) return bitch("order range is not valid"); rr->order = i; - i = extract_integer(&s, "preference"); + i = extract_integer(&s, "preference", NULL); if (i < 0) return NULL; if (i >= 65536) diff -Naur validns-0.8/nid.c validns-0.8_git20160720/nid.c --- validns-0.8/nid.c 2014-02-11 15:46:20.000000000 -0500 +++ validns-0.8_git20160720/nid.c 2016-02-04 09:14:15.000000000 -0500 @@ -22,7 +22,7 @@ struct rr_nid *rr = getmem(sizeof(*rr)); int preference; - rr->preference = preference = extract_integer(&s, "NID preference"); + rr->preference = preference = extract_integer(&s, "NID preference", NULL); if (preference < 0) return NULL; if (extract_u64(&s, "NodeID", &rr->node_id) < 0) diff -Naur validns-0.8/nsec3.c validns-0.8_git20160720/nsec3.c --- validns-0.8/nsec3.c 2014-02-11 15:45:31.000000000 -0500 +++ validns-0.8_git20160720/nsec3.c 2016-02-04 09:14:15.000000000 -0500 @@ -31,7 +31,7 @@ char *str_type = NULL; int ltype; - i = extract_integer(&s, "hash algorithm"); + i = extract_integer(&s, "hash algorithm", NULL); if (i < 0) return NULL; if (i > 255) @@ -40,7 +40,7 @@ return bitch("unrecognized or unsupported hash algorithm"); rr->hash_algorithm = i; - i = extract_integer(&s, "flags"); + i = extract_integer(&s, "flags", NULL); if (i < 0) return NULL; if (i > 255) @@ -52,7 +52,7 @@ opt_out = 1; rr->flags = i; - i = extract_integer(&s, "iterations"); + i = extract_integer(&s, "iterations", NULL); if (i < 0) return NULL; if (i > 2500) diff -Naur validns-0.8/nsec3param.c validns-0.8_git20160720/nsec3param.c --- validns-0.8/nsec3param.c 2014-02-11 15:45:41.000000000 -0500 +++ validns-0.8_git20160720/nsec3param.c 2016-02-04 09:14:15.000000000 -0500 @@ -27,7 +27,7 @@ struct rr *ret_rr; int i; - i = extract_integer(&s, "hash algorithm"); + i = extract_integer(&s, "hash algorithm", NULL); if (i < 0) return NULL; if (i > 255) @@ -36,7 +36,7 @@ return bitch("unrecognized or unsupported hash algorithm"); rr->hash_algorithm = i; - i = extract_integer(&s, "flags"); + i = extract_integer(&s, "flags", NULL); if (i < 0) return NULL; if (i > 255) @@ -45,7 +45,7 @@ return bitch("flags is supposed to be 0 for NSEC3PARAM"); rr->flags = i; - i = extract_integer(&s, "iterations"); + i = extract_integer(&s, "iterations", NULL); if (i < 0) return NULL; if (i > 2500) diff -Naur validns-0.8/px.c validns-0.8_git20160720/px.c --- validns-0.8/px.c 2014-02-11 15:46:50.000000000 -0500 +++ validns-0.8_git20160720/px.c 2016-02-04 09:14:15.000000000 -0500 @@ -21,7 +21,7 @@ { struct rr_px *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "PX preference"); + rr->preference = extract_integer(&s, "PX preference", NULL); if (rr->preference < 0) return NULL; diff -Naur validns-0.8/rr.c validns-0.8_git20160720/rr.c --- validns-0.8/rr.c 2014-02-11 15:45:34.000000000 -0500 +++ validns-0.8_git20160720/rr.c 2016-02-04 09:14:15.000000000 -0500 @@ -432,7 +432,7 @@ s = skip_white_space(s); if (!s) return NULL; - len = extract_integer(&s, "custom data size"); + len = extract_integer(&s, "custom data size", NULL); if (len < 0) return NULL; if (len > 65535) goto invalid; @@ -810,7 +810,7 @@ char *str_alg; if (isdigit(**s)) { - alg = extract_integer(s, what); + alg = extract_integer(s, what, NULL); if (algorithm_type(alg) == ALG_UNSUPPORTED) { bitch("bad or unsupported algorithm %d", alg); return ALG_UNSUPPORTED; diff -Naur validns-0.8/rr.h validns-0.8_git20160720/rr.h --- validns-0.8/rr.h 2014-02-11 15:46:57.000000000 -0500 +++ validns-0.8_git20160720/rr.h 2016-02-04 09:14:15.000000000 -0500 @@ -201,11 +201,15 @@ }; extern struct rr_methods dhcid_methods; +struct rr_txt_segment { + struct binary_data txt; + struct rr_txt_segment *next; +}; struct rr_txt { struct rr rr; int count; - struct binary_data txt[1]; + struct rr_txt_segment *txt; }; extern struct rr_methods txt_methods; @@ -458,10 +462,18 @@ uint16_t key_tag; int pkey_built; void *pkey; + /* extras */ + int key_type; + struct rr_dnskey *next_key; }; extern struct rr_methods dnskey_methods; +#define KEY_TYPE_UNUSED 0 +#define KEY_TYPE_KSK 1 +#define KEY_TYPE_ZSK 2 + int dnskey_build_pkey(struct rr_dnskey *rr); +void dnskey_ksk_policy_check(void); struct rr_ds { diff -Naur validns-0.8/rrsig.c validns-0.8_git20160720/rrsig.c --- validns-0.8/rrsig.c 2014-02-11 15:45:39.000000000 -0500 +++ validns-0.8_git20160720/rrsig.c 2016-02-04 09:14:15.000000000 -0500 @@ -64,7 +64,7 @@ return bitch("private algorithms are not supported in RRSIG"); } - rr->labels = extract_integer(&s, "labels"); + rr->labels = extract_integer(&s, "labels", NULL); if (rr->labels < 0) return NULL; /* TODO validate labels, see http://tools.ietf.org/html/rfc4034#section-3.1.3 */ @@ -79,7 +79,7 @@ if (ts < 0) return NULL; rr->sig_inception = ts; - key_tag = extract_integer(&s, "key tag"); + key_tag = extract_integer(&s, "key tag", NULL); if (key_tag < 0) return NULL; rr->key_tag = key_tag; @@ -434,6 +434,12 @@ unsigned long e = 0; for (i = 0; i < k->n_keys; i++) { if (k->to_verify[i].ok) { + if (k->to_verify[i].rr->rr.rr_set->named_rr->flags & NAME_FLAG_APEX) { + if (k->to_verify[i].key->key_type == KEY_TYPE_UNUSED) + k->to_verify[i].key->key_type = KEY_TYPE_KSK; + } else { + k->to_verify[i].key->key_type = KEY_TYPE_ZSK; + } ok = 1; break; } else { diff -Naur validns-0.8/rt.c validns-0.8_git20160720/rt.c --- validns-0.8/rt.c 2014-02-11 15:46:53.000000000 -0500 +++ validns-0.8_git20160720/rt.c 2016-02-04 09:14:15.000000000 -0500 @@ -21,7 +21,7 @@ { struct rr_rt *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "RT preference"); + rr->preference = extract_integer(&s, "RT preference", NULL); if (rr->preference < 0) return NULL; diff -Naur validns-0.8/soa.c validns-0.8_git20160720/soa.c --- validns-0.8/soa.c 2014-02-11 15:45:26.000000000 -0500 +++ validns-0.8_git20160720/soa.c 2016-02-04 09:14:15.000000000 -0500 @@ -27,7 +27,7 @@ if (!rr->mname) return NULL; rr->rname = extract_name(&s, "rname", 0); if (!rr->rname) return NULL; - i = extract_integer(&s, "serial"); + i = extract_integer(&s, "serial", NULL); if (i < 0) return NULL; if (i > 4294967295UL) return bitch("serial is out of range"); rr->serial = i; @@ -39,6 +39,9 @@ if (rr->expire < 0) return NULL; rr->minimum = extract_timevalue(&s, "minimum"); if (rr->minimum < 0) return NULL; + if (ttl < 0 && G.opt.soa_minttl_as_default_ttl) { + ttl = rr->minimum; + } if (*s) { return bitch("garbage after valid SOA data"); } diff -Naur validns-0.8/srv.c validns-0.8_git20160720/srv.c --- validns-0.8/srv.c 2014-02-11 15:45:48.000000000 -0500 +++ validns-0.8_git20160720/srv.c 2016-02-04 09:14:15.000000000 -0500 @@ -24,21 +24,21 @@ /* TODO validate `name` (underscores etc) http://tools.ietf.org/html/rfc2782 */ - i = extract_integer(&s, "priority"); + i = extract_integer(&s, "priority", NULL); if (i < 0) return NULL; if (i >= 65536) return bitch("priority range is not valid"); rr->priority = i; - i = extract_integer(&s, "weight"); + i = extract_integer(&s, "weight", NULL); if (i < 0) return NULL; if (i >= 65536) return bitch("weight range is not valid"); rr->weight = i; - i = extract_integer(&s, "port"); + i = extract_integer(&s, "port", NULL); if (i < 0) return NULL; if (i >= 65536) diff -Naur validns-0.8/sshfp.c validns-0.8_git20160720/sshfp.c --- validns-0.8/sshfp.c 2014-02-11 15:45:51.000000000 -0500 +++ validns-0.8_git20160720/sshfp.c 2016-02-04 09:14:15.000000000 -0500 @@ -22,13 +22,13 @@ struct rr_sshfp *rr = getmem(sizeof(*rr)); int algorithm, fp_type; - algorithm = extract_integer(&s, "algorithm"); + algorithm = extract_integer(&s, "algorithm", NULL); if (algorithm < 0) return NULL; - if (algorithm != 1 && algorithm != 2 && algorithm != 3) + if (algorithm != 1 && algorithm != 2 && algorithm != 3 && algorithm != 4) return bitch("unsupported algorithm"); rr->algorithm = algorithm; - fp_type = extract_integer(&s, "fp type"); + fp_type = extract_integer(&s, "fp type", NULL); if (fp_type < 0) return NULL; if (fp_type != 1 && fp_type != 2) return bitch("unsupported fp_type"); diff -Naur validns-0.8/t/issues/36-include/empty-include.zone validns-0.8_git20160720/t/issues/36-include/empty-include.zone --- validns-0.8/t/issues/36-include/empty-include.zone 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/36-include/empty-include.zone 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,4 @@ +$ORIGIN example.com. +@ IN 200 SOA ns hostmaster 1 10800 3600 2592000 1200 + IN NS ns +$INCLUDE ; there is no include, and it is wrong diff -Naur validns-0.8/t/issues/36-include/inc2.inc validns-0.8_git20160720/t/issues/36-include/inc2.inc --- validns-0.8/t/issues/36-include/inc2.inc 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/36-include/inc2.inc 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,2 @@ +$ORIGIN inc2 ; i.e., inc2.inc1.example.com. +@ A 55.55.55.55 diff -Naur validns-0.8/t/issues/36-include/include.zone validns-0.8_git20160720/t/issues/36-include/include.zone --- validns-0.8/t/issues/36-include/include.zone 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/36-include/include.zone 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,6 @@ +$ORIGIN example.com. +@ IN 200 SOA ns hostmaster 1 10800 3600 2592000 1200 + IN NS ns +$INCLUDE reldir/inc1.inc ; relative to the zone file +; here we should be back to our origin +@ IN A 99.99.99.99 diff -Naur validns-0.8/t/issues/36-include/missing-include.zone validns-0.8_git20160720/t/issues/36-include/missing-include.zone --- validns-0.8/t/issues/36-include/missing-include.zone 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/36-include/missing-include.zone 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,4 @@ +$ORIGIN example.com. +@ IN 200 SOA ns hostmaster 1 10800 3600 2592000 1200 + IN NS ns +$INCLUDE nosuch.inc diff -Naur validns-0.8/t/issues/36-include/reldir/inc1.inc validns-0.8_git20160720/t/issues/36-include/reldir/inc1.inc --- validns-0.8/t/issues/36-include/reldir/inc1.inc 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/36-include/reldir/inc1.inc 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,5 @@ +$ORIGIN inc1 ; i.e., inc1.example.com. +@ A 11.11.11.11 +$INCLUDE inc2.inc ; still relative to the zone file, not to this dir +; should be back to this origin +@ AAAA 1111::1111 diff -Naur validns-0.8/t/issues/41-ksk-policy-check/dsset-example.sec. validns-0.8_git20160720/t/issues/41-ksk-policy-check/dsset-example.sec. --- validns-0.8/t/issues/41-ksk-policy-check/dsset-example.sec. 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/41-ksk-policy-check/dsset-example.sec. 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,2 @@ +example.sec. IN DS 7686 7 1 51B9CD8F901235705C6D353ADA23736AE954B4DE +example.sec. IN DS 7686 7 2 9EC80B8BAD67C66954B8FE726E06CA7840282C7F444BE51A916ED11C 36908A3F diff -Naur validns-0.8/t/issues/41-ksk-policy-check/example.sec validns-0.8_git20160720/t/issues/41-ksk-policy-check/example.sec --- validns-0.8/t/issues/41-ksk-policy-check/example.sec 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/41-ksk-policy-check/example.sec 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,12 @@ +$TTL 1d +@ IN SOA ns.example.sec. hostmaster.example.sec. ( + 1 ; Serial + 604800 ; Refresh + 86400 ; Retry + 2419200 ; Expire + 604800 ) ; Negative Cache TTL + IN NS ns1.example.net. +subA IN NS ns1.example.net. +subb IN NS ns1.example.net. +subC IN NS ns1.example.net. +myMX IN MX 5 mx.example.net. diff -Naur validns-0.8/t/issues/41-ksk-policy-check/example.sec.signed validns-0.8_git20160720/t/issues/41-ksk-policy-check/example.sec.signed --- validns-0.8/t/issues/41-ksk-policy-check/example.sec.signed 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/41-ksk-policy-check/example.sec.signed 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,131 @@ +; File written on Tue Jun 30 15:31:27 2015 +; dnssec_signzone version 9.9.7 +example.sec. 86400 IN SOA ns.example.sec. hostmaster.example.sec. ( + 1 ; serial + 604800 ; refresh (1 week) + 86400 ; retry (1 day) + 2419200 ; expire (4 weeks) + 604800 ; minimum (1 week) + ) + 86400 RRSIG SOA 7 2 86400 ( + 20150730123127 20150630123127 64232 example.sec. + b1Qs5d/0a4IDAvFPVvDKqWpir4189XoPOD4E + 804eiNXRLP2ShkEUBPil44+6Ikwup5Im24XU + PLnmStjUFHVniicvwbwT/IY4etXR4xNoBHUc + BU8LiADPpZGfJ1tC/s/IHLcPbX21OltyYzi0 + ++z9gxZGy4vCG5gYCH0vm+Q96fY= ) + 86400 NS ns1.example.net. + 86400 RRSIG NS 7 2 86400 ( + 20150730123127 20150630123127 64232 example.sec. + gyqsk3xSnKefnjTOVzJS4sdDFiJ5cPEupSkP + +LGXGRDGrclY6V9mkfddQz3MkeCCjujvQNAi + NpZllyzFj221se5bHLAVydkT0jhl2jgp8bsL + DBk15FGa7SXcwtpXn5rkDvR1/wmS7M/aYnrY + 3j5dTSSsOlZQLENWBEtct9QSNbU= ) + 86400 DNSKEY 256 3 7 ( + AwEAAaMBYu1QXBi6AII33FKwWpHhOkGMhcVc + IWJ73npEFjvDe0jJfLjkghnij4tMfDI8MPIZ + 6xwVLYsEshxsDNEJJGdZ1dUvfJDxSCv8Wp0a + 2IffxQ5NDRHSpUw27yJoQfI5gUqvor+wGTNC + UWx2OU0Y1BOy1whHtVbDl1gt1R6/8mOZ + ) ; ZSK; alg = NSEC3RSASHA1; key id = 64232 + 86400 DNSKEY 257 3 7 ( + AwEAAciLWglw17dt8EDAN88BrQYCIaGPifC4 + pxrizfz3S1cC4XbSyRW5loj5SSHVveUmmIV9 + 0MTEOhGCDUVq/qiYG7NgTNHn3YiqyRU3sirw + 4SACFiwln/ejxFDpQkeAbZMCzU8FQhTIB1K9 + y7QRiLacI6naULzgP3h4PsdQSQmw3/TWy973 + M+lHzwkgVq6ML42L18rGG0sn1KQDNSs/6sd9 + dcRjPo7uJ2OuUsnbu/5N3vWYLciSBUnY27FU + vbFLkVIq072wjUMIb0Xc2EgYGRFKyV2MMckL + voD7vPclBE0Krv9fO/B2/KXsbObTgz4m5iQN + F45QLU02kmvwB4iyIzIk9O0= + ) ; KSK; alg = NSEC3RSASHA1; key id = 7686 + 86400 RRSIG DNSKEY 7 2 86400 ( + 20150730123127 20150630123127 7686 example.sec. + YQ42WBCr7e4MR51W+d6Awkxdff7tTNiA1qfJ + wsst0UiNXKAv504YRcS6B34u4CfG59lWWtcd + +xBHU7Zuox5nehsLEkFAneD1YrJLkgVw03nZ + NzDNWFvlxfQ2/tJ7vGbjKG2cEwUnbJKl+Kcl + JTAc5JzZegfM75M0Z4Yi9NiDjicpHbaICtKJ + 5WZ6T5nVFo1nl2xCq2CiXiR1+jGKARUW+btO + NzHMApLQszDo7CMgvYJoHy0CHAV1Uc7Ka4zO + P3dVYkwu1Puk+gixhNUqo+UhKgLB2JUYdci7 + cQ1JR9RzqEXzyZgGpLmXCOEOc8KD2c2dDN5L + uvOV40OrWhST/bAQ+Q== ) + 86400 RRSIG DNSKEY 7 2 86400 ( + 20150730123127 20150630123127 64232 example.sec. + lKX35bocQ1iR4VTW0Es+2bZ2qX1ON7OGU1fO + Pb0ZqueG2GYgI63VE4Jv3WeOmGg/Tkjvsdb6 + bMHVuVpxHvQKRqqzfaQmY7nzoDe53LfSJewj + p2TvdhvpPRroEZGXXPmVl46R/p+jlYMJd47T + o0oqB/BvQPUS61a5NThagGq6vJM= ) + 0 NSEC3PARAM 1 0 10 - + 0 RRSIG NSEC3PARAM 7 2 0 ( + 20150730123127 20150630123127 64232 example.sec. + hNJlc3JuGYBpnYEZQrhqNwrIL2fBegnnR4ii + TOW+0Km2maqF5ZZMxBZ7x54gW4T0amXXz89+ + uE+l02eknf/FgM81FFOrQvJul0toOzKW9g67 + e2VwQAwcw7g6H06cSsypXM/h9wvsNQpoSdx0 + rq6qU2ruYM9NmJf+xUzUk38AFUw= ) +subA.example.sec. 86400 IN NS ns1.example.net. +subb.example.sec. 86400 IN NS ns1.example.net. +subC.example.sec. 86400 IN NS ns1.example.net. +93GL7KF6D2G7J2PSLEO2CIA70A3MM4KQ.example.sec. 604800 IN NSEC3 1 0 10 - ( + CSLD6RFNKVSKA73DGNI0EOM95Q8DKGBQ + NS ) + 604800 RRSIG NSEC3 7 3 604800 ( + 20150730123127 20150630123127 64232 example.sec. + JRhyC3PbmnvYBkXzV5GmIBnj5LJTnrVeC1t3 + v6t6o+3udfPZRecHw2cApf/Oed8H9jCeox77 + vA13/fLXui635CYAcqXYxVgO4g0au1d1S6lo + N2Pw96JXDNhIqyVBVj1Ii2ZOQLWXZ8YgZRQ6 + lxgww8m0QGC8FjEnzR8z2liSG88= ) +3ED4GMVJJ0FT4TCFDKNFQ5EPEFSDBPNM.example.sec. 604800 IN NSEC3 1 0 10 - ( + 93GL7KF6D2G7J2PSLEO2CIA70A3MM4KQ + NS ) + 604800 RRSIG NSEC3 7 3 604800 ( + 20150730123127 20150630123127 64232 example.sec. + B9L5NrHjO/J6FDmv7DjT1xq/f8jiB2WTEXSl + bFeUVcTivoyvdyfNNTH+YlzJesqTtQ9GaEPQ + ouzw7XbdyvtJ//GD+vrO/7XwfrVmkckQgEVl + zPm70TksAkwLzj0uY6WBIGIPq/KJMM14f6El + ct5w2KtgvF9sazFP+KMchU5Be3Q= ) +myMX.example.sec. 86400 IN MX 5 mx.example.net. + 86400 RRSIG MX 7 3 86400 ( + 20150730123127 20150630123127 64232 example.sec. + lh8vFwFg77gLtLyXbzqzYSlebkzn3yAlXHU2 + /hgiyUWYcuZa5E33Ul+ZrUJPCGLaUQs3X+yL + p/uk6LP2dnMaf/X1mow/tyYNtIdn0MhTYNqs + WmYV1Ga/NSoErtoHYoNgeqV1w0Q/nfhipMdX + RekpxVR6RUUt2d3LS8UIH+pEYd8= ) +CSLD6RFNKVSKA73DGNI0EOM95Q8DKGBQ.example.sec. 604800 IN NSEC3 1 0 10 - ( + JC1M8I9IPBEENK9RDGMN9LQKAMMSQEVV + MX RRSIG ) + 604800 RRSIG NSEC3 7 3 604800 ( + 20150730123127 20150630123127 64232 example.sec. + menCNV7RkbVWmfhuPfoYHfHCEtvQmVb3+p/x + WYVymu5hXUPQ2+K4Ns0jQ+om4GuTmXmm1DYY + IjIXv4jthJoD6jydqN6Hr+tr0ewxr6mHXj3I + RizTBuw4zcgPUrIRVQStkMtwyjN4Nlznhg7I + txZ14uH1G4U1DgkR2oC6YZsSqi8= ) +JC1M8I9IPBEENK9RDGMN9LQKAMMSQEVV.example.sec. 604800 IN NSEC3 1 0 10 - ( + NLF2NKFTCGVVRC4C941FOOCD00TPI9DV + NS SOA RRSIG DNSKEY NSEC3PARAM ) + 604800 RRSIG NSEC3 7 3 604800 ( + 20150730123127 20150630123127 64232 example.sec. + ggLIoKQYmI9GeBkSccVdE87G1QQwGGO0HlrN + dg9Ah5QiWWjZ5icSOU4vyEm0XiqkFCrGEAq0 + 9L4HMOFuELMa28dAhVxOvZldbXizXUSCbWCS + miYFLOIKcQ9IcmzeEgg+uJzHdAyYSSK2Jb+0 + YYuoXOhiZwzluj+u2i6kbf6wDY4= ) +NLF2NKFTCGVVRC4C941FOOCD00TPI9DV.example.sec. 604800 IN NSEC3 1 0 10 - ( + 3ED4GMVJJ0FT4TCFDKNFQ5EPEFSDBPNM + NS ) + 604800 RRSIG NSEC3 7 3 604800 ( + 20150730123127 20150630123127 64232 example.sec. + buRQJjfJDIbRFZFr8s7odGSxqnrSHXXN/AAu + tbG1k2L7WD+DGYFiRnR5Uia/C2oL186PqBtT + R8oDKf/4zr5qOsZz9xYabaBqG98JVXwPTiFk + JBoc7sFcwGJ16hj9Zey05aNs1h5RZm6BL8W0 + 9bRF3qIezckG0VA+U7ASTLNH4ME= ) diff -Naur validns-0.8/t/issues/41-ksk-policy-check/Kexample.sec.+007+07686.key validns-0.8_git20160720/t/issues/41-ksk-policy-check/Kexample.sec.+007+07686.key --- validns-0.8/t/issues/41-ksk-policy-check/Kexample.sec.+007+07686.key 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/41-ksk-policy-check/Kexample.sec.+007+07686.key 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 7686, for example.sec. +; Created: 20150630133112 (Tue Jun 30 15:31:12 2015) +; Publish: 20150630133112 (Tue Jun 30 15:31:12 2015) +; Activate: 20150630133112 (Tue Jun 30 15:31:12 2015) +example.sec. IN DNSKEY 257 3 7 AwEAAciLWglw17dt8EDAN88BrQYCIaGPifC4pxrizfz3S1cC4XbSyRW5 loj5SSHVveUmmIV90MTEOhGCDUVq/qiYG7NgTNHn3YiqyRU3sirw4SAC Fiwln/ejxFDpQkeAbZMCzU8FQhTIB1K9y7QRiLacI6naULzgP3h4PsdQ SQmw3/TWy973M+lHzwkgVq6ML42L18rGG0sn1KQDNSs/6sd9dcRjPo7u J2OuUsnbu/5N3vWYLciSBUnY27FUvbFLkVIq072wjUMIb0Xc2EgYGRFK yV2MMckLvoD7vPclBE0Krv9fO/B2/KXsbObTgz4m5iQNF45QLU02kmvw B4iyIzIk9O0= diff -Naur validns-0.8/t/issues/41-ksk-policy-check/Kexample.sec.+007+07686.private validns-0.8_git20160720/t/issues/41-ksk-policy-check/Kexample.sec.+007+07686.private --- validns-0.8/t/issues/41-ksk-policy-check/Kexample.sec.+007+07686.private 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/41-ksk-policy-check/Kexample.sec.+007+07686.private 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 7 (NSEC3RSASHA1) +Modulus: yItaCXDXt23wQMA3zwGtBgIhoY+J8LinGuLN/PdLVwLhdtLJFbmWiPlJIdW95SaYhX3QxMQ6EYINRWr+qJgbs2BM0efdiKrJFTeyKvDhIAIWLCWf96PEUOlCR4BtkwLNTwVCFMgHUr3LtBGItpwjqdpQvOA/eHg+x1BJCbDf9NbL3vcz6UfPCSBWrowvjYvXysYbSyfUpAM1Kz/qx311xGM+ju4nY65Sydu7/k3e9ZgtyJIFSdjbsVS9sUuRUirTvbCNQwhvRdzYSBgZEUrJXYwxyQu+gPu89yUETQqu/1878Hb8pexs5tODPibmJA0XjlAtTTaSa/AHiLIjMiT07Q== +PublicExponent: AQAB +PrivateExponent: d5kDfRXaz/20hikcH0v0j9y9icg8j17P6WzRQ8eHGsERDPfwDBC+AboJLzB1Ky+1TgcWdgJATyisGXYRoSH1gygvKA+LQnH3sbuheZJl79zOtE1L9TepYEd7y4B/2GiXYETWf+Y619Fwpla+nYjIjAcylzF1KLctWVg79peROEXC0zb+IxWQFIBpe7OzTZ1qxG8ymm6uiu9KXH6qQi3BLSarxj5rY+tO8oj0qQNOGkbSVsXFax0arZ0qMRFT5UooOm+2Yl8Q9Z/PC52qwNqkSDZ2QeoYTJx5tDFhuVJxXhioxGIueA4QuCRA4cRL2U5ZnCYcQa10JFE2O4N990eLUQ== +Prime1: 5LW1fl8ky4bBaIPg48Cq8bXQIvaK5syFTvzzMopuTeD6PGwOByuzc4u9KLVrDRebjeYfNVkqXIJAHMjolOr4jURWp2Q3FUrewqdgyY2ULSLMmQo0+dHkvjJIs2A/6vNme+MtFms6msJjyzj3EhLf32djvCH+jWStP3Vb/jopYWs= +Prime2: 4HlJJB25JSLygHd0GWi8yu0z3FaYhWXnIs8bwpT8er1lH+tsBeYI8ughuX9h19STMRnBhAh0ZlQaKHOrPTsdVOFQJWr6aUbWIAhv5m+ij1IFsQ58DKnsYP0DXiNkR7K4pXO8yzPTo9UfaMCJAKYipENTgpfb43sVBQnDIGr9oQc= +Exponent1: aJpK9g9h7swlLT4T31bBWGeFWFhWUxT7a5L5UAZMSMY67OOmztTH8HLbAwFmgshnVtEHOQkc/M59sCybY3DMWSAGWezV3KEvnOucstJUEQi3ds9aR2AeNHcfFRtSYI0ONF9EwdotJZb+uXXGWrfTOIQ681LA7746FqoAdxf20R0= +Exponent2: QlFS3Iqzglc60d14vXEGJeXCZpxm3zJmARCzIN+nYBPIZo/FEFEP38PZAtaxb3RsMBtt4rYkvX6nY8AYnTRzy/ntFcDvTl8RL9GOTcQ5gKI48EBZQdyJ63WUoyFNpSkWCDuTUW10X3i9mNMZJsnufh0t9O0sl55rbVue/Frfp80= +Coefficient: aLnGdfeRJ3nSjmbby8IDkJ+W+gFGOHd3XAMDSNP9D8kn6B3JyAfY6FDSg0+Bh+F80PFNGsESkYimXlWr3B6NlC0Gq99hPSV8yU2pYHq3TPVB0tWOAkNVIXM9icEH9wshCQH7wD7cPDWvhhgcgo64nYOGYeK6sjTL7XDtRanvbP8= +Created: 20150630133112 +Publish: 20150630133112 +Activate: 20150630133112 diff -Naur validns-0.8/t/issues/41-ksk-policy-check/Kexample.sec.+007+64232.key validns-0.8_git20160720/t/issues/41-ksk-policy-check/Kexample.sec.+007+64232.key --- validns-0.8/t/issues/41-ksk-policy-check/Kexample.sec.+007+64232.key 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/41-ksk-policy-check/Kexample.sec.+007+64232.key 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 64232, for example.sec. +; Created: 20150630133105 (Tue Jun 30 15:31:05 2015) +; Publish: 20150630133105 (Tue Jun 30 15:31:05 2015) +; Activate: 20150630133105 (Tue Jun 30 15:31:05 2015) +example.sec. IN DNSKEY 256 3 7 AwEAAaMBYu1QXBi6AII33FKwWpHhOkGMhcVcIWJ73npEFjvDe0jJfLjk ghnij4tMfDI8MPIZ6xwVLYsEshxsDNEJJGdZ1dUvfJDxSCv8Wp0a2Iff xQ5NDRHSpUw27yJoQfI5gUqvor+wGTNCUWx2OU0Y1BOy1whHtVbDl1gt 1R6/8mOZ diff -Naur validns-0.8/t/issues/41-ksk-policy-check/Kexample.sec.+007+64232.private validns-0.8_git20160720/t/issues/41-ksk-policy-check/Kexample.sec.+007+64232.private --- validns-0.8/t/issues/41-ksk-policy-check/Kexample.sec.+007+64232.private 1969-12-31 19:00:00.000000000 -0500 +++ validns-0.8_git20160720/t/issues/41-ksk-policy-check/Kexample.sec.+007+64232.private 2016-02-04 09:14:15.000000000 -0500 @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 7 (NSEC3RSASHA1) +Modulus: owFi7VBcGLoAgjfcUrBakeE6QYyFxVwhYnveekQWO8N7SMl8uOSCGeKPi0x8Mjww8hnrHBUtiwSyHGwM0QkkZ1nV1S98kPFIK/xanRrYh9/FDk0NEdKlTDbvImhB8jmBSq+iv7AZM0JRbHY5TRjUE7LXCEe1VsOXWC3VHr/yY5k= +PublicExponent: AQAB +PrivateExponent: ATf/b1rMdXreihq00QF0i+atMtREI8eekEfwz+U2bVf20gJ/pjo/JsZk4FvACfgdPZIoCdu2rXVph4DfT6jL1t7sDY/9mfcMd2Zge6eB8Kat3QpdDu4qClgkXFTYFLj2lQ5Bm/b+YbQ8fiPlZovp7YGFodmsjfnNvbT7UiOiSKE= +Prime1: 1wNWdr5FIrew1NTzpbeClZr5NIIoRBpEPsSDCBZpbRDZ944LcjWgrJpVlG1klkp/cR/zcSzrq+637rva30jglQ== +Prime2: whQSB4wqB87wyYrewJLU5qFY5Up/YiZ0iyD4m4OIQMk/K7eXtuqFuSOP4xTR4WAWHIyRixa1F85/eh7y6+9h9Q== +Exponent1: XjHZJEYw9Yex0VvFrdjaPX5aJJXM3CEButnOabGf2Cckxl4VR6CU1mj6iv7trSXP9RhBR1idmoIHVHA57832jQ== +Exponent2: dtzn9etoSoP5gNYmevbyoZWr5jJsNeardhJpcIVsS5F1uQamSob0A2G+XCuCJ3A72pxU/0SXAM+dz2NpEAr6iQ== +Coefficient: egVfeiBCmggrVDolCSvAIg+XEb+YmLcD1SLT5qFLuqCtPKWGDx9lGMbqbx5s2gzeeoAPL1r34pohHNLMCqCNdw== +Created: 20150630133105 +Publish: 20150630133105 +Activate: 20150630133105 diff -Naur validns-0.8/t/test.pl validns-0.8_git20160720/t/test.pl --- validns-0.8/t/test.pl 2014-02-11 15:08:39.000000000 -0500 +++ validns-0.8_git20160720/t/test.pl 2016-02-04 09:14:15.000000000 -0500 @@ -215,6 +215,35 @@ like(shift @e, qr/leading zero octets in public key exponent/, "leading zeroes in exponent 2"); is(+@e, 0, "no unaccounted errors for DNSKEY policy checks"); +# issue 36: https://github.com/tobez/validns/issues/36 - $include implementation +run('./validns', @threads, 't/issues/36-include/empty-include.zone'); +isnt(rc, 0, 'empty include detected'); +@e = split /\n/, stderr; +like(shift @e, qr/\bINCLUDE directive with empty file name\b/, "Expected error with empty INCLUDE"); +is(+@e, 0, "no unaccounted errors for empty include"); + +run('./validns', @threads, 't/issues/36-include/missing-include.zone'); +isnt(rc, 0, 'missing include detected'); +@e = split /\n/, stderr; +like(shift @e, qr/\bNo such file or directory\b/, "Expected error with missing INCLUDE file"); +is(+@e, 0, "no unaccounted errors for missing include"); + +run('./validns', @threads, '-v', 't/issues/36-include/include.zone'); +is(rc, 0, 'zone with nested includes parses ok'); +@e = split /\n/, stderr; +for my $rx ((qr/\d:\s+example\.com\.\s+IN\s+\d+\s+NS\s+ns\.example\.com\./, + qr/\d:\s+inc1\.example\.com\.\s+IN\s+\d+\s+A\s+11\.11\.11\.11/, + qr/\d:\s+inc2\.inc1\.example\.com\.\s+IN\s+\d+\s+A\s+55\.55\.55\.55/, + qr/\d:\s+inc1\.example\.com\.\s+IN\s+\d+\s+AAAA\s+1111::1111/, + qr/\d:\s+example\.com\.\s+IN\s+\d+\s+A\s+99\.99\.99\.99/)) +{ + my $ok = 0; + for my $e (@e) { + $ok = 1 if $e =~ $rx; + } + is($ok, 1, "found expected record with correct ORIGIN tracked across INCLUDEs"); +} + # issue 21: https://github.com/tobez/validns/issues/21 run('./validns', @threads, '-t1345815800', 't/issues/21-nsec3-without-corresponding/example.sec.signed'); is(rc, 0, 'issue 21 did not come back'); @@ -227,6 +256,19 @@ run('./validns', @threads, '-t1345815800', 't/issues/25-nsec/example.sec.signed'); is(rc, 0, 'issue 25 did not come back'); +# issue 41: https://github.com/tobez/validns/issues/41 +run('./validns', @threads, '-t1345815800', '-pksk-exists', 't/issues/25-nsec/example.sec.signed'); +isnt(rc, 0, 'KSK policy check fails'); +@e = split /\n/, stderr; +like(shift @e, qr/\bNo KSK found\b/, "KSK policy check produces expected error output"); +is(+@e, 0, "no unaccounted errors for KSK policy check"); + +run('./validns', @threads, '-t1435671103', '-pksk-exists', 't/issues/41-ksk-policy-check/example.sec.signed'); +is(rc, 0, 'signed zone with KSK parses ok when KSK policy check is active'); + +run('./validns', @threads, '-pksk-exists', 't/zones/galaxyplus.org'); +is(rc, 0, 'unsigned zone ignores KSK policy checks'); + # issue 26: https://github.com/tobez/validns/issues/26 run('./validns', @threads, '-t1349357570', 't/issues/26-spurios-glue/example.sec.signed.no-optout'); is(rc, 0, 'issue 26 did not come back (NSEC3 NO optout)'); diff -Naur validns-0.8/t/zones/galaxyplus.org validns-0.8_git20160720/t/zones/galaxyplus.org --- validns-0.8/t/zones/galaxyplus.org 2011-05-16 15:42:03.000000000 -0400 +++ validns-0.8_git20160720/t/zones/galaxyplus.org 2016-02-04 09:14:15.000000000 -0500 @@ -18,4 +18,5 @@ cvs A 194.28.255.11 v6 AAAA 2001:2010:1::feef text TXT "text1" "Another text" "One more" +bigtext TXT "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "20" "21" "22" "what is the meaning of this" *.meow CNAME www diff -Naur validns-0.8/textparse.c validns-0.8_git20160720/textparse.c --- validns-0.8/textparse.c 2014-02-11 15:44:53.000000000 -0500 +++ validns-0.8_git20160720/textparse.c 2016-02-04 09:14:15.000000000 -0500 @@ -40,8 +40,7 @@ } if (*s == 0) { if (file_info->paren_mode) { - if (fgets(file_info->buf, 2048, file_info->file)) { - file_info->line++; + if (read_zone_line()) { return skip_white_space(file_info->buf); } else { return bitch("unexpected end of file"); @@ -77,7 +76,7 @@ int d, l, ol; while (1) { - if (isalnum(*s) || *s == '_' || *s == '.' || *s == '-' || *s == '/') { + if (isalnum(*s) || *s == '_' || *s == '.' || *s == '-' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$')) { if (t-buf >= 1022) return bitch("name too long"); *t++ = *s++; @@ -125,19 +124,19 @@ return bitch("%s should not be empty", what); if (buf[l-1] != '.') { - if (!G.opt.current_origin) { + if (!file_info->current_origin) { return bitch("do not know origin to determine %s", what); } - ol = strlen(G.opt.current_origin); - if (G.opt.current_origin[0] == '.') { + ol = strlen(file_info->current_origin); + if (file_info->current_origin[0] == '.') { if (l + ol >= 1023) return bitch("name too long"); - strcat(buf, G.opt.current_origin); + strcat(buf, file_info->current_origin); } else { if (l + ol >= 1022) return bitch("name too long"); strcat(buf, "."); - strcat(buf, G.opt.current_origin); + strcat(buf, file_info->current_origin); } } @@ -177,12 +176,12 @@ if (*s && !isspace(*s) && *s != ';' && *s != ')') { return bitch("literal @ in %s is not all by itself", what); } - if (!G.opt.current_origin) { + if (!file_info->current_origin) { return bitch("do not know origin to expand @ in %s", what); } - r = quickstrdup(G.opt.current_origin); + r = quickstrdup(file_info->current_origin); } else { - if (!(isalnum(*s) || *s == '_' || *s == '.' || *s == '/')) { + if (!(isalnum(*s) || *s == '_' || *s == '.' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$'))) { if (*s == '*') { wildcard = 1; } else { @@ -192,7 +191,7 @@ } } s++; - while (isalnum(*s) || *s == '.' || *s == '-' || *s == '_' || *s == '/') + while (isalnum(*s) || *s == '.' || *s == '-' || *s == '_' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$')) s++; if (*s && !isspace(*s) && *s != ';' && *s != ')') { if (*s == '\\') @@ -205,14 +204,14 @@ if (*(s-1) == '.') { r = quickstrdup(*input); } else { - if (!G.opt.current_origin) { + if (!file_info->current_origin) { return bitch("do not know origin to determine %s", what); } - r = getmem(strlen(*input) + 1 + strlen(G.opt.current_origin) + 1); - if (G.opt.current_origin[0] == '.') { - strcpy(mystpcpy(r, *input), G.opt.current_origin); + r = getmem(strlen(*input) + 1 + strlen(file_info->current_origin) + 1); + if (file_info->current_origin[0] == '.') { + strcpy(mystpcpy(r, *input), file_info->current_origin); } else { - strcpy(mystpcpy(mystpcpy(r, *input), "."), G.opt.current_origin); + strcpy(mystpcpy(mystpcpy(r, *input), "."), file_info->current_origin); } } *s = c; @@ -277,7 +276,7 @@ return r; } -long long extract_integer(char **input, char *what) +long long extract_integer(char **input, char *what, const char *extra_delimiters) { char *s = *input; long long r = -1; @@ -292,8 +291,10 @@ while (isdigit(*s)) s++; if (*s && !isspace(*s) && *s != ';' && *s != ')') { - bitch("%s is not valid", what); - return -1; + if (!extra_delimiters || strchr(extra_delimiters, *s) == NULL) { + bitch("%s is not valid", what); + return -1; + } } if (!*s) end = s; c = *s; @@ -708,7 +709,17 @@ int c; if (*s != '"') { - bitch("for now, %s must be put in double quotes", what); + while (*s && !isspace(*s)) { + o[l++] = *s++; + } + *input = skip_white_space(s); + if (!*input) + return r; /* bitching's done elsewhere */ + + o[l] = 0; + r.data = getmem(l+1); + r.length = l; + memcpy(r.data, o, l+1); return r; } s++; @@ -742,8 +753,7 @@ } } if (!*s) { - if (fgets(file_info->buf, 2048, file_info->file)) { - file_info->line++; + if (read_zone_line()) { s = file_info->buf; goto more_text; } else { @@ -998,3 +1008,32 @@ for (; (*to = *from); ++from, ++to); return(to); } + +size_t +mystrlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} + diff -Naur validns-0.8/textparse.h validns-0.8_git20160720/textparse.h --- validns-0.8/textparse.h 2014-02-11 15:45:46.000000000 -0500 +++ validns-0.8_git20160720/textparse.h 2016-02-04 09:14:15.000000000 -0500 @@ -33,12 +33,13 @@ */ #define KEEP_CAPITALIZATION 32 +#define DOLLAR_OK_IN_NAMES 64 int empty_line_or_comment(char *s); char *skip_white_space(char *s); char *extract_name(char **input, char *what, int options); char *extract_label(char **input, char *what, void *is_temporary); -long long extract_integer(char **input, char *what); +long long extract_integer(char **input, char *what, const char *extra_delimiters); long extract_timevalue(char **input, char *what); long long extract_timestamp(char **input, char *what); int extract_ipv4(char **input, char *what, struct in_addr *addr); @@ -59,7 +60,9 @@ void add_bit_to_set(struct binary_data *set, int bit); struct binary_data compressed_set(struct binary_data *set); -/* stpcpy(3) is not available everywhere */ -char *mystpcpy(char *to, const char *from); +char *mystpcpy(char *to, const char *from); /* stpcpy(3) is not available everywhere */ +size_t mystrlcat(char *dst, const char *src, size_t siz); /* so is strlcat */ + +char *read_zone_line(void); #endif diff -Naur validns-0.8/tlsa.c validns-0.8_git20160720/tlsa.c --- validns-0.8/tlsa.c 2014-02-11 15:46:23.000000000 -0500 +++ validns-0.8_git20160720/tlsa.c 2016-02-04 09:14:15.000000000 -0500 @@ -28,19 +28,19 @@ struct rr_tlsa *rr = getmem(sizeof(*rr)); int cert_usage, selector, matching_type; - cert_usage = extract_integer(&s, "certificate usage field"); + cert_usage = extract_integer(&s, "certificate usage field", NULL); if (cert_usage < 0) return NULL; if (cert_usage > 3) return bitch("bad certificate usage field"); rr->cert_usage = cert_usage; - selector = extract_integer(&s, "selector field"); + selector = extract_integer(&s, "selector field", NULL); if (selector < 0) return NULL; if (selector > 1) return bitch("bad selector field"); rr->selector = selector; - matching_type = extract_integer(&s, "matching type field"); + matching_type = extract_integer(&s, "matching type field", NULL); if (matching_type < 0) return NULL; if (matching_type > 2) return bitch("bad matching type field"); diff -Naur validns-0.8/txt.c validns-0.8_git20160720/txt.c --- validns-0.8/txt.c 2014-02-11 15:45:53.000000000 -0500 +++ validns-0.8_git20160720/txt.c 2016-02-04 09:14:15.000000000 -0500 @@ -23,28 +23,36 @@ static struct rr *txt_parse(char *name, long ttl, int type, char *s) { struct rr_txt *rr; - struct binary_data txt[20]; + struct binary_data txt; + struct rr_txt_segment *first = NULL; + struct rr_txt_segment *last = NULL; + struct rr_txt_segment *cur = NULL; int i; i = 0; while (*s) { - if (i >= 20) - return bitch("program limit: too many text segments"); - txt[i] = extract_text(&s, "text segment"); - if (txt[i].length < 0) + freeall_temp(); + txt = extract_text(&s, "text segment"); + if (txt.length < 0) return NULL; - if (txt[i].length > 255) + if (txt.length > 255) return bitch("TXT segment too long"); i++; + cur = getmem(sizeof(*cur)); + cur->txt = txt; + cur->next = NULL; + if (!first) + first = cur; + if (last) + last->next = cur; + last = cur; } if (i == 0) return bitch("empty text record"); - rr = getmem(sizeof(*rr) + sizeof(struct binary_data) * (i-1)); + rr = getmem(sizeof(*rr)); rr->count = i; - for (i = 0; i < rr->count; i++) { - rr->txt[i] = txt[i]; - } + rr->txt = first; return store_record(type, name, ttl, rr); } @@ -53,14 +61,15 @@ { RRCAST(txt); char ss[1024]; - int i; char *s = ss; int l; + struct rr_txt_segment *seg = rr->txt; - for (i = 0; i < rr->count; i++) { + while (seg) { /* XXX would be nice to escape " with \ in strings */ - l = snprintf(s, 1024-(s-ss), "\"%s\" ", rr->txt[i].data); + l = snprintf(s, 1024-(s-ss), "\"%s\" ", seg->txt.data); s += l; + seg = seg->next; } return quickstrdup_temp(ss); } @@ -69,14 +78,15 @@ { RRCAST(txt); struct binary_data r, t; - int i; + struct rr_txt_segment *seg = rr->txt; r = bad_binary_data(); t.length = 0; t.data = NULL; - for (i = 0; i < rr->count; i++) { - r = compose_binary_data("db", 1, t, rr->txt[i]); + while (seg) { + r = compose_binary_data("db", 1, t, seg->txt); t = r; + seg = seg->next; } return r; } diff -Naur validns-0.8/usage.mdwn validns-0.8_git20160720/usage.mdwn --- validns-0.8/usage.mdwn 2014-02-11 15:42:32.000000000 -0500 +++ validns-0.8_git20160720/usage.mdwn 2016-02-04 09:14:15.000000000 -0500 @@ -48,6 +48,7 @@ - ns-alias - rp-txt-exists - tlsa-host + - ksk-exists - all -n *N* @@ -64,6 +65,9 @@ -v : be extra verbose +-M +: use SOA MINTTL as the default TTL when no TTL specified + -I *path* : use this path for $INCLUDE files @@ -130,12 +134,11 @@ - TXT domain name mentioned in RP record must have a corresponding TXT record if it is within the zone - domain name of a TLSA record must be a proper prefixed DNS name +- a KSK key must exist in a signed zone # BUGS - textual segments in *TXT* and *HINFO* must be enclosed in double quotes; -- there cannot be more than 20 textual segments in a *TXT* record; -- *$INCLUDE* directive is not implemented; - a dot within a label is not currently supported; If at least one NSEC3 record uses opt-out flag, diff -Naur validns-0.8/validns.1 validns-0.8_git20160720/validns.1 --- validns-0.8/validns.1 2014-02-11 15:43:21.000000000 -0500 +++ validns-0.8_git20160720/validns.1 2016-02-04 09:14:15.000000000 -0500 @@ -1,4 +1,4 @@ -.TH VALIDNS 1 "April 2011" +.TH "VALIDNS" "1" "April 2011" "" "" .SH NAME .PP validns \- DNS and DSNSEC zone file validator @@ -53,6 +53,8 @@ .IP \[bu] 2 tlsa\-host .IP \[bu] 2 +ksk\-exists +.IP \[bu] 2 all .RE .TP @@ -78,6 +80,11 @@ .RS .RE .TP +.B \-M +use SOA MINTTL as the default TTL when no TTL specified +.RS +.RE +.TP .B \-I \f[I]path\f[] use this path for $INCLUDE files .RS @@ -178,15 +185,13 @@ record if it is within the zone .IP \[bu] 2 domain name of a TLSA record must be a proper prefixed DNS name +.IP \[bu] 2 +a KSK key must exist in a signed zone .SH BUGS .IP \[bu] 2 textual segments in \f[I]TXT\f[] and \f[I]HINFO\f[] must be enclosed in double quotes; .IP \[bu] 2 -there cannot be more than 20 textual segments in a \f[I]TXT\f[] record; -.IP \[bu] 2 -\f[I]$INCLUDE\f[] directive is not implemented; -.IP \[bu] 2 a dot within a label is not currently supported; .PP If at least one NSEC3 record uses opt\-out flag, \f[C]validns\f[]