Exemplo n.º 1
0
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));
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
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);
}