]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
-Z option to ldns-verify-zone to require ZONEMD
authorWillem Toorop <willem@nlnetlabs.nl>
Fri, 20 Nov 2020 22:28:17 +0000 (23:28 +0100)
committerWillem Toorop <willem@nlnetlabs.nl>
Fri, 20 Nov 2020 22:28:17 +0000 (23:28 +0100)
But when given once, does not require DNSSEC.
When given twice requires both DNSSEC and a valid ZONEMD RR

examples/ldns-verify-zone.1.in
examples/ldns-verify-zone.c

index 2cee807f250c76e37011cb8a78f285ba71dace05..beef1fc1c8a435a80c60b5c7ba5a9bd87f20fb77 100644 (file)
@@ -72,6 +72,12 @@ Set the verbosity level (default 3):
  5: Print the zone after it has been read, the result, 
     any errors, and the names that are being checked
 
+.TP
+\fB-Z\fR
+Requires a valid ZONEMD RR to be present. When given once, this option will
+permit verifying only the ZONEMD RR of an unsigned zone. When given more than
+once, the zone needs to be validly DNSSEC signed as well.
+
 .LP
 \fIperiod\fRs are given in ISO 8601 duration format:
 .RS
index 4acfacddacb1ada2ee2c9160dff8b420de32c436..80a1be1461b36849a699688b24a170688371772b 100644 (file)
@@ -736,6 +736,11 @@ static void print_usage(FILE *out, const char *progname)
               "for validating it regardless.\n");
        fprintf(out, "\t-v\t\tshows the version and exits\n");
        fprintf(out, "\t-V [0-5]\tset verbosity level (default 3)\n");
+       fprintf(out, "\t-Z\t\tRequires a valid ZONEMD RR to be present.\n");
+       fprintf(out, "\t\t\tWhen given once, this option will permit verifying"
+              "\n\t\t\tjust the ZONEMD RR of an unsigned zone. When given "
+              "\n\t\t\tmore than once, the zone needs to be validly DNSSEC"
+              "\n\t\t\tsigned as well.");
        fprintf(out, "\n<period>s are given in ISO 8601 duration format: "
               "P[n]Y[n]M[n]DT[n]H[n]M[n]S\n");
        fprintf(out, "\nif no file is given standard input is read\n");
@@ -758,12 +763,14 @@ main(int argc, char **argv)
        ldns_rr_list *keys = ldns_rr_list_new();
        size_t nkeys = 0;
        const char *progname = argv[0];
+       int zonemd_required = 0;
+       ldns_dnssec_rrsets *zonemd_rrset;
 
        check_time = ldns_time(NULL);
        myout = stdout;
        myerr = stderr;
 
