158d83921SDag-Erling Smørgrav /* $OpenBSD: getrrsetbyname.c,v 1.10 2005/03/30 02:58:28 tedu Exp $ */
258d83921SDag-Erling Smørgrav
358d83921SDag-Erling Smørgrav /*
458d83921SDag-Erling Smørgrav * Copyright (c) 2007 Simon Vallet / Genoscope <svallet@genoscope.cns.fr>
558d83921SDag-Erling Smørgrav *
658d83921SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without
758d83921SDag-Erling Smørgrav * modification, are permitted provided that the following conditions
858d83921SDag-Erling Smørgrav * are met:
958d83921SDag-Erling Smørgrav *
1058d83921SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright
1158d83921SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer.
1258d83921SDag-Erling Smørgrav *
1358d83921SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright
1458d83921SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the
1558d83921SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution.
1658d83921SDag-Erling Smørgrav *
1758d83921SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1858d83921SDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1958d83921SDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2058d83921SDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2158d83921SDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2258d83921SDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2358d83921SDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2458d83921SDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2558d83921SDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2658d83921SDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2758d83921SDag-Erling Smørgrav */
2858d83921SDag-Erling Smørgrav
2958d83921SDag-Erling Smørgrav /*
3058d83921SDag-Erling Smørgrav * Portions Copyright (c) 1999-2001 Internet Software Consortium.
3158d83921SDag-Erling Smørgrav *
3258d83921SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any
3358d83921SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above
3458d83921SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies.
3558d83921SDag-Erling Smørgrav *
3658d83921SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
3758d83921SDag-Erling Smørgrav * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
3858d83921SDag-Erling Smørgrav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
3958d83921SDag-Erling Smørgrav * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
4058d83921SDag-Erling Smørgrav * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
4158d83921SDag-Erling Smørgrav * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
4258d83921SDag-Erling Smørgrav * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
4358d83921SDag-Erling Smørgrav * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4458d83921SDag-Erling Smørgrav */
4558d83921SDag-Erling Smørgrav
4658d83921SDag-Erling Smørgrav #include "includes.h"
4758d83921SDag-Erling Smørgrav
4858d83921SDag-Erling Smørgrav #if !defined (HAVE_GETRRSETBYNAME) && defined (HAVE_LDNS)
4958d83921SDag-Erling Smørgrav
5058d83921SDag-Erling Smørgrav #include <stdlib.h>
5158d83921SDag-Erling Smørgrav #include <string.h>
5258d83921SDag-Erling Smørgrav
5358d83921SDag-Erling Smørgrav #include <ldns/ldns.h>
5458d83921SDag-Erling Smørgrav
5558d83921SDag-Erling Smørgrav #include "getrrsetbyname.h"
5658d83921SDag-Erling Smørgrav #include "log.h"
5758d83921SDag-Erling Smørgrav #include "xmalloc.h"
5858d83921SDag-Erling Smørgrav
5958d83921SDag-Erling Smørgrav #define malloc(x) (xmalloc(x))
6058d83921SDag-Erling Smørgrav #define calloc(x, y) (xcalloc((x),(y)))
6158d83921SDag-Erling Smørgrav
6258d83921SDag-Erling Smørgrav int
getrrsetbyname(const char * hostname,unsigned int rdclass,unsigned int rdtype,unsigned int flags,struct rrsetinfo ** res)6358d83921SDag-Erling Smørgrav getrrsetbyname(const char *hostname, unsigned int rdclass,
6458d83921SDag-Erling Smørgrav unsigned int rdtype, unsigned int flags,
6558d83921SDag-Erling Smørgrav struct rrsetinfo **res)
6658d83921SDag-Erling Smørgrav {
6758d83921SDag-Erling Smørgrav int result;
6858d83921SDag-Erling Smørgrav unsigned int i, j, index_ans, index_sig;
6958d83921SDag-Erling Smørgrav struct rrsetinfo *rrset = NULL;
7058d83921SDag-Erling Smørgrav struct rdatainfo *rdata;
7158d83921SDag-Erling Smørgrav size_t len;
72*bc5531deSDag-Erling Smørgrav ldns_resolver *ldns_res = NULL;
7358d83921SDag-Erling Smørgrav ldns_rdf *domain = NULL;
7458d83921SDag-Erling Smørgrav ldns_pkt *pkt = NULL;
7558d83921SDag-Erling Smørgrav ldns_rr_list *rrsigs = NULL, *rrdata = NULL;
7658d83921SDag-Erling Smørgrav ldns_status err;
7758d83921SDag-Erling Smørgrav ldns_rr *rr;
7858d83921SDag-Erling Smørgrav
7958d83921SDag-Erling Smørgrav /* check for invalid class and type */
8058d83921SDag-Erling Smørgrav if (rdclass > 0xffff || rdtype > 0xffff) {
8158d83921SDag-Erling Smørgrav result = ERRSET_INVAL;
8258d83921SDag-Erling Smørgrav goto fail;
8358d83921SDag-Erling Smørgrav }
8458d83921SDag-Erling Smørgrav
8558d83921SDag-Erling Smørgrav /* don't allow queries of class or type ANY */
8658d83921SDag-Erling Smørgrav if (rdclass == 0xff || rdtype == 0xff) {
8758d83921SDag-Erling Smørgrav result = ERRSET_INVAL;
8858d83921SDag-Erling Smørgrav goto fail;
8958d83921SDag-Erling Smørgrav }
9058d83921SDag-Erling Smørgrav
9158d83921SDag-Erling Smørgrav /* don't allow flags yet, unimplemented */
9258d83921SDag-Erling Smørgrav if (flags) {
9358d83921SDag-Erling Smørgrav result = ERRSET_INVAL;
9458d83921SDag-Erling Smørgrav goto fail;
9558d83921SDag-Erling Smørgrav }
9658d83921SDag-Erling Smørgrav
9758d83921SDag-Erling Smørgrav /* Initialize resolver from resolv.conf */
9858d83921SDag-Erling Smørgrav domain = ldns_dname_new_frm_str(hostname);
9958d83921SDag-Erling Smørgrav if ((err = ldns_resolver_new_frm_file(&ldns_res, NULL)) != \
10058d83921SDag-Erling Smørgrav LDNS_STATUS_OK) {
10158d83921SDag-Erling Smørgrav result = ERRSET_FAIL;
10258d83921SDag-Erling Smørgrav goto fail;
10358d83921SDag-Erling Smørgrav }
10458d83921SDag-Erling Smørgrav
10558d83921SDag-Erling Smørgrav #ifdef LDNS_DEBUG
10658d83921SDag-Erling Smørgrav ldns_resolver_set_debug(ldns_res, true);
10758d83921SDag-Erling Smørgrav #endif /* LDNS_DEBUG */
10858d83921SDag-Erling Smørgrav
10958d83921SDag-Erling Smørgrav ldns_resolver_set_dnssec(ldns_res, true); /* Use DNSSEC */
11058d83921SDag-Erling Smørgrav
11158d83921SDag-Erling Smørgrav /* make query */
11258d83921SDag-Erling Smørgrav pkt = ldns_resolver_query(ldns_res, domain, rdtype, rdclass, LDNS_RD);
11358d83921SDag-Erling Smørgrav
11458d83921SDag-Erling Smørgrav /*** TODO: finer errcodes -- see original **/
11558d83921SDag-Erling Smørgrav if (!pkt || ldns_pkt_ancount(pkt) < 1) {
11658d83921SDag-Erling Smørgrav result = ERRSET_FAIL;
11758d83921SDag-Erling Smørgrav goto fail;
11858d83921SDag-Erling Smørgrav }
11958d83921SDag-Erling Smørgrav
12058d83921SDag-Erling Smørgrav /* initialize rrset */
12158d83921SDag-Erling Smørgrav rrset = calloc(1, sizeof(struct rrsetinfo));
12258d83921SDag-Erling Smørgrav if (rrset == NULL) {
12358d83921SDag-Erling Smørgrav result = ERRSET_NOMEMORY;
12458d83921SDag-Erling Smørgrav goto fail;
12558d83921SDag-Erling Smørgrav }
12658d83921SDag-Erling Smørgrav
12758d83921SDag-Erling Smørgrav rrdata = ldns_pkt_rr_list_by_type(pkt, rdtype, LDNS_SECTION_ANSWER);
12858d83921SDag-Erling Smørgrav rrset->rri_nrdatas = ldns_rr_list_rr_count(rrdata);
12958d83921SDag-Erling Smørgrav if (!rrset->rri_nrdatas) {
13058d83921SDag-Erling Smørgrav result = ERRSET_NODATA;
13158d83921SDag-Erling Smørgrav goto fail;
13258d83921SDag-Erling Smørgrav }
13358d83921SDag-Erling Smørgrav
13458d83921SDag-Erling Smørgrav /* copy name from answer section */
13558d83921SDag-Erling Smørgrav len = ldns_rdf_size(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0)));
13658d83921SDag-Erling Smørgrav if ((rrset->rri_name = malloc(len)) == NULL) {
13758d83921SDag-Erling Smørgrav result = ERRSET_NOMEMORY;
13858d83921SDag-Erling Smørgrav goto fail;
13958d83921SDag-Erling Smørgrav }
14058d83921SDag-Erling Smørgrav memcpy(rrset->rri_name,
14158d83921SDag-Erling Smørgrav ldns_rdf_data(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0))), len);
14258d83921SDag-Erling Smørgrav
14358d83921SDag-Erling Smørgrav rrset->rri_rdclass = ldns_rr_get_class(ldns_rr_list_rr(rrdata, 0));
14458d83921SDag-Erling Smørgrav rrset->rri_rdtype = ldns_rr_get_type(ldns_rr_list_rr(rrdata, 0));
14558d83921SDag-Erling Smørgrav rrset->rri_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrdata, 0));
14658d83921SDag-Erling Smørgrav
14758d83921SDag-Erling Smørgrav debug2("ldns: got %u answers from DNS", rrset->rri_nrdatas);
14858d83921SDag-Erling Smørgrav
14958d83921SDag-Erling Smørgrav /* Check for authenticated data */
15058d83921SDag-Erling Smørgrav if (ldns_pkt_ad(pkt)) {
15158d83921SDag-Erling Smørgrav rrset->rri_flags |= RRSET_VALIDATED;
15258d83921SDag-Erling Smørgrav } else { /* AD is not set, try autonomous validation */
15358d83921SDag-Erling Smørgrav ldns_rr_list * trusted_keys = ldns_rr_list_new();
15458d83921SDag-Erling Smørgrav
15558d83921SDag-Erling Smørgrav debug2("ldns: trying to validate RRset");
15658d83921SDag-Erling Smørgrav /* Get eventual sigs */
15758d83921SDag-Erling Smørgrav rrsigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG,
15858d83921SDag-Erling Smørgrav LDNS_SECTION_ANSWER);
15958d83921SDag-Erling Smørgrav
16058d83921SDag-Erling Smørgrav rrset->rri_nsigs = ldns_rr_list_rr_count(rrsigs);
16158d83921SDag-Erling Smørgrav debug2("ldns: got %u signature(s) (RRTYPE %u) from DNS",
16258d83921SDag-Erling Smørgrav rrset->rri_nsigs, LDNS_RR_TYPE_RRSIG);
16358d83921SDag-Erling Smørgrav
16458d83921SDag-Erling Smørgrav if ((err = ldns_verify_trusted(ldns_res, rrdata, rrsigs,
16558d83921SDag-Erling Smørgrav trusted_keys)) == LDNS_STATUS_OK) {
16658d83921SDag-Erling Smørgrav rrset->rri_flags |= RRSET_VALIDATED;
16758d83921SDag-Erling Smørgrav debug2("ldns: RRset is signed with a valid key");
16858d83921SDag-Erling Smørgrav } else {
16958d83921SDag-Erling Smørgrav debug2("ldns: RRset validation failed: %s",
17058d83921SDag-Erling Smørgrav ldns_get_errorstr_by_id(err));
17158d83921SDag-Erling Smørgrav }
17258d83921SDag-Erling Smørgrav
17358d83921SDag-Erling Smørgrav ldns_rr_list_deep_free(trusted_keys);
17458d83921SDag-Erling Smørgrav }
17558d83921SDag-Erling Smørgrav
17658d83921SDag-Erling Smørgrav /* allocate memory for answers */
17758d83921SDag-Erling Smørgrav rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
17858d83921SDag-Erling Smørgrav sizeof(struct rdatainfo));
17958d83921SDag-Erling Smørgrav
18058d83921SDag-Erling Smørgrav if (rrset->rri_rdatas == NULL) {
18158d83921SDag-Erling Smørgrav result = ERRSET_NOMEMORY;
18258d83921SDag-Erling Smørgrav goto fail;
18358d83921SDag-Erling Smørgrav }
18458d83921SDag-Erling Smørgrav
18558d83921SDag-Erling Smørgrav /* allocate memory for signatures */
18658d83921SDag-Erling Smørgrav if (rrset->rri_nsigs > 0) {
18758d83921SDag-Erling Smørgrav rrset->rri_sigs = calloc(rrset->rri_nsigs,
18858d83921SDag-Erling Smørgrav sizeof(struct rdatainfo));
18958d83921SDag-Erling Smørgrav
19058d83921SDag-Erling Smørgrav if (rrset->rri_sigs == NULL) {
19158d83921SDag-Erling Smørgrav result = ERRSET_NOMEMORY;
19258d83921SDag-Erling Smørgrav goto fail;
19358d83921SDag-Erling Smørgrav }
19458d83921SDag-Erling Smørgrav }
19558d83921SDag-Erling Smørgrav
19658d83921SDag-Erling Smørgrav /* copy answers & signatures */
19758d83921SDag-Erling Smørgrav for (i=0, index_ans=0, index_sig=0; i< pkt->_header->_ancount; i++) {
19858d83921SDag-Erling Smørgrav rdata = NULL;
19958d83921SDag-Erling Smørgrav rr = ldns_rr_list_rr(ldns_pkt_answer(pkt), i);
20058d83921SDag-Erling Smørgrav
20158d83921SDag-Erling Smørgrav if (ldns_rr_get_class(rr) == rrset->rri_rdclass &&
20258d83921SDag-Erling Smørgrav ldns_rr_get_type(rr) == rrset->rri_rdtype) {
20358d83921SDag-Erling Smørgrav rdata = &rrset->rri_rdatas[index_ans++];
20458d83921SDag-Erling Smørgrav }
20558d83921SDag-Erling Smørgrav
20658d83921SDag-Erling Smørgrav if (rr->_rr_class == rrset->rri_rdclass &&
20758d83921SDag-Erling Smørgrav rr->_rr_type == LDNS_RR_TYPE_RRSIG &&
20858d83921SDag-Erling Smørgrav rrset->rri_sigs) {
20958d83921SDag-Erling Smørgrav rdata = &rrset->rri_sigs[index_sig++];
21058d83921SDag-Erling Smørgrav }
21158d83921SDag-Erling Smørgrav
21258d83921SDag-Erling Smørgrav if (rdata) {
21358d83921SDag-Erling Smørgrav size_t rdata_offset = 0;
21458d83921SDag-Erling Smørgrav
21558d83921SDag-Erling Smørgrav rdata->rdi_length = 0;
21658d83921SDag-Erling Smørgrav for (j=0; j< rr->_rd_count; j++) {
21758d83921SDag-Erling Smørgrav rdata->rdi_length +=
21858d83921SDag-Erling Smørgrav ldns_rdf_size(ldns_rr_rdf(rr, j));
21958d83921SDag-Erling Smørgrav }
22058d83921SDag-Erling Smørgrav
22158d83921SDag-Erling Smørgrav rdata->rdi_data = malloc(rdata->rdi_length);
22258d83921SDag-Erling Smørgrav if (rdata->rdi_data == NULL) {
22358d83921SDag-Erling Smørgrav result = ERRSET_NOMEMORY;
22458d83921SDag-Erling Smørgrav goto fail;
22558d83921SDag-Erling Smørgrav }
22658d83921SDag-Erling Smørgrav
22758d83921SDag-Erling Smørgrav /* Re-create the raw DNS RDATA */
22858d83921SDag-Erling Smørgrav for (j=0; j< rr->_rd_count; j++) {
22958d83921SDag-Erling Smørgrav len = ldns_rdf_size(ldns_rr_rdf(rr, j));
23058d83921SDag-Erling Smørgrav memcpy(rdata->rdi_data + rdata_offset,
23158d83921SDag-Erling Smørgrav ldns_rdf_data(ldns_rr_rdf(rr, j)), len);
23258d83921SDag-Erling Smørgrav rdata_offset += len;
23358d83921SDag-Erling Smørgrav }
23458d83921SDag-Erling Smørgrav }
23558d83921SDag-Erling Smørgrav }
23658d83921SDag-Erling Smørgrav
23758d83921SDag-Erling Smørgrav *res = rrset;
23858d83921SDag-Erling Smørgrav result = ERRSET_SUCCESS;
23958d83921SDag-Erling Smørgrav
24058d83921SDag-Erling Smørgrav fail:
24158d83921SDag-Erling Smørgrav /* freerrset(rrset); */
24258d83921SDag-Erling Smørgrav ldns_rdf_deep_free(domain);
24358d83921SDag-Erling Smørgrav ldns_pkt_free(pkt);
24458d83921SDag-Erling Smørgrav ldns_rr_list_deep_free(rrsigs);
24558d83921SDag-Erling Smørgrav ldns_rr_list_deep_free(rrdata);
24658d83921SDag-Erling Smørgrav ldns_resolver_deep_free(ldns_res);
24758d83921SDag-Erling Smørgrav
24858d83921SDag-Erling Smørgrav return result;
24958d83921SDag-Erling Smørgrav }
25058d83921SDag-Erling Smørgrav
25158d83921SDag-Erling Smørgrav
25258d83921SDag-Erling Smørgrav void
freerrset(struct rrsetinfo * rrset)25358d83921SDag-Erling Smørgrav freerrset(struct rrsetinfo *rrset)
25458d83921SDag-Erling Smørgrav {
25558d83921SDag-Erling Smørgrav u_int16_t i;
25658d83921SDag-Erling Smørgrav
25758d83921SDag-Erling Smørgrav if (rrset == NULL)
25858d83921SDag-Erling Smørgrav return;
25958d83921SDag-Erling Smørgrav
26058d83921SDag-Erling Smørgrav if (rrset->rri_rdatas) {
26158d83921SDag-Erling Smørgrav for (i = 0; i < rrset->rri_nrdatas; i++) {
26258d83921SDag-Erling Smørgrav if (rrset->rri_rdatas[i].rdi_data == NULL)
26358d83921SDag-Erling Smørgrav break;
26458d83921SDag-Erling Smørgrav free(rrset->rri_rdatas[i].rdi_data);
26558d83921SDag-Erling Smørgrav }
26658d83921SDag-Erling Smørgrav free(rrset->rri_rdatas);
26758d83921SDag-Erling Smørgrav }
26858d83921SDag-Erling Smørgrav
26958d83921SDag-Erling Smørgrav if (rrset->rri_sigs) {
27058d83921SDag-Erling Smørgrav for (i = 0; i < rrset->rri_nsigs; i++) {
27158d83921SDag-Erling Smørgrav if (rrset->rri_sigs[i].rdi_data == NULL)
27258d83921SDag-Erling Smørgrav break;
27358d83921SDag-Erling Smørgrav free(rrset->rri_sigs[i].rdi_data);
27458d83921SDag-Erling Smørgrav }
27558d83921SDag-Erling Smørgrav free(rrset->rri_sigs);
27658d83921SDag-Erling Smørgrav }
27758d83921SDag-Erling Smørgrav
27858d83921SDag-Erling Smørgrav if (rrset->rri_name)
27958d83921SDag-Erling Smørgrav free(rrset->rri_name);
28058d83921SDag-Erling Smørgrav free(rrset);
28158d83921SDag-Erling Smørgrav }
28258d83921SDag-Erling Smørgrav
28358d83921SDag-Erling Smørgrav
28458d83921SDag-Erling Smørgrav #endif /* !defined (HAVE_GETRRSETBYNAME) && defined (HAVE_LDNS) */
285