Пример #1
0
int
acl_key_matches(acl_options_t* acl, struct query* q)
{
	if(acl->blocked)
		return 1;
	if(acl->nokey) {
		if(q->tsig.status == TSIG_NOT_PRESENT)
			return 1;
		return 0;
	}
	/* check name of tsig key */
	if(q->tsig.status != TSIG_OK) {
		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail query has no TSIG"));
		return 0; /* query has no TSIG */
	}
	if(q->tsig.error_code != TSIG_ERROR_NOERROR) {
		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail, tsig has error"));
		return 0; /* some tsig error */
	}
	if(!acl->key_options->tsig_key) {
		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail no config"));
		return 0; /* key not properly configged */
	}
	if(dname_compare(q->tsig.key_name,
		acl->key_options->tsig_key->name) != 0) {
		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail wrong key name"));
		return 0; /* wrong key name */
	}
	if(tsig_strlowercmp(q->tsig.algorithm->short_name,
		acl->key_options->algorithm) != 0) {
		DEBUG(DEBUG_XFRD,2, (LOG_ERR, "query tsig wrong algorithm"));
		return 0; /* no such algo */
	}
	return 1;
}
Пример #2
0
void
config_print_zone(nsd_options_t* opt, const char* k, int s, const char *o, const char *z)
{
	zone_options_t* zone;
	ip_address_option_t* ip;

	if (k) {
		/* find key */
		key_options_t* key = opt->keys;
		for( ; key ; key=key->next) {
			if(strcmp(key->name, k) == 0) {
				if (s) {
					quote(key->secret);
				} else {
					quote(key->algorithm);
				}
				return;
			}
		}
		printf("Could not find key %s\n", k);
		return;
	}

	if (!o) {
		return;
	}

	if (z) {
		const dname_type *dname = dname_parse(opt->region, z);
		if(!dname) {
			printf("Could not parse zone name %s\n", z);
			exit(1);
		}
		/* look per zone */
		RBTREE_FOR(zone, zone_options_t*, opt->zone_options)
		{
			if (dname_compare(dname, zone->node.key) == 0) {
				/* -z matches, return are in the defines */
				ZONE_GET_STR(name, o);
				ZONE_GET_STR(zonefile, o);
				ZONE_GET_ACL(request_xfr, o);
				ZONE_GET_ACL(provide_xfr, o);
				ZONE_GET_ACL(allow_notify, o);
				ZONE_GET_ACL(notify, o);
				ZONE_GET_BIN(notify_retry, o);
				ZONE_GET_OUTGOING(outgoing_interface, o);
				ZONE_GET_BIN(allow_axfr_fallback, o);
				printf("Zone option not handled: %s %s\n", z, o);
				exit(1);
			}
		}
		printf("Zone does not exist: %s\n", z);
		exit(1);
	} else {
Пример #3
0
static int
rdatas_equal(rdata_atom_type *a, rdata_atom_type *b, int num, uint16_t type)
{
	int k;
	for(k = 0; k < num; k++)
	{
		if(rdata_atom_is_domain(type, k)) {
			if(dname_compare(domain_dname(a[k].domain),
				domain_dname(b[k].domain))!=0)
				return 0;
		} else {
			/* check length */
			if(a[k].data[0] != b[k].data[0])
				return 0;
			/* check data */
			if(memcmp(a[k].data+1, b[k].data+1, a[k].data[0])!=0)
				return 0;
		}
	}
	return 1;
}
Пример #4
0
static void
xfrd_init_zones()
{
	zone_type *dbzone;
	zone_options_t *zone_opt;
	xfrd_zone_t *xzone;
	const dname_type* dname;

	assert(xfrd->zones == 0);
	assert(xfrd->nsd->db != 0);

	xfrd->zones = rbtree_create(xfrd->region,
		(int (*)(const void *, const void *)) dname_compare);
	xfrd->notify_zones = rbtree_create(xfrd->region,
		(int (*)(const void *, const void *)) dname_compare);

	RBTREE_FOR(zone_opt, zone_options_t*, xfrd->nsd->options->zone_options)
	{
		DEBUG(DEBUG_XFRD,1, (LOG_INFO, "Zone %s\n", zone_opt->name));
		dname = dname_parse(xfrd->region, zone_opt->name);
		if(!dname) {
			log_msg(LOG_ERR, "xfrd: Could not parse zone name %s.", zone_opt->name);
			continue;
		}

		dbzone = domain_find_zone(domain_table_find(xfrd->nsd->db->domains, dname));
		if(dbzone && dname_compare(dname, domain_dname(dbzone->apex)) != 0)
			dbzone = 0; /* we found a parent zone */
		DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: adding %s zone %s\n",
			dbzone?"filled":"empty", zone_opt->name));

		init_notify_send(xfrd->notify_zones, xfrd->netio,
			xfrd->region, dname, zone_opt, dbzone);
		if(!zone_is_slave(zone_opt)) {
			DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: zone %s, master zone has no outgoing xfr requests", zone_opt->name));
			continue;
		}

		xzone = (xfrd_zone_t*)region_alloc(xfrd->region, sizeof(xfrd_zone_t));
		memset(xzone, 0, sizeof(xfrd_zone_t));
		xzone->apex = dname;
		xzone->apex_str = zone_opt->name;
		xzone->state = xfrd_zone_refreshing;
		xzone->dirty = 0;
		xzone->zone_options = zone_opt;
		/* first retry will use first master */
		xzone->master = 0;
		xzone->master_num = 0;
		xzone->next_master = 0;
		xzone->fresh_xfr_timeout = XFRD_TRANSFER_TIMEOUT_START;

		xzone->soa_nsd_acquired = 0;
		xzone->soa_disk_acquired = 0;
		xzone->soa_notified_acquired = 0;
		/* [0]=1, [1]=0; "." domain name */
		xzone->soa_nsd.prim_ns[0] = 1;
		xzone->soa_nsd.email[0] = 1;
		xzone->soa_disk.prim_ns[0]=1;
		xzone->soa_disk.email[0]=1;
		xzone->soa_notified.prim_ns[0]=1;
		xzone->soa_notified.email[0]=1;

		xzone->zone_handler.fd = -1;
		xzone->zone_handler.timeout = 0;
		xzone->zone_handler.user_data = xzone;
		xzone->zone_handler.event_types =
			NETIO_EVENT_READ|NETIO_EVENT_TIMEOUT;
		xzone->zone_handler.event_handler = xfrd_handle_zone;
		netio_add_handler(xfrd->netio, &xzone->zone_handler);
		xzone->tcp_conn = -1;
		xzone->tcp_waiting = 0;
		xzone->udp_waiting = 0;

		tsig_create_record_custom(&xzone->tsig, xfrd->region, 0, 0, 4);

		if(dbzone && dbzone->soa_rrset && dbzone->soa_rrset->rrs) {
			xzone->soa_nsd_acquired = xfrd_time();
			xzone->soa_disk_acquired = xfrd_time();
			/* we only use the first SOA in the rrset */
			xfrd_copy_soa(&xzone->soa_nsd, dbzone->soa_rrset->rrs);
			xfrd_copy_soa(&xzone->soa_disk, dbzone->soa_rrset->rrs);
		}
		/* set refreshing anyway, we have data but it may be old */
		xfrd_set_refresh_now(xzone);

		xzone->node.key = dname;
		rbtree_insert(xfrd->zones, (rbnode_t*)xzone);
	}
	DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: started server %d secondary zones", (int)xfrd->zones->count));
}
Пример #5
0
int
print_rr(FILE *out,
         struct state_pretty_rr *state,
         rr_type *record)
{
	region_type *region = region_create(xalloc, free);
        buffer_type *output = buffer_create(region, MAX_RDLENGTH);
        rrtype_descriptor_type *descriptor
                = rrtype_descriptor_by_type(record->type);
        int result;
        const dname_type *owner = domain_dname(record->owner);
        const dname_type *owner_origin
                = dname_origin(region, owner);
        int owner_changed
                = (!state->previous_owner
                   || dname_compare(state->previous_owner, owner) != 0);
        if (owner_changed) {
                int origin_changed = (!state->previous_owner_origin
                                      || dname_compare(
                                              state->previous_owner_origin,
                                              owner_origin) != 0);
                if (origin_changed) {
                        buffer_printf(
                                output,
                                "$ORIGIN %s\n",
                                dname_to_string(owner_origin, NULL));
                }

                set_previous_owner(state, owner);
                buffer_printf(output,
                              "%s",
                              dname_to_string(owner,
                                              state->previous_owner_origin));
        }

        buffer_printf(output,
                      "\t%lu\t%s\t%s",
                      (unsigned long) record->ttl,
                      rrclass_to_string(record->klass),
                      rrtype_to_string(record->type));

        result = print_rdata(output, descriptor, record);
        if (!result) {
                /*
                 * Some RDATA failed to print, so print the record's
                 * RDATA in unknown format.
                 */
                result = rdata_atoms_to_unknown_string(output,
                                                       descriptor,
                                                       record->rdata_count,
                                                       record->rdatas);
        }

        if (result) {
                buffer_printf(output, "\n");
                buffer_flip(output);
		(void)write_data(out, buffer_current(output), buffer_remaining(output));
/*              fflush(out); */
        }

	region_destroy(region);
        return result;
}
Пример #6
0
/* return value 0: syntaxerror,badIXFR, 1:OK, 2:done_and_skip_it */
static int
apply_ixfr(namedb_type* db, FILE *in, const off_t* startpos,
	const char* zone, uint32_t serialno, nsd_options_t* opt,
	uint16_t id, uint32_t seq_nr, uint32_t seq_total,
	int* is_axfr, int* delete_mode, int* rr_count,
	size_t child_count)
{
	uint32_t filelen, msglen, pkttype, timestamp[2];
	int qcount, ancount, counter;
	buffer_type* packet;
	region_type* region;
	int i;
	uint16_t rrlen;
	const dname_type *dname_zone, *dname;
	zone_type* zone_db;
	domain_type* last_in_list;
	char file_zone_name[3072];
	uint32_t file_serial, file_seq_nr;
	uint16_t file_id;
	off_t mempos;

	memmove(&mempos, startpos, sizeof(off_t));
	if(fseeko(in, mempos, SEEK_SET) == -1) {
		log_msg(LOG_INFO, "could not fseeko: %s.", strerror(errno));
		return 0;
	}
	/* read ixfr packet RRs and apply to in memory db */

	if(!diff_read_32(in, &pkttype) || pkttype != DIFF_PART_IXFR) {
		log_msg(LOG_ERR, "could not read type or wrong type");
		return 0;
	}
	if(!diff_read_32(in, &timestamp[0]) ||
	   !diff_read_32(in, &timestamp[1])) {
		log_msg(LOG_ERR, "could not read timestamp");
		return 0;
	}

	if(!diff_read_32(in, &filelen)) {
		log_msg(LOG_ERR, "could not read len");
		return 0;
	}

	/* read header */
	if(filelen < QHEADERSZ + sizeof(uint32_t)*3 + sizeof(uint16_t)) {
		log_msg(LOG_ERR, "msg too short");
		return 0;
	}

	region = region_create(xalloc, free);
	if(!region) {
		log_msg(LOG_ERR, "out of memory");
		return 0;
	}

	if(!diff_read_str(in, file_zone_name, sizeof(file_zone_name)) ||
		!diff_read_32(in, &file_serial) ||
		!diff_read_16(in, &file_id) ||
		!diff_read_32(in, &file_seq_nr))
	{
		log_msg(LOG_ERR, "could not part data");
		region_destroy(region);
		return 0;
	}

	if(strcmp(file_zone_name, zone) != 0 || serialno != file_serial ||
		id != file_id || seq_nr != file_seq_nr) {
		log_msg(LOG_ERR, "internal error: reading part with changed id");
		region_destroy(region);
		return 0;
	}
	msglen = filelen - sizeof(uint32_t)*3 - sizeof(uint16_t)
		- strlen(file_zone_name);
	packet = buffer_create(region, QIOBUFSZ);
	dname_zone = dname_parse(region, zone);
	zone_db = find_zone(db, dname_zone, opt, child_count);
	if(!zone_db) {
		log_msg(LOG_ERR, "no zone exists");
		region_destroy(region);
		/* break out and stop the IXFR, ignore it */
		return 2;
	}

	if(msglen > QIOBUFSZ) {
		log_msg(LOG_ERR, "msg too long");
		region_destroy(region);
		return 0;
	}
	buffer_clear(packet);
	if(fread(buffer_begin(packet), msglen, 1, in) != 1) {
		log_msg(LOG_ERR, "short fread: %s", strerror(errno));
		region_destroy(region);
		return 0;
	}
	buffer_set_limit(packet, msglen);

	/* only answer section is really used, question, additional and
	   authority section RRs are skipped */
	qcount = QDCOUNT(packet);
	ancount = ANCOUNT(packet);
	buffer_skip(packet, QHEADERSZ);

	/* skip queries */
	for(i=0; i<qcount; ++i)
		if(!packet_skip_rr(packet, 1)) {
			log_msg(LOG_ERR, "bad RR in question section");
			region_destroy(region);
			return 0;
		}

	DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: started packet for zone %s",
			dname_to_string(dname_zone, 0)));
	/* first RR: check if SOA and correct zone & serialno */
	if(*rr_count == 0) {
		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s parse first RR",
			dname_to_string(dname_zone, 0)));
		dname = dname_make_from_packet(region, packet, 1, 1);
		if(!dname) {
			log_msg(LOG_ERR, "could not parse dname");
			region_destroy(region);
			return 0;
		}
		if(dname_compare(dname_zone, dname) != 0) {
			log_msg(LOG_ERR, "SOA dname %s not equal to zone",
				dname_to_string(dname,0));
			log_msg(LOG_ERR, "zone dname is %s",
				dname_to_string(dname_zone,0));
			region_destroy(region);
			return 0;
		}
		if(!buffer_available(packet, 10)) {
			log_msg(LOG_ERR, "bad SOA RR");
			region_destroy(region);
			return 0;
		}
		if(buffer_read_u16(packet) != TYPE_SOA ||
			buffer_read_u16(packet) != CLASS_IN) {
			log_msg(LOG_ERR, "first RR not SOA IN");
			region_destroy(region);
			return 0;
		}
		buffer_skip(packet, sizeof(uint32_t)); /* ttl */
		if(!buffer_available(packet, buffer_read_u16(packet)) ||
			!packet_skip_dname(packet) /* skip prim_ns */ ||
			!packet_skip_dname(packet) /* skip email */) {
			log_msg(LOG_ERR, "bad SOA RR");
			region_destroy(region);
			return 0;
		}
		if(buffer_read_u32(packet) != serialno) {
			buffer_skip(packet, -4);
			log_msg(LOG_ERR, "SOA serial %d different from commit %d",
				buffer_read_u32(packet), serialno);
			region_destroy(region);
			return 0;
		}
		buffer_skip(packet, sizeof(uint32_t)*4);
		counter = 1;
		*rr_count = 1;
		*is_axfr = 0;
		*delete_mode = 0;

		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s start count %d, ax %d, delmode %d",
			dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));
	}
	else  counter = 0;

	last_in_list = zone_db->apex;
	for(; counter < ancount; ++counter,++(*rr_count))
	{
		uint16_t type, klass;
		uint32_t ttl;

		if(!(dname=dname_make_from_packet(region, packet, 1,1))) {
			log_msg(LOG_ERR, "bad xfr RR dname %d", *rr_count);
			region_destroy(region);
			return 0;
		}
		if(!buffer_available(packet, 10)) {
			log_msg(LOG_ERR, "bad xfr RR format %d", *rr_count);
			region_destroy(region);
			return 0;
		}
		type = buffer_read_u16(packet);
		klass = buffer_read_u16(packet);
		ttl = buffer_read_u32(packet);
		rrlen = buffer_read_u16(packet);
		if(!buffer_available(packet, rrlen)) {
			log_msg(LOG_ERR, "bad xfr RR rdata %d, len %d have %d",
				*rr_count, rrlen, (int)buffer_remaining(packet));
			region_destroy(region);
			return 0;
		}
		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s parsed count %d, ax %d, delmode %d",
			dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));

		if(*rr_count == 1 && type != TYPE_SOA) {
			/* second RR: if not SOA: this is an AXFR; delete all zone contents */
			delete_zone_rrs(db, zone_db);
			/* add everything else (incl end SOA) */
			*delete_mode = 0;
			*is_axfr = 1;
			DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s sawAXFR count %d, ax %d, delmode %d",
				dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));
		}
		if(*rr_count == 1 && type == TYPE_SOA) {
			/* if the serial no of the SOA equals the serialno, then AXFR */
			size_t bufpos = buffer_position(packet);
			uint32_t thisserial;
			if(!packet_skip_dname(packet) ||
				!packet_skip_dname(packet) ||
				buffer_remaining(packet) < sizeof(uint32_t)*5)
			{
				log_msg(LOG_ERR, "bad xfr SOA RR formerr.");
				region_destroy(region);
				return 0;
			}
			thisserial = buffer_read_u32(packet);
			if(thisserial == serialno) {
				/* AXFR */
				delete_zone_rrs(db, zone_db);
				*delete_mode = 0;
				*is_axfr = 1;
			}
			/* must have stuff in memory for a successful IXFR,
			 * the serial number of the SOA has been checked
			 * previously (by check_for_bad_serial) if it exists */
			if(!*is_axfr && !domain_find_rrset(zone_db->apex,
				zone_db, TYPE_SOA)) {
				log_msg(LOG_ERR, "%s SOA serial %d is not "
					"in memory, skip IXFR", zone, serialno);
				region_destroy(region);
				/* break out and stop the IXFR, ignore it */
				return 2;
			}
			buffer_set_position(packet, bufpos);
		}
		if(type == TYPE_SOA && !*is_axfr) {
			/* switch from delete-part to add-part and back again,
			   just before soa - so it gets deleted and added too */
			/* this means we switch to delete mode for the final SOA */
			*delete_mode = !*delete_mode;
			DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s IXFRswapdel count %d, ax %d, delmode %d",
				dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));
		}
		if(type == TYPE_TSIG || type == TYPE_OPT) {
			/* ignore pseudo RRs */
			buffer_skip(packet, rrlen);
			continue;
		}

		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "xfr %s RR dname is %s type %s",
			*delete_mode?"del":"add",
			dname_to_string(dname,0), rrtype_to_string(type)));
		if(*delete_mode) {
			/* delete this rr */
			if(!*is_axfr && type == TYPE_SOA && counter==ancount-1
				&& seq_nr == seq_total-1) {
				continue; /* do not delete final SOA RR for IXFR */
			}
			if(!delete_RR(db, dname, type, klass, last_in_list, packet,
				rrlen, zone_db, region, *is_axfr)) {
				region_destroy(region);
				return 0;
			}
			if (!*is_axfr && last_in_list->nextdiff) {
				last_in_list = last_in_list->nextdiff;
			}
		}
		else
		{
			/* add this rr */
			if(!add_RR(db, dname, type, klass, ttl, packet,
				rrlen, zone_db, *is_axfr)) {
				region_destroy(region);
				return 0;
			}
		}
	}
	fix_empty_terminals(zone_db);
	region_destroy(region);
	return 1;
}
Пример #7
0
/*
 * Reads the specified zone into the memory
 * nsd_options can be NULL if no config file is passed.
 */
