static inline isc_boolean_t checkowner_in_a(ARGS_CHECKOWNER) { dns_name_t prefix, suffix; REQUIRE(type == dns_rdatatype_a); REQUIRE(rdclass == dns_rdataclass_in); UNUSED(type); UNUSED(rdclass); /* * Handle Active Diretory gc._msdcs.<forest> name. */ if (dns_name_countlabels(name) > 2U) { dns_name_init(&prefix, NULL); dns_name_init(&suffix, NULL); dns_name_split(name, dns_name_countlabels(name) - 2, &prefix, &suffix); if (dns_name_equal(&gc_msdcs, &prefix) && dns_name_ishostname(&suffix, ISC_FALSE)) return (ISC_TRUE); } return (dns_name_ishostname(name, wildcard)); }
void dns_compress_add(dns_compress_t *cctx, const dns_name_t *name, const dns_name_t *prefix, isc_uint16_t offset) { dns_name_t tname; unsigned int start; unsigned int n; unsigned int count; unsigned int hash; dns_compressnode_t *node; unsigned int length; unsigned int tlength; isc_uint16_t toffset; REQUIRE(VALID_CCTX(cctx)); REQUIRE(dns_name_isabsolute(name)); dns_name_init(&tname, NULL); n = dns_name_countlabels(name); count = dns_name_countlabels(prefix); if (dns_name_isabsolute(prefix)) count--; start = 0; length = name_length(name); while (count > 0) { if (offset >= 0x4000) break; dns_name_getlabelsequence(name, start, n, &tname); hash = dns_name_hash(&tname, ISC_FALSE) % DNS_COMPRESS_TABLESIZE; tlength = name_length(&tname); toffset = (isc_uint16_t)(offset + (length - tlength)); /* * Create a new node and add it. */ if (cctx->count < DNS_COMPRESS_INITIALNODES) node = &cctx->initialnodes[cctx->count]; else { node = isc_mem_get(cctx->mctx, sizeof(dns_compressnode_t)); if (node == NULL) return; } node->count = cctx->count++; node->offset = toffset; dns_name_toregion(&tname, &node->r); node->labels = (isc_uint8_t)dns_name_countlabels(&tname); node->next = cctx->table[hash]; cctx->table[hash] = node; start++; n--; count--; } }
static void print_name (dns_name_t * name) { isc_result_t result; isc_buffer_t source; isc_region_t r; char s[1000]; isc_buffer_init (&source, s, sizeof (s)); if (dns_name_countlabels (name) > 0) result = dns_name_totext (name, ISC_FALSE, &source); else result = ISC_R_SUCCESS; if (result == ISC_R_SUCCESS) { isc_buffer_usedregion (&source, &r); if (r.length > 0) printf ("%.*s\n", (int) r.length, r.base); else printf ("<empty text name>\n"); } else printf ("error: %s\n", dns_result_totext (result)); }
static inline void name_to_gbuffer(dns_name_t *name, isc_buffer_t *buffer, gss_buffer_desc *gbuffer) { dns_name_t tname, *namep; isc_region_t r; isc_result_t result; if (!dns_name_isabsolute(name)) namep = name; else { unsigned int labels; dns_name_init(&tname, NULL); labels = dns_name_countlabels(name); dns_name_getlabelsequence(name, 0, labels - 1, &tname); namep = &tname; } result = dns_name_toprincipal(namep, buffer); RUNTIME_CHECK(result == ISC_R_SUCCESS); isc_buffer_putuint8(buffer, 0); isc_buffer_usedregion(buffer, &r); REGION_TO_GBUFFER(r, *gbuffer); }
isc_result_t dns_dlzfindzone(dns_view_t *view, dns_name_t *name, unsigned int minlabels, dns_db_t **dbp) { dns_fixedname_t fname; dns_name_t *zonename; unsigned int namelabels; unsigned int i; isc_result_t result; dns_dlzfindzone_t findzone; dns_dlzdb_t *dlzdatabase; /* * Performs checks to make sure data is as we expect it to be. */ REQUIRE(DNS_DLZ_VALID(view->dlzdatabase)); REQUIRE(name != NULL); REQUIRE(dbp != NULL && *dbp == NULL); /* setup a "fixed" dns name */ dns_fixedname_init(&fname); zonename = dns_fixedname_name(&fname); /* count the number of labels in the name */ namelabels = dns_name_countlabels(name); /* * loop through starting with the longest domain name and * trying shorter names portions of the name until we find a * match, have an error, or are below the 'minlabels' * threshold. minlabels is 0, if the standard database didn't * have a zone name match. Otherwise minlabels is the number * of labels in that name. We need to beat that for a * "better" match for the DLZ database to be authoritative * instead of the standard database. */ for (i = namelabels; i > minlabels && i > 1; i--) { if (i == namelabels) { result = dns_name_copy(name, zonename, NULL); if (result != ISC_R_SUCCESS) return (result); } else dns_name_split(name, i, NULL, zonename); /* ask SDLZ driver if the zone is supported */ dlzdatabase = view->dlzdatabase; findzone = dlzdatabase->implementation->methods->findzone; result = (*findzone)(dlzdatabase->implementation->driverarg, dlzdatabase->dbdata, dlzdatabase->mctx, view->rdclass, zonename, dbp); if (result != ISC_R_NOTFOUND) return (result); } return (ISC_R_NOTFOUND); }
/* * Find the longest match of name in the table. * If match is found return ISC_TRUE. prefix, suffix and offset are updated. * If no match is found return ISC_FALSE. */ isc_boolean_t dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name, dns_name_t *prefix, isc_uint16_t *offset) { dns_name_t tname, nname; dns_compressnode_t *node = NULL; unsigned int labels, hash, n; REQUIRE(VALID_CCTX(cctx)); REQUIRE(dns_name_isabsolute(name) == ISC_TRUE); REQUIRE(offset != NULL); if (cctx->count == 0) return (ISC_FALSE); labels = dns_name_countlabels(name); INSIST(labels > 0); dns_name_init(&tname, NULL); dns_name_init(&nname, NULL); for (n = 0; n < labels - 1; n++) { dns_name_getlabelsequence(name, n, labels - n, &tname); hash = dns_name_hash(&tname, ISC_FALSE) % DNS_COMPRESS_TABLESIZE; for (node = cctx->table[hash]; node != NULL; node = node->next) { NODENAME(node, &nname); if ((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0) { if (dns_name_caseequal(&nname, &tname)) break; } else { if (dns_name_equal(&nname, &tname)) break; } } if (node != NULL) break; } /* * If node == NULL, we found no match at all. */ if (node == NULL) return (ISC_FALSE); if (n == 0) dns_name_reset(prefix); else dns_name_getlabelsequence(name, 0, n, prefix); *offset = node->offset; return (ISC_TRUE); }
isc_result_t dnsname_to_dn(zone_register_t *zr, dns_name_t *name, dns_name_t *zone, ld_string_t *target) { isc_result_t result; int label_count; const char *zone_dn = NULL; char *dns_str = NULL; char *escaped_name = NULL; int dummy; dns_name_t labels; unsigned int common_labels; dns_namereln_t namereln; REQUIRE(zr != NULL); REQUIRE(name != NULL); REQUIRE(target != NULL); isc_mem_t * mctx = zr_get_mctx(zr); str_clear(target); /* Find the DN of the zone we belong to. */ CHECK(zr_get_zone_dn(zr, zone, &zone_dn)); namereln = dns_name_fullcompare(name, zone, &dummy, &common_labels); if (namereln != dns_namereln_equal) { label_count = dns_name_countlabels(name) - common_labels; dns_name_init(&labels, NULL); dns_name_getlabelsequence(name, 0, label_count, &labels); CHECK(dns_name_tostring(&labels, &dns_str, mctx)); CHECK(dns_to_ldap_dn_escape(mctx, dns_str, &escaped_name)); CHECK(str_cat_char(target, "idnsName=")); CHECK(str_cat_char(target, escaped_name)); /* * Modification of following line can affect modify_ldap_common(). * See line with: char *zone_dn = strstr(str_buf(owner_dn),", ") + 1; */ CHECK(str_cat_char(target, ", ")); } CHECK(str_cat_char(target, zone_dn)); cleanup: if (dns_str) isc_mem_free(mctx, dns_str); if (escaped_name) isc_mem_free(mctx, escaped_name); return result; }
void ns_lwsearchctx_init(ns_lwsearchctx_t *sctx, ns_lwsearchlist_t *list, dns_name_t *name, unsigned int ndots) { INSIST(sctx != NULL); sctx->relname = name; sctx->searchname = NULL; sctx->doneexact = ISC_FALSE; sctx->exactfirst = ISC_FALSE; sctx->ndots = ndots; if (dns_name_isabsolute(name) || list == NULL) { sctx->list = NULL; return; } sctx->list = list; sctx->searchname = ISC_LIST_HEAD(sctx->list->names); if (dns_name_countlabels(name) > ndots) sctx->exactfirst = ISC_TRUE; }
isc_result_t dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, isc_boolean_t ignoretime, isc_mem_t *mctx, dns_rdata_t *sigrdata, dns_name_t *wild) { dns_rdata_rrsig_t sig; dns_fixedname_t fnewname; isc_region_t r; isc_buffer_t envbuf; dns_rdata_t *rdatas; int nrdatas, i; isc_stdtime_t now; isc_result_t ret; unsigned char data[300]; dst_context_t *ctx = NULL; int labels = 0; isc_uint32_t flags; REQUIRE(name != NULL); REQUIRE(set != NULL); REQUIRE(key != NULL); REQUIRE(mctx != NULL); REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig); ret = dns_rdata_tostruct(sigrdata, &sig, NULL); if (ret != ISC_R_SUCCESS) return (ret); if (isc_serial_lt(sig.timeexpire, sig.timesigned)) return (DNS_R_SIGINVALID); if (!ignoretime) { isc_stdtime_get(&now); /* * Is SIG temporally valid? */ if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) return (DNS_R_SIGFUTURE); else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) return (DNS_R_SIGEXPIRED); } /* * Is the key allowed to sign data? */ flags = dst_key_flags(key); if (flags & DNS_KEYTYPE_NOAUTH) return (DNS_R_KEYUNAUTHORIZED); if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) return (DNS_R_KEYUNAUTHORIZED); ret = dst_context_create(key, mctx, &ctx); if (ret != ISC_R_SUCCESS) goto cleanup_struct; /* * Digest the SIG rdata (not including the signature). */ ret = digest_sig(ctx, sigrdata, &sig); if (ret != ISC_R_SUCCESS) goto cleanup_context; /* * If the name is an expanded wildcard, use the wildcard name. */ dns_fixedname_init(&fnewname); labels = dns_name_countlabels(name) - 1; RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), NULL) == ISC_R_SUCCESS); if (labels - sig.labels > 0) dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1, NULL, dns_fixedname_name(&fnewname)); dns_name_toregion(dns_fixedname_name(&fnewname), &r); /* * Create an envelope for each rdata: <name|type|class|ttl>. */ isc_buffer_init(&envbuf, data, sizeof(data)); if (labels - sig.labels > 0) { isc_buffer_putuint8(&envbuf, 1); isc_buffer_putuint8(&envbuf, '*'); memcpy(data + 2, r.base, r.length); } else memcpy(data, r.base, r.length); isc_buffer_add(&envbuf, r.length); isc_buffer_putuint16(&envbuf, set->type); isc_buffer_putuint16(&envbuf, set->rdclass); isc_buffer_putuint32(&envbuf, sig.originalttl); ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); if (ret != ISC_R_SUCCESS) goto cleanup_context; isc_buffer_usedregion(&envbuf, &r); for (i = 0; i < nrdatas; i++) { isc_uint16_t len; isc_buffer_t lenbuf; isc_region_t lenr; /* * Skip duplicates. */ if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0) continue; /* * Digest the envelope. */ ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_array; /* * Digest the rdata length. */ isc_buffer_init(&lenbuf, &len, sizeof(len)); INSIST(rdatas[i].length < 65536); isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length); isc_buffer_usedregion(&lenbuf, &lenr); /* * Digest the rdata. */ ret = dst_context_adddata(ctx, &lenr); if (ret != ISC_R_SUCCESS) goto cleanup_array; ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); if (ret != ISC_R_SUCCESS) goto cleanup_array; } r.base = sig.signature; r.length = sig.siglen; ret = dst_context_verify(ctx, &r); if (ret == DST_R_VERIFYFAILURE) ret = DNS_R_SIGINVALID; cleanup_array: isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); cleanup_context: dst_context_destroy(&ctx); cleanup_struct: dns_rdata_freestruct(&sig); if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) { if (wild != NULL) RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, dns_fixedname_name(&fnewname), wild, NULL) == ISC_R_SUCCESS); ret = DNS_R_FROMWILDCARD; } return (ret); }
isc_result_t dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, isc_stdtime_t *inception, isc_stdtime_t *expire, isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata) { dns_rdata_rrsig_t sig; dns_rdata_t tmpsigrdata; dns_rdata_t *rdatas; int nrdatas, i; isc_buffer_t sigbuf, envbuf; isc_region_t r; dst_context_t *ctx = NULL; isc_result_t ret; isc_buffer_t *databuf = NULL; char data[256 + 8]; isc_uint32_t flags; unsigned int sigsize; dns_fixedname_t fnewname; REQUIRE(name != NULL); REQUIRE(dns_name_countlabels(name) <= 255); REQUIRE(set != NULL); REQUIRE(key != NULL); REQUIRE(inception != NULL); REQUIRE(expire != NULL); REQUIRE(mctx != NULL); REQUIRE(sigrdata != NULL); if (*inception >= *expire) return (DNS_R_INVALIDTIME); /* * Is the key allowed to sign data? */ flags = dst_key_flags(key); if (flags & DNS_KEYTYPE_NOAUTH) return (DNS_R_KEYUNAUTHORIZED); if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) return (DNS_R_KEYUNAUTHORIZED); sig.mctx = mctx; sig.common.rdclass = set->rdclass; sig.common.rdtype = dns_rdatatype_rrsig; ISC_LINK_INIT(&sig.common, link); dns_name_init(&sig.signer, NULL); dns_name_clone(dst_key_name(key), &sig.signer); sig.covered = set->type; sig.algorithm = dst_key_alg(key); sig.labels = dns_name_countlabels(name) - 1; if (dns_name_iswildcard(name)) sig.labels--; sig.originalttl = set->ttl; sig.timesigned = *inception; sig.timeexpire = *expire; sig.keyid = dst_key_id(key); ret = dst_key_sigsize(key, &sigsize); if (ret != ISC_R_SUCCESS) return (ret); sig.siglen = sigsize; /* * The actual contents of sig.signature are not important yet, since * they're not used in digest_sig(). */ sig.signature = isc_mem_get(mctx, sig.siglen); if (sig.signature == NULL) return (ISC_R_NOMEMORY); ret = isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18); if (ret != ISC_R_SUCCESS) goto cleanup_signature; dns_rdata_init(&tmpsigrdata); ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass, sig.common.rdtype, &sig, databuf); if (ret != ISC_R_SUCCESS) goto cleanup_databuf; ret = dst_context_create(key, mctx, &ctx); if (ret != ISC_R_SUCCESS) goto cleanup_databuf; /* * Digest the SIG rdata. */ ret = digest_sig(ctx, &tmpsigrdata, &sig); if (ret != ISC_R_SUCCESS) goto cleanup_context; dns_fixedname_init(&fnewname); RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), NULL) == ISC_R_SUCCESS); dns_name_toregion(dns_fixedname_name(&fnewname), &r); /* * Create an envelope for each rdata: <name|type|class|ttl>. */ isc_buffer_init(&envbuf, data, sizeof(data)); memcpy(data, r.base, r.length); isc_buffer_add(&envbuf, r.length); isc_buffer_putuint16(&envbuf, set->type); isc_buffer_putuint16(&envbuf, set->rdclass); isc_buffer_putuint32(&envbuf, set->ttl); ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); if (ret != ISC_R_SUCCESS) goto cleanup_context; isc_buffer_usedregion(&envbuf, &r); for (i = 0; i < nrdatas; i++) { isc_uint16_t len; isc_buffer_t lenbuf; isc_region_t lenr; /* * Skip duplicates. */ if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0) continue; /* * Digest the envelope. */ ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_array; /* * Digest the length of the rdata. */ isc_buffer_init(&lenbuf, &len, sizeof(len)); INSIST(rdatas[i].length < 65536); isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length); isc_buffer_usedregion(&lenbuf, &lenr); ret = dst_context_adddata(ctx, &lenr); if (ret != ISC_R_SUCCESS) goto cleanup_array; /* * Digest the rdata. */ ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); if (ret != ISC_R_SUCCESS) goto cleanup_array; } isc_buffer_init(&sigbuf, sig.signature, sig.siglen); ret = dst_context_sign(ctx, &sigbuf); if (ret != ISC_R_SUCCESS) goto cleanup_array; isc_buffer_usedregion(&sigbuf, &r); if (r.length != sig.siglen) { ret = ISC_R_NOSPACE; goto cleanup_array; } memcpy(sig.signature, r.base, sig.siglen); ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass, sig.common.rdtype, &sig, buffer); cleanup_array: isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); cleanup_context: dst_context_destroy(&ctx); cleanup_databuf: isc_buffer_free(&databuf); cleanup_signature: isc_mem_put(mctx, sig.signature, sig.siglen); return (ret); }
int main(int argc, char *argv[]) { char s[1000]; isc_result_t result; dns_fixedname_t wname, wname2, oname, compname, downname; isc_buffer_t source; isc_region_t r; dns_name_t *name, *origin, *comp, *down; isc_boolean_t downcase = ISC_FALSE; size_t len; isc_boolean_t quiet = ISC_FALSE; isc_boolean_t concatenate = ISC_FALSE; isc_boolean_t got_name = ISC_FALSE; isc_boolean_t check_absolute = ISC_FALSE; isc_boolean_t check_wildcard = ISC_FALSE; isc_boolean_t test_downcase = ISC_FALSE; isc_boolean_t inplace = ISC_FALSE; isc_boolean_t want_split = ISC_FALSE; unsigned int labels, split_label = 0; dns_fixedname_t fprefix, fsuffix; dns_name_t *prefix, *suffix; int ch; while ((ch = isc_commandline_parse(argc, argv, "acdiqs:w")) != -1) { switch (ch) { case 'a': check_absolute = ISC_TRUE; break; case 'c': concatenate = ISC_TRUE; break; case 'd': test_downcase = ISC_TRUE; break; case 'i': inplace = ISC_TRUE; break; case 'q': quiet = ISC_TRUE; break; case 's': want_split = ISC_TRUE; split_label = atoi(isc_commandline_argument); break; case 'w': check_wildcard = ISC_TRUE; break; } } argc -= isc_commandline_index; argv += isc_commandline_index; if (argc > 0) { if (strcasecmp("none", argv[0]) == 0) origin = NULL; else { len = strlen(argv[0]); isc_buffer_init(&source, argv[0], len); isc_buffer_add(&source, len); dns_fixedname_init(&oname); origin = &oname.name; result = dns_name_fromtext(origin, &source, dns_rootname, ISC_FALSE, NULL); if (result != 0) { fprintf(stderr, "dns_name_fromtext() failed: %d\n", result); exit(1); } } } else if (concatenate) origin = NULL; else origin = dns_rootname; if (argc >= 1) { if (strcasecmp("none", argv[1]) == 0) comp = NULL; else { len = strlen(argv[1]); isc_buffer_init(&source, argv[1], len); isc_buffer_add(&source, len); dns_fixedname_init(&compname); comp = &compname.name; result = dns_name_fromtext(comp, &source, origin, ISC_FALSE, NULL); if (result != 0) { fprintf(stderr, "dns_name_fromtext() failed: %d\n", result); exit(1); } } } else comp = NULL; dns_fixedname_init(&wname); name = dns_fixedname_name(&wname); dns_fixedname_init(&wname2); while (fgets(s, sizeof(s), stdin) != NULL) { len = strlen(s); if (len > 0U && s[len - 1] == '\n') { s[len - 1] = '\0'; len--; } isc_buffer_init(&source, s, len); isc_buffer_add(&source, len); if (len > 0U) result = dns_name_fromtext(name, &source, origin, downcase, NULL); else { if (name == dns_fixedname_name(&wname)) dns_fixedname_init(&wname); else dns_fixedname_init(&wname2); result = ISC_R_SUCCESS; } if (result != ISC_R_SUCCESS) { printf("%s\n", dns_result_totext(result)); if (name == dns_fixedname_name(&wname)) dns_fixedname_init(&wname); else dns_fixedname_init(&wname2); continue; } if (check_absolute && dns_name_countlabels(name) > 0) { if (dns_name_isabsolute(name)) printf("absolute\n"); else printf("relative\n"); } if (check_wildcard && dns_name_countlabels(name) > 0) { if (dns_name_iswildcard(name)) printf("wildcard\n"); else printf("not wildcard\n"); } dns_name_toregion(name, &r); if (!quiet) { print_wirename(&r); printf("%u labels, %u bytes.\n", dns_name_countlabels(name), r.length); } if (concatenate) { if (got_name) { printf("Concatenating.\n"); result = dns_name_concatenate(&wname.name, &wname2.name, &wname2.name, NULL); name = &wname2.name; if (result == ISC_R_SUCCESS) { if (check_absolute && dns_name_countlabels(name) > 0) { if (dns_name_isabsolute(name)) printf("absolute\n"); else printf("relative\n"); } if (check_wildcard && dns_name_countlabels(name) > 0) { if (dns_name_iswildcard(name)) printf("wildcard\n"); else printf("not " "wildcard\n"); } dns_name_toregion(name, &r); if (!quiet) { print_wirename(&r); printf("%u labels, " "%u bytes.\n", dns_name_countlabels(name), r.length); } } else printf("%s\n", dns_result_totext(result)); got_name = ISC_FALSE; } else got_name = ISC_TRUE; } isc_buffer_init(&source, s, sizeof(s)); if (dns_name_countlabels(name) > 0) result = dns_name_totext(name, ISC_FALSE, &source); else result = ISC_R_SUCCESS; if (result == ISC_R_SUCCESS) { isc_buffer_usedregion(&source, &r); if (r.length > 0) printf("%.*s\n", (int)r.length, r.base); else printf("<empty text name>\n"); if (!quiet) { printf("%u bytes.\n", source.used); } } else printf("%s\n", dns_result_totext(result)); if (test_downcase) { if (inplace) { down = name; } else { dns_fixedname_init(&downname); down = dns_fixedname_name(&downname); } result = dns_name_downcase(name, down, NULL); INSIST(result == ISC_R_SUCCESS); if (!quiet) { dns_name_toregion(down, &r); print_wirename(&r); printf("%u labels, %u bytes.\n", dns_name_countlabels(down), r.length); } isc_buffer_init(&source, s, sizeof(s)); print_name(down); } if (comp != NULL && dns_name_countlabels(name) > 0) { int order; unsigned int nlabels; dns_namereln_t namereln; namereln = dns_name_fullcompare(name, comp, &order, &nlabels); if (!quiet) { if (order < 0) printf("<"); else if (order > 0) printf(">"); else printf("="); switch (namereln) { case dns_namereln_contains: printf(", contains"); break; case dns_namereln_subdomain: printf(", subdomain"); break; case dns_namereln_commonancestor: printf(", common ancestor"); break; default: break; } if (namereln != dns_namereln_none && namereln != dns_namereln_equal) printf(", nlabels = %u", nlabels); printf("\n"); } printf("dns_name_equal() returns %s\n", dns_name_equal(name, comp) ? "TRUE" : "FALSE"); } labels = dns_name_countlabels(name); if (want_split && split_label < labels) { dns_fixedname_init(&fprefix); prefix = dns_fixedname_name(&fprefix); dns_fixedname_init(&fsuffix); suffix = dns_fixedname_name(&fsuffix); printf("splitting at label %u: ", split_label); dns_name_split(name, split_label, prefix, suffix); printf("\n prefix = "); print_name(prefix); printf(" suffix = "); print_name(suffix); } if (concatenate) { if (got_name) name = &wname2.name; else name = &wname.name; } } return (0); }
/* * Find the longest match of name in the table. * If match is found return ISC_TRUE. prefix, suffix and offset are updated. * If no match is found return ISC_FALSE. */ isc_boolean_t dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name, dns_name_t *prefix, isc_uint16_t *offset) { dns_name_t tname; dns_compressnode_t *node = NULL; unsigned int labels, i, n; unsigned int numlabels; unsigned char *p; REQUIRE(VALID_CCTX(cctx)); REQUIRE(dns_name_isabsolute(name) == ISC_TRUE); REQUIRE(offset != NULL); if (ISC_UNLIKELY((cctx->allowed & DNS_COMPRESS_ENABLED) == 0)) return (ISC_FALSE); if (cctx->count == 0) return (ISC_FALSE); labels = dns_name_countlabels(name); INSIST(labels > 0); dns_name_init(&tname, NULL); numlabels = labels > 3U ? 3U : labels; p = name->ndata; for (n = 0; n < numlabels - 1; n++) { unsigned char ch, llen; unsigned int firstoffset, length; firstoffset = (unsigned int)(p - name->ndata); length = name->length - firstoffset; /* * We calculate the table index using the first * character in the first label of the suffix name. */ ch = p[1]; i = tableindex[ch]; if (ISC_LIKELY((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0)) { for (node = cctx->table[i]; node != NULL; node = node->next) { if (ISC_UNLIKELY(node->name.length != length)) continue; if (ISC_LIKELY(memcmp(node->name.ndata, p, length) == 0)) goto found; } } else { for (node = cctx->table[i]; node != NULL; node = node->next) { unsigned int l, count; unsigned char c; unsigned char *label1, *label2; if (ISC_UNLIKELY(node->name.length != length)) continue; l = labels - n; if (ISC_UNLIKELY(node->name.labels != l)) continue; label1 = node->name.ndata; label2 = p; while (ISC_LIKELY(l-- > 0)) { count = *label1++; if (count != *label2++) goto cont1; /* no bitstring support */ INSIST(count <= 63); /* Loop unrolled for performance */ while (ISC_LIKELY(count > 3)) { c = maptolower[label1[0]]; if (c != maptolower[label2[0]]) goto cont1; c = maptolower[label1[1]]; if (c != maptolower[label2[1]]) goto cont1; c = maptolower[label1[2]]; if (c != maptolower[label2[2]]) goto cont1; c = maptolower[label1[3]]; if (c != maptolower[label2[3]]) goto cont1; count -= 4; label1 += 4; label2 += 4; } while (ISC_LIKELY(count-- > 0)) { c = maptolower[*label1++]; if (c != maptolower[*label2++]) goto cont1; } } break; cont1: continue; } } if (node != NULL) break; llen = *p; p += llen + 1; } found: /* * If node == NULL, we found no match at all. */ if (node == NULL) return (ISC_FALSE); if (n == 0) dns_name_reset(prefix); else dns_name_getlabelsequence(name, 0, n, prefix); *offset = (node->offset & 0x7fff); return (ISC_TRUE); }
static isc_boolean_t checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) { #ifdef USE_GETADDRINFO struct addrinfo hints, *ai, *cur; char namebuf[DNS_NAME_FORMATSIZE + 1]; char ownerbuf[DNS_NAME_FORMATSIZE]; int result; int level = ISC_LOG_ERROR; isc_boolean_t answer = ISC_TRUE; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; dns_name_format(name, namebuf, sizeof(namebuf) - 1); /* * Turn off search. */ if (dns_name_countlabels(name) > 1U) strcat(namebuf, "."); dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); result = getaddrinfo(namebuf, NULL, &hints, &ai); dns_name_format(name, namebuf, sizeof(namebuf) - 1); switch (result) { case 0: /* * Work around broken getaddrinfo() implementations that * fail to set ai_canonname on first entry. */ cur = ai; while (cur != NULL && cur->ai_canonname == NULL && cur->ai_next != NULL) cur = cur->ai_next; if (cur != NULL && cur->ai_canonname != NULL && strcasecmp(cur->ai_canonname, namebuf) != 0) { if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0) level = ISC_LOG_WARNING; if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) { if (!logged(namebuf, ERR_IS_SRVCNAME)) { dns_zone_log(zone, level, "%s/SRV '%s'" " (out of zone) is a " "CNAME '%s' (illegal)", ownerbuf, namebuf, cur->ai_canonname); add(namebuf, ERR_IS_SRVCNAME); } if (level == ISC_LOG_ERROR) answer = ISC_FALSE; } } freeaddrinfo(ai); return (answer); case EAI_NONAME: #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) case EAI_NODATA: #endif if (!logged(namebuf, ERR_NO_ADDRESSES)) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/SRV '%s' (out of zone) " "has no addresses records (A or AAAA)", ownerbuf, namebuf); add(namebuf, ERR_NO_ADDRESSES); } /* XXX950 make fatal for 9.5.0. */ return (ISC_TRUE); default: if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { dns_zone_log(zone, ISC_LOG_WARNING, "getaddrinfo(%s) failed: %s", namebuf, gai_strerror(result)); add(namebuf, ERR_LOOKUP_FAILURE); } return (ISC_TRUE); } #else return (ISC_TRUE); #endif }
static isc_boolean_t checkns(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner, dns_rdataset_t *a, dns_rdataset_t *aaaa) { #ifdef USE_GETADDRINFO dns_rdataset_t *rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; struct addrinfo hints, *ai, *cur; char namebuf[DNS_NAME_FORMATSIZE + 1]; char ownerbuf[DNS_NAME_FORMATSIZE]; char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")]; isc_boolean_t answer = ISC_TRUE; isc_boolean_t match; const char *type; void *ptr = NULL; int result; REQUIRE(a == NULL || !dns_rdataset_isassociated(a) || a->type == dns_rdatatype_a); REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) || aaaa->type == dns_rdatatype_aaaa); memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; dns_name_format(name, namebuf, sizeof(namebuf) - 1); /* * Turn off search. */ if (dns_name_countlabels(name) > 1U) strcat(namebuf, "."); dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); result = getaddrinfo(namebuf, NULL, &hints, &ai); dns_name_format(name, namebuf, sizeof(namebuf) - 1); switch (result) { case 0: /* * Work around broken getaddrinfo() implementations that * fail to set ai_canonname on first entry. */ cur = ai; while (cur != NULL && cur->ai_canonname == NULL && cur->ai_next != NULL) cur = cur->ai_next; if (cur != NULL && cur->ai_canonname != NULL && strcasecmp(cur->ai_canonname, namebuf) != 0 && !logged(namebuf, ERR_IS_CNAME)) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' (out of zone) " "is a CNAME '%s' (illegal)", ownerbuf, namebuf, cur->ai_canonname); /* XXX950 make fatal for 9.5.0 */ /* answer = ISC_FALSE; */ add(namebuf, ERR_IS_CNAME); } break; case EAI_NONAME: #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) case EAI_NODATA: #endif if (!logged(namebuf, ERR_NO_ADDRESSES)) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' (out of zone) " "has no addresses records (A or AAAA)", ownerbuf, namebuf); add(namebuf, ERR_NO_ADDRESSES); } /* XXX950 make fatal for 9.5.0 */ return (ISC_TRUE); default: if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { dns_zone_log(zone, ISC_LOG_WARNING, "getaddrinfo(%s) failed: %s", namebuf, gai_strerror(result)); add(namebuf, ERR_LOOKUP_FAILURE); } return (ISC_TRUE); } if (a == NULL || aaaa == NULL) return (answer); /* * Check that all glue records really exist. */ if (!dns_rdataset_isassociated(a)) goto checkaaaa; result = dns_rdataset_first(a); while (result == ISC_R_SUCCESS) { dns_rdataset_current(a, &rdata); match = ISC_FALSE; for (cur = ai; cur != NULL; cur = cur->ai_next) { if (cur->ai_family != AF_INET) continue; ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr; if (memcmp(ptr, rdata.data, rdata.length) == 0) { match = ISC_TRUE; break; } } if (!match && !logged(namebuf, ERR_EXTRA_A)) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' " "extra GLUE A record (%s)", ownerbuf, namebuf, inet_ntop(AF_INET, rdata.data, addrbuf, sizeof(addrbuf))); add(namebuf, ERR_EXTRA_A); /* XXX950 make fatal for 9.5.0 */ /* answer = ISC_FALSE; */ } dns_rdata_reset(&rdata); result = dns_rdataset_next(a); } checkaaaa: if (!dns_rdataset_isassociated(aaaa)) goto checkmissing; result = dns_rdataset_first(aaaa); while (result == ISC_R_SUCCESS) { dns_rdataset_current(aaaa, &rdata); match = ISC_FALSE; for (cur = ai; cur != NULL; cur = cur->ai_next) { if (cur->ai_family != AF_INET6) continue; ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr; if (memcmp(ptr, rdata.data, rdata.length) == 0) { match = ISC_TRUE; break; } } if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' " "extra GLUE AAAA record (%s)", ownerbuf, namebuf, inet_ntop(AF_INET6, rdata.data, addrbuf, sizeof(addrbuf))); add(namebuf, ERR_EXTRA_AAAA); /* XXX950 make fatal for 9.5.0. */ /* answer = ISC_FALSE; */ } dns_rdata_reset(&rdata); result = dns_rdataset_next(aaaa); } checkmissing: /* * Check that all addresses appear in the glue. */ if (!logged(namebuf, ERR_MISSING_GLUE)) { isc_boolean_t missing_glue = ISC_FALSE; for (cur = ai; cur != NULL; cur = cur->ai_next) { switch (cur->ai_family) { case AF_INET: rdataset = a; ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr; type = "A"; break; case AF_INET6: rdataset = aaaa; ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr; type = "AAAA"; break; default: continue; } match = ISC_FALSE; if (dns_rdataset_isassociated(rdataset)) result = dns_rdataset_first(rdataset); else result = ISC_R_FAILURE; while (result == ISC_R_SUCCESS && !match) { dns_rdataset_current(rdataset, &rdata); if (memcmp(ptr, rdata.data, rdata.length) == 0) match = ISC_TRUE; dns_rdata_reset(&rdata); result = dns_rdataset_next(rdataset); } if (!match) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' " "missing GLUE %s record (%s)", ownerbuf, namebuf, type, inet_ntop(cur->ai_family, ptr, addrbuf, sizeof(addrbuf))); /* XXX950 make fatal for 9.5.0. */ /* answer = ISC_FALSE; */ missing_glue = ISC_TRUE; } } if (missing_glue) add(namebuf, ERR_MISSING_GLUE); } freeaddrinfo(ai); return (answer); #else return (ISC_TRUE); #endif }
isc_result_t dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx, dns_tsig_keyring_t *ring) { isc_result_t result = ISC_R_SUCCESS; dns_rdata_tkey_t tkeyin, tkeyout; isc_boolean_t freetkeyin = ISC_FALSE; dns_name_t *qname, *name, *keyname, *signer, tsigner; dns_fixedname_t fkeyname; dns_rdataset_t *tkeyset; dns_rdata_t rdata; dns_namelist_t namelist; char tkeyoutdata[512]; isc_buffer_t tkeyoutbuf; REQUIRE(msg != NULL); REQUIRE(tctx != NULL); REQUIRE(ring != NULL); ISC_LIST_INIT(namelist); /* * Interpret the question section. */ result = dns_message_firstname(msg, DNS_SECTION_QUESTION); if (result != ISC_R_SUCCESS) return (DNS_R_FORMERR); qname = NULL; dns_message_currentname(msg, DNS_SECTION_QUESTION, &qname); /* * Look for a TKEY record that matches the question. */ tkeyset = NULL; name = NULL; result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL, qname, dns_rdatatype_tkey, 0, &name, &tkeyset); if (result != ISC_R_SUCCESS) { /* * Try the answer section, since that's where Win2000 * puts it. */ name = NULL; if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname, dns_rdatatype_tkey, 0, &name, &tkeyset) != ISC_R_SUCCESS) { result = DNS_R_FORMERR; tkey_log("dns_tkey_processquery: couldn't find a TKEY " "matching the question"); goto failure; } } result = dns_rdataset_first(tkeyset); if (result != ISC_R_SUCCESS) { result = DNS_R_FORMERR; goto failure; } dns_rdata_init(&rdata); dns_rdataset_current(tkeyset, &rdata); RETERR(dns_rdata_tostruct(&rdata, &tkeyin, NULL)); freetkeyin = ISC_TRUE; if (tkeyin.error != dns_rcode_noerror) { result = DNS_R_FORMERR; goto failure; } /* * Before we go any farther, verify that the message was signed. * GSSAPI TKEY doesn't require a signature, the rest do. */ dns_name_init(&tsigner, NULL); result = dns_message_signer(msg, &tsigner); if (result != ISC_R_SUCCESS) { if (tkeyin.mode == DNS_TKEYMODE_GSSAPI && result == ISC_R_NOTFOUND) signer = NULL; else { tkey_log("dns_tkey_processquery: query was not " "properly signed - rejecting"); result = DNS_R_FORMERR; goto failure; } } else signer = &tsigner; tkeyout.common.rdclass = tkeyin.common.rdclass; tkeyout.common.rdtype = tkeyin.common.rdtype; ISC_LINK_INIT(&tkeyout.common, link); tkeyout.mctx = msg->mctx; dns_name_init(&tkeyout.algorithm, NULL); dns_name_clone(&tkeyin.algorithm, &tkeyout.algorithm); tkeyout.inception = tkeyout.expire = 0; tkeyout.mode = tkeyin.mode; tkeyout.error = 0; tkeyout.keylen = tkeyout.otherlen = 0; tkeyout.key = tkeyout.other = NULL; /* * A delete operation must have a fully specified key name. If this * is not a delete, we do the following: * if (qname != ".") * keyname = qname + defaultdomain * else * keyname = <random hex> + defaultdomain */ if (tkeyin.mode != DNS_TKEYMODE_DELETE) { dns_tsigkey_t *tsigkey = NULL; if (tctx->domain == NULL && tkeyin.mode != DNS_TKEYMODE_GSSAPI) { tkey_log("dns_tkey_processquery: tkey-domain not set"); result = DNS_R_REFUSED; goto failure; } dns_fixedname_init(&fkeyname); keyname = dns_fixedname_name(&fkeyname); if (!dns_name_equal(qname, dns_rootname)) { unsigned int n = dns_name_countlabels(qname); RUNTIME_CHECK(dns_name_copy(qname, keyname, NULL) == ISC_R_SUCCESS); dns_name_getlabelsequence(keyname, 0, n - 1, keyname); } else { static char hexdigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; unsigned char randomdata[16]; char randomtext[32]; isc_buffer_t b; unsigned int i, j; result = isc_entropy_getdata(tctx->ectx, randomdata, sizeof(randomdata), NULL, 0); if (result != ISC_R_SUCCESS) goto failure; for (i = 0, j = 0; i < sizeof(randomdata); i++) { unsigned char val = randomdata[i]; randomtext[j++] = hexdigits[val >> 4]; randomtext[j++] = hexdigits[val & 0xF]; } isc_buffer_init(&b, randomtext, sizeof(randomtext)); isc_buffer_add(&b, sizeof(randomtext)); result = dns_name_fromtext(keyname, &b, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto failure; } if (tkeyin.mode == DNS_TKEYMODE_GSSAPI) { /* Yup. This is a hack */ result = dns_name_concatenate(keyname, dns_rootname, keyname, NULL); if (result != ISC_R_SUCCESS) goto failure; } else { result = dns_name_concatenate(keyname, tctx->domain, keyname, NULL); if (result != ISC_R_SUCCESS) goto failure; } result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring); if (result == ISC_R_SUCCESS) { tkeyout.error = dns_tsigerror_badname; dns_tsigkey_detach(&tsigkey); goto failure_with_tkey; } else if (result != ISC_R_NOTFOUND) goto failure; } else
void dns_compress_add(dns_compress_t *cctx, const dns_name_t *name, const dns_name_t *prefix, isc_uint16_t offset) { dns_name_t tname, xname; unsigned int start; unsigned int n; unsigned int count; unsigned int i; dns_compressnode_t *node; unsigned int length; unsigned int tlength; isc_uint16_t toffset; unsigned char *tmp; isc_region_t r; REQUIRE(VALID_CCTX(cctx)); REQUIRE(dns_name_isabsolute(name)); if (ISC_UNLIKELY((cctx->allowed & DNS_COMPRESS_ENABLED) == 0)) return; if (offset >= 0x4000) return; dns_name_init(&tname, NULL); dns_name_init(&xname, NULL); n = dns_name_countlabels(name); count = dns_name_countlabels(prefix); if (dns_name_isabsolute(prefix)) count--; if (count == 0) return; start = 0; dns_name_toregion(name, &r); length = r.length; tmp = isc_mem_get(cctx->mctx, length); if (tmp == NULL) return; /* * Copy name data to 'tmp' and make 'r' use 'tmp'. */ memmove(tmp, r.base, r.length); r.base = tmp; dns_name_fromregion(&xname, &r); if (count > 2U) count = 2U; while (count > 0) { unsigned char ch; dns_name_getlabelsequence(&xname, start, n, &tname); /* * We calculate the table index using the first * character in the first label of tname. */ ch = tname.ndata[1]; i = tableindex[ch]; tlength = name_length(&tname); toffset = (isc_uint16_t)(offset + (length - tlength)); if (toffset >= 0x4000) break; /* * Create a new node and add it. */ if (cctx->count < DNS_COMPRESS_INITIALNODES) node = &cctx->initialnodes[cctx->count]; else { node = isc_mem_get(cctx->mctx, sizeof(dns_compressnode_t)); if (node == NULL) break; } node->count = cctx->count++; /* * 'node->r.base' becomes 'tmp' when start == 0. * Record this by setting 0x8000 so it can be freed later. */ if (start == 0) toffset |= 0x8000; node->offset = toffset; dns_name_toregion(&tname, &node->r); dns_name_init(&node->name, NULL); node->name.length = node->r.length; node->name.ndata = node->r.base; node->name.labels = tname.labels; node->name.attributes = DNS_NAMEATTR_ABSOLUTE; node->next = cctx->table[i]; cctx->table[i] = node; start++; n--; count--; } if (start == 0) isc_mem_put(cctx->mctx, tmp, length); }
/*% * Return ISC_R_SUCCESS if we can determine that the name doesn't exist * or we can determine whether there is data or not at the name. * If the name does not exist return the wildcard name. * * Return ISC_R_IGNORE when the NSEC is not the appropriate one. */ isc_result_t dns_nsec_noexistnodata(dns_rdatatype_t type, dns_name_t *name, dns_name_t *nsecname, dns_rdataset_t *nsecset, isc_boolean_t *exists, isc_boolean_t *data, dns_name_t *wild, dns_nseclog_t logit, void *arg) { int order; dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; dns_namereln_t relation; unsigned int olabels, nlabels, labels; dns_rdata_nsec_t nsec; isc_boolean_t atparent; isc_boolean_t ns; isc_boolean_t soa; REQUIRE(exists != NULL); REQUIRE(data != NULL); REQUIRE(nsecset != NULL && nsecset->type == dns_rdatatype_nsec); result = dns_rdataset_first(nsecset); if (result != ISC_R_SUCCESS) { (*logit)(arg, ISC_LOG_DEBUG(3), "failure processing NSEC set"); return (result); } dns_rdataset_current(nsecset, &rdata); (*logit)(arg, ISC_LOG_DEBUG(3), "looking for relevant NSEC"); relation = dns_name_fullcompare(name, nsecname, &order, &olabels); if (order < 0) { /* * The name is not within the NSEC range. */ (*logit)(arg, ISC_LOG_DEBUG(3), "NSEC does not cover name, before NSEC"); return (ISC_R_IGNORE); } if (order == 0) { /* * The names are the same. If we are validating "." * then atparent should not be set as there is no parent. */ atparent = (olabels != 1) && dns_rdatatype_atparent(type); ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns); soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa); if (ns && !soa) { if (!atparent) { /* * This NSEC record is from somewhere higher in * the DNS, and at the parent of a delegation. * It can not be legitimately used here. */ (*logit)(arg, ISC_LOG_DEBUG(3), "ignoring parent nsec"); return (ISC_R_IGNORE); } } else if (atparent && ns && soa) { /* * This NSEC record is from the child. * It can not be legitimately used here. */ (*logit)(arg, ISC_LOG_DEBUG(3), "ignoring child nsec"); return (ISC_R_IGNORE); } if (type == dns_rdatatype_cname || type == dns_rdatatype_nxt || type == dns_rdatatype_nsec || type == dns_rdatatype_key || !dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) { *exists = ISC_TRUE; *data = dns_nsec_typepresent(&rdata, type); (*logit)(arg, ISC_LOG_DEBUG(3), "nsec proves name exists (owner) data=%d", *data); return (ISC_R_SUCCESS); } (*logit)(arg, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists"); return (ISC_R_IGNORE); } if (relation == dns_namereln_subdomain && dns_nsec_typepresent(&rdata, dns_rdatatype_ns) && !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) { /* * This NSEC record is from somewhere higher in * the DNS, and at the parent of a delegation. * It can not be legitimately used here. */ (*logit)(arg, ISC_LOG_DEBUG(3), "ignoring parent nsec"); return (ISC_R_IGNORE); } result = dns_rdata_tostruct(&rdata, &nsec, NULL); if (result != ISC_R_SUCCESS) return (result); relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels); if (order == 0) { dns_rdata_freestruct(&nsec); (*logit)(arg, ISC_LOG_DEBUG(3), "ignoring nsec matches next name"); return (ISC_R_IGNORE); } if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) { /* * The name is not within the NSEC range. */ dns_rdata_freestruct(&nsec); (*logit)(arg, ISC_LOG_DEBUG(3), "ignoring nsec because name is past end of range"); return (ISC_R_IGNORE); } if (order > 0 && relation == dns_namereln_subdomain) { (*logit)(arg, ISC_LOG_DEBUG(3), "nsec proves name exist (empty)"); dns_rdata_freestruct(&nsec); *exists = ISC_TRUE; *data = ISC_FALSE; return (ISC_R_SUCCESS); } if (wild != NULL) { dns_name_t common; dns_name_init(&common, NULL); if (olabels > nlabels) { labels = dns_name_countlabels(nsecname); dns_name_getlabelsequence(nsecname, labels - olabels, olabels, &common); } else { labels = dns_name_countlabels(&nsec.next); dns_name_getlabelsequence(&nsec.next, labels - nlabels, nlabels, &common); } result = dns_name_concatenate(dns_wildcardname, &common, wild, NULL); if (result != ISC_R_SUCCESS) { dns_rdata_freestruct(&nsec); (*logit)(arg, ISC_LOG_DEBUG(3), "failure generating wildcard name"); return (result); } } dns_rdata_freestruct(&nsec); (*logit)(arg, ISC_LOG_DEBUG(3), "nsec range ok"); *exists = ISC_FALSE; return (ISC_R_SUCCESS); }