Home | History | Annotate | Line # | Download | only in dist
      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 					size_t oldmaxlen = query->maxlen;
    120 					if(total_added == 0)
    121 						/* RR > 16K can be first RR */
    122 						query->maxlen = (query->tcp?TCP_MAX_MESSAGE_LEN:UDP_MAX_MESSAGE_LEN);
    123 					added = packet_encode_rr(
    124 						query,
    125 						query->axfr_current_domain,
    126 						query->axfr_current_rrset->rrs[query->axfr_current_rr],
    127 						query->axfr_current_rrset->rrs[query->axfr_current_rr]->ttl);
    128 					if(total_added == 0) {
    129 						query->maxlen = oldmaxlen;
    130 						if(query_overflow(query)) {
    131 							if(added) {
    132 								++total_added;
    133 								++query->axfr_current_rr;
    134 								goto return_answer;
    135 							}
    136 						}
    137 					}
    138 					if (!added)
    139 						goto return_answer;
    140 					++total_added;
    141 					++query->axfr_current_rr;
    142 				}
    143 			}
    144 
    145 			query->axfr_current_rrset = query->axfr_current_rrset->next;
    146 			query->axfr_current_rr = 0;
    147 		}
    148 		assert(query->axfr_current_domain);
    149 		query->axfr_current_domain
    150 			= domain_next(query->axfr_current_domain);
    151 	}
    152 
    153 	/* Add terminating SOA RR.  */
    154 	assert(query->axfr_zone->soa_rrset->rr_count == 1);
    155 	added = packet_encode_rr(query,
    156 				 query->axfr_zone->apex,
    157 				 query->axfr_zone->soa_rrset->rrs[0],
    158 				 query->axfr_zone->soa_rrset->rrs[0]->ttl);
    159 	if (added) {
    160 		++total_added;
    161 		query->tsig_sign_it = 1; /* sign last packet */
    162 		query->axfr_is_done = 1;
    163 	}
    164 
    165 return_answer:
    166 	AA_SET(query->packet);
    167 	ANCOUNT_SET(query->packet, total_added);
    168 	NSCOUNT_SET(query->packet, 0);
    169 	ARCOUNT_SET(query->packet, 0);
    170 
    171 	/* check if it needs tsig signatures */
    172 	if(query->tsig.status == TSIG_OK) {
    173 #if AXFR_TSIG_SIGN_EVERY_NTH > 0
    174 		if(query->tsig.updates_since_last_prepare >= AXFR_TSIG_SIGN_EVERY_NTH) {
    175 #endif
    176 			query->tsig_sign_it = 1;
    177 #if AXFR_TSIG_SIGN_EVERY_NTH > 0
    178 		}
    179 #endif
    180 	}
    181 	query_clear_compression_tables(query);
    182 	return QUERY_IN_AXFR;
    183 }
    184 
    185 /* See if the query can be admitted. */
    186 static int axfr_ixfr_can_admit_query(struct nsd* nsd, struct query* q)
    187 {
    188 	struct acl_options *acl = NULL;
    189 	struct zone_options* zone_opt;
    190 
    191 #ifdef HAVE_SSL
    192 	/* tls-auth-xfr-only is set and this is not an authenticated TLS */
    193 	if (nsd->options->tls_auth_xfr_only && !q->tls_auth) {
    194 		if (verbosity >= 2) {
    195 			char address[128], proxy[128];
    196 			addr2str(&q->client_addr, address, sizeof(address));
    197 			addr2str(&q->remote_addr, proxy, sizeof(proxy));
    198 			VERBOSITY(2, (LOG_INFO, "%s for %s from %s refused tls-auth-xfr-only",
    199 				(q->qtype==TYPE_AXFR?"axfr":"ixfr"),
    200 				dname_to_string(q->qname, NULL),
    201 				address));
    202 		}
    203 		RCODE_SET(q->packet, RCODE_REFUSE);
    204 		/* RFC8914 - Extended DNS Errors
    205 		 * 4.19.  Extended DNS Error Code 18 - Prohibited */
    206 		q->edns.ede = EDE_PROHIBITED;
    207 		return 0;
    208 	}
    209 #endif
    210 
    211 	zone_opt = zone_options_find(nsd->options, q->qname);
    212 	if(zone_opt && q->is_proxied && acl_check_incoming_block_proxy(
    213 		zone_opt->pattern->provide_xfr, q, &acl) == -1) {
    214 		/* the proxy address is blocked */
    215 		if (verbosity >= 2) {
    216 			char address[128], proxy[128];
    217 			addr2str(&q->client_addr, address, sizeof(address));
    218 			addr2str(&q->remote_addr, proxy, sizeof(proxy));
    219 			VERBOSITY(2, (LOG_INFO, "%s for %s from %s via proxy %s refused because of proxy, %s %s",
    220 				(q->qtype==TYPE_AXFR?"axfr":"ixfr"),
    221 				dname_to_string(q->qname, NULL),
    222 				address, proxy,
    223 				(acl?acl->ip_address_spec:"."),
    224 				(acl ? ( acl->nokey    ? "NOKEY"
    225 				      : acl->blocked  ? "BLOCKED"
    226 				      : acl->key_name )
    227 				    : "no acl matches")));
    228 		}
    229 		RCODE_SET(q->packet, RCODE_REFUSE);
    230 		/* RFC8914 - Extended DNS Errors
    231 		 * 4.19.  Extended DNS Error Code 18 - Prohibited */
    232 		q->edns.ede = EDE_PROHIBITED;
    233 		return 0;
    234 	}
    235 	if(!zone_opt ||
    236 	   acl_check_incoming(zone_opt->pattern->provide_xfr, q, &acl)==-1)
    237 	{
    238 		if (verbosity >= 2) {
    239 			char a[128];
    240 			addr2str(&q->client_addr, a, sizeof(a));
    241 			VERBOSITY(2, (LOG_INFO, "%s for %s from %s refused, %s",
    242 				(q->qtype==TYPE_AXFR?"axfr":"ixfr"),
    243 				dname_to_string(q->qname, NULL), a, acl?"blocked":"no acl matches"));
    244 		}
    245 		DEBUG(DEBUG_XFRD,1, (LOG_INFO, "%s refused, %s",
    246 			(q->qtype==TYPE_AXFR?"axfr":"ixfr"),
    247 			acl?"blocked":"no acl matches"));
    248 		if (!zone_opt) {
    249 			RCODE_SET(q->packet, RCODE_NOTAUTH);
    250 		} else {
    251 			RCODE_SET(q->packet, RCODE_REFUSE);
    252 			/* RFC8914 - Extended DNS Errors
    253 			 * 4.19.  Extended DNS Error Code 18 - Prohibited */
    254 			q->edns.ede = EDE_PROHIBITED;
    255 		}
    256 		return 0;
    257 	}
    258 #ifdef HAVE_SSL
    259 	DEBUG(DEBUG_XFRD,1, (LOG_INFO, "%s admitted acl %s %s %s",
    260 		(q->qtype==TYPE_AXFR?"axfr":"ixfr"),
    261 		acl->ip_address_spec, acl->key_name?acl->key_name:"NOKEY",
    262 		(q->tls||q->tls_auth)?(q->tls?"tls":"tls-auth"):""));
    263 #else
    264 	DEBUG(DEBUG_XFRD,1, (LOG_INFO, "%s admitted acl %s %s",
    265 		(q->qtype==TYPE_AXFR?"axfr":"ixfr"),
    266 		acl->ip_address_spec, acl->key_name?acl->key_name:"NOKEY"));
    267 #endif
    268 	if (verbosity >= 1) {
    269 		char a[128];
    270 		addr2str(&q->client_addr, a, sizeof(a));
    271 #ifdef HAVE_SSL
    272 		VERBOSITY(1, (LOG_INFO, "%s for %s from %s %s %s",
    273 			(q->qtype==TYPE_AXFR?"axfr":"ixfr"),
    274 			dname_to_string(q->qname, NULL), a,
    275 			(q->tls||q->tls_auth)?(q->tls?"tls":"tls-auth"):"",
    276 			q->cert_cn?q->cert_cn:"not-verified"));
    277 #else
    278 		VERBOSITY(1, (LOG_INFO, "%s for %s from %s",
    279 			(q->qtype==TYPE_AXFR?"axfr":"ixfr"),
    280 			dname_to_string(q->qname, NULL), a));
    281 #endif
    282 	}
    283 	return 1;
    284 }
    285 
    286 /*
    287  * Answer if this is an AXFR or IXFR query.
    288  */
    289 query_state_type
    290 answer_axfr_ixfr(struct nsd *nsd, struct query *q)
    291 {
    292 	/* Is it AXFR? */
    293 	switch (q->qtype) {
    294 	case TYPE_AXFR:
    295 		if (q->tcp) {
    296 			if(!axfr_ixfr_can_admit_query(nsd, q))
    297 				return QUERY_PROCESSED;
    298 			return query_axfr(nsd, q, 1);
    299 		}
    300 		/* AXFR over UDP queries are discarded. */
    301 		RCODE_SET(q->packet, RCODE_IMPL);
    302 		return QUERY_PROCESSED;
    303 	case TYPE_IXFR:
    304 		if(!axfr_ixfr_can_admit_query(nsd, q)) {
    305 			/* get rid of authority section, if present */
    306 			NSCOUNT_SET(q->packet, 0);
    307 			ARCOUNT_SET(q->packet, 0);
    308 			if(QDCOUNT(q->packet) > 0 && (size_t)QHEADERSZ+4+
    309 				q->qname->name_size <= buffer_limit(q->packet)) {
    310 				buffer_set_position(q->packet, QHEADERSZ+4+
    311 					q->qname->name_size);
    312 			}
    313 			return QUERY_PROCESSED;
    314 		}
    315 		return query_ixfr(nsd, q);
    316 	default:
    317 		return QUERY_DISCARDED;
    318 	}
    319 }
    320