unsigned int
zonec_read(const char* name, const char* zonefile, zone_type* zone)
{
	const dname_type *dname;

	totalrrs = 0;
	startzonec = time(NULL);
	parser->errors = 0;

	dname = dname_parse(parser->rr_region, name);
	if (!dname) {
		zc_error("incorrect zone name '%s'", name);
		return 1;
	}

#ifndef ROOT_SERVER
	/* Is it a root zone? Are we a root server then? Idiot proof. */
	if (dname->label_count == 1) {
		zc_error("not configured as a root server");
		return 1;
	}
#endif

	/* Open the zone file */
	if (!zone_open(zonefile, 3600, CLASS_IN, dname)) {
		zc_error("cannot open '%s': %s", zonefile, strerror(errno));
		return 1;
	}
	parser->current_zone = zone;

	/* Parse and process all RRs.  */
	yyparse();

	/* remove origin if it was unused */
	if(parser->origin != error_domain)
		domain_table_deldomain(parser->db, parser->origin);
	/* rr_region has been emptied by now */
	dname = dname_parse(parser->rr_region, name);

	/* check if zone file contained a correct SOA record */
	if (!parser->current_zone) {
		zc_error("zone configured as '%s' has no content.", name);
	} else if(!parser->current_zone->soa_rrset ||
		parser->current_zone->soa_rrset->rr_count == 0) {
		zc_error("zone configured as '%s' has no SOA record.", name);
	} else if(dname_compare(domain_dname(
		parser->current_zone->soa_rrset->rrs[0].owner), dname) != 0) {
		zc_error("zone configured as '%s', but SOA has owner '%s'.",
			name, domain_to_string(
			parser->current_zone->soa_rrset->rrs[0].owner));
	}
	region_free_all(parser->rr_region);

	parser_flush();
	fclose(yyin);
	if(!zone_is_slave(zone->opts))
		check_dname(zone);

	parser->filename = NULL;
	return parser->errors;
}