From: W.C.A. Wijngaards Date: Wed, 22 Jul 2026 09:33:54 +0000 (+0200) Subject: Merge branch 'branch-1.25.2' X-Git-Tag: release-1.26.0rc1~39 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=91ac449bcd3e1edc813a565a8c176990b5407b08;p=thirdparty%2Funbound.git Merge branch 'branch-1.25.2' --- 91ac449bcd3e1edc813a565a8c176990b5407b08 diff --cc services/authzone.c index 430674b0c,e7a553916..4218b8e82 --- a/services/authzone.c +++ b/services/authzone.c @@@ -5853,35 -5743,9 +5853,34 @@@ xfr_master_add_addrs(struct auth_master } } +/** check if the lookup target name equals the found answer name. */ +static int +xfer_target_equals_answer_name(struct auth_master* lookup_target, + struct ub_packed_rrset_key* answer, struct query_info* rq, + struct reply_info* rep) +{ + uint8_t qname[LDNS_MAX_DOMAINLEN+1]; + size_t qname_len; + if(!lookup_target) return 0; + if(!answer) return 0; + qname_len = sizeof(qname); + if(sldns_str2wire_dname_buf(lookup_target->host, qname, &qname_len) + != 0) { + verbose(VERB_ALGO, "xfer_target_equals_answer_name: could not parse auth host name"); + return 0; + } + if(query_dname_compare(answer->rk.dname, qname) == 0) + return 1; + /* It could be a CNAME. */ + if(reply_find_rrset_section_an(rep, qname, qname_len, + LDNS_RR_TYPE_CNAME, rq->qclass)) + return 1; + return 0; +} + /** callback for task_transfer lookup of host name, of A or AAAA */ void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf, - enum sec_status ATTR_UNUSED(sec), char* ATTR_UNUSED(why_bogus), - int ATTR_UNUSED(was_ratelimited)) + enum sec_status sec, char* why_bogus, int ATTR_UNUSED(was_ratelimited)) { struct auth_xfer* xfr = (struct auth_xfer*)arg; struct module_env* env; diff --cc services/cache/rrset.c index 6fd9bc6e7,79bf473bb..9b0319140 --- a/services/cache/rrset.c +++ b/services/cache/rrset.c @@@ -268,8 -291,14 +298,16 @@@ void rrset_cache_update_wildcard(struc { struct rrset_ref ref; uint8_t wc_dname[LDNS_MAX_DOMAINLEN+3]; + uint8_t* new_dname; + size_t new_dname_len; + + /* See if the RRSIG signer name allows this wildcard, + * the new rrset should fall within the zone of the RRSIG signer(s). */ + if(!dname_subdomain_rrsig_signers(ce, rrset)) { + verbose(VERB_ALGO, "wildcard canonical parent outside signer authority"); + return; + } + rrset = packed_rrset_copy_alloc(rrset, alloc, timenow); if(!rrset) { log_err("malloc failure in rrset_cache_update_wildcard"); diff --cc services/listen_dnsport.c index 58b74863f,38b493a25..8ef084e5e --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@@ -2168,7 -2167,7 +2167,7 @@@ void tcp_req_info_clear(struct tcp_req_ while(open) { nopen = open->next; mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp, -- NULL); ++ NULL, NULL); free(open); open = nopen; } @@@ -3607,6 -3615,11 +3615,11 @@@ stream_tree_del(rbnode_type* node, void if(!node) return; stream = (struct doq_stream*)node; + if(stream->mesh_state) { + mesh_state_remove_reply(stream->mesh, stream->mesh_state, - args->conn->doq_socket->cp, stream); ++ args->conn->doq_socket->cp, NULL, stream); + stream->mesh_state = NULL; + } if(stream->in) doq_table_quic_size_subtract(table, stream->inlen); if(stream->out) @@@ -3626,10 -3639,13 +3639,14 @@@ doq_conn_delete(struct doq_conn* conn, lock_rw_unlock(&conn->table->conid_lock); /* Remove the app data from ngtcp2 before SSL_free of conn->ssl, * because the ngtcp2 conn is deleted. */ - SSL_set_app_data(conn->ssl, NULL); + if(conn->ssl) + SSL_set_app_data(conn->ssl, NULL); if(conn->stream_tree.count != 0) { - traverse_postorder(&conn->stream_tree, stream_tree_del, table); + struct doq_stream_tree_del_args args; + memset(&args, 0, sizeof(args)); + args.table = table; + args.conn = conn; + traverse_postorder(&conn->stream_tree, stream_tree_del, &args); } free(conn->key.dcid); SSL_free(conn->ssl); @@@ -3942,6 -3954,11 +3955,11 @@@ doq_stream_close(struct doq_conn* conn if(stream->is_closed) return 1; stream->is_closed = 1; + if(stream->mesh_state) { + mesh_state_remove_reply(stream->mesh, stream->mesh_state, - conn->doq_socket->cp, stream); ++ conn->doq_socket->cp, NULL, stream); + stream->mesh_state = NULL; + } doq_stream_off_write_list(conn, stream); if(send_shutdown) { verbose(VERB_ALGO, "doq: shutdown stream_id %d with app_error_code %d", diff --cc services/mesh.c index edfac6cf4,99361b17f..d664e4797 --- a/services/mesh.c +++ b/services/mesh.c @@@ -590,9 -554,10 +594,11 @@@ void mesh_new_client(struct mesh_area* goto servfail_mem; } } + added_tcp = 1; if(rep->c->use_h2) { http2_stream_add_meshstate(rep->c->h2_stream, mesh, s); + } else if(rep->c->type == comm_doq && rep->doq_stream) { + doq_stream_add_meshstate(rep->doq_stream, mesh, s); } /* add serve expired timer if required and not already there */ if(timeout && !mesh_serve_expired_init(s, timeout)) { @@@ -648,12 -611,9 +654,14 @@@ servfail_mem qinfo, qid, qflags, edns); if(rep->c->use_h2) http2_stream_remove_mesh_state(rep->c->h2_stream); + else if(rep->c->type == comm_doq && rep->doq_stream) + doq_stream_remove_mesh_state(rep->doq_stream); comm_point_send_reply(rep); + if(added_reply_without_accounting) { + mesh_remove_reply_without_accounting(s, repadded); + if(added_tcp && rep->c->tcp_req_info) + tcp_req_info_remove_mesh_state(rep->c->tcp_req_info, s); + } if(added) mesh_state_delete(&s->s); return; @@@ -2437,7 -2388,7 +2459,8 @@@ void mesh_list_remove(struct mesh_state } void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m, - struct comm_point* cp, struct http2_stream* h2_stream) - struct comm_point* cp, struct doq_stream* doq_stream) ++ struct comm_point* cp, struct http2_stream* h2_stream, ++ struct doq_stream* doq_stream) { struct mesh_reply* n, *prev = NULL; n = m->reply_list; @@@ -2446,7 -2397,7 +2469,9 @@@ if(!n) return; /* nothing to remove, also no accounting needed */ while(n) { if(n->query_reply.c == cp - && (!h2_stream || n->h2_stream == h2_stream)) { - && (!doq_stream || n->query_reply.doq_stream == doq_stream)) { ++ && (!h2_stream || n->h2_stream == h2_stream) ++ && (!doq_stream || n->query_reply.doq_stream == doq_stre ++am)) { /* unlink it */ if(prev) prev->next = n->next; else m->reply_list = n->next; diff --cc services/mesh.h index 77b3c7025,6ea63d098..0f1d91c00 --- a/services/mesh.h +++ b/services/mesh.h @@@ -705,11 -683,11 +705,14 @@@ void mesh_list_remove(struct mesh_state * @param mesh: to update the counters. * @param m: the mesh state. * @param cp: the comm_point to remove from the list. + * @param h2_stream: if not NULL, it specifies the h2_stream to match + * for the delete. + * @param doq_stream: if not NULL, it specifies the doq_stream to match + * for the delete. */ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m, - struct comm_point* cp, struct http2_stream* h2_stream); - struct comm_point* cp, struct doq_stream* doq_stream); ++ struct comm_point* cp, struct http2_stream* h2_stream, ++ struct doq_stream* doq_stream); /** Callback for when the serve expired client timer has run out. Tries to * find an expired answer in the cache and reply that to the client. @@@ -756,9 -734,12 +759,13 @@@ void mesh_respond_serve_expired(struct * @param qflags: flags from client query. * @param cb: callback function. * @param cb_arg: callback user arg. + * @param unique_info: if not NULL, used to find a unique state for removal. */ void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo, - uint16_t qflags, mesh_cb_func_type cb, void* cb_arg); + uint16_t qflags, mesh_cb_func_type cb, void* cb_arg, void* unique_info); + /** Copy the client info to the query region. */ + struct respip_client_info* mesh_copy_client_info(struct regional* region, + struct respip_client_info* cinfo); + #endif /* SERVICES_MESH_H */ diff --cc services/outside_network.c index 4d29165d3,9dfa8b4d0..50028fc1e --- a/services/outside_network.c +++ b/services/outside_network.c @@@ -1707,11 -1702,11 +1702,17 @@@ static int setup_if(struct port_if* pif !netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen, &pif->pfxlen)) return 0; +#ifdef INT_MAX + if(numfd > (size_t)INT_MAX) { + log_err("num_ports exceeds INT_MAX"); + return 0; + } ++#endif + #ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION + pif->shpif = shared_ports_find_if(shp, &pif->addr, pif->addrlen, + pif->pfxlen); + #else + (void)shp; #endif pif->maxout = (int)numfd; pif->inuse = 0; diff --cc util/netevent.c index 37b29bc24,b7092b88a..432fead1b --- a/util/netevent.c +++ b/util/netevent.c @@@ -3241,7 -3166,7 +3233,7 @@@ static void http2_stream_delete(struct { if(h2_stream->mesh_state) { mesh_state_remove_reply(h2_stream->mesh, h2_stream->mesh_state, - h2_session->c, h2_stream); - h2_session->c, NULL); ++ h2_session->c, h2_stream, NULL); h2_stream->mesh_state = NULL; } http2_req_stream_clear(h2_stream); diff --cc validator/val_sigcrypt.c index 674db9d40,16c01d2ee..8cfbb1466 --- a/validator/val_sigcrypt.c +++ b/validator/val_sigcrypt.c @@@ -1106,7 -1094,7 +1106,8 @@@ canonicalize_rdata(sldns_buffer* buf, s size_t len) { uint8_t* datstart = sldns_buffer_current(buf)-len+2; + uint8_t* datend = sldns_buffer_current(buf); + size_t firstlen; switch(ntohs(rrset->rk.type)) { case LDNS_RR_TYPE_NXT: case LDNS_RR_TYPE_NS: @@@ -1125,9 -1113,10 +1126,10 @@@ case LDNS_RR_TYPE_RP: case LDNS_RR_TYPE_SOA: /* two names after another */ - query_dname_tolower(datstart); + canon_dname_tolower(datstart, datend); - canon_dname_tolower(datstart + - dname_valid(datstart, len-2), datend); + firstlen = dname_valid(datstart, len-2); + if(firstlen && firstlen < len-2) - query_dname_tolower(datstart + firstlen); ++ canon_dname_tolower(datstart + firstlen, datend); return; case LDNS_RR_TYPE_RT: case LDNS_RR_TYPE_AFSDB: @@@ -1153,9 -1142,10 +1155,10 @@@ if(len < 2+2+1) return; datstart += 2; - query_dname_tolower(datstart); + canon_dname_tolower(datstart, datend); - canon_dname_tolower(datstart + - dname_valid(datstart, len-2-2), datend); + firstlen = dname_valid(datstart, len-2-2); + if(firstlen && firstlen < len-2-2) - query_dname_tolower(datstart + firstlen); ++ canon_dname_tolower(datstart + firstlen, datend); return; case LDNS_RR_TYPE_NAPTR: if(len < 2+4)