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