예제 #1
0
/**
 * Add RR to query.
 *
 */
int
query_add_rr(query_type* q, ldns_rr* rr)
{
    size_t i = 0;
    size_t tc_mark = 0;
    size_t rdlength_pos = 0;
    uint16_t rdlength = 0;

    ods_log_assert(q);
    ods_log_assert(q->buffer);
    ods_log_assert(rr);

    /* set truncation mark, in case rr does not fit */
    tc_mark = buffer_position(q->buffer);
    /* owner type class ttl */
    if (!buffer_available(q->buffer, ldns_rdf_size(ldns_rr_owner(rr)))) {
        goto query_add_rr_tc;
    }
    buffer_write_rdf(q->buffer, ldns_rr_owner(rr));
    if (!buffer_available(q->buffer, sizeof(uint16_t) + sizeof(uint16_t) +
        sizeof(uint32_t) + sizeof(rdlength))) {
        goto query_add_rr_tc;
    }
    buffer_write_u16(q->buffer, (uint16_t) ldns_rr_get_type(rr));
    buffer_write_u16(q->buffer, (uint16_t) ldns_rr_get_class(rr));
    buffer_write_u32(q->buffer, (uint32_t) ldns_rr_ttl(rr));
    /* skip rdlength */
    rdlength_pos = buffer_position(q->buffer);
    buffer_skip(q->buffer, sizeof(rdlength));
    /* write rdata */
    for (i=0; i < ldns_rr_rd_count(rr); i++) {
        if (!buffer_available(q->buffer, ldns_rdf_size(ldns_rr_rdf(rr, i)))) {
            goto query_add_rr_tc;
        }
        buffer_write_rdf(q->buffer, ldns_rr_rdf(rr, i));
    }

    if (!query_overflow(q)) {
        /* write rdlength */
        rdlength = buffer_position(q->buffer) - rdlength_pos - sizeof(rdlength);
        buffer_write_u16_at(q->buffer, rdlength_pos, rdlength);
        /* position updated by buffer_write() */
        return 1;
    }

query_add_rr_tc:
    buffer_set_position(q->buffer, tc_mark);
    ods_log_assert(!query_overflow(q));
    return 0;

}
예제 #2
0
void
drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p)
{
	ldns_rr_list *hostnames;

	if (verbosity < 5) {
		return;
	}

	hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);

	fprintf(fd, ";; Received %d bytes from %s#%d(",
			(int) ldns_pkt_size(p),
			ldns_rdf2str(ldns_pkt_answerfrom(p)),
			(int) ldns_resolver_port(r));
	/* if we can resolve this print it, other print the ip again */
	if (hostnames) {
		ldns_rdf_print(fd,
				ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
		ldns_rr_list_deep_free(hostnames);
	} else {
		fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p)));
	}
	fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
}
예제 #3
0
/** convert and print rdata */
static void
print_rd(int t, char* data, size_t len)
{
	size_t i, pos = 0;
	uint8_t* rd = (uint8_t*)malloc(len+2);
	ldns_rr* rr = ldns_rr_new();
	ldns_status status;
	if(!rd || !rr) {
		fprintf(stderr, "out of memory");
		exit(1);
	}
	ldns_rr_set_type(rr, t);
	ldns_write_uint16(rd, len);
	memmove(rd+2, data, len);
	ldns_rr_set_owner(rr, NULL);
	status = ldns_wire2rdf(rr, rd, len+2, &pos);
	if(status != LDNS_STATUS_OK) {
		free(rd);
		ldns_rr_free(rr);
		printf("error_printing_data");
		return;
	}
	for(i=0; i<ldns_rr_rd_count(rr); i++) {
		printf(" ");
		ldns_rdf_print(stdout, ldns_rr_rdf(rr, i));
	}
	ldns_rr_free(rr);
	free(rd);
}
예제 #4
0
파일: host2wire.c 프로젝트: LANJr4D/iEnum
ldns_status
ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
{
	uint16_t i;
	uint16_t rdl_pos = 0;
	
	if (ldns_rr_owner(rr)) {
		(void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
	}
	
	if (ldns_buffer_reserve(buffer, 4)) {
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
	}

	if (section != LDNS_SECTION_QUESTION) {
		if (ldns_buffer_reserve(buffer, 6)) {
			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
			/* remember pos for later */
			rdl_pos = ldns_buffer_position(buffer);
			ldns_buffer_write_u16(buffer, 0);
		}	

		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
			(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
		}
		
		if (rdl_pos != 0) {
			ldns_buffer_write_u16_at(buffer, rdl_pos,
			                         ldns_buffer_position(buffer)
		        	                   - rdl_pos - 2);
		}
	}
	return ldns_buffer_status(buffer);
}
예제 #5
0
void
drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p)
{
	ldns_rr_list *new_nss;
	ldns_rr_list *hostnames;

	if (verbosity < 5) {
		return;
	}

	hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);

	new_nss = ldns_pkt_rr_list_by_type(p,
			LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
	ldns_rr_list_print(fd, new_nss);

	/* new_nss can be empty.... */

	fprintf(fd, ";; Received %d bytes from %s#%d(",
			(int) ldns_pkt_size(p),
			ldns_rdf2str(ldns_pkt_answerfrom(p)),
			(int) ldns_resolver_port(r));
	/* if we can resolve this print it, other print the ip again */
	if (hostnames) {
		ldns_rdf_print(fd,
				ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
		ldns_rr_list_deep_free(hostnames);
	} else {
		fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p)));
	}
	fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
}
예제 #6
0
/**
 * Publish the NSEC3 parameters as indicated by the signer configuration.
 *
 */
ods_status
zone_publish_nsec3param(zone_type* zone)
{
    rrset_type* rrset = NULL;
    rr_type* n3prr = NULL;
    ldns_rr* rr = NULL;
    ods_status status = ODS_STATUS_OK;

    if (!zone || !zone->name || !zone->db || !zone->signconf) {
        return ODS_STATUS_ASSERT_ERR;
    }
    if (!zone->signconf->nsec3params) {
        /* NSEC */
        ods_log_assert(zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC);
        return ODS_STATUS_OK;
    }

    if (!zone->signconf->nsec3params->rr) {
        rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS);
        if (!rr) {
            ods_log_error("[%s] unable to publish nsec3params for zone %s: "
                "error creating rr (%s)", zone_str, zone->name,
                ods_status2str(status));
            return ODS_STATUS_MALLOC_ERR;
        }
        ldns_rr_set_class(rr, zone->klass);
        ldns_rr_set_ttl(rr, 0);
        ldns_rr_set_owner(rr, ldns_rdf_clone(zone->apex));
        ldns_nsec3_add_param_rdfs(rr,
            zone->signconf->nsec3params->algorithm, 0,
            zone->signconf->nsec3params->iterations,
            zone->signconf->nsec3params->salt_len,
            zone->signconf->nsec3params->salt_data);
        /**
         * Always set bit 7 of the flags to zero,
         * according to rfc5155 section 11
         */
        ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(rr, 1)), 7, 0);
        zone->signconf->nsec3params->rr = rr;
    }
    ods_log_assert(zone->signconf->nsec3params->rr);
    status = zone_add_rr(zone, zone->signconf->nsec3params->rr, 0);
    if (status == ODS_STATUS_UNCHANGED) {
        /* rr already exists, adjust pointer */
        rrset = zone_lookup_rrset(zone, zone->apex, LDNS_RR_TYPE_NSEC3PARAMS);
        ods_log_assert(rrset);
        n3prr = rrset_lookup_rr(rrset, zone->signconf->nsec3params->rr);
        ods_log_assert(n3prr);
        if (n3prr->rr != zone->signconf->nsec3params->rr) {
            ldns_rr_free(zone->signconf->nsec3params->rr);
        }
        zone->signconf->nsec3params->rr = n3prr->rr;
        status = ODS_STATUS_OK;
    } else if (status != ODS_STATUS_OK) {
        ods_log_error("[%s] unable to publish nsec3params for zone %s: "
            "error adding nsec3params (%s)", zone_str,
            zone->name, ods_status2str(status));
    }
    return status;
}
예제 #7
0
파일: zonefile.c 프로젝트: hstern/libmy
uint32_t
zonefile_get_serial(struct zonefile *z)
{
	ldns_rdf *rdf = ldns_rr_rdf(z->rr_soa, 2);
	assert(rdf != NULL);
	return (ldns_rdf2native_int32(rdf));
}
예제 #8
0
/**
 * return a specific rdf
 * \param[in] type type of RR
 * \param[in] rr   the rr itself
 * \param[in] pos  at which postion to get it
 * \return the rdf sought
 */
