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)); }
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); }
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); }
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); }
static void lookup_find(dns_lookup_t *lookup, dns_fetchevent_t *event) { isc_result_t result; isc_boolean_t want_restart; isc_boolean_t send_event; dns_name_t *name, *fname, *prefix; dns_fixedname_t foundname, fixed; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned int nlabels; int order; dns_namereln_t namereln; dns_rdata_cname_t cname; dns_rdata_dname_t dname; REQUIRE(VALID_LOOKUP(lookup)); LOCK(&lookup->lock); result = ISC_R_SUCCESS; name = dns_fixedname_name(&lookup->name); do { lookup->restarts++; want_restart = ISC_FALSE; send_event = ISC_TRUE; if (event == NULL && !lookup->canceled) { dns_fixedname_init(&foundname); fname = dns_fixedname_name(&foundname); INSIST(!dns_rdataset_isassociated(&lookup->rdataset)); INSIST(!dns_rdataset_isassociated (&lookup->sigrdataset)); /* * If we have restarted then clear the old node. */ if (lookup->event->node != NULL) { INSIST(lookup->event->db != NULL); dns_db_detachnode(lookup->event->db, &lookup->event->node); } if (lookup->event->db != NULL) dns_db_detach(&lookup->event->db); result = view_find(lookup, fname); if (result == ISC_R_NOTFOUND) { /* * We don't know anything about the name. * Launch a fetch. */ if (lookup->event->node != NULL) { INSIST(lookup->event->db != NULL); dns_db_detachnode(lookup->event->db, &lookup->event->node); } if (lookup->event->db != NULL) dns_db_detach(&lookup->event->db); result = start_fetch(lookup); if (result == ISC_R_SUCCESS) send_event = ISC_FALSE; goto done; } } else if (event != NULL) { result = event->result; fname = dns_fixedname_name(&event->foundname); dns_resolver_destroyfetch(&lookup->fetch); INSIST(event->rdataset == &lookup->rdataset); INSIST(event->sigrdataset == &lookup->sigrdataset); } else fname = NULL; /* Silence compiler warning. */ /* * If we've been canceled, forget about the result. */ if (lookup->canceled) result = ISC_R_CANCELED; switch (result) { case ISC_R_SUCCESS: result = build_event(lookup); if (event == NULL) break; if (event->db != NULL) dns_db_attach(event->db, &lookup->event->db); if (event->node != NULL) dns_db_attachnode(lookup->event->db, event->node, &lookup->event->node); break; case DNS_R_CNAME: /* * Copy the CNAME's target into the lookup's * query name and start over. */ result = dns_rdataset_first(&lookup->rdataset); if (result != ISC_R_SUCCESS) break; dns_rdataset_current(&lookup->rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &cname, NULL); dns_rdata_reset(&rdata); if (result != ISC_R_SUCCESS) break; result = dns_name_copy(&cname.cname, name, NULL); dns_rdata_freestruct(&cname); if (result == ISC_R_SUCCESS) { want_restart = ISC_TRUE; send_event = ISC_FALSE; } break; case DNS_R_DNAME: namereln = dns_name_fullcompare(name, fname, &order, &nlabels); INSIST(namereln == dns_namereln_subdomain); /* * Get the target name of the DNAME. */ result = dns_rdataset_first(&lookup->rdataset); if (result != ISC_R_SUCCESS) break; dns_rdataset_current(&lookup->rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &dname, NULL); dns_rdata_reset(&rdata); if (result != ISC_R_SUCCESS) break; /* * Construct the new query name and start over. */ dns_fixedname_init(&fixed); prefix = dns_fixedname_name(&fixed); dns_name_split(name, nlabels, prefix, NULL); result = dns_name_concatenate(prefix, &dname.dname, name, NULL); dns_rdata_freestruct(&dname); if (result == ISC_R_SUCCESS) { want_restart = ISC_TRUE; send_event = ISC_FALSE; } break; default: send_event = ISC_TRUE; } if (dns_rdataset_isassociated(&lookup->rdataset)) dns_rdataset_disassociate(&lookup->rdataset); if (dns_rdataset_isassociated(&lookup->sigrdataset)) dns_rdataset_disassociate(&lookup->sigrdataset); done: if (event != NULL) { if (event->node != NULL) dns_db_detachnode(event->db, &event->node); if (event->db != NULL) dns_db_detach(&event->db); isc_event_free(ISC_EVENT_PTR(&event)); } /* * Limit the number of restarts. */ if (want_restart && lookup->restarts == MAX_RESTARTS) { want_restart = ISC_FALSE; result = ISC_R_QUOTA; send_event = ISC_TRUE; } } while (want_restart); if (send_event) { lookup->event->result = result; lookup->event->ev_sender = lookup; isc_task_sendanddetach(&lookup->task, (isc_event_t **)(void *)&lookup->event); dns_view_detach(&lookup->view); } UNLOCK(&lookup->lock); }