/** setup qinfo and edns */ static int setup_qinfo_edns(struct libworker* w, struct ctx_query* q, struct query_info* qinfo, struct edns_data* edns) { ldns_rdf* rdf; qinfo->qtype = (uint16_t)q->res->qtype; qinfo->qclass = (uint16_t)q->res->qclass; rdf = ldns_dname_new_frm_str(q->res->qname); if(!rdf) { return 0; } #ifdef UNBOUND_ALLOC_LITE qinfo->qname = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf)); qinfo->qname_len = ldns_rdf_size(rdf); ldns_rdf_deep_free(rdf); rdf = 0; #else qinfo->qname = ldns_rdf_data(rdf); qinfo->qname_len = ldns_rdf_size(rdf); #endif edns->edns_present = 1; edns->ext_rcode = 0; edns->edns_version = 0; edns->bits = EDNS_DO; if(ldns_buffer_capacity(w->back->udp_buff) < 65535) edns->udp_size = (uint16_t)ldns_buffer_capacity( w->back->udp_buff); else edns->udp_size = 65535; ldns_rdf_free(rdf); return 1; }
/** * Add new RR. It converts ldns RR to wire format. * @param anchors: anchor storage. * @param buffer: parsing buffer. * @param rr: the rr (allocated by caller). * @return NULL on error, else the trust anchor. */ static struct trust_anchor* anchor_store_new_rr(struct val_anchors* anchors, ldns_buffer* buffer, ldns_rr* rr) { struct trust_anchor* ta; ldns_rdf* owner = ldns_rr_owner(rr); ldns_status status; ldns_buffer_clear(buffer); ldns_buffer_skip(buffer, 2); /* skip rdatalen */ status = ldns_rr_rdata2buffer_wire(buffer, rr); if(status != LDNS_STATUS_OK) { log_err("error converting trustanchor to wireformat: %s", ldns_get_errorstr_by_id(status)); return NULL; } ldns_buffer_flip(buffer); ldns_buffer_write_u16_at(buffer, 0, ldns_buffer_limit(buffer) - 2); if(!(ta=anchor_store_new_key(anchors, ldns_rdf_data(owner), ldns_rr_get_type(rr), ldns_rr_get_class(rr), ldns_buffer_begin(buffer), ldns_buffer_limit(buffer)))) { return NULL; } log_nametypeclass(VERB_QUERY, "adding trusted key", ldns_rdf_data(owner), ldns_rr_get_type(rr), ldns_rr_get_class(rr)); return ta; }
/** * 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; }
ldns_status ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf) { if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf)); } return ldns_buffer_status(buffer); }
ldns_status ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name) { if (ldns_buffer_reserve(buffer, ldns_rdf_size(name))) { ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name)); } return ldns_buffer_status(buffer); }
/* put this here tmp. for debugging */ void xprintf_rdf(ldns_rdf *rd) { /* assume printable string */ fprintf(stderr, "size\t:%u\n", (unsigned int)ldns_rdf_size(rd)); fprintf(stderr, "type\t:%u\n", (unsigned int)ldns_rdf_get_type(rd)); fprintf(stderr, "data\t:[%.*s]\n", (int)ldns_rdf_size(rd), (char*)ldns_rdf_data(rd)); }
/** add hint to delegation hints */ static int ah(struct delegpt* dp, const char* sv, const char* ip) { struct sockaddr_storage addr; socklen_t addrlen; ldns_rdf* rdf = ldns_dname_new_frm_str(sv); if(!rdf) { log_err("could not parse %s", sv); return 0; } if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0) || !extstrtoaddr(ip, &addr, &addrlen) || !delegpt_add_target_mlc(dp, ldns_rdf_data(rdf), ldns_rdf_size(rdf), &addr, addrlen, 0, 0)) { ldns_rdf_deep_free(rdf); return 0; } ldns_rdf_deep_free(rdf); return 1; }
size_t ldns_rr_dnskey_key_size(const ldns_rr *key) { if (!key || !ldns_rr_dnskey_key(key) || !ldns_rr_dnskey_algorithm(key)) { return 0; } return ldns_rr_dnskey_key_size_raw((unsigned char*)ldns_rdf_data(ldns_rr_dnskey_key(key)), ldns_rdf_size(ldns_rr_dnskey_key(key)), ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(key)) ); }
/* Returns whether the last label in the name is a root label (a empty label). * Note that it is not enough to just test the last character to be 0, * because it may be part of the last label itself. */ static bool ldns_dname_last_label_is_root_label(const ldns_rdf* dname) { size_t src_pos; size_t len = 0; for (src_pos = 0; src_pos < ldns_rdf_size(dname); src_pos += len + 1) { len = ldns_rdf_data(dname)[src_pos]; } assert(src_pos == ldns_rdf_size(dname)); return src_pos > 0 && len == 0; }
/* code from rdata.c */ static struct sockaddr_storage * ldns_rdf2native_sockaddr_storage_port( const ldns_rdf *rd, uint16_t port, size_t *size) { struct sockaddr_storage *data; struct sockaddr_in *data_in; struct sockaddr_in6 *data_in6; data = LDNS_MALLOC(struct sockaddr_storage); if (!data) { return NULL; } /* zero the structure for portability */ memset(data, 0, sizeof(struct sockaddr_storage)); switch(ldns_rdf_get_type(rd)) { case LDNS_RDF_TYPE_A: #ifndef S_SPLINT_S data->ss_family = AF_INET; #endif data_in = (struct sockaddr_in*) data; data_in->sin_port = (in_port_t)htons(port); memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd)); *size = sizeof(struct sockaddr_in); return data; case LDNS_RDF_TYPE_AAAA: #ifndef S_SPLINT_S data->ss_family = AF_INET6; #endif data_in6 = (struct sockaddr_in6*) data; data_in6->sin6_port = (in_port_t)htons(port); memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd)); *size = sizeof(struct sockaddr_in6); return data; default: LDNS_FREE(data); return NULL; } }
/** * Insert insecure anchor * @param anchors: anchor storage. * @param str: the domain name. * @return NULL on error, Else last trust anchor point */ static struct trust_anchor* anchor_insert_insecure(struct val_anchors* anchors, const char* str) { struct trust_anchor* ta; ldns_rdf* nm = ldns_dname_new_frm_str(str); if(!nm) { log_err("parse error in domain name '%s'", str); return NULL; } ta = anchor_store_new_key(anchors, ldns_rdf_data(nm), LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, NULL, 0); ldns_rdf_deep_free(nm); return ta; }
/** process nsec3 params and perform hashing */ static void process_nsec3(int argc, char* argv[]) { char line[10240]; ldns_rdf* salt; ldns_rdf* in, *out; ldns_status status; status = ldns_str2rdf_nsec3_salt(&salt, argv[5]); if(status != LDNS_STATUS_OK) fatal_exit("Could not parse salt %s: %s", argv[5], ldns_get_errorstr_by_id(status)); log_assert(argc == 6); while(fgets(line, (int)sizeof(line), stdin)) { if(strlen(line) > 0) line[strlen(line)-1] = 0; /* remove trailing newline */ if(line[0]==0) continue; status = ldns_str2rdf_dname(&in, line); if(status != LDNS_STATUS_OK) fatal_exit("Could not parse name %s: %s", line, ldns_get_errorstr_by_id(status)); ldns_rdf_print(stdout, in); printf(" -> "); /* arg 3 is flags, unused */ out = ldns_nsec3_hash_name(in, (uint8_t)atoi(argv[2]), (uint16_t)atoi(argv[4]), ldns_rdf_data(salt)[0], ldns_rdf_data(salt)+1); if(!out) fatal_exit("Could not hash %s", line); ldns_rdf_print(stdout, out); printf("\n"); ldns_rdf_deep_free(in); ldns_rdf_deep_free(out); } ldns_rdf_deep_free(salt); }
ldns_status ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf) { size_t i; uint8_t *rdf_data; if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) { if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { rdf_data = ldns_rdf_data(rdf); for (i = 0; i < ldns_rdf_size(rdf); i++) { ldns_buffer_write_u8(buffer, LDNS_DNAME_NORMALIZE(rdf_data[i])); } } } else { /* direct copy for all other types */ if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf)); } } return ldns_buffer_status(buffer); }
getdns_return_t getdns_convert_fqdn_to_dns_name( const char *fqdn_as_string, struct getdns_bindata **dns_name_wire_fmt) { ldns_rdf *rdf; if (ldns_str2rdf_dname(&rdf, fqdn_as_string) != LDNS_STATUS_OK) return GETDNS_RETURN_GENERIC_ERROR;; *dns_name_wire_fmt = malloc(sizeof(struct getdns_bindata)); if (*dns_name_wire_fmt) { (*dns_name_wire_fmt)->size = ldns_rdf_size(rdf); (*dns_name_wire_fmt)->data = ldns_rdf_data(rdf); } ldns_rdf_free(rdf); return *dns_name_wire_fmt ? GETDNS_RETURN_GOOD : GETDNS_RETURN_MEMORY_ERROR; }
/** Match q edns data to p raw edns data */ static int match_ednsdata(ldns_pkt* q, struct reply_packet* p) { size_t qdlen, pdlen; uint8_t *qd, *pd; if(!ldns_pkt_edns(q) || !ldns_pkt_edns_data(q)) { verbose(3, "No EDNS data\n"); return 0; } qdlen = ldns_rdf_size(ldns_pkt_edns_data(q)); pdlen = ldns_buffer_limit(p->raw_ednsdata); qd = ldns_rdf_data(ldns_pkt_edns_data(q)); pd = ldns_buffer_begin(p->raw_ednsdata); if( qdlen == pdlen && 0 == memcmp(qd, pd, qdlen) ) return 1; verbose(3, "EDNS data does not match.\n"); verbose_hex(3, qd, qdlen, "q:"); verbose_hex(3, pd, pdlen, "p:"); return 0; }
/** make NULL entries for stubs */ static int make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg) { struct config_stub* s; for(s = cfg->stubs; s; s = s->next) { ldns_rdf* rdf = ldns_dname_new_frm_str(s->name); if(!rdf) { log_err("cannot parse stub name '%s'", s->name); return 0; } if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, ldns_rdf_data(rdf))) { ldns_rdf_deep_free(rdf); log_err("out of memory"); return 0; } ldns_rdf_deep_free(rdf); } return 1; }
ldns_status ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name, uint16_t port, ldns_dane_transport transport) { char buf[LDNS_MAX_DOMAINLEN]; size_t s; assert(tlsa_owner != NULL); assert(name != NULL); assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME); s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port); buf[0] = (char)(s - 1); switch(transport) { case LDNS_DANE_TRANSPORT_TCP: s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp"); break; case LDNS_DANE_TRANSPORT_UDP: s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp"); break; case LDNS_DANE_TRANSPORT_SCTP: s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp"); break; default: return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT; } if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) { return LDNS_STATUS_DOMAINNAME_OVERFLOW; } memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name)); *tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, s + ldns_rdf_size(name), buf); if (*tlsa_owner == NULL) { return LDNS_STATUS_MEM_ERR; } return LDNS_STATUS_OK; }
/** parse commandline argument domain name */ static int parse_arg_name(SSL* ssl, char* str, uint8_t** res, size_t* len, int* labs) { ldns_rdf* rdf; *res = NULL; *len = 0; *labs = 0; rdf = ldns_dname_new_frm_str(str); if(!rdf) { ssl_printf(ssl, "error cannot parse name %s\n", str); return 0; } *res = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf)); ldns_rdf_deep_free(rdf); if(!*res) { ssl_printf(ssl, "error out of memory\n"); return 0; } *labs = dname_count_size_labels(*res, len); return 1; }
/** set stub host names */ static int read_stubs_host(struct config_stub* s, struct delegpt* dp) { struct config_strlist* p; ldns_rdf* rdf; for(p = s->hosts; p; p = p->next) { log_assert(p->str); rdf = ldns_dname_new_frm_str(p->str); if(!rdf) { log_err("cannot parse stub %s nameserver name: '%s'", s->name, p->str); return 0; } if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0)) { ldns_rdf_deep_free(rdf); log_err("out of memory"); return 0; } ldns_rdf_deep_free(rdf); } return 1; }
/** set stub name */ static struct delegpt* read_stubs_name(struct config_stub* s) { struct delegpt* dp; ldns_rdf* rdf; if(!s->name) { log_err("stub zone without a name"); return NULL; } rdf = ldns_dname_new_frm_str(s->name); if(!rdf) { log_err("cannot parse stub zone name %s", s->name); return NULL; } if(!(dp=delegpt_create_mlc(ldns_rdf_data(rdf)))) { ldns_rdf_deep_free(rdf); log_err("out of memory"); return NULL; } ldns_rdf_deep_free(rdf); return dp; }
/** read root hints from file */ static int read_root_hints(struct iter_hints* hints, char* fname) { int lineno = 0; uint32_t default_ttl = 0; ldns_rdf* origin = NULL; ldns_rdf* prev_rr = NULL; struct delegpt* dp; ldns_rr* rr = NULL; ldns_status status; uint16_t c = LDNS_RR_CLASS_IN; FILE* f = fopen(fname, "r"); if(!f) { log_err("could not read root hints %s: %s", fname, strerror(errno)); return 0; } dp = delegpt_create_mlc(NULL); if(!dp) { log_err("out of memory reading root hints"); fclose(f); return 0; } verbose(VERB_QUERY, "Reading root hints from %s", fname); dp->has_parent_side_NS = 1; while(!feof(f)) { status = ldns_rr_new_frm_fp_l(&rr, f, &default_ttl, &origin, &prev_rr, &lineno); if(status == LDNS_STATUS_SYNTAX_EMPTY || status == LDNS_STATUS_SYNTAX_TTL || status == LDNS_STATUS_SYNTAX_ORIGIN) continue; if(status != LDNS_STATUS_OK) { log_err("reading root hints %s %d: %s", fname, lineno, ldns_get_errorstr_by_id(status)); goto stop_read; } if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) { if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(ldns_rr_rdf(rr, 0)), 0)) { log_err("out of memory reading root hints"); goto stop_read; } c = ldns_rr_get_class(rr); if(!dp->name) { if(!delegpt_set_name_mlc(dp, ldns_rdf_data(ldns_rr_owner(rr)))){ log_err("out of memory."); goto stop_read; } } } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_A) { struct sockaddr_in sa; socklen_t len = (socklen_t)sizeof(sa); memset(&sa, 0, len); sa.sin_family = AF_INET; sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); memmove(&sa.sin_addr, ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET_SIZE); if(!delegpt_add_target_mlc(dp, ldns_rdf_data(ldns_rr_owner(rr)), ldns_rdf_size(ldns_rr_owner(rr)), (struct sockaddr_storage*)&sa, len, 0, 0)) { log_err("out of memory reading root hints"); goto stop_read; } } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) { struct sockaddr_in6 sa; socklen_t len = (socklen_t)sizeof(sa); memset(&sa, 0, len); sa.sin6_family = AF_INET6; sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); memmove(&sa.sin6_addr, ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET6_SIZE); if(!delegpt_add_target_mlc(dp, ldns_rdf_data(ldns_rr_owner(rr)), ldns_rdf_size(ldns_rr_owner(rr)), (struct sockaddr_storage*)&sa, len, 0, 0)) { log_err("out of memory reading root hints"); goto stop_read; } } else { log_warn("root hints %s:%d skipping type %d", fname, lineno, ldns_rr_get_type(rr)); } ldns_rr_free(rr); } if (origin) ldns_rdf_deep_free(origin); if (prev_rr) ldns_rdf_deep_free(prev_rr); fclose(f); if(!dp->name) { log_warn("root hints %s: no NS content", fname); delegpt_free_mlc(dp); return 1; } if(!hints_insert(hints, c, dp, 0)) { return 0; } delegpt_log(VERB_QUERY, dp); return 1; stop_read: if (origin) ldns_rdf_deep_free(origin); if (prev_rr) ldns_rdf_deep_free(prev_rr); delegpt_free_mlc(dp); fclose(f); return 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; }
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; }
int main(int argc, char *argv[]) { FILE *keyfp; char *keyname; ldns_rr *k; uint16_t flags; char *program = argv[0]; int nofile = 0; ldns_rdf *origin = NULL; ldns_status result; argv++, argc--; while (argc && argv[0][0] == '-') { if (strcmp(argv[0], "-n") == 0) { nofile=1; } else { usage(stderr, program); exit(EXIT_FAILURE); } argv++, argc--; } if (argc != 1) { usage(stderr, program); exit(EXIT_FAILURE); } keyname = strdup(argv[0]); keyfp = fopen(keyname, "r"); if (!keyfp) { fprintf(stderr, "Failed to open public key file %s: %s\n", keyname, strerror(errno)); exit(EXIT_FAILURE); } result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL); /* what does this while loop do? */ while (result == LDNS_STATUS_SYNTAX_ORIGIN) { result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL); } if (result != LDNS_STATUS_OK) { fprintf(stderr, "Could not read public key from file %s: %s\n", keyname, ldns_get_errorstr_by_id(result)); exit(EXIT_FAILURE); } fclose(keyfp); flags = ldns_read_uint16(ldns_rdf_data(ldns_rr_dnskey_flags(k))); flags |= LDNS_KEY_REVOKE_KEY; if (!ldns_rr_dnskey_set_flags(k, ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, flags))) { fprintf(stderr, "Revocation failed\n"); exit(EXIT_FAILURE); } /* print the public key RR to .key */ if (nofile) ldns_rr_print(stdout,k); else { keyfp = fopen(keyname, "w"); if (!keyfp) { fprintf(stderr, "Unable to open %s: %s\n", keyname, strerror(errno)); exit(EXIT_FAILURE); } else { ldns_rr_print(keyfp, k); fclose(keyfp); fprintf(stdout, "DNSKEY revoked\n"); } } free(keyname); ldns_rr_free(k); exit(EXIT_SUCCESS); }