1 1.1 christos /* 2 1.1 christos * axfr.c -- generating AXFR responses. 3 1.1 christos * 4 1.1 christos * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 1.1 christos * 6 1.1 christos * See LICENSE for the license. 7 1.1 christos * 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include "config.h" 11 1.1 christos 12 1.1 christos #include "axfr.h" 13 1.1 christos #include "dns.h" 14 1.1 christos #include "packet.h" 15 1.1 christos #include "options.h" 16 1.1.1.4 christos #include "ixfr.h" 17 1.1 christos 18 1.1.1.3 christos /* draft-ietf-dnsop-rfc2845bis-06, section 5.3.1 says to sign every packet */ 19 1.1.1.3 christos #define AXFR_TSIG_SIGN_EVERY_NTH 0 /* tsig sign every N packets. */ 20 1.1 christos 21 1.1 christos query_state_type 22 1.1.1.4 christos query_axfr(struct nsd *nsd, struct query *query, int wstats) 23 1.1 christos { 24 1.1 christos domain_type *closest_match; 25 1.1 christos domain_type *closest_encloser; 26 1.1 christos int exact; 27 1.1 christos int added; 28 1.1 christos uint16_t total_added = 0; 29 1.1 christos 30 1.1 christos if (query->axfr_is_done) 31 1.1 christos return QUERY_PROCESSED; 32 1.1 christos 33 1.1 christos if (query->maxlen > AXFR_MAX_MESSAGE_LEN) 34 1.1 christos query->maxlen = AXFR_MAX_MESSAGE_LEN; 35 1.1 christos 36 1.1 christos assert(!query_overflow(query)); 37 1.1 christos /* only keep running values for most packets */ 38 1.1 christos query->tsig_prepare_it = 0; 39 1.1 christos query->tsig_update_it = 1; 40 1.1 christos if(query->tsig_sign_it) { 41 1.1 christos /* prepare for next updates */ 42 1.1 christos query->tsig_prepare_it = 1; 43 1.1 christos query->tsig_sign_it = 0; 44 1.1 christos } 45 1.1 christos 46 1.1 christos if (query->axfr_zone == NULL) { 47 1.1 christos domain_type* qdomain; 48 1.1 christos /* Start AXFR. */ 49 1.1.1.4 christos if(wstats) { 50 1.1.1.4 christos STATUP(nsd, raxfr); 51 1.1.1.4 christos } 52 1.1 christos exact = namedb_lookup(nsd->db, 53 1.1 christos query->qname, 54 1.1 christos &closest_match, 55 1.1 christos &closest_encloser); 56 1.1 christos 57 1.1 christos qdomain = closest_encloser; 58 1.1 christos query->axfr_zone = domain_find_zone(nsd->db, closest_encloser); 59 1.1 christos 60 1.1 christos if (!exact 61 1.1 christos || query->axfr_zone == NULL 62 1.1 christos || query->axfr_zone->apex != qdomain 63 1.1 christos || query->axfr_zone->soa_rrset == NULL) 64 1.1 christos { 65 1.1 christos /* No SOA no transfer */ 66 1.1 christos RCODE_SET(query->packet, RCODE_NOTAUTH); 67 1.1 christos return QUERY_PROCESSED; 68 1.1 christos } 69 1.1.1.4 christos if(wstats) { 70 1.1.1.4 christos ZTATUP(nsd, query->axfr_zone, raxfr); 71 1.1.1.4 christos } 72 1.1 christos 73 1.1 christos query->axfr_current_domain = qdomain; 74 1.1 christos query->axfr_current_rrset = NULL; 75 1.1 christos query->axfr_current_rr = 0; 76 1.1 christos if(query->tsig.status == TSIG_OK) { 77 1.1 christos query->tsig_sign_it = 1; /* sign first packet in stream */ 78 1.1 christos } 79 1.1 christos 80 1.1 christos query_add_compression_domain(query, qdomain, QHEADERSZ); 81 1.1 christos 82 1.1 christos assert(query->axfr_zone->soa_rrset->rr_count == 1); 83 1.1 christos added = packet_encode_rr(query, 84 1.1 christos query->axfr_zone->apex, 85 1.1.1.6 christos query->axfr_zone->soa_rrset->rrs[0], 86 1.1.1.6 christos query->axfr_zone->soa_rrset->rrs[0]->ttl); 87 1.1 christos if (!added) { 88 1.1 christos /* XXX: This should never happen... generate error code? */ 89 1.1 christos abort(); 90 1.1 christos } 91 1.1 christos ++total_added; 92 1.1 christos } else { 93 1.1 christos /* 94 1.1 christos * Query name and EDNS need not be repeated after the 95 1.1 christos * first response packet. 96 1.1 christos */ 97 1.1 christos query->edns.status = EDNS_NOT_PRESENT; 98 1.1 christos buffer_set_limit(query->packet, QHEADERSZ); 99 1.1 christos QDCOUNT_SET(query->packet, 0); 100 1.1 christos query_prepare_response(query); 101 1.1 christos } 102 1.1 christos 103 1.1 christos /* Add zone RRs until answer is full. */ 104 1.1 christos while (query->axfr_current_domain != NULL && 105 1.1 christos domain_is_subdomain(query->axfr_current_domain, 106 1.1 christos query->axfr_zone->apex)) 107 1.1 christos { 108 1.1 christos if (!query->axfr_current_rrset) { 109 1.1 christos query->axfr_current_rrset = domain_find_any_rrset( 110 1.1 christos query->axfr_current_domain, 111 1.1 christos query->axfr_zone); 112 1.1 christos query->axfr_current_rr = 0; 113 1.1 christos } 114 1.1 christos while (query->axfr_current_rrset) { 115 1.1 christos if (query->axfr_current_rrset != query->axfr_zone->soa_rrset 116 1.1 christos && query->axfr_current_rrset->zone == query->axfr_zone) 117 1.1 christos { 118 1.1 christos while (query->axfr_current_rr < query->axfr_current_rrset->rr_count) { 119 1.1.1.5 christos size_t oldmaxlen = query->maxlen; 120 1.1.1.5 christos if(total_added == 0) 121 1.1.1.5 christos /* RR > 16K can be first RR */ 122 1.1.1.5 christos query->maxlen = (query->tcp?TCP_MAX_MESSAGE_LEN:UDP_MAX_MESSAGE_LEN); 123 1.1 christos added = packet_encode_rr( 124 1.1 christos query, 125 1.1 christos query->axfr_current_domain, 126 1.1.1.6 christos query->axfr_current_rrset->rrs[query->axfr_current_rr], 127 1.1.1.6 christos query->axfr_current_rrset->rrs[query->axfr_current_rr]->ttl); 128 1.1.1.5 christos if(total_added == 0) { 129 1.1.1.5 christos query->maxlen = oldmaxlen; 130 1.1.1.5 christos if(query_overflow(query)) { 131 1.1.1.5 christos if(added) { 132 1.1.1.5 christos ++total_added; 133 1.1.1.5 christos ++query->axfr_current_rr; 134 1.1.1.5 christos goto return_answer; 135 1.1.1.5 christos } 136 1.1.1.5 christos } 137 1.1.1.5 christos } 138 1.1 christos if (!added) 139 1.1 christos goto return_answer; 140 1.1 christos ++total_added; 141 1.1 christos ++query->axfr_current_rr; 142 1.1 christos } 143 1.1 christos } 144 1.1 christos 145 1.1 christos query->axfr_current_rrset = query->axfr_current_rrset->next; 146 1.1 christos query->axfr_current_rr = 0; 147 1.1 christos } 148 1.1 christos assert(query->axfr_current_domain); 149 1.1 christos query->axfr_current_domain 150 1.1 christos = domain_next(query->axfr_current_domain); 151 1.1 christos } 152 1.1 christos 153 1.1 christos /* Add terminating SOA RR. */ 154 1.1 christos assert(query->axfr_zone->soa_rrset->rr_count == 1); 155 1.1 christos added = packet_encode_rr(query, 156 1.1 christos query->axfr_zone->apex, 157 1.1.1.6 christos query->axfr_zone->soa_rrset->rrs[0], 158 1.1.1.6 christos query->axfr_zone->soa_rrset->rrs[0]->ttl); 159 1.1 christos if (added) { 160 1.1 christos ++total_added; 161 1.1 christos query->tsig_sign_it = 1; /* sign last packet */ 162 1.1 christos query->axfr_is_done = 1; 163 1.1 christos } 164 1.1 christos 165 1.1 christos return_answer: 166 1.1 christos AA_SET(query->packet); 167 1.1 christos ANCOUNT_SET(query->packet, total_added); 168 1.1 christos NSCOUNT_SET(query->packet, 0); 169 1.1 christos ARCOUNT_SET(query->packet, 0); 170 1.1 christos 171 1.1 christos /* check if it needs tsig signatures */ 172 1.1 christos if(query->tsig.status == TSIG_OK) { 173 1.1.1.3 christos #if AXFR_TSIG_SIGN_EVERY_NTH > 0 174 1.1 christos if(query->tsig.updates_since_last_prepare >= AXFR_TSIG_SIGN_EVERY_NTH) { 175 1.1.1.3 christos #endif 176 1.1 christos query->tsig_sign_it = 1; 177 1.1.1.3 christos #if AXFR_TSIG_SIGN_EVERY_NTH > 0 178 1.1 christos } 179 1.1.1.3 christos #endif 180 1.1 christos } 181 1.1 christos query_clear_compression_tables(query); 182 1.1 christos return QUERY_IN_AXFR; 183 1.1 christos } 184 1.1 christos 185 1.1.1.4 christos /* See if the query can be admitted. */ 186 1.1.1.4 christos static int axfr_ixfr_can_admit_query(struct nsd* nsd, struct query* q) 187 1.1.1.4 christos { 188 1.1.1.4 christos struct acl_options *acl = NULL; 189 1.1.1.4 christos struct zone_options* zone_opt; 190 1.1.1.6 christos 191 1.1.1.6 christos #ifdef HAVE_SSL 192 1.1.1.6 christos /* tls-auth-xfr-only is set and this is not an authenticated TLS */ 193 1.1.1.6 christos if (nsd->options->tls_auth_xfr_only && !q->tls_auth) { 194 1.1.1.6 christos if (verbosity >= 2) { 195 1.1.1.6 christos char address[128], proxy[128]; 196 1.1.1.6 christos addr2str(&q->client_addr, address, sizeof(address)); 197 1.1.1.6 christos addr2str(&q->remote_addr, proxy, sizeof(proxy)); 198 1.1.1.6 christos VERBOSITY(2, (LOG_INFO, "%s for %s from %s refused tls-auth-xfr-only", 199 1.1.1.6 christos (q->qtype==TYPE_AXFR?"axfr":"ixfr"), 200 1.1.1.6 christos dname_to_string(q->qname, NULL), 201 1.1.1.6 christos address)); 202 1.1.1.6 christos } 203 1.1.1.6 christos RCODE_SET(q->packet, RCODE_REFUSE); 204 1.1.1.6 christos /* RFC8914 - Extended DNS Errors 205 1.1.1.6 christos * 4.19. Extended DNS Error Code 18 - Prohibited */ 206 1.1.1.6 christos q->edns.ede = EDE_PROHIBITED; 207 1.1.1.6 christos return 0; 208 1.1.1.6 christos } 209 1.1.1.6 christos #endif 210 1.1.1.6 christos 211 1.1.1.4 christos zone_opt = zone_options_find(nsd->options, q->qname); 212 1.1.1.5 christos if(zone_opt && q->is_proxied && acl_check_incoming_block_proxy( 213 1.1.1.5 christos zone_opt->pattern->provide_xfr, q, &acl) == -1) { 214 1.1.1.5 christos /* the proxy address is blocked */ 215 1.1.1.5 christos if (verbosity >= 2) { 216 1.1.1.5 christos char address[128], proxy[128]; 217 1.1.1.5 christos addr2str(&q->client_addr, address, sizeof(address)); 218 1.1.1.5 christos addr2str(&q->remote_addr, proxy, sizeof(proxy)); 219 1.1.1.5 christos VERBOSITY(2, (LOG_INFO, "%s for %s from %s via proxy %s refused because of proxy, %s %s", 220 1.1.1.5 christos (q->qtype==TYPE_AXFR?"axfr":"ixfr"), 221 1.1.1.5 christos dname_to_string(q->qname, NULL), 222 1.1.1.5 christos address, proxy, 223 1.1.1.5 christos (acl?acl->ip_address_spec:"."), 224 1.1.1.5 christos (acl ? ( acl->nokey ? "NOKEY" 225 1.1.1.5 christos : acl->blocked ? "BLOCKED" 226 1.1.1.5 christos : acl->key_name ) 227 1.1.1.5 christos : "no acl matches"))); 228 1.1.1.5 christos } 229 1.1.1.5 christos RCODE_SET(q->packet, RCODE_REFUSE); 230 1.1.1.5 christos /* RFC8914 - Extended DNS Errors 231 1.1.1.5 christos * 4.19. Extended DNS Error Code 18 - Prohibited */ 232 1.1.1.5 christos q->edns.ede = EDE_PROHIBITED; 233 1.1.1.5 christos return 0; 234 1.1.1.5 christos } 235 1.1.1.4 christos if(!zone_opt || 236 1.1.1.4 christos acl_check_incoming(zone_opt->pattern->provide_xfr, q, &acl)==-1) 237 1.1.1.4 christos { 238 1.1.1.4 christos if (verbosity >= 2) { 239 1.1.1.4 christos char a[128]; 240 1.1.1.5 christos addr2str(&q->client_addr, a, sizeof(a)); 241 1.1.1.4 christos VERBOSITY(2, (LOG_INFO, "%s for %s from %s refused, %s", 242 1.1.1.4 christos (q->qtype==TYPE_AXFR?"axfr":"ixfr"), 243 1.1.1.4 christos dname_to_string(q->qname, NULL), a, acl?"blocked":"no acl matches")); 244 1.1.1.4 christos } 245 1.1.1.4 christos DEBUG(DEBUG_XFRD,1, (LOG_INFO, "%s refused, %s", 246 1.1.1.4 christos (q->qtype==TYPE_AXFR?"axfr":"ixfr"), 247 1.1.1.4 christos acl?"blocked":"no acl matches")); 248 1.1.1.4 christos if (!zone_opt) { 249 1.1.1.4 christos RCODE_SET(q->packet, RCODE_NOTAUTH); 250 1.1.1.4 christos } else { 251 1.1.1.4 christos RCODE_SET(q->packet, RCODE_REFUSE); 252 1.1.1.4 christos /* RFC8914 - Extended DNS Errors 253 1.1.1.4 christos * 4.19. Extended DNS Error Code 18 - Prohibited */ 254 1.1.1.4 christos q->edns.ede = EDE_PROHIBITED; 255 1.1.1.4 christos } 256 1.1.1.4 christos return 0; 257 1.1.1.4 christos } 258 1.1.1.6 christos #ifdef HAVE_SSL 259 1.1.1.6 christos DEBUG(DEBUG_XFRD,1, (LOG_INFO, "%s admitted acl %s %s %s", 260 1.1.1.6 christos (q->qtype==TYPE_AXFR?"axfr":"ixfr"), 261 1.1.1.6 christos acl->ip_address_spec, acl->key_name?acl->key_name:"NOKEY", 262 1.1.1.6 christos (q->tls||q->tls_auth)?(q->tls?"tls":"tls-auth"):"")); 263 1.1.1.6 christos #else 264 1.1.1.4 christos DEBUG(DEBUG_XFRD,1, (LOG_INFO, "%s admitted acl %s %s", 265 1.1.1.4 christos (q->qtype==TYPE_AXFR?"axfr":"ixfr"), 266 1.1.1.4 christos acl->ip_address_spec, acl->key_name?acl->key_name:"NOKEY")); 267 1.1.1.6 christos #endif 268 1.1.1.4 christos if (verbosity >= 1) { 269 1.1.1.4 christos char a[128]; 270 1.1.1.5 christos addr2str(&q->client_addr, a, sizeof(a)); 271 1.1.1.6 christos #ifdef HAVE_SSL 272 1.1.1.6 christos VERBOSITY(1, (LOG_INFO, "%s for %s from %s %s %s", 273 1.1.1.6 christos (q->qtype==TYPE_AXFR?"axfr":"ixfr"), 274 1.1.1.6 christos dname_to_string(q->qname, NULL), a, 275 1.1.1.6 christos (q->tls||q->tls_auth)?(q->tls?"tls":"tls-auth"):"", 276 1.1.1.6 christos q->cert_cn?q->cert_cn:"not-verified")); 277 1.1.1.6 christos #else 278 1.1.1.4 christos VERBOSITY(1, (LOG_INFO, "%s for %s from %s", 279 1.1.1.4 christos (q->qtype==TYPE_AXFR?"axfr":"ixfr"), 280 1.1.1.4 christos dname_to_string(q->qname, NULL), a)); 281 1.1.1.6 christos #endif 282 1.1.1.4 christos } 283 1.1.1.4 christos return 1; 284 1.1.1.4 christos } 285 1.1.1.4 christos 286 1.1 christos /* 287 1.1 christos * Answer if this is an AXFR or IXFR query. 288 1.1 christos */ 289 1.1 christos query_state_type 290 1.1 christos answer_axfr_ixfr(struct nsd *nsd, struct query *q) 291 1.1 christos { 292 1.1 christos /* Is it AXFR? */ 293 1.1 christos switch (q->qtype) { 294 1.1 christos case TYPE_AXFR: 295 1.1 christos if (q->tcp) { 296 1.1.1.4 christos if(!axfr_ixfr_can_admit_query(nsd, q)) 297 1.1 christos return QUERY_PROCESSED; 298 1.1.1.4 christos return query_axfr(nsd, q, 1); 299 1.1 christos } 300 1.1.1.3 christos /* AXFR over UDP queries are discarded. */ 301 1.1.1.3 christos RCODE_SET(q->packet, RCODE_IMPL); 302 1.1.1.3 christos return QUERY_PROCESSED; 303 1.1 christos case TYPE_IXFR: 304 1.1.1.4 christos if(!axfr_ixfr_can_admit_query(nsd, q)) { 305 1.1.1.4 christos /* get rid of authority section, if present */ 306 1.1.1.4 christos NSCOUNT_SET(q->packet, 0); 307 1.1.1.4 christos ARCOUNT_SET(q->packet, 0); 308 1.1.1.4 christos if(QDCOUNT(q->packet) > 0 && (size_t)QHEADERSZ+4+ 309 1.1.1.4 christos q->qname->name_size <= buffer_limit(q->packet)) { 310 1.1.1.4 christos buffer_set_position(q->packet, QHEADERSZ+4+ 311 1.1.1.4 christos q->qname->name_size); 312 1.1.1.4 christos } 313 1.1.1.4 christos return QUERY_PROCESSED; 314 1.1.1.3 christos } 315 1.1.1.4 christos return query_ixfr(nsd, q); 316 1.1 christos default: 317 1.1 christos return QUERY_DISCARDED; 318 1.1 christos } 319 1.1 christos } 320