]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
change do_ede to be local-zone specific and add places for more EDE codes
authorTCY16 <tom@nlnetlabs.nl>
Fri, 19 Nov 2021 10:27:13 +0000 (11:27 +0100)
committerTCY16 <tom@nlnetlabs.nl>
Fri, 19 Nov 2021 10:27:13 +0000 (11:27 +0100)
services/localzone.c
services/localzone.h
util/config_file.c
util/config_file.h
util/configlexer.lex
util/configparser.y
validator/validator.c

index d74191f9a96a9fdfc376d57ad913a4678e25505d..cf6411cc8b078b4d7eb62df2a6d12273c5110db7 100644 (file)
@@ -156,6 +156,7 @@ local_zone_create(uint8_t* nm, size_t len, int labs,
        z->name = nm;
        z->namelen = len;
        z->namelabs = labs;
+       z->do_ede = 0;
        lock_rw_init(&z->lock);
        z->region = regional_create_nochunk(sizeof(struct regional));
        if(!z->region) {
@@ -657,6 +658,53 @@ lz_enter_zone_tag(struct local_zones* zones, char* zname, uint8_t* list,
        return r;
 }
 
+/** enter do-ede option into zone */
+static int
+lz_enter_ede_respond(struct local_zones* zones, char* zname, char* option)
+{
+       uint8_t dname[LDNS_MAX_DOMAINLEN+1];
+       size_t dname_len = sizeof(dname);
+       uint8_t ede_option = 0;
+       int dname_label_count;
+       struct local_zone* z;
+
+       /* parse zone name */
+       if(sldns_str2wire_dname_buf(zname, dname, &dname_len) != 0) {
+               log_err("cannot parse zone name in local-zone-do-ede: %s",
+                       zname);
+               return 0;
+       }
+       dname_label_count = dname_count_labels(dname);
+
+       /* parse option */
+       if(strcmp(option, "yes") == 0)
+               ede_option = 1;
+       else if(strcmp(option, "no") == 0)
+               return 1; /* no need to change the default value */
+
+       /* find localzone entry */
+       lock_rw_rdlock(&zones->lock);
+       z = local_zones_find(zones, dname,
+                   dname_len, dname_label_count, LDNS_RR_CLASS_IN);
+       if(!z) {
+               lock_rw_unlock(&zones->lock);
+               log_err("no local-zone for local-zone-do-ede %s", zname);
+               return 0;
+       }
+       lock_rw_wrlock(&z->lock);
+       lock_rw_unlock(&zones->lock);
+
+       if (z->do_ede) {
+               lock_rw_unlock(&z->lock);
+               log_err("duplicate local-zone-do-ede %s", zname);
+               return 1;
+       }
+
+       z->do_ede = 1; /* respond with EDEs in this local-zone */
+       lock_rw_unlock(&z->lock);
+       return 1;
+}
+
 /** enter override into zone */
 static int
 lz_enter_override(struct local_zones* zones, char* zname, char* netblock,
@@ -943,6 +991,18 @@ lz_enter_overrides(struct local_zones* zones, struct config_file* cfg)
        return 1;
 }
 
+/** parse local-zone-do-ede: statements */
+static int
+lz_enter_ede_respond_zones(struct local_zones* zones, struct config_file* cfg)
+{
+       struct config_str2list* p;
+       for(p = cfg->local_zone_do_ede; p; p = p->next) {
+               if(!lz_enter_ede_respond(zones, p->str, p->str2))
+                       return 0;
+       }
+       return 1;
+}
+
 /** setup parent pointers, so that a lookup can be done for closest match */
 static void
 init_parents(struct local_zones* zones)
@@ -1124,6 +1184,11 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
        if(!lz_enter_overrides(zones, cfg)) {
                return 0;
        }
+       /* enter EDE (RFC8914) response option for local zones */
+       if(!lz_enter_ede_respond_zones(zones, cfg)) {
+               return 0;
+       }
+
        /* create implicit transparent zone from data. */
        if(!lz_setup_implicit(zones, cfg)) {
                return 0;
@@ -1288,10 +1353,11 @@ local_encode(struct query_info* qinfo, struct module_env* env,
 
 /** encode answer consisting of 1 rrset (with EDE code) */
 static int
-local_encode_ede(struct query_info* qinfo, struct module_env* env,
-       struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
-       struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec,
-       int rcode, sldns_ede_code ede_code, const char* ede_txt)
+local_encode_ede(struct local_zone* zone, struct query_info* qinfo,
+       struct module_env* env, struct edns_data* edns,
+       struct comm_reply* repinfo, sldns_buffer* buf, struct regional* temp,
+       struct ub_packed_rrset_key* rrset, int ansec, int rcode,
+       sldns_ede_code ede_code, const char* ede_txt)
 {
        struct reply_info rep;
        uint16_t udpsize;
@@ -1315,7 +1381,9 @@ local_encode_ede(struct query_info* qinfo, struct module_env* env,
                        *(uint16_t*)sldns_buffer_begin(buf),
                        sldns_buffer_read_u16_at(buf, 2), edns);
        } else {
-               edns_opt_list_append_ede(&edns->opt_list_out, temp, ede_code, ede_txt);
+               if(ede_code >= 0 && zone->do_ede)
+                       edns_opt_list_append_ede(&edns->opt_list_out,
+                               temp, ede_code, ede_txt);
 
                if(!reply_info_answer_encode(qinfo, &rep,
                        *(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2),
@@ -1330,10 +1398,10 @@ local_encode_ede(struct query_info* qinfo, struct module_env* env,
 
 /** encode local error answer */
 static void
-local_error_encode(struct query_info* qinfo, struct module_env* env,
-       struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
-       struct regional* temp, int rcode, int r, sldns_ede_code ede_code,
-       const char* ede_txt)
+local_error_encode(struct local_zone* zone, struct query_info* qinfo,
+       struct module_env* env, struct edns_data* edns,
+       struct comm_reply* repinfo, sldns_buffer* buf, struct regional* temp,
+       int rcode, int r, sldns_ede_code ede_code, const char* ede_txt)
 {
        edns->edns_version = EDNS_ADVERTISED_VERSION;
        edns->udp_size = EDNS_ADVERTISED_SIZE;
@@ -1343,7 +1411,7 @@ local_error_encode(struct query_info* qinfo, struct module_env* env,
        if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
                rcode, edns, repinfo, temp, env->now_tv))
                edns->opt_list_inplace_cb_out = NULL;
-       if(ede_code >= 0 && env->cfg->local_data_do_ede)
+       if(ede_code >= 0 && zone->do_ede)
                edns_opt_list_append_ede(&edns->opt_list_out, temp, ede_code, ede_txt);
        error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf),
                sldns_buffer_read_u16_at(buf, 2), edns);
@@ -1540,7 +1608,7 @@ local_data_answer(struct local_zone* z, struct module_env* env,
 
                        if(newtargetlen > LDNS_MAX_DOMAINLEN) {
                                qinfo->local_alias = NULL;
-                               local_error_encode(qinfo, env, edns,repinfo,
+                               local_error_encode(z, qinfo, env, edns,repinfo,
                                        buf, temp, LDNS_RCODE_YXDOMAIN,
                                        (LDNS_RCODE_YXDOMAIN|BIT_AA),
                                        LDNS_EDE_OTHER,
@@ -1647,7 +1715,7 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
                return 1;
        } else if(lz_type == local_zone_refuse
                || lz_type == local_zone_always_refuse) {
-               local_error_encode(qinfo, env, edns, repinfo, buf, temp,
+               local_error_encode(z, qinfo, env, edns, repinfo, buf, temp,
                        LDNS_RCODE_REFUSED, (LDNS_RCODE_REFUSED|BIT_AA),
                        LDNS_EDE_BLOCKED, "");
                return 1;
@@ -1674,7 +1742,7 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
                if(z != NULL && z->soa && z->soa_negative)
                        return local_encode(qinfo, env, edns, repinfo, buf, temp,
                                z->soa_negative, 0, rcode);
-               local_error_encode(qinfo, env, edns, repinfo, buf, temp,
+               local_error_encode(z, qinfo, env, edns, repinfo, buf, temp,
                        rcode, (rcode|BIT_AA), LDNS_EDE_BLOCKED, "");
                return 1;
        } else if(lz_type == local_zone_typetransparent
@@ -1713,11 +1781,11 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
                        d.rr_len = &rr_len;
                        d.rr_data = &rr_datas;
                        d.rr_ttl = &rr_ttl;
-                       return local_encode_ede(qinfo, env, edns, repinfo, buf, temp,
+                       return local_encode_ede(z, qinfo, env, edns, repinfo, buf, temp,
                                &lrr, 1, LDNS_RCODE_NOERROR, LDNS_EDE_FORGED_ANSWER, "");
                } else {
                        /* NODATA: No EDE needed */
-                       local_error_encode(qinfo, env, edns, repinfo, buf,
+                       local_error_encode(z, qinfo, env, edns, repinfo, buf,
                                temp, LDNS_RCODE_NOERROR,
                                (LDNS_RCODE_NOERROR|BIT_AA), -1, NULL);
                }
@@ -1733,7 +1801,7 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
                        return local_encode(qinfo, env, edns, repinfo, buf, temp,
                                z->soa_negative, 0, rcode);
                /* NODATA: No EDE needed */
-               local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode,
+               local_error_encode(z, qinfo, env, edns, repinfo, buf, temp, rcode,
                        (rcode|BIT_AA), -1, NULL);
                return 1;
        }
index 9a06a7f84f49cc36b55961128376211e8a81e69a..3a45ca166c8090e9453bca93f1c51560b3d9d03b 100644 (file)
@@ -164,6 +164,8 @@ struct local_zone {
         * artificial negative SOA rrset (TTL is the minimum of the TTL and the
         * SOA.MINIMUM). */
        struct ub_packed_rrset_key* soa_negative;
+        /** should local_data result in EDE (RFC8914) code inclusion? */
+        int do_ede;
 };
 
 /**
index 0d992528b87da008b40959bbb14db3352e236d23..8b7ed5618b9c63221c73bbf59408a89a66f206b3 100644 (file)
@@ -373,7 +373,7 @@ config_create(void)
        cfg->ipset_name_v4 = NULL;
        cfg->ipset_name_v6 = NULL;
 #endif
-       cfg->local_data_do_ede = 0;
+       cfg->local_zone_do_ede = NULL;
        return cfg;
 error_exit:
        config_delete(cfg);
@@ -791,7 +791,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
                }
                oi[cfg->num_out_ifs++] = d;
                cfg->out_ifs = oi;
-       } else S_YNO("local-data-do-ede:", local_data_do_ede)
+       } // else S_YNO("local-zone-do-ede:", local_zone_do_ede)
        else {
                /* unknown or unsupported (from the set_option interface):
                 * interface, outgoing-interface, access-control,
@@ -1241,6 +1241,7 @@ config_get_option(struct config_file* cfg, const char* opt,
 #ifdef USE_IPSET
        else O_STR(opt, "name-v4", ipset_name_v4)
        else O_STR(opt, "name-v6", ipset_name_v6)
+       else O_LS3(opt, "local-zone-do-ede", local_zone_do_ede)
 #endif
        /* not here:
         * outgoing-permit, outgoing-avoid - have list of ports
index e9e43e43f108f81fbbb19c5af1ca04cbea2e7c8b..18b47007d6b5dcd1a49704357da5faa0462f6a8c 100644 (file)
@@ -670,8 +670,8 @@ struct config_file {
        char* ipset_name_v6;
 #endif
 
-       /** should local_data result in EDE (RFC8914) code inclusion? */
-       int local_data_do_ede;
+       /** should a local_zone results inlude an EDE (RFC8914) code? */
+       struct config_str2list* local_zone_do_ede;
 };
 
 /** from cfg username, after daemonize setup performed */
index 27809911a80f4c959fb80ee1ad1d47197f220975..c934c42d06c8ea61c6580218309c72ec622f5c90 100644 (file)
@@ -549,7 +549,7 @@ tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
 edns-client-string{COLON}      { YDVAR(2, VAR_EDNS_CLIENT_STRING) }
 edns-client-string-opcode{COLON} { YDVAR(1, VAR_EDNS_CLIENT_STRING_OPCODE) }
 nsid{COLON}                    { YDVAR(1, VAR_NSID ) }
-local-data-do-ede{COLON}       { YDVAR(1, VAR_LOCAL_DATA_DO_EDE) }
+local-zone-do-ede{COLON}       { YDVAR(2, VAR_LOCAL_DATA_DO_EDE) }
 <INITIAL,val>{NEWLINE}         { LEXOUT(("NL\n")); cfg_parser->line++; }
 
        /* Quoted strings. Strip leading and ending quotes */
index d0d103af7488e6b0bb199f809f5b8b8ab0e0be47..4d9ec393c3500348fa62f5f14e1f8fbab7fd1c35 100644 (file)
@@ -310,7 +310,7 @@ content_server: server_num_threads | server_verbosity | server_port |
        server_edns_client_string_opcode | server_nsid |
        server_zonemd_permissive_mode | server_max_reuse_tcp_queries |
        server_tcp_reuse_timeout | server_tcp_auth_query_timeout |
-       server_local_data_do_ede
+       server_local_zone_do_ede
 
        ;
 stubstart: VAR_STUB_ZONE
@@ -2208,14 +2208,15 @@ server_local_data_ptr: VAR_LOCAL_DATA_PTR STRING_ARG
                }
        }
        ;
-server_local_data_do_ede: VAR_LOCAL_DATA_DO_EDE STRING_ARG
+server_local_zone_do_ede: VAR_LOCAL_DATA_DO_EDE STRING_ARG STRING_ARG
        {
-               OUTYY(("P(server_local_data_do_ede:%s)\n", $2));
-               if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+               OUTYY(("P(server_local_zone_do_ede:%s %s)\n", $2, $3));
+               if(strcmp($3, "yes") != 0 && strcmp($3, "no") != 0)
                        yyerror("expected yes or no.");
-               else cfg_parser->cfg->local_data_do_ede =
-                       (strcmp($2, "yes")==0);
-               free($2);
+               if(!cfg_str2list_insert(&cfg_parser->cfg->local_zone_do_ede,
+                       $2, $3)) {
+                       yyerror("out of memory adding local-zone-do-ede");
+               }
        }
        ;
 server_minimal_responses: VAR_MINIMAL_RESPONSES STRING_ARG
@@ -3016,14 +3017,6 @@ view_local_data_ptr: VAR_LOCAL_DATA_PTR STRING_ARG
                }
        }
        ;
-// view_local_data_do_ede: VAR_LOCAL_DATA_DO_EDE STRING_ARG
-//     {
-//             OUTYY(("P(view_local_data_do_ede:%s)\n", $2));
-//             if(!cfg_strlist_insert(&cfg_parser->cfg->views->local_data_do_ede, $2)) {
-//                     fatal_exit("out of memory adding local-data");
-//             }
-//     }
-//     ;
 view_first: VAR_VIEW_FIRST STRING_ARG
        {
                OUTYY(("P(view-first:%s)\n", $2));
index c5e351e8396ed4b71c6717cdcc2bc9a1c7c11d07..5f5804264e7f34b80d21838ab2129b461b48a05b 100644 (file)
@@ -1637,6 +1637,9 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
                return 1;
        } else if(key_entry_isbad(vq->key_entry)) {
                /* key is bad, chain is bad, reply is bogus */
+
+               // @TODO ADD Error Code 6 - DNSSEC Bogus + text chain of trust?
+
                errinf_dname(qstate, "key for validation", vq->key_entry->name);
                errinf(qstate, "is marked as invalid");
                if(key_entry_get_reason(vq->key_entry)) {
@@ -1854,6 +1857,9 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
                        LDNS_RR_TYPE_DNSKEY, vq->key_entry->key_class);
                vq->chase_reply->security = sec_status_bogus;
                errinf(qstate, "while building chain of trust");
+
+               // @TODO ADD Error Code 6 - DNSSEC Bogus + text chain of trust?
+
                if(vq->restart_count >= ve->max_restart)
                        key_cache_insert(ve->kcache, vq->key_entry, qstate);
                return 1;