-       while ((c = getopt(argc, argv, "ae:hi:k:vV:p:St:")) != -1) {
+       while ((c = getopt(argc, argv, "ae:hi:k:vV:p:St:Z")) != -1) {
                switch(c) {
                 case 'a':
                         apexonly = true;
@@ -859,6 +866,9 @@ main(int argc, char **argv)
                case 'V':
                        verbosity = atoi(optarg);
                        break;
+               case 'Z':
+                       zonemd_required += 1;
+                       break;
                }
        }
        if (do_sigchase && nkeys == 0) {
@@ -897,68 +907,73 @@ main(int argc, char **argv)
 
        s = ldns_dnssec_zone_new_frm_fp_l(&dnssec_zone, fp, NULL, 0,
                        LDNS_RR_CLASS_IN, &line_nr);
-       if (s == LDNS_STATUS_OK) {
-               if (!dnssec_zone->soa) {
-                       if (verbosity > 0) {
-                               fprintf(myerr,
-                                       "; Error: no SOA in the zone\n");
-                       }
-                       exit(EXIT_FAILURE);
-               }
-
-               result = ldns_dnssec_zone_mark_glue(dnssec_zone);
-               if (result != LDNS_STATUS_OK) {
-                       if (verbosity > 0) {
-                               fprintf(myerr,
-                                       "There were errors identifying the "
-                                       "glue in the zone\n");
-                       }
+       if (s != LDNS_STATUS_OK) {
+               if (verbosity > 0) {
+                       fprintf(myerr, "%s at line %d\n",
+                               ldns_get_errorstr_by_id(s), line_nr);
                }
-               if (verbosity >= 5) {
-                       ldns_dnssec_zone_print(myout, dnssec_zone);
+                exit(EXIT_FAILURE);
+       }
+       if (!dnssec_zone->soa) {
+               if (verbosity > 0) {
+                       fprintf(myerr,
+                               "; Error: no SOA in the zone\n");
                }
+               exit(EXIT_FAILURE);
+       }
 
+       result = ldns_dnssec_zone_mark_glue(dnssec_zone);
+       if (result != LDNS_STATUS_OK) {
+               if (verbosity > 0) {
+                       fprintf(myerr,
+                               "There were errors identifying the "
+                               "glue in the zone\n");
+               }
+       }
+       if (verbosity >= 5) {
+               ldns_dnssec_zone_print(myout, dnssec_zone);
+       }
+       zonemd_rrset = ldns_dnssec_zone_find_rrset(dnssec_zone,
+                               dnssec_zone->soa->name, LDNS_RR_TYPE_ZONEMD);
+
+       if (zonemd_required == 1
+       &&  !ldns_dnssec_zone_find_rrset(dnssec_zone,
+                               dnssec_zone->soa->name, LDNS_RR_TYPE_DNSKEY))
+               ; /* pass */
+       else
                result = verify_dnssec_zone(dnssec_zone,
                                dnssec_zone->soa->name, keys, apexonly,
                                percentage);
 
-               if (!result) {
-                       result = ldns_dnssec_zone_verify_zonemd(dnssec_zone);
-                       if (verbosity > 3) {
-                               if (result)
-                                       fprintf( myerr
-                                              , "Could not validate"
-                                                " zone digest: %s\n"
-                                              , ldns_get_errorstr_by_id(
-                                                      result));
-                               else
-                                       fprintf( myout
-                                              , "Zone digest matched"
-                                                " the zone content\n");
-                       }
-               }
-               if (result == LDNS_STATUS_OK) {
-                       if (verbosity >= 3) {
-                               fprintf(myout,
-                                       "Zone is verified and complete\n");
-                       }
-               } else {
-                       if (verbosity > 0) {
-                               fprintf(myerr,
-                                       "There were errors in the zone\n");
-                       }
-               }
+       if (zonemd_required && !zonemd_rrset) {
+               fprintf(myerr, "ZONEMD was required but not found\n");
+               result = LDNS_STATUS_NO_ZONEMD;
 
-               ldns_dnssec_zone_deep_free(dnssec_zone);
-       } else {
-               if (verbosity > 0) {
-                       fprintf(myerr, "%s at line %d\n",
-                               ldns_get_errorstr_by_id(s), line_nr);
-               }
-                exit(EXIT_FAILURE);
+       } else if (result == LDNS_STATUS_OK) {
+               result = ldns_dnssec_zone_verify_zonemd(dnssec_zone);
+               if (verbosity <= 3)
+                       ; /* pass */
+               
+               else if (result)
+                       fprintf( myerr, "Could not validate zone digest: %s\n"
+                              , ldns_get_errorstr_by_id(result));
+
+               /* Result is also SUCCESS with proven ZONEMD absence,
+                * then we should not print "matched the content"
+                */
+               else if (zonemd_rrset)
+                       fprintf( myout
+                              , "Zone digest matched the zone content\n");
        }
-       fclose(fp);
+       if (result == LDNS_STATUS_OK) {
+               if (verbosity >= 3) {
+                       fprintf(myout, "Zone is verified and complete\n");
+               }
+       } else if (verbosity > 0)
+               fprintf(myerr, "There were errors in the zone\n");
 
+       ldns_dnssec_zone_deep_free(dnssec_zone);
+       fclose(fp);
        exit(result);
 }