diff --git a/validator/val_neg.c b/validator/val_neg.c index 66fd81899..e82f335b9 100644 --- a/validator/val_neg.c +++ b/validator/val_neg.c @@ -62,6 +62,13 @@ #include "sldns/rrdef.h" #include "sldns/sbuffer.h" +/** + * The maximum salt length that the negative cache is willing to use. + * Larger salt increases the computation time, while recommendations are + * for zero salt length for zones. + */ +#define MAX_SALT_LENGTH 64 + int val_neg_data_compare(const void* a, const void* b) { struct val_neg_data* x = (struct val_neg_data*)a; @@ -826,7 +833,11 @@ void neg_insert_data(struct val_neg_cache* neg, (slen != 0 && zone->nsec3_salt && s && memcmp(zone->nsec3_salt, s, slen) != 0))) { - if(slen > 0) { + if(slen > MAX_SALT_LENGTH) { + /* RFC 9276 s3.1: operators SHOULD NOT use a salt; large + * salts inflate per-hash block count. Decline to cache. */ + return; + } else if(slen > 0) { uint8_t* sa = memdup(s, slen); if(sa) { free(zone->nsec3_salt); @@ -1165,6 +1176,15 @@ neg_find_nsec3_ce(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len, uint8_t hashce[NSEC3_SHA_LEN]; uint8_t b32[257]; size_t celen, b32len; + int hashmax = MAX_NSEC3_CALCULATIONS; + if(qlabs > hashmax) { + /* strip leading labels so the walk costs at most + * MAX_NSEC3_CALCULATIONS hashes, mirroring val_nsec3.c */ + while(qlabs > hashmax) { + dname_remove_label(&qname, &qname_len); + qlabs--; + } + } *nclen = 0; while(qlabs > 0) { @@ -1265,6 +1285,12 @@ neg_nsec3_proof_ds(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len, if(!zone->nsec3_hash) return NULL; /* not nsec3 zone */ + if(!topname && qlabs > zone->labs + 1) + return NULL; /* iterator caller; opt-out proof would be discarded + * at the !topname check below anyway. + * The qlabs check allows the exact-match for + * the one-label-below-zone case. */ + if(!(data=neg_find_nsec3_ce(zone, qname, qname_len, qlabs, buf, hashnc, &nclen))) { return NULL; diff --git a/validator/val_nsec3.c b/validator/val_nsec3.c index 998fcc4e3..04f53daf6 100644 --- a/validator/val_nsec3.c +++ b/validator/val_nsec3.c @@ -59,11 +59,6 @@ #include "sldns/sbuffer.h" #include "util/config_file.h" -/** - * Max number of NSEC3 calculations at once, suspend query for later. - * 8 is low enough and allows for cases where multiple proofs are needed. - */ -#define MAX_NSEC3_CALCULATIONS 8 /** * When all allowed NSEC3 calculations at once resulted in error treat as * bogus. NSEC3 hash errors are not cached and this helps breaks loops with diff --git a/validator/val_nsec3.h b/validator/val_nsec3.h index f668a270f..a13e92991 100644 --- a/validator/val_nsec3.h +++ b/validator/val_nsec3.h @@ -98,6 +98,12 @@ struct sldns_buffer; /** The SHA1 hash algorithm for NSEC3 */ #define NSEC3_HASH_SHA1 0x01 +/** + * Max number of NSEC3 calculations at once, suspend query for later. + * 8 is low enough and allows for cases where multiple proofs are needed. + */ +#define MAX_NSEC3_CALCULATIONS 8 + /** * Cache table for NSEC3 hashes. * It keeps a *pointer* to the region its items are allocated.