static ldns_rdf *
ldns_rr_function(ldns_rr_type type, const ldns_rr *rr, size_t pos)
{
        if (!rr || ldns_rr_get_type(rr) != type) {
                return NULL;
        }
        return ldns_rr_rdf(rr, pos);
}
예제 #9
0
파일: zinfo.c 프로젝트: benlaurie/ldns
struct zversion_t* zversion_read(struct zone_entry_t* entry, uint32_t serial)
{
	const char* fn = zinfo_ixfr_name(entry, serial);
	struct zversion_t* v;
	FILE* in = fopen(fn, "ra");
	ldns_status status;
	ldns_rr* rr = 0;
	uint32_t dttl = 3600;
	ldns_rdf* origin = 0, *prev = 0;
	int line_nr = 1;
	if(!in) {
		perror(fn);
		return NULL;
	}
	v = (struct zversion_t*)calloc(1, sizeof(*v));
	if(!v) {
		fclose(in);
		printf("out of memory\n");
		return NULL;
	}
	v->serial = serial;
	v->ixfr = ldns_rr_list_new();
	while(!feof(in)) {
		status = ldns_rr_new_frm_fp_l(&rr, in, &dttl, &origin, 
			&prev, &line_nr);
		if(status == LDNS_STATUS_SYNTAX_TTL || 
			status == LDNS_STATUS_SYNTAX_ORIGIN ||
			status == LDNS_STATUS_SYNTAX_EMPTY)
			continue;
		if(status != LDNS_STATUS_OK) {
			printf("error %s:%d: %s\n", fn, line_nr, 
				ldns_get_errorstr_by_id(status));
			fclose(in);
			ldns_rdf_deep_free(origin);
			ldns_rdf_deep_free(prev);
			ldns_rr_list_deep_free(v->ixfr);
			free(v);
			return NULL;
		}
		ldns_rr_list_push_rr(v->ixfr, rr);
	}
	ldns_rdf_deep_free(origin);
	ldns_rdf_deep_free(prev);
	fclose(in);
	if(ldns_rr_list_rr_count(v->ixfr) < 1 || 
		ldns_rr_get_type(ldns_rr_list_rr(v->ixfr, 0)) 
			!= LDNS_RR_TYPE_SOA) {
		printf("invalid IXFR format in %s\n", fn);
		ldns_rr_list_deep_free(v->ixfr);
		free(v);
		return NULL;
	}
	v->next_serial = ldns_rdf2native_int32(ldns_rr_rdf(
		ldns_rr_list_rr(v->ixfr, 0), 2));
	return v;
}
예제 #10
0
/* A/AAAA records */
ldns_rdf *
ldns_rr_a_address(const ldns_rr *r)
{
	/* 2 types to check, cannot use the macro */
	if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A &&
			ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) {
		return NULL;
	}
	return ldns_rr_rdf(r, 0);
}
예제 #11
0
파일: host2wire.c 프로젝트: LANJr4D/iEnum
ldns_status
ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
{
	uint16_t i;

	/* it must be a sig RR */
	if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
		return LDNS_STATUS_ERR;
	}
	
	/* Convert all the rdfs, except the actual signature data
	 * rdf number 8  - the last, hence: -1 */
	for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
		if (ldns_rr_rdf(rr, i)) {
			(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
		}
	}

	return ldns_buffer_status(buffer);
}
예제 #12
0
파일: host2wire.c 프로젝트: LANJr4D/iEnum
ldns_status
ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
{
	uint16_t i;
	/* convert all the rdf's */
	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
		(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
	}

	return ldns_buffer_status(buffer);
}
예제 #13
0
/** get authority section SOA serial value */
static uint32_t get_serial(ldns_pkt* p)
{
	ldns_rr *rr = ldns_rr_list_rr(ldns_pkt_authority(p), 0);
	ldns_rdf *rdf;
	uint32_t val;
	if(!rr) return 0;
	rdf = ldns_rr_rdf(rr, 2);
	if(!rdf) return 0;
	val = ldns_rdf2native_int32(rdf);
	verbose(3, "found serial %u in msg. ", (int)val);
	return val;
}
예제 #14
0
void
ldns_rr_soa_increment_func_data(ldns_rr *soa, 
		ldns_soa_serial_increment_func_t f, void *data)
{
	ldns_rdf *prev_soa_serial_rdf;
	if ( !soa || !f || ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA 
			|| !ldns_rr_rdf(soa, 2)) {
		return;
	}
	prev_soa_serial_rdf = ldns_rr_set_rdf(
		  soa
		, ldns_native2rdf_int32(
			  LDNS_RDF_TYPE_INT32
			, (*f)( ldns_rdf2native_int32(
					ldns_rr_rdf(soa, 2))
			      , data
			)
		)
		, 2
	);
	LDNS_FREE(prev_soa_serial_rdf);
}
예제 #15
0
ldns_status
ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr)
{
	ldns_rdf *address;
	if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A &&
			ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) {
		return LDNS_STATUS_ERR;
	}
	address = ldns_rr_rdf(rr, 0); /* extract the ip number */
	if (address) {
		return ldns_resolver_push_nameserver(r, address);
	} else {
		return LDNS_STATUS_ERR;
	}
}
예제 #16
0
ldns_status
ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
{
	ldns_buffer *qb;
	ldns_status result;
	ldns_rdf *tsig_mac = NULL;

	qb = ldns_buffer_new(LDNS_MIN_BUFLEN);

	if (query_pkt && ldns_pkt_tsig(query_pkt)) {
		tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3);
	}

	if (!query_pkt ||
	    ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) {
		result = LDNS_STATUS_ERR;
	} else {
        	result = ldns_send_buffer(result_packet, r, qb, tsig_mac);
	}

	ldns_buffer_free(qb);

	return result;
}
예제 #17
0
파일: dns.c 프로젝트: ariosx/passivedns
int cache_dns_objects(packetinfo *pi, ldns_rdf *rdf_data,
                      ldns_buffer *buff, ldns_pkt *dns_pkt)
{
    int           j;
    int           dns_answer_domain_cnt;
    uint64_t      dnshash;
    ldns_status   status;
    pdns_record   *pr = NULL;
    ldns_rr_list  *dns_answer_domains;
    unsigned char *domain_name = 0;

    ldns_buffer_clear(buff);
    status = ldns_rdf2buffer_str(buff, rdf_data);

    if (status != LDNS_STATUS_OK) {
        dlog("[D] Error in ldns_rdf2buffer_str(): %d\n", status);
        return -1;
    }

    dns_answer_domains    = ldns_pkt_answer(dns_pkt);
    dns_answer_domain_cnt = ldns_rr_list_rr_count(dns_answer_domains);
    domain_name           = (unsigned char *) ldns_buffer2str(buff);

    if (domain_name == NULL) {
        dlog("[D] Error in ldns_buffer2str(%p)\n", buff);
        return -1;
    }
    else {
        dlog("[D] domain_name: %s\n", domain_name);
        dlog("[D] dns_answer_domain_cnt: %d\n",dns_answer_domain_cnt);
    }

    if (dns_answer_domain_cnt == 0 && ldns_pkt_get_rcode(dns_pkt) != 0) {
        uint16_t rcode = ldns_pkt_get_rcode(dns_pkt);
        dlog("[D] Error return code: %d\n", rcode);

        /* PROBLEM:
         * As there is no valid ldns_rr here and we can't fake one that will
         * be very unique, we cant push this to the normal
         * bucket[hash->linked_list]. We should probably allocate a static
         * bucket[MAX_NXDOMAIN] to hold NXDOMAINS, and when that is full, pop
         * out the oldest (LRU). A simple script querying for random non-existing
         * domains could easily put stress on passivedns (think conficker etc.)
         * if the bucket is to big or non-efficient. We would still store data
         * such as: firstseen,lastseen,client_ip,server_ip,class,query,NXDOMAIN
         */
         if (config.dnsfe & (pdns_chk_dnsfe(rcode))) {
            ldns_rr_list  *dns_query_domains;
            ldns_rr       *rr;

            dnshash = hash(domain_name);
            dlog("[D] Hash: %lu\n", dnshash);
            /* Check if the node exists, if not, make it */
            pr = get_pdns_record(dnshash, pi, domain_name);

            /* Set the SRC flag: */
            //lname_node->srcflag |= pdns_chk_dnsfe(rcode);
            dns_query_domains = ldns_pkt_question(dns_pkt);
            rr = ldns_rr_list_rr(dns_query_domains, 0);
            if ((pr->last_seen.tv_sec - pr->last_print.tv_sec) >= config.dnsprinttime) {
                /* Print the SRC Error record */
                print_passet(pr, NULL, rr, rdf_data, rcode);
            }
        } else {
            dlog("[D] Error return code %d was not processed:%d\n",
                 pdns_chk_dnsfe(rcode), config.dnsfe);
        }
        free(domain_name);
        return 0;
    }

    for (j = 0; j < dns_answer_domain_cnt; j++)
    {
        int           offset = -1;
        ldns_rr       *rr;
        ldns_rdf      *rname;
        unsigned char *rdomain_name = 0;

        rr = ldns_rr_list_rr(dns_answer_domains, j);

        switch (ldns_rr_get_type(rr)) {
            case LDNS_RR_TYPE_AAAA:
                if (config.dnsf & DNS_CHK_AAAA)
                    offset = 0;
                break;
            case LDNS_RR_TYPE_A:
                if (config.dnsf & DNS_CHK_A)
                    offset = 0;
                break;
            case LDNS_RR_TYPE_PTR:
                if (config.dnsf & DNS_CHK_PTR)
                    offset = 0;
                break;
            case LDNS_RR_TYPE_CNAME:
                if (config.dnsf & DNS_CHK_CNAME)
                    offset = 0;
                break;
            case LDNS_RR_TYPE_DNAME:
                if (config.dnsf & DNS_CHK_DNAME)
                    offset = 0;
                break;
            case LDNS_RR_TYPE_NAPTR:
                if (config.dnsf & DNS_CHK_NAPTR)
                    offset = 0;
                break;
            case LDNS_RR_TYPE_RP:
                if (config.dnsf & DNS_CHK_RP)
                    offset = 0;
                break;
            case LDNS_RR_TYPE_SRV:
                if (config.dnsf & DNS_CHK_SRV)
                    offset = 3;
                break;
            case LDNS_RR_TYPE_TXT:
                if (config.dnsf & DNS_CHK_TXT)
                    offset = 0;
                break;
            case LDNS_RR_TYPE_SOA:
                if (config.dnsf & DNS_CHK_SOA)
                    offset = 0;
                break;
            case LDNS_RR_TYPE_MX:
                if (config.dnsf & DNS_CHK_MX)
                    offset = 1;
                break;
            case LDNS_RR_TYPE_NS:
                if (config.dnsf & DNS_CHK_NS)
                    offset = 0;
                break;
            default:
                offset = -1;
                dlog("[D] ldns_rr_get_type: %d\n", ldns_rr_get_type(rr));
                break;
        }

        if (offset == -1) {
            dlog("[D] LDNS_RR_TYPE not enabled/supported: %d\n",
                 ldns_rr_get_type(rr));
            //data_offset = 0;
            continue;
        }

        /* Get the rdf data from the rr */
        rname = ldns_rr_rdf(rr, offset);

        if (rname == NULL) {
            dlog("[D] ldns_rr_rdf returned: NULL\n");
            continue;
        }

        ldns_buffer_clear(buff);
        ldns_rdf2buffer_str(buff, rname);
        rdomain_name = (unsigned char *) ldns_buffer2str(buff);

        if (rdomain_name == NULL) {
            dlog("[D] ldns_buffer2str returned: NULL\n");
            continue;
        }
        dlog("[D] rdomain_name: %s\n", rdomain_name);

        if (pr == NULL) {
            dnshash = hash(domain_name);
            dlog("[D] Hash: %lu\n", dnshash);
            /* Check if the node exists, if not, make it */
            pr = get_pdns_record(dnshash, pi, domain_name);
        }

        /* Update the pdns record with the pdns asset */
        update_pdns_record_asset(pi, pr, rr, rdomain_name);

        /* If CNAME, free domain_name, and cp rdomain_name to domain_name */
        if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_CNAME) {
            if (config.dnsf & DNS_CHK_CNAME) {
                int len;
                free(domain_name);
                len = strlen((char *)rdomain_name);
                domain_name = calloc(1, (len + 1));
                strncpy((char *)domain_name, (char *)rdomain_name, len);
                dnshash = hash(domain_name);
                dlog("[D] Hash: %lu\n", dnshash);
                pr = get_pdns_record(dnshash, pi, domain_name);
            }
        }

        /* Free the rdomain_name */
        free(rdomain_name);
    }
    free(domain_name);
    return 0;
}
예제 #18
0
bool
ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char* key_name,
	const char *key_data, ldns_rdf *orig_mac_rdf, int tsig_timers_only)
{
	ldns_rdf *fudge_rdf;
	ldns_rdf *algorithm_rdf;
	ldns_rdf *time_signed_rdf;
	ldns_rdf *orig_id_rdf;
	ldns_rdf *error_rdf;
	ldns_rdf *other_data_rdf;
	ldns_rdf *pkt_mac_rdf;
	ldns_rdf *my_mac_rdf;
	ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name);
	uint16_t pkt_id, orig_pkt_id;
	ldns_status status;

	uint8_t *prepared_wire = NULL;
	size_t prepared_wire_size = 0;

	ldns_rr *orig_tsig = ldns_pkt_tsig(pkt);

	if (!orig_tsig || ldns_rr_rd_count(orig_tsig) <= 6) {
		ldns_rdf_deep_free(key_name_rdf);
		return false;
	}
	algorithm_rdf = ldns_rr_rdf(orig_tsig, 0);
	time_signed_rdf = ldns_rr_rdf(orig_tsig, 1);
	fudge_rdf = ldns_rr_rdf(orig_tsig, 2);
	pkt_mac_rdf = ldns_rr_rdf(orig_tsig, 3);
	orig_id_rdf = ldns_rr_rdf(orig_tsig, 4);
	error_rdf = ldns_rr_rdf(orig_tsig, 5);
	other_data_rdf = ldns_rr_rdf(orig_tsig, 6);

	/* remove temporarily */
	ldns_pkt_set_tsig(pkt, NULL);
	/* temporarily change the id to the original id */
	pkt_id = ldns_pkt_id(pkt);
	orig_pkt_id = ldns_rdf2native_int16(orig_id_rdf);
	ldns_pkt_set_id(pkt, orig_pkt_id);

	prepared_wire = ldns_tsig_prepare_pkt_wire(wire, wirelen, &prepared_wire_size);

	status = ldns_tsig_mac_new(&my_mac_rdf, prepared_wire, prepared_wire_size,
			key_data, key_name_rdf, fudge_rdf, algorithm_rdf,
			time_signed_rdf, error_rdf, other_data_rdf, orig_mac_rdf, tsig_timers_only);

	LDNS_FREE(prepared_wire);

	if (status != LDNS_STATUS_OK) {
		ldns_rdf_deep_free(key_name_rdf);
		return false;
	}
	/* Put back the values */
	ldns_pkt_set_tsig(pkt, orig_tsig);
	ldns_pkt_set_id(pkt, pkt_id);

	ldns_rdf_deep_free(key_name_rdf);

	if (ldns_rdf_compare(pkt_mac_rdf, my_mac_rdf) == 0) {
		ldns_rdf_deep_free(my_mac_rdf);
		return true;
	} else {
		ldns_rdf_deep_free(my_mac_rdf);
		return false;
	}
}
예제 #19
0
ldns_status
ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
					   ldns_rr_list *new_rrs,
					   ldns_key_list *key_list,
					   int (*func)(ldns_rr *, void *),
					   void *arg,
					   uint8_t algorithm,
					   uint8_t flags,
					   uint16_t iterations,
					   uint8_t salt_length,
					   uint8_t *salt)
{
	ldns_rr *nsec3, *nsec3params;
	ldns_status result = LDNS_STATUS_OK;

	/* zone is already sorted */
	ldns_dnssec_zone_mark_glue(zone);

	/* TODO if there are already nsec3s presents and their
	 * parameters are the same as these, we don't have to recreate
	 */
	if (zone->names) {
		/* add empty nonterminals */
		ldns_dnssec_zone_add_empty_nonterminals(zone);

		nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec;
		if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) {
			/* no need to recreate */
		} else {
			if (!ldns_dnssec_zone_find_rrset(zone,
									   zone->soa->name,
									   LDNS_RR_TYPE_NSEC3PARAMS)) {
				/* create and add the nsec3params rr */
				nsec3params =
					ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS);
				ldns_rr_set_owner(nsec3params,
							   ldns_rdf_clone(zone->soa->name));
				ldns_nsec3_add_param_rdfs(nsec3params,
									 algorithm,
									 flags,
									 iterations,
									 salt_length,
									 salt);
				/* always set bit 7 of the flags to zero, according to
				 * rfc5155 section 11 */
				ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3params, 1)), 7, 0);
				ldns_dnssec_zone_add_rr(zone, nsec3params);
				ldns_rr_list_push_rr(new_rrs, nsec3params);
			}
			result = ldns_dnssec_zone_create_nsec3s(zone,
											new_rrs,
											algorithm,
											flags,
											iterations,
											salt_length,
											salt);
			if (result != LDNS_STATUS_OK) {
				return result;
			}
		}

		result = ldns_dnssec_zone_create_rrsigs(zone,
										new_rrs,
										key_list,
										func,
										arg);
	}
	
	return result;
}
예제 #20
0
ldns_status
ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
						 ldns_rr_list *new_rrs,
						 uint8_t algorithm,
						 uint8_t flags,
						 uint16_t iterations,
						 uint8_t salt_length,
						 uint8_t *salt)
{
	ldns_rbnode_t *first_name_node;
	ldns_rbnode_t *current_name_node;
	ldns_dnssec_name *current_name;
	ldns_status result = LDNS_STATUS_OK;
	ldns_rr *nsec_rr;
	ldns_rr_list *nsec3_list;
	uint32_t nsec_ttl;
	ldns_dnssec_rrsets *soa;
	
	if (!zone || !new_rrs || !zone->names) {
		return LDNS_STATUS_ERR;
	}
	
	/* the TTL of NSEC rrs should be set to the minimum TTL of
	 * the zone SOA (RFC4035 Section 2.3)
	 */
	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
	
	/* did the caller actually set it? if not,
	 * fall back to default ttl
	 */
	if (soa && soa->rrs && soa->rrs->rr) {
		nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(
		                                     soa->rrs->rr, 6));
	} else {
		nsec_ttl = LDNS_DEFAULT_TTL;
	}

	nsec3_list = ldns_rr_list_new();

	first_name_node = ldns_dnssec_name_node_next_nonglue(
					  ldns_rbtree_first(zone->names));
	
	current_name_node = first_name_node;

	while (current_name_node &&
	       current_name_node != LDNS_RBTREE_NULL) {
		current_name = (ldns_dnssec_name *) current_name_node->data;
		nsec_rr = ldns_dnssec_create_nsec3(current_name,
		                                   NULL,
		                                   zone->soa->name,
		                                   algorithm,
		                                   flags,
		                                   iterations,
		                                   salt_length,
		                                   salt);
		/* by default, our nsec based generator adds rrsigs
		 * remove the bitmap for empty nonterminals */
		if (!current_name->rrsets) {
			ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr));
		}
		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
		ldns_dnssec_name_add_rr(current_name, nsec_rr);
		ldns_rr_list_push_rr(new_rrs, nsec_rr);
		ldns_rr_list_push_rr(nsec3_list, nsec_rr);
		current_name_node = ldns_dnssec_name_node_next_nonglue(
		                   ldns_rbtree_next(current_name_node));
	}

	ldns_rr_list_sort_nsec3(nsec3_list);
	ldns_dnssec_chain_nsec3_list(nsec3_list);
	if (result != LDNS_STATUS_OK) {
		return result;
	}
	
	ldns_rr_list_free(nsec3_list);
	return result;
}
예제 #21
0
ldns_status
ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone,
                              ldns_rr_list *new_rrs)
{

	ldns_rbnode_t *first_node, *cur_node, *next_node;
	ldns_dnssec_name *cur_name, *next_name;
	ldns_rr *nsec_rr;
	uint32_t nsec_ttl;
	ldns_dnssec_rrsets *soa;
	
	/* the TTL of NSEC rrs should be set to the minimum TTL of
	 * the zone SOA (RFC4035 Section 2.3)
	 */
	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
	
	/* did the caller actually set it? if not,
	 * fall back to default ttl
	 */
	if (soa && soa->rrs && soa->rrs->rr) {
		nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(
		                                     soa->rrs->rr, 6));
	} else {
		nsec_ttl = LDNS_DEFAULT_TTL;
	}
	
	first_node = ldns_dnssec_name_node_next_nonglue(
			       ldns_rbtree_first(zone->names));
	cur_node = first_node;
	if (cur_node) {
		next_node = ldns_dnssec_name_node_next_nonglue(
			           ldns_rbtree_next(cur_node));
	} else {
		next_node = NULL;
	}

	while (cur_node && next_node) {
		cur_name = (ldns_dnssec_name *)cur_node->data;
		next_name = (ldns_dnssec_name *)next_node->data;
		nsec_rr = ldns_dnssec_create_nsec(cur_name,
		                                  next_name,
		                                  LDNS_RR_TYPE_NSEC);
		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
		ldns_dnssec_name_add_rr(cur_name, nsec_rr);
		ldns_rr_list_push_rr(new_rrs, nsec_rr);
		cur_node = next_node;
		if (cur_node) {
			next_node = ldns_dnssec_name_node_next_nonglue(
                               ldns_rbtree_next(cur_node));
		}
	}

	if (cur_node && !next_node) {
		cur_name = (ldns_dnssec_name *)cur_node->data;
		next_name = (ldns_dnssec_name *)first_node->data;
		nsec_rr = ldns_dnssec_create_nsec(cur_name,
		                                  next_name,
		                                  LDNS_RR_TYPE_NSEC);
		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
		ldns_dnssec_name_add_rr(cur_name, nsec_rr);
		ldns_rr_list_push_rr(new_rrs, nsec_rr);
	} else {
		printf("error\n");
	}

	return LDNS_STATUS_OK;
}
예제 #22
0
/**
 * Read ixfr journal from file.
 *
 *
 */
ods_status
backup_read_ixfr(FILE* in, void* zone)
{
    zone_type* z = (zone_type*) zone;
    ods_status result = ODS_STATUS_OK;
    ldns_rr* rr = NULL;
    ldns_rdf* prev = NULL;
    ldns_rdf* orig = NULL;
    ldns_rdf* dname = NULL;
    ldns_status status = LDNS_STATUS_OK;
    char line[SE_ADFILE_MAXLINE];
    uint32_t serial = 0;
    unsigned l = 0;
    unsigned first_soa = 1; /* expect soa first */
    unsigned del_mode = 0;

    ods_log_assert(in);
    ods_log_assert(z);

    /* $ORIGIN <zone name> */
    dname = adapi_get_origin(z);
    if (!dname) {
        ods_log_error("[%s] error getting default value for $ORIGIN",
                      backup_str);
        return ODS_STATUS_ERR;
    }
    orig = ldns_rdf_clone(dname);
    if (!orig) {
        ods_log_error("[%s] error setting default value for $ORIGIN",
                      backup_str);
        return ODS_STATUS_ERR;
    }
    /* read RRs */
    while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
            != NULL) {
        /* check status */
        if (status != LDNS_STATUS_OK) {
            ods_log_error("[%s] error reading RR #%i (%s): %s",
                          backup_str, l, ldns_get_errorstr_by_id(status), line);
            result = ODS_STATUS_ERR;
            goto backup_ixfr_done;
        }
        if (first_soa == 2) {
            ods_log_error("[%s] bad ixfr journal: trailing RRs after final "
                          "SOA", backup_str);
            ldns_rr_free(rr);
            rr = NULL;
            result = ODS_STATUS_ERR;
            goto backup_ixfr_done;
        }
        if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
            serial = ldns_rdf2native_int32(
                         ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
            if (first_soa) {
                ods_log_debug("[%s] ixfr first SOA: %s", backup_str,
                              ldns_rr2str(rr));
                /* first SOA */
                ldns_rr_free(rr);
                rr = NULL;
                if (z->db->outserial != serial) {
                    ods_log_error("[%s] bad ixfr journal: first SOA wrong "
                                  "serial (was %u, expected %u)", backup_str,
                                  serial, z->db->outserial);
                    result = ODS_STATUS_ERR;
                    goto backup_ixfr_done;
                }
                first_soa = 0;
                continue;
            }
            ods_log_assert(!first_soa);
            if (!del_mode) {
                if (z->db->outserial == serial) {
                    /* final SOA */
                    ods_log_debug("[%s] ixfr final SOA: %s", backup_str,
                                  ldns_rr2str(rr));
                    ldns_rr_free(rr);
                    rr = NULL;
                    result = ODS_STATUS_OK;
                    first_soa = 2;
                    continue;
                } else {
                    ods_log_debug("[%s] new part SOA: %s", backup_str,
                                  ldns_rr2str(rr));
                    lock_basic_lock(&z->ixfr->ixfr_lock);
                    ixfr_purge(z->ixfr);
                    lock_basic_unlock(&z->ixfr->ixfr_lock);
                }
            } else {
                ods_log_debug("[%s] second part SOA: %s", backup_str,
                              ldns_rr2str(rr));
            }
            del_mode = !del_mode;
        }
        /* ixfr add or del rr */
        if (first_soa) {
            ods_log_error("[%s] bad ixfr journal: first RR not SOA",
                          backup_str);
            ldns_rr_free(rr);
            rr = NULL;
            result = ODS_STATUS_ERR;
            goto backup_ixfr_done;
        }
        ods_log_assert(!first_soa);
        lock_basic_lock(&z->ixfr->ixfr_lock);
        if (del_mode) {
            ods_log_debug("[%s] -IXFR: %s", backup_str, ldns_rr2str(rr));
            ixfr_del_rr(z->ixfr, rr);
        } else {
            ods_log_debug("[%s] +IXFR: %s", backup_str, ldns_rr2str(rr));
            ixfr_add_rr(z->ixfr, rr);
        }
        lock_basic_unlock(&z->ixfr->ixfr_lock);
    }
    if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
        ods_log_error("[%s] error reading RR #%i (%s): %s",
                      backup_str, l, ldns_get_errorstr_by_id(status), line);
        result = ODS_STATUS_ERR;
    }

backup_ixfr_done:
    if (orig) {
        ldns_rdf_deep_free(orig);
        orig = NULL;
    }
    if (prev) {
        ldns_rdf_deep_free(prev);
        prev = NULL;
    }
    return result;
}
예제 #23
0
파일: host2wire.c 프로젝트: LANJr4D/iEnum
ldns_status
ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
						const ldns_rr *rr,
						int section)
{
	uint16_t i;
	uint16_t rdl_pos = 0;
	bool pre_rfc3597 = false;
	switch (ldns_rr_get_type(rr)) {
	case LDNS_RR_TYPE_NS:
	case LDNS_RR_TYPE_MD:
	case LDNS_RR_TYPE_MF:
	case LDNS_RR_TYPE_CNAME:
	case LDNS_RR_TYPE_SOA:
	case LDNS_RR_TYPE_MB:
	case LDNS_RR_TYPE_MG:
	case LDNS_RR_TYPE_MR:
	case LDNS_RR_TYPE_PTR:
	case LDNS_RR_TYPE_HINFO:
	case LDNS_RR_TYPE_MINFO:
	case LDNS_RR_TYPE_MX:
	case LDNS_RR_TYPE_RP:
	case LDNS_RR_TYPE_AFSDB:
	case LDNS_RR_TYPE_RT:
	case LDNS_RR_TYPE_SIG:
	case LDNS_RR_TYPE_PX:
	case LDNS_RR_TYPE_NXT:
	case LDNS_RR_TYPE_NAPTR:
	case LDNS_RR_TYPE_KX:
	case LDNS_RR_TYPE_SRV:
	case LDNS_RR_TYPE_DNAME:
	case LDNS_RR_TYPE_A6:
		pre_rfc3597 = true;
		break;
	default:
		break;
	}
	
	if (ldns_rr_owner(rr)) {
		(void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
	}
	
	if (ldns_buffer_reserve(buffer, 4)) {
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
	}

	if (section != LDNS_SECTION_QUESTION) {
		if (ldns_buffer_reserve(buffer, 6)) {
			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
			/* remember pos for later */
			rdl_pos = ldns_buffer_position(buffer);
			ldns_buffer_write_u16(buffer, 0);
		}	

		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
			if (pre_rfc3597) {
				(void) ldns_rdf2buffer_wire_canonical(buffer,
											   ldns_rr_rdf(rr, i));
			} else {
				(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
			}
		}
		
		if (rdl_pos != 0) {
			ldns_buffer_write_u16_at(buffer, rdl_pos,
			                         ldns_buffer_position(buffer)
		        	                   - rdl_pos - 2);
		}
	}
	return ldns_buffer_status(buffer);
}
예제 #24
0
/* same naive method as in drill0.9 
 * We resolver _ALL_ the names, which is ofcourse not needed
 * We _do_ use the local resolver to do that, so it still is
 * fast, but it can be made to run much faster
 */
ldns_pkt *
do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
		ldns_rr_class c)
{
	ldns_resolver *res;
	ldns_pkt *p;
	ldns_rr_list *new_nss_a;
	ldns_rr_list *new_nss_aaaa;
	ldns_rr_list *final_answer;
	ldns_rr_list *new_nss;
	ldns_rr_list *ns_addr;
	uint16_t loop_count;
	ldns_rdf *pop; 
	ldns_status status;
	size_t i;
	
	loop_count = 0;
	new_nss_a = NULL;
	new_nss_aaaa = NULL;
	new_nss = NULL;
	ns_addr = NULL;
	final_answer = NULL;
	p = ldns_pkt_new();
	res = ldns_resolver_new();

	if (!p) {
		if (res) {
			ldns_resolver_free(res);
		}
                error("Memory allocation failed");
                return NULL;
	}
	if (!res) {
		ldns_pkt_free(p);
                error("Memory allocation failed");
                return NULL;
        }

	/* transfer some properties of local_res to res,
	 * because they were given on the commandline */
	ldns_resolver_set_ip6(res, 
			ldns_resolver_ip6(local_res));
	ldns_resolver_set_port(res, 
			ldns_resolver_port(local_res));
	ldns_resolver_set_debug(res, 
			ldns_resolver_debug(local_res));
	ldns_resolver_set_dnssec(res, 
			ldns_resolver_dnssec(local_res));
	ldns_resolver_set_fail(res, 
			ldns_resolver_fail(local_res));
	ldns_resolver_set_usevc(res, 
			ldns_resolver_usevc(local_res));
	ldns_resolver_set_random(res, 
			ldns_resolver_random(local_res));
	ldns_resolver_set_recursive(res, false);

	/* setup the root nameserver in the new resolver */
	status = ldns_resolver_push_nameserver_rr_list(res, global_dns_root);
	if (status != LDNS_STATUS_OK) {
		fprintf(stderr, "Error adding root servers to resolver: %s\n", ldns_get_errorstr_by_id(status));
		ldns_rr_list_print(stdout, global_dns_root);
		ldns_resolver_free(res);
		ldns_pkt_free(p);
		return NULL;
	}

	/* this must be a real query to local_res */
	status = ldns_resolver_send(&p, res, ldns_dname_new_frm_str("."), LDNS_RR_TYPE_NS, c, 0);
	/* p can still be NULL */


	if (ldns_pkt_empty(p)) {
		warning("No root server information received");
	} 
	
	if (status == LDNS_STATUS_OK) {
		if (!ldns_pkt_empty(p)) {
			drill_pkt_print(stdout, local_res, p);
		}
	} else {
		error("cannot use local resolver");
		return NULL;
	}

	status = ldns_resolver_send(&p, res, name, t, c, 0);

	while(status == LDNS_STATUS_OK && 
	      ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) {

		if (!p) {
			/* some error occurred, bail out */
			return NULL;
		}

		new_nss_a = ldns_pkt_rr_list_by_type(p,
				LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL);
		new_nss_aaaa = ldns_pkt_rr_list_by_type(p,
				LDNS_RR_TYPE_AAAA, LDNS_SECTION_ADDITIONAL);
		new_nss = ldns_pkt_rr_list_by_type(p,
				LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY);

		if (verbosity != -1) {
			ldns_rr_list_print(stdout, new_nss);
		}
		/* checks itself for verbosity */
		drill_pkt_print_footer(stdout, local_res, p);
		
		/* remove the old nameserver from the resolver */
		while(ldns_resolver_pop_nameserver(res)) { /* do it */ }

		/* also check for new_nss emptyness */

		if (!new_nss_aaaa && !new_nss_a) {
			/* 
			 * no nameserver found!!! 
			 * try to resolve the names we do got 
			 */
			for(i = 0; i < ldns_rr_list_rr_count(new_nss); i++) {
				/* get the name of the nameserver */
				pop = ldns_rr_rdf(ldns_rr_list_rr(new_nss, i), 0);
				if (!pop) {
					break;
				}

				ldns_rr_list_print(stdout, new_nss);
				ldns_rdf_print(stdout, pop);
				/* retrieve it's addresses */
				ns_addr = ldns_rr_list_cat_clone(ns_addr,
					ldns_get_rr_list_addr_by_name(local_res, pop, c, 0));
			}

			if (ns_addr) {
				if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) != 
						LDNS_STATUS_OK) {
					error("Error adding new nameservers");
					ldns_pkt_free(p); 
					return NULL;
				}
				ldns_rr_list_free(ns_addr);
			} else {
				ldns_rr_list_print(stdout, ns_addr);
				error("Could not find the nameserver ip addr; abort");
				ldns_pkt_free(p);
				return NULL;
			}
		}

		/* add the new ones */
		if (new_nss_aaaa) {
			if (ldns_resolver_push_nameserver_rr_list(res, new_nss_aaaa) != 
					LDNS_STATUS_OK) {
				error("adding new nameservers");
				ldns_pkt_free(p); 
				return NULL;
			}
		}
		if (new_nss_a) {
			if (ldns_resolver_push_nameserver_rr_list(res, new_nss_a) != 
					LDNS_STATUS_OK) {
				error("adding new nameservers");
				ldns_pkt_free(p); 
				return NULL;
			}
		}

		if (loop_count++ > 20) {
			/* unlikely that we are doing something usefull */
			error("Looks like we are looping");
			ldns_pkt_free(p); 
			return NULL;
		}
		
		status = ldns_resolver_send(&p, res, name, t, c, 0);
		new_nss_aaaa = NULL;
		new_nss_a = NULL;
		ns_addr = NULL;
	}

	status = ldns_resolver_send(&p, res, name, t, c, 0);

	if (!p) {
		return NULL;
	}

	new_nss = ldns_pkt_authority(p);
	final_answer = ldns_pkt_answer(p);

	if (verbosity != -1) {
		ldns_rr_list_print(stdout, final_answer);
		ldns_rr_list_print(stdout, new_nss);

	}
	drill_pkt_print_footer(stdout, local_res, p);
	ldns_pkt_free(p); 
	return NULL;
}
예제 #25
0
int
getrrsetbyname(const char *hostname, unsigned int rdclass,
	       unsigned int rdtype, unsigned int flags,
	       struct rrsetinfo **res)
{
	int result;
	unsigned int i, j, index_ans, index_sig;
	struct rrsetinfo *rrset = NULL;
	struct rdatainfo *rdata;
	size_t len;
	ldns_resolver *ldns_res;
	ldns_rdf *domain = NULL;
	ldns_pkt *pkt = NULL;
	ldns_rr_list *rrsigs = NULL, *rrdata = NULL;
	ldns_status err;
	ldns_rr *rr;

	/* check for invalid class and type */
	if (rdclass > 0xffff || rdtype > 0xffff) {
		result = ERRSET_INVAL;
		goto fail;
	}

	/* don't allow queries of class or type ANY */
	if (rdclass == 0xff || rdtype == 0xff) {
		result = ERRSET_INVAL;
		goto fail;
	}

	/* don't allow flags yet, unimplemented */
	if (flags) {
		result = ERRSET_INVAL;
		goto fail;
	}

	/* Initialize resolver from resolv.conf */
	domain = ldns_dname_new_frm_str(hostname);
	if ((err = ldns_resolver_new_frm_file(&ldns_res, NULL)) != \
	    LDNS_STATUS_OK) {
		result = ERRSET_FAIL;
		goto fail;
	}

#ifdef LDNS_DEBUG
	ldns_resolver_set_debug(ldns_res, true);
#endif /* LDNS_DEBUG */

	ldns_resolver_set_dnssec(ldns_res, true); /* Use DNSSEC */

	/* make query */
	pkt = ldns_resolver_query(ldns_res, domain, rdtype, rdclass, LDNS_RD);

	/*** TODO: finer errcodes -- see original **/
	if (!pkt || ldns_pkt_ancount(pkt) < 1) {
		result = ERRSET_FAIL;
		goto fail;
	}

	/* initialize rrset */
	rrset = calloc(1, sizeof(struct rrsetinfo));
	if (rrset == NULL) {
		result = ERRSET_NOMEMORY;
		goto fail;
	}

	rrdata = ldns_pkt_rr_list_by_type(pkt, rdtype, LDNS_SECTION_ANSWER);
	rrset->rri_nrdatas = ldns_rr_list_rr_count(rrdata);
	if (!rrset->rri_nrdatas) {
		result = ERRSET_NODATA;
		goto fail;
	}

	/* copy name from answer section */
	len = ldns_rdf_size(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0)));
	if ((rrset->rri_name = malloc(len)) == NULL) {
		result = ERRSET_NOMEMORY;
		goto fail;
	}
	memcpy(rrset->rri_name,
	    ldns_rdf_data(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0))), len);

	rrset->rri_rdclass = ldns_rr_get_class(ldns_rr_list_rr(rrdata, 0));
	rrset->rri_rdtype = ldns_rr_get_type(ldns_rr_list_rr(rrdata, 0));
	rrset->rri_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrdata, 0));

	debug2("ldns: got %u answers from DNS", rrset->rri_nrdatas);

	/* Check for authenticated data */
	if (ldns_pkt_ad(pkt)) {
		rrset->rri_flags |= RRSET_VALIDATED;
	} else { /* AD is not set, try autonomous validation */
		ldns_rr_list * trusted_keys = ldns_rr_list_new();

		debug2("ldns: trying to validate RRset");
		/* Get eventual sigs */
		rrsigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG,
		    LDNS_SECTION_ANSWER);

		rrset->rri_nsigs = ldns_rr_list_rr_count(rrsigs);
		debug2("ldns: got %u signature(s) (RRTYPE %u) from DNS",
		       rrset->rri_nsigs, LDNS_RR_TYPE_RRSIG);

		if ((err = ldns_verify_trusted(ldns_res, rrdata, rrsigs,
		     trusted_keys)) == LDNS_STATUS_OK) {
			rrset->rri_flags |= RRSET_VALIDATED;
			debug2("ldns: RRset is signed with a valid key");
		} else {
			debug2("ldns: RRset validation failed: %s",
			    ldns_get_errorstr_by_id(err));
		}

		ldns_rr_list_deep_free(trusted_keys);
	}

	/* allocate memory for answers */
	rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
	   sizeof(struct rdatainfo));

	if (rrset->rri_rdatas == NULL) {
		result = ERRSET_NOMEMORY;
		goto fail;
	}

	/* allocate memory for signatures */
	if (rrset->rri_nsigs > 0) {
		rrset->rri_sigs = calloc(rrset->rri_nsigs,
		    sizeof(struct rdatainfo));

		if (rrset->rri_sigs == NULL) {
			result = ERRSET_NOMEMORY;
			goto fail;
		}
	}

	/* copy answers & signatures */
	for (i=0, index_ans=0, index_sig=0; i< pkt->_header->_ancount; i++) {
		rdata = NULL;
		rr = ldns_rr_list_rr(ldns_pkt_answer(pkt), i);

		if (ldns_rr_get_class(rr) == rrset->rri_rdclass &&
		    ldns_rr_get_type(rr) == rrset->rri_rdtype) {
			rdata = &rrset->rri_rdatas[index_ans++];
		}

		if (rr->_rr_class == rrset->rri_rdclass &&
		    rr->_rr_type == LDNS_RR_TYPE_RRSIG &&
		    rrset->rri_sigs) {
			rdata = &rrset->rri_sigs[index_sig++];
		}

		if (rdata) {
			size_t rdata_offset = 0;

			rdata->rdi_length = 0;
			for (j=0; j< rr->_rd_count; j++) {
				rdata->rdi_length +=
				    ldns_rdf_size(ldns_rr_rdf(rr, j));
			}

			rdata->rdi_data = malloc(rdata->rdi_length);
			if (rdata->rdi_data == NULL) {
				result = ERRSET_NOMEMORY;
				goto fail;
			}

			/* Re-create the raw DNS RDATA */
			for (j=0; j< rr->_rd_count; j++) {
				len = ldns_rdf_size(ldns_rr_rdf(rr, j));
				memcpy(rdata->rdi_data + rdata_offset,
				       ldns_rdf_data(ldns_rr_rdf(rr, j)), len);
				rdata_offset += len;
			}
		}
	}

	*res = rrset;
	result = ERRSET_SUCCESS;

fail:
	/* freerrset(rrset); */
	ldns_rdf_deep_free(domain);
	ldns_pkt_free(pkt);
	ldns_rr_list_deep_free(rrsigs);
	ldns_rr_list_deep_free(rrdata);
	ldns_resolver_deep_free(ldns_res);

	return result;
}
예제 #26
0
static ldns_status
ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone,
		ldns_rr_list *new_rrs,
		uint8_t algorithm,
		uint8_t flags,
		uint16_t iterations,
		uint8_t salt_length,
		uint8_t *salt,
		ldns_rbtree_t **map)
{
	ldns_rbnode_t *first_name_node;
	ldns_rbnode_t *current_name_node;
	ldns_dnssec_name *current_name;
	ldns_status result = LDNS_STATUS_OK;
	ldns_rr *nsec_rr;
	ldns_rr_list *nsec3_list;
	uint32_t nsec_ttl;
	ldns_dnssec_rrsets *soa;
	ldns_rbnode_t *hashmap_node;

	if (!zone || !new_rrs || !zone->names) {
		return LDNS_STATUS_ERR;
	}

	/* the TTL of NSEC rrs should be set to the minimum TTL of
	 * the zone SOA (RFC4035 Section 2.3)
	 */
	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);

	/* did the caller actually set it? if not,
	 * fall back to default ttl
	 */
	if (soa && soa->rrs && soa->rrs->rr
			&& ldns_rr_rdf(soa->rrs->rr, 6) != NULL) {
		nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6));
	} else {
		nsec_ttl = LDNS_DEFAULT_TTL;
	}

	if (zone->hashed_names) {
		ldns_traverse_postorder(zone->hashed_names,
				ldns_hashed_names_node_free, NULL);
		LDNS_FREE(zone->hashed_names);
	}
	zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
	if (zone->hashed_names && map) {
		*map = zone->hashed_names;
	}

	first_name_node = ldns_dnssec_name_node_next_nonglue(
					  ldns_rbtree_first(zone->names));

	current_name_node = first_name_node;

	while (current_name_node && current_name_node != LDNS_RBTREE_NULL &&
			result == LDNS_STATUS_OK) {

		current_name = (ldns_dnssec_name *) current_name_node->data;
		nsec_rr = ldns_dnssec_create_nsec3(current_name,
		                                   NULL,
		                                   zone->soa->name,
		                                   algorithm,
		                                   flags,
		                                   iterations,
		                                   salt_length,
		                                   salt);
		/* by default, our nsec based generator adds rrsigs
		 * remove the bitmap for empty nonterminals */
		if (!current_name->rrsets) {
			ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr));
		}
		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
		result = ldns_dnssec_name_add_rr(current_name, nsec_rr);
		ldns_rr_list_push_rr(new_rrs, nsec_rr);
		if (ldns_rr_owner(nsec_rr)) {
			hashmap_node = LDNS_MALLOC(ldns_rbnode_t);
			if (hashmap_node == NULL) {
				return LDNS_STATUS_MEM_ERR;
			}
			current_name->hashed_name = 
				ldns_dname_label(ldns_rr_owner(nsec_rr), 0);

			if (current_name->hashed_name == NULL) {
				LDNS_FREE(hashmap_node);
				return LDNS_STATUS_MEM_ERR;
			}
			hashmap_node->key  = current_name->hashed_name;
			hashmap_node->data = current_name;

			if (! ldns_rbtree_insert(zone->hashed_names
						, hashmap_node)) {
				LDNS_FREE(hashmap_node);
			}
		}
		current_name_node = ldns_dnssec_name_node_next_nonglue(
		                   ldns_rbtree_next(current_name_node));
	}
	if (result != LDNS_STATUS_OK) {
		return result;
	}

	/* Make sorted list of nsec3s (via zone->hashed_names)
	 */
	nsec3_list = ldns_rr_list_new();
	if (nsec3_list == NULL) {
		return LDNS_STATUS_MEM_ERR;
	}
	for ( hashmap_node  = ldns_rbtree_first(zone->hashed_names)
	    ; hashmap_node != LDNS_RBTREE_NULL
	    ; hashmap_node  = ldns_rbtree_next(hashmap_node)
	    ) {
		current_name = (ldns_dnssec_name *) hashmap_node->data;
		nsec_rr = ((ldns_dnssec_name *) hashmap_node->data)->nsec;
		if (nsec_rr) {
			ldns_rr_list_push_rr(nsec3_list, nsec_rr);
		}
	}
	result = ldns_dnssec_chain_nsec3_list(nsec3_list);
	ldns_rr_list_free(nsec3_list);

	return result;
}
예제 #27
0
/**
 * Process SOA.
 *
 */
static ods_status
adapi_process_soa(zone_type* zone, ldns_rr* rr, int add, int backup)
{
    uint32_t tmp = 0;
    ldns_rdf* soa_rdata = NULL;
    ods_status status = ODS_STATUS_OK;

    ods_log_assert(rr);
    ods_log_assert(zone);
    ods_log_assert(zone->name);
    ods_log_assert(zone->signconf);

    if (backup) {
        /* no need to do processing */
        return ODS_STATUS_OK;
    }
    if (zone->signconf->soa_ttl) {
        tmp = (uint32_t) duration2time(zone->signconf->soa_ttl);
        ods_log_verbose("[%s] zone %s set soa ttl to %u",
            adapi_str, zone->name, tmp);
        ldns_rr_set_ttl(rr, tmp);
    }
    if (zone->signconf->soa_min) {
        tmp = (uint32_t) duration2time(zone->signconf->soa_min);
        ods_log_verbose("[%s] zone %s set soa minimum to %u",
            adapi_str, zone->name, tmp);
        soa_rdata = ldns_rr_set_rdf(rr,
            ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, tmp),
            SE_SOA_RDATA_MINIMUM);
        if (soa_rdata) {
            ldns_rdf_deep_free(soa_rdata);
            soa_rdata = NULL;
        } else {
            ods_log_error("[%s] unable to %s soa to zone %s: failed to replace "
                "soa minimum rdata", adapi_str, add?"add":"delete",
                zone->name);
            return ODS_STATUS_ASSERT_ERR;
        }
    }
    if (!add) {
        /* we are done */
        return ODS_STATUS_OK;
    }
    tmp = ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
    status = namedb_update_serial(zone->db, zone->name,
        zone->signconf->soa_serial, tmp);
    if (status != ODS_STATUS_OK) {
        ods_log_error("[%s] unable to add soa to zone %s: failed to replace "
            "soa serial rdata (%s)", adapi_str, zone->name,
            ods_status2str(status));
        if (status == ODS_STATUS_CONFLICT_ERR) {
            ods_log_error("[%s] If this is the result of a key rollover, "
                "please increment the serial in the unsigned zone %s",
                adapi_str, zone->name);
        }
        return status;
    }
    ods_log_verbose("[%s] zone %s set soa serial to %u", adapi_str,
        zone->name, zone->db->intserial);
    soa_rdata = ldns_rr_set_rdf(rr, ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
        zone->db->intserial), SE_SOA_RDATA_SERIAL);
    if (soa_rdata) {
        ldns_rdf_deep_free(soa_rdata);
        soa_rdata = NULL;
    } else {
        ods_log_error("[%s] unable to add soa to zone %s: failed to replace "
            "soa serial rdata", adapi_str, zone->name);
        return ODS_STATUS_ERR;
    }
    zone->db->serial_updated = 1;
    return ODS_STATUS_OK;
}
예제 #28
0
파일: adfile.c 프로젝트: bbczeuz/opendnssec
/**
 * Read zone file.
 *
 */
static ods_status
adfile_read_file(FILE* fd, zone_type* zone)
{
    ods_status result = ODS_STATUS_OK;
    ldns_rr* rr = NULL;
    ldns_rdf* prev = NULL;
    ldns_rdf* orig = NULL;
    ldns_rdf* dname = NULL;
    uint32_t ttl = 0;
    uint32_t new_serial = 0;
    ldns_status status = LDNS_STATUS_OK;
    char line[SE_ADFILE_MAXLINE];
    unsigned int line_update_interval = 100000;
    unsigned int line_update = line_update_interval;
    unsigned int l = 0;

    ods_log_assert(fd);
    ods_log_assert(zone);

    /* $ORIGIN <zone name> */
    dname = adapi_get_origin(zone);
    if (!dname) {
        ods_log_error("[%s] error getting default value for $ORIGIN",
            adapter_str);
        return ODS_STATUS_ERR;
    }
    orig = ldns_rdf_clone(dname);
    if (!orig) {
        ods_log_error("[%s] error setting default value for $ORIGIN",
            adapter_str);
        return ODS_STATUS_ERR;
    }
    /* $TTL <default ttl> */
    ttl = adapi_get_ttl(zone);
    /* read RRs */
    while ((rr = adfile_read_rr(fd, zone, line, &orig, &prev, &ttl,
        &status, &l)) != NULL) {
        /* check status */
        if (status != LDNS_STATUS_OK) {
            ods_log_error("[%s] error reading RR at line %i (%s): %s",
                adapter_str, l, ldns_get_errorstr_by_id(status), line);
            result = ODS_STATUS_ERR;
            break;
        }
        /* debug update */
        if (l > line_update) {
            ods_log_debug("[%s] ...at line %i: %s", adapter_str, l, line);
            line_update += line_update_interval;
        }
        /* SOA? */
        if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
            new_serial =
              ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
        }
        /* add to the database */
        result = adapi_add_rr(zone, rr, 0);
        if (result == ODS_STATUS_UNCHANGED) {
            ods_log_debug("[%s] skipping RR at line %i (duplicate): %s",
                adapter_str, l, line);
            ldns_rr_free(rr);
            rr = NULL;
            result = ODS_STATUS_OK;
            continue;
        } else if (result != ODS_STATUS_OK) {
            ods_log_error("[%s] error adding RR at line %i: %s",
                adapter_str, l, line);
            ldns_rr_free(rr);
            rr = NULL;
            break;
        }
    }
    /* and done */
    if (orig) {
        ldns_rdf_deep_free(orig);
        orig = NULL;
    }
    if (prev) {
        ldns_rdf_deep_free(prev);
        prev = NULL;
    }
    if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
        ods_log_error("[%s] error reading RR at line %i (%s): %s",
            adapter_str, l, ldns_get_errorstr_by_id(status), line);
        result = ODS_STATUS_ERR;
    }
    /* input zone ok, set inbound serial and apply differences */
    if (result == ODS_STATUS_OK) {
        result = namedb_examine(zone->db);
        if (result != ODS_STATUS_OK) {
            ods_log_error("[%s] unable to read file: zonefile contains errors",
                adapter_str);
            return result;
        }
        adapi_set_serial(zone, new_serial);
    }
    return result;
}
예제 #29
0
static ldns_rr_list *
retrieve_dnskeys(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
		ldns_rr_class c, ldns_rr_list *dns_root)
{
	ldns_resolver *res;
	ldns_pkt *p;
	ldns_rr_list *new_nss_a;
	ldns_rr_list *new_nss_aaaa;
	ldns_rr_list *final_answer;
	ldns_rr_list *new_nss;
	ldns_rr_list *ns_addr;
	ldns_rr_list *ns_addr2;
	uint16_t loop_count;
	ldns_rdf *pop; 
	ldns_status status;
	size_t i;

	size_t nss_i;
	ldns_rr_list *answer_list = NULL;
	ldns_rr_list *authority_list = NULL;
	
	size_t last_nameserver_count;
	ldns_rdf **last_nameservers;

	loop_count = 0;
	new_nss_a = NULL;
	new_nss_aaaa = NULL;
	new_nss = NULL;
	ns_addr = NULL;
	ns_addr2 = NULL;
	final_answer = NULL;
	p = ldns_pkt_new();
	res = ldns_resolver_new();
	
	if (!p || !res) {
                fprintf(stderr, "Memory allocation failed");
                return NULL;
        }

	if (verbosity >= 2) {
		printf("Finding dnskey data for zone: ");
		ldns_rdf_print(stdout, name);
		printf("\n\n");
	}

	/* transfer some properties of local_res to res,
	 * because they were given on the commandline */
	ldns_resolver_set_ip6(res, 
			ldns_resolver_ip6(local_res));
	ldns_resolver_set_port(res, 
			ldns_resolver_port(local_res));
	ldns_resolver_set_debug(res, 
			ldns_resolver_debug(local_res));
	ldns_resolver_set_dnssec(res, 
			ldns_resolver_dnssec(local_res));
	ldns_resolver_set_fail(res, 
			ldns_resolver_fail(local_res));
	ldns_resolver_set_usevc(res, 
			ldns_resolver_usevc(local_res));
	ldns_resolver_set_random(res, 
			ldns_resolver_random(local_res));
	ldns_resolver_set_recursive(res, false);

	/* setup the root nameserver in the new resolver */
	status = ldns_resolver_push_nameserver_rr_list(res, dns_root);
	if (status != LDNS_STATUS_OK) {
		fprintf(stderr, "Error setting root nameservers in resolver: %s\n", ldns_get_errorstr_by_id(status));
		return NULL;
	}

	ldns_pkt_free(p);
	status = ldns_resolver_send(&p, res, name, t, c, 0);
	if (status != LDNS_STATUS_OK) {
		fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status));
		return NULL;
	}

	if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
		printf("Error in packet:\n");
		ldns_pkt_print(stdout, p);
		return NULL;
	}

	if (verbosity >= 4) {
		ldns_pkt_print(stdout, p);
		printf("\n\n");
	}

	/* from now on, use TCP */
	ldns_resolver_set_usevc(res, true);

	while(status == LDNS_STATUS_OK && 
	      ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) {

		if (verbosity >= 3) {
			printf("This is a delegation!\n\n");
		}
		if (address_family == 0 || address_family == 1) {
			new_nss_a = ldns_pkt_rr_list_by_type(p,
					LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL);
		} else {
			new_nss_a = ldns_rr_list_new();
		}
		if (address_family == 0 || address_family == 2) {
			new_nss_aaaa = ldns_pkt_rr_list_by_type(p,
					LDNS_RR_TYPE_AAAA, LDNS_SECTION_ADDITIONAL);
		} else {
			new_nss_aaaa = ldns_rr_list_new();
		}
		new_nss = ldns_pkt_rr_list_by_type(p,
				LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY);

		/* remove the old nameserver from the resolver */
		while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); }

		/* also check for new_nss emptyness */

		if (!new_nss_aaaa && !new_nss_a) {
			/* 
			 * no nameserver found!!! 
			 * try to resolve the names we do got 
			 */
			if (verbosity >= 3) {
				printf("Did not get address record for nameserver, doing seperate query.\n");
			}
			ns_addr = ldns_rr_list_new();
			for(i = 0; (size_t) i < ldns_rr_list_rr_count(new_nss); i++) {
				/* get the name of the nameserver */
				pop = ldns_rr_rdf(ldns_rr_list_rr(new_nss, i), 0);
				if (!pop) {
					break;
				}

				/* retrieve it's addresses */
				ns_addr2 = ldns_get_rr_list_addr_by_name(local_res, pop, c, 0);
				if (!ldns_rr_list_cat(ns_addr, ns_addr2)) {
					fprintf(stderr, "Internal error adding nameserver address.\n");
					exit(EXIT_FAILURE);
				}
				ldns_rr_list_free(ns_addr2);
			}

			if (ns_addr) {
				if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) != 
						LDNS_STATUS_OK) {
					fprintf(stderr, "Error adding new nameservers");
					ldns_pkt_free(p); 
					return NULL;
				}
				ldns_rr_list_deep_free(ns_addr);
			} else {
				ldns_rr_list_print(stdout, ns_addr);
				fprintf(stderr, "Could not find the nameserver ip addr; abort");
				ldns_pkt_free(p);
				return NULL;
			}
		}

		/* normally, the first working ns is used, but we need all now, so do it one by one
		 * if the answer is null, take it from the next resolver
		 * if the answer is not, compare it to that of the next resolver
		 * error if different, continue if the same
		 * if answer list null and no resolvers left die.
		 */

		ldns_rr_list_deep_free(answer_list);
		ldns_rr_list_deep_free(authority_list);
		answer_list = NULL;
		authority_list = NULL;
		for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_aaaa); nss_i++) {
			while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); }

			status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0));
			if (status != LDNS_STATUS_OK) {
				fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
			}
			
			if (verbosity >= 1) {
				fprintf(stdout, "Querying nameserver: ");
				ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_aaaa, nss_i)));
				fprintf(stdout, " (");
				ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0));
				fprintf(stdout, ")\n");
			}
			status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0));
			if (status != LDNS_STATUS_OK) {
				fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
			}

			ldns_pkt_free(p);
			status = ldns_resolver_send(&p, res, name, t, c, 0);
			if (status == LDNS_STATUS_OK && p) {
				if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
					printf("Error in packet:\n");
					ldns_pkt_print(stdout, p);
					return NULL;
				}

				if (verbosity >= 4) {
					ldns_pkt_print(stdout, p);
					printf("\n\n");
				}

				if (answer_list) {
					if (verbosity >= 2) {
						printf("Comparing answer list of answer to previous\n\n");
					}
					ldns_rr_list_sort(ldns_pkt_answer(p));
					ldns_rr_list_sort(answer_list);
					if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) {
						fprintf(stderr, "ERROR: different answer answer from nameserver\n");
						fprintf(stderr, "\nI had (from previous servers):\n");
						ldns_rr_list_print(stderr, answer_list);
						fprintf(stderr, "\nI received (from nameserver at ");
						ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
						fprintf(stderr, "):\n");
						ldns_rr_list_print(stderr, ldns_pkt_answer(p));
						exit(EXIT_FAILURE);
					}
				} else {
					answer_list = ldns_rr_list_clone(ldns_pkt_answer(p));
					ldns_rr_list_sort(answer_list);
					if (verbosity >= 2) {
						printf("First answer list for this set, nothing to compare with\n\n");
					}
				}
				if (authority_list) {
					if (verbosity >= 2) {
						printf("Comparing authority list of answer to previous\n\n");
					}
					ldns_rr_list_sort(ldns_pkt_authority(p));
					ldns_rr_list_sort(authority_list);
					if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) {
						fprintf(stderr, "ERROR: different authority answer from nameserver\n");
						fprintf(stderr, "\nI had (from previous servers):\n");
						ldns_rr_list_print(stderr, authority_list);
						fprintf(stderr, "\nI received (from nameserver at ");
						ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
						fprintf(stderr, "):\n");
						ldns_rr_list_print(stderr, ldns_pkt_authority(p));
						exit(EXIT_FAILURE);
					}
				} else {
					authority_list = ldns_rr_list_clone(ldns_pkt_authority(p));
					ldns_rr_list_sort(authority_list);
					if (verbosity >= 2) {
						printf("First authority list for this set, nothing to compare with\n\n");
					}
					if (verbosity >= 3) {
						printf("NS RRset:\n");
						ldns_rr_list_print(stdout, authority_list);
						printf("\n");
					}
				}
			}
		}

		ldns_rr_list_deep_free(answer_list);
		ldns_rr_list_deep_free(authority_list);
		answer_list = NULL;
		authority_list = NULL;
		for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_a); nss_i++) {

			while((pop = ldns_resolver_pop_nameserver(res))) {ldns_rdf_deep_free(pop); }

			if (verbosity >= 1) {
				fprintf(stdout, "Querying nameserver: ");
				ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_a, nss_i)));
				fprintf(stdout, " (");
				ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0));
				fprintf(stdout, ")\n");
			}
			status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0));
			if (status != LDNS_STATUS_OK) {
				fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
			}
			
			ldns_pkt_free(p);
			status = ldns_resolver_send(&p, res, name, t, c, 0);

			if (status == LDNS_STATUS_OK) {
				if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
					printf("Error in packet:\n");
					ldns_pkt_print(stdout, p);
					return NULL;
				}

				if (verbosity >= 4) {
					ldns_pkt_print(stdout, p);
					printf("\n\n");
				}

				if (answer_list) {
					if (verbosity >= 2) {
						printf("Comparing answer list of answer to previous\n\n");
					}
					ldns_rr_list_sort(ldns_pkt_answer(p));
					ldns_rr_list_sort(answer_list);
					if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) {
						fprintf(stderr, "ERROR: different answer answer from nameserver\n");
						fprintf(stderr, "\nI had (from previous servers):\n");
						ldns_rr_list_print(stderr, answer_list);
						fprintf(stderr, "\nI received (from nameserver at ");
						ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
						fprintf(stderr, "):\n");
						ldns_rr_list_print(stderr, ldns_pkt_answer(p));
						exit(EXIT_FAILURE);
					}
				} else {
					if (verbosity >= 2) {
						printf("First answer list for this set, nothing to compare with\n\n");
					}
					answer_list = ldns_rr_list_clone(ldns_pkt_answer(p));
					ldns_rr_list_sort(answer_list);
				}
				if (authority_list) {
					if (verbosity >= 2) {
						printf("Comparing authority list of answer to previous\n\n");
					}
					ldns_rr_list_sort(ldns_pkt_authority(p));
					ldns_rr_list_sort(authority_list);
					if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) {
						fprintf(stderr, "ERROR: different authority answer from nameserver\n");
						fprintf(stderr, "\nI had (from previous servers):\n");
						ldns_rr_list_print(stderr, authority_list);
						fprintf(stderr, "\nI received (from nameserver at ");
						ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
						fprintf(stderr, "):\n");
						ldns_rr_list_print(stderr, ldns_pkt_authority(p));
						exit(EXIT_FAILURE);
					}
				} else {
					if (verbosity >= 2) {
						printf("First authority list for this set, nothing to compare with\n\n");
					}
					authority_list = ldns_rr_list_clone(ldns_pkt_authority(p));
					ldns_rr_list_sort(authority_list);
					if (verbosity >= 3) {
						printf("NS RRset:\n");
						ldns_rr_list_print(stdout, authority_list);
						printf("\n");
					}
				}
			}
		}
		ldns_rr_list_deep_free(authority_list);
		authority_list = NULL;
		
		if (loop_count++ > 20) {
			/* unlikely that we are doing something usefull */
			fprintf(stderr, "Looks like we are looping");
			ldns_pkt_free(p); 
			return NULL;
		}
		
		ldns_pkt_free(p);

		if (verbosity >= 3) {
			fprintf(stdout, "This level ok. Continuing to next.\n\n");
		}

		status = ldns_resolver_send(&p, res, name, t, c, 0);
		
		if (status != LDNS_STATUS_OK) {
			fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status));
			return NULL;
		}

		if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
			printf("Error in packet:\n");
			ldns_pkt_print(stdout, p);
			return NULL;
		}

		if (verbosity >= 4) {
			ldns_pkt_print(stdout, p);
			printf("\n\n");
		}


		ldns_rr_list_deep_free(new_nss_aaaa);
		ldns_rr_list_deep_free(new_nss_a);
		ldns_rr_list_deep_free(new_nss);
		new_nss_aaaa = NULL;
		new_nss_a = NULL;
		ns_addr = NULL;
	}

	ldns_rr_list_deep_free(answer_list);
	answer_list = NULL;
	/* clone the nameserver list, we are going to handle them one by one */
	last_nameserver_count = 0;
	last_nameservers = LDNS_XMALLOC(ldns_rdf *, ldns_resolver_nameserver_count(res));

	pop = NULL;
	while((pop = ldns_resolver_pop_nameserver(res))) { 
		last_nameservers[last_nameserver_count] = pop;
		last_nameserver_count++;
	}

	for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) {
		/* remove previous nameserver */
		while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); }

		if (verbosity >= 1) {
			printf("Querying nameserver: ");
			ldns_rdf_print(stdout, last_nameservers[nss_i]);
			printf("\n");
		}
		status = ldns_resolver_push_nameserver(res, last_nameservers[nss_i]);
		if (status != LDNS_STATUS_OK) {
			fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
		}

		ldns_pkt_free(p);
		status = ldns_resolver_send(&p, res, name, t, c, 0);

		if (!p) {
			fprintf(stderr, "no packet received\n");
			return NULL;
		}

		if (status == LDNS_STATUS_RES_NO_NS) {
			fprintf(stderr, "Error: nameserver at ");
			ldns_rdf_print(stderr, last_nameservers[nss_i]);
			fprintf(stderr, " not responding. Unable to check RRset here, aborting.\n");
			return NULL;
		}

		if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
			printf("Error in packet:\n");
			ldns_pkt_print(stdout, p);
			return NULL;
		}

		if (answer_list) {
			if (verbosity >= 2) {
				printf("1Comparing answer rr list of answer to previous\n");
			}
			ldns_rr_list_sort(ldns_pkt_answer(p));
			ldns_rr_list_sort(answer_list);
			if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) {
				printf("ERROR: different answer section in response from nameserver\n");
				fprintf(stderr, "\nI had:\n");
				ldns_rr_list_print(stderr, answer_list);
				fprintf(stderr, "\nI received (from nameserver at ");
				ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
				fprintf(stderr, "):\n");
				ldns_rr_list_print(stderr, ldns_pkt_answer(p));
				exit(EXIT_FAILURE);
			}
		} else {
			if (verbosity >= 2) {
				printf("First answer rr list for this set, nothing to compare with\n");
			}
			answer_list = ldns_rr_list_clone(ldns_pkt_answer(p));
			if (verbosity >= 3) {
				printf("DNSKEY RRset:\n");
				ldns_rr_list_print(stdout, answer_list);
			}
		}

	}

	for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) {
		ldns_rdf_deep_free(last_nameservers[nss_i]);
	}
	LDNS_FREE(last_nameservers);
	ldns_resolver_deep_free(res);
	ldns_pkt_free(p);
	return answer_list;
}
예제 #30
0
int
main(int argc, char *argv[])
{
	ldns_resolver *res;
	ldns_rdf *ns;
	ldns_rdf *domain;
	ldns_rr_list *l = NULL;

	ldns_rr_list *dns_root = NULL;
	const char *root_file = "/etc/named.root";

	ldns_status status;
	
	int i;

	char *domain_str;
	char *outputfile_str;
	ldns_buffer *outputfile_buffer;
	FILE *outputfile;
	ldns_rr *k;
	
	bool insecure = false;
	ldns_pkt *pkt;

	domain = NULL;
	res = NULL;

	if (argc < 2) {
		usage(stdout, argv[0]);
		exit(EXIT_FAILURE);
	} else {
		for (i = 1; i < argc; i++) {
			if (strncmp("-4", argv[i], 3) == 0) {
				if (address_family != 0) {
					fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n");
					exit(EXIT_FAILURE);
				}
				address_family = 1;
			} else if (strncmp("-6", argv[i], 3) == 0) {
				if (address_family != 0) {
					fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n");
					exit(EXIT_FAILURE);
				}
				address_family = 2;
			} else if (strncmp("-h", argv[i], 3) == 0) {
				usage(stdout, argv[0]);
				exit(EXIT_SUCCESS);
			} else if (strncmp("-i", argv[i], 2) == 0) {
				insecure = true;
			} else if (strncmp("-r", argv[i], 2) == 0) {
				if (strlen(argv[i]) > 2) {
					root_file = argv[i]+2;
				} else if (i+1 >= argc) {
					usage(stdout, argv[0]);
					exit(EXIT_FAILURE);
				} else {
					root_file = argv[i+1];
					i++;
				}
			} else if (strncmp("-s", argv[i], 3) == 0) {
				store_in_file = true;
			} else if (strncmp("-v", argv[i], 2) == 0) {
				if (strlen(argv[i]) > 2) {
					verbosity = atoi(argv[i]+2);
				} else if (i+1 > argc) {
					usage(stdout, argv[0]);
					exit(EXIT_FAILURE);
				} else {
					verbosity = atoi(argv[i+1]);
					i++;
				}
			} else {
				/* create a rdf from the command line arg */
				if (domain) {
					fprintf(stdout, "You can only specify one domain at a time\n");
					exit(EXIT_FAILURE);
				}

				domain = ldns_dname_new_frm_str(argv[i]);
			}

		}
		if (!domain) {
			usage(stdout, argv[0]);
			exit(EXIT_FAILURE);
		}
	}

	dns_root = read_root_hints(root_file);
	if (!dns_root) {
		fprintf(stderr, "cannot read the root hints file\n");
		exit(EXIT_FAILURE);
	}

	/* create a new resolver from /etc/resolv.conf */
	status = ldns_resolver_new_frm_file(&res, NULL);

	if (status != LDNS_STATUS_OK) {
		fprintf(stderr, "Warning: Unable to create stub resolver from /etc/resolv.conf:\n");
		fprintf(stderr, "%s\n", ldns_get_errorstr_by_id(status));
		fprintf(stderr, "defaulting to nameserver at 127.0.0.1 for separate nameserver name lookups\n");
		res = ldns_resolver_new();
		ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, "127.0.0.1");
		status = ldns_resolver_push_nameserver(res, ns);
		if (status != LDNS_STATUS_OK) {
			fprintf(stderr, "Unable to create stub resolver: %s\n", ldns_get_errorstr_by_id(status));
			exit(EXIT_FAILURE);
		}
		ldns_rdf_deep_free(ns);
	}

	ldns_resolver_set_ip6(res, address_family);

	if (insecure) {
		pkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD);
		if (pkt) {
		l = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_DNSKEY, LDNS_SECTION_ANY_NOQUESTION);
		}
	} else {
		l = retrieve_dnskeys(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, dns_root);
	}
	
	/* separator for result data and verbosity data */
	if (verbosity > 0) {
		fprintf(stdout, "; ---------------------------\n");
		fprintf(stdout, "; Got the following keys:\n");
	}
	if (l) {
		if (store_in_file) {
			/* create filename:
			 * K<domain>.+<alg>.+<id>.key
			 */
			for (i = 0; (size_t) i < ldns_rr_list_rr_count(l); i++) {
				k = ldns_rr_list_rr(l, (size_t) i);
				
				outputfile_buffer = ldns_buffer_new(300);
				domain_str = ldns_rdf2str(ldns_rr_owner(k));
				ldns_buffer_printf(outputfile_buffer, "K%s+%03u+%05u.key", domain_str, ldns_rdf2native_int8(ldns_rr_rdf(k, 2)),
					(unsigned int) ldns_calc_keytag(k));
				outputfile_str = ldns_buffer_export(outputfile_buffer);
				
				if (verbosity >= 1) {
					fprintf(stdout, "Writing key to file %s\n", outputfile_str);
				}
				
				outputfile = fopen(outputfile_str, "w");
				if (!outputfile) {
					fprintf(stderr, "Error writing key to file %s: %s\n", outputfile_str, strerror(errno));
				} else {
					ldns_rr_print(outputfile, k);
					fclose(outputfile);
				}
				
				LDNS_FREE(domain_str);
				LDNS_FREE(outputfile_str);
				LDNS_FREE(outputfile_buffer);
			}
		} else {
			ldns_rr_list_print(stdout, l);
		}
	} else {
		fprintf(stderr, "no answer packet received, stub resolver config:\n");
		ldns_resolver_print(stderr, res);
	}
	printf("\n");

	ldns_rdf_deep_free(domain);
	ldns_resolver_deep_free(res);
	ldns_rr_list_deep_free(l);
	ldns_rr_list_deep_free(dns_root);
	return EXIT_SUCCESS;
}