]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix for autotrust state-file line overflow, that can give
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 27 May 2026 10:09:01 +0000 (12:09 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 27 May 2026 10:09:01 +0000 (12:09 +0200)
  hold-down bypass. Thanks to Qifan Zhang, Palo Alto Networks,
  for the report.

doc/Changelog
validator/autotrust.c

index 4579cee29bcb55dbeb9051dd1f20fba70b3a359f..7945a98cd72f46887a9c47adb26d6ed5c21d078e 100644 (file)
@@ -1,3 +1,8 @@
+27 May 2026: Wouter
+       - Fix for autotrust state-file line overflow, that can give
+         hold-down bypass. Thanks to Qifan Zhang, Palo Alto Networks,
+         for the report.
+
 26 May 2026: Wouter
        - Fix for mesh new client and mesh new callback to rollback the
          added address, tcp mesh state and callback when there is a failure
index a0f61885f5dd7a2fbd065c3510139f80b435c305..0238653d393845a51f5d308fa7110b7a6ca1a9f3 100644 (file)
@@ -160,10 +160,12 @@ verbose_key(struct autr_ta* ta, enum verbosity_value level,
  * Parse comments 
  * @param str: to parse
  * @param ta: trust key autotrust metadata
+ * @param header_seen: if an autotrust file header was seen.
+ *     Without such a header it is a list of resource records.
  * @return false on failure.
  */
 static int
-parse_comments(char* str, struct autr_ta* ta)
+parse_comments(char* str, struct autr_ta* ta, int header_seen)
 {
         int len = (int)strlen(str), pos = 0, timestamp = 0;
         char* comment = (char*) malloc(sizeof(char)*len+1);
@@ -196,10 +198,18 @@ parse_comments(char* str, struct autr_ta* ta)
                 free(comment);
                 return 0;
         }
-        if (pos <= 0)
-                ta->s = AUTR_STATE_VALID;
-        else
-        {
+        if (pos <= 0) {
+               if(header_seen) {
+                       /* There was an autotrust trust anchor file header,
+                        * with a ;; id=.. line, so the entries
+                        * have to have ;;state= annotations. */
+                       log_err("trust anchor in state file has no ;;state= "
+                               "annotation, ignoring");
+                       free(comment);
+                       return 0;
+               }
+               ta->s = AUTR_STATE_VALID;
+        } else {
                 int s = (int) comments[pos] - '0';
                 switch(s)
                 {
@@ -523,12 +533,14 @@ add_trustanchor_frm_str(struct val_anchors* anchors, char* str,
  * @param prev: passed to ldns.
  * @param prev_len: length of prev
  * @param skip: if true, the result is NULL, but not an error, skip it.
+ * @param header_seen: if an autotrust file header was seen.
+ *     Without such a header it is a list of resource records.
  * @return false on failure, otherwise the tp read.
  */
 static struct trust_anchor*
 load_trustanchor(struct val_anchors* anchors, char* str, const char* fname,
        uint8_t* origin, size_t origin_len, uint8_t** prev, size_t* prev_len,
-       int* skip)
+       int* skip, int header_seen)
 {
        struct autr_ta* ta = NULL;
        struct trust_anchor* tp = NULL;
@@ -538,7 +550,7 @@ load_trustanchor(struct val_anchors* anchors, char* str, const char* fname,
        if(!ta)
                return NULL;
        lock_basic_lock(&tp->lock);
-       if(!parse_comments(str, ta)) {
+       if(!parse_comments(str, ta, header_seen)) {
                lock_basic_unlock(&tp->lock);
                return NULL;
        }
@@ -992,8 +1004,8 @@ int autr_read_file(struct val_anchors* anchors, const char* nm)
         FILE* fd;
         /* keep track of line numbers */
         int line_nr = 0;
-        /* single line */
-        char line[10240];
+        /* single line, enough space for large DNSKEY, 64K, in hex and dname */
+        char line[10240+65536*2];
        /* trust point being read */
        struct trust_anchor *tp = NULL, *tp2;
        int r;
@@ -1030,7 +1042,7 @@ int autr_read_file(struct val_anchors* anchors, const char* nm)
                        continue;
                r = 0;
                 if(!(tp2=load_trustanchor(anchors, line, nm, origin,
-                       origin_len, &prev, &prev_len, &r))) {
+                       origin_len, &prev, &prev_len, &r, (tp!=NULL)))) {
                        if(!r) log_err("failed to load trust anchor from %s "
                                "at line %i, skipping", nm, line_nr);
                         /* try to do the rest */