Пример #1
0
static isc_result_t
ldapdb_create(const char *zone, int argc, char **argv,
	      void *driverdata, void **dbdata)
{
	struct ldapdb_data *data;
	char *s, *filter = NULL, *extensions = NULL;
	int defaultttl;

	UNUSED(driverdata);

	/* we assume that only one thread will call create at a time */
	/* want to do this only once for all instances */

	if ((argc < 2)
	    || (argv[0] != strstr( argv[0], "ldap://"))
	    || ((defaultttl = atoi(argv[1])) < 1))
                return (ISC_R_FAILURE);
        data = isc_mem_get(ns_g_mctx, sizeof(struct ldapdb_data));
        if (data == NULL)
                return (ISC_R_NOMEMORY);

	memset(data, 0, sizeof(struct ldapdb_data));
	data->hostport = isc_mem_strdup(ns_g_mctx, argv[0] + strlen("ldap://"));
	if (data->hostport == NULL) {
		free_data(data);
		return (ISC_R_NOMEMORY);
	}

	data->defaultttl = defaultttl;

	s = strchr(data->hostport, '/');
	if (s != NULL) {
		*s++ = '\0';
		data->base = s;
		/* attrs, scope, filter etc? */
		s = strchr(s, '?');
		if (s != NULL) {
			*s++ = '\0';
			/* ignore attributes */
			s = strchr(s, '?');
			if (s != NULL) {
				*s++ = '\0';
				/* ignore scope */
				s = strchr(s, '?');
				if (s != NULL) {
					*s++ = '\0';
					/* filter */
					filter = s;
					s = strchr(s, '?');
					if (s != NULL) {
						*s++ = '\0';
						/* extensions */
						extensions = s;
						s = strchr(s, '?');
						if (s != NULL) {
							*s++ = '\0';
						}
						if (*extensions == '\0') {
							extensions = NULL;
						}
					}
					if (*filter == '\0') {
						filter = NULL;
					}
				}
			}
		}
		if (*data->base == '\0') {
			data->base = NULL;
		}
	}

	/* parse extensions */
	if (extensions != NULL) {
		int err;

		err = parseextensions(extensions, data);
		if (err < 0) {
			/* err should be -1 or -2 */
			free_data(data);
			if (err == -1) {
				isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
					      "LDAP sdb zone '%s': URL: extension syntax error", zone);
			} else if (err == -2) {
				isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
					      "LDAP sdb zone '%s': URL: unknown critical extension", zone);
			}
			return (ISC_R_FAILURE);
		}
	}

	if ((data->base != NULL && unhex(data->base) == NULL) ||
	    (filter != NULL && unhex(filter) == NULL) ||
	    (data->bindname != NULL && unhex(data->bindname) == NULL) ||
	    (data->bindpw != NULL && unhex(data->bindpw) == NULL)) {
		free_data(data);
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,	
			      "LDAP sdb zone '%s': URL: bad hex values", zone);
		return (ISC_R_FAILURE);
	}

	/* compute filterall and filterone once and for all */
	if (filter == NULL) {
		data->filteralllen = strlen(zone) + strlen("(zoneName=)") + 1;
		data->filteronelen = strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1;
	} else {
		data->filteralllen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=))") + 1;
		data->filteronelen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1;
	}

	data->filterall = isc_mem_get(ns_g_mctx, data->filteralllen);
	if (data->filterall == NULL) {
		free_data(data);
		return (ISC_R_NOMEMORY);
	}
	data->filterone = isc_mem_get(ns_g_mctx, data->filteronelen);
	if (data->filterone == NULL) {
		free_data(data);
		return (ISC_R_NOMEMORY);
	}

	if (filter == NULL) {
		sprintf(data->filterall, "(zoneName=%s)", zone);
		sprintf(data->filterone, "(&(zoneName=%s)(relativeDomainName=", zone); 
	} else {
		sprintf(data->filterall, "(&%s(zoneName=%s))", filter, zone);
		sprintf(data->filterone, "(&%s(zoneName=%s)(relativeDomainName=", filter, zone);
	}
	data->filtername = data->filterone + strlen(data->filterone);

	/* support URLs with literal IPv6 addresses */
	data->hostname = isc_mem_strdup(ns_g_mctx, data->hostport + (*data->hostport == '[' ? 1 : 0));
	if (data->hostname == NULL) {
		free_data(data);
		return (ISC_R_NOMEMORY);
	}

	if (*data->hostport == '[' &&
	    (s = strchr(data->hostname, ']')) != NULL )
		*s++ = '\0';
	else
		s = data->hostname;
	s = strchr(s, ':');
	if (s != NULL) {
		*s++ = '\0';
		data->portno = atoi(s);
	} else
		data->portno = LDAP_PORT;

	*dbdata = data;
	return (ISC_R_SUCCESS);
}
static void
include_callback(const char *filename, void *arg) {
	char **argp = (char **) arg;
	*argp = isc_mem_strdup(mctx, filename);
}
Пример #3
0
/*% constructs a query list by parsing a string into query segments */
static isc_result_t
build_querylist(isc_mem_t *mctx, const char *query_str, char **zone,
		char **record, char **client, query_list_t **querylist,
		unsigned int flags)
{
	isc_result_t result;
	isc_boolean_t foundzone = isc_boolean_false;
	isc_boolean_t foundrecord = isc_boolean_false;
	isc_boolean_t foundclient = isc_boolean_false;
	char *temp_str = NULL;
	char *right_str = NULL;
	query_list_t *tql;
	query_segment_t *tseg = NULL;

	REQUIRE(querylist != NULL && *querylist == NULL);
	REQUIRE(mctx != NULL);

	/* if query string is null, or zero length */
	if (query_str == NULL || strlen(query_str) < 1) {
		if ((flags & SDLZH_REQUIRE_QUERY) == 0)
			/* we don't need it were ok. */
			return (ISC_R_SUCCESS);
		else
			/* we did need it, PROBLEM!!! */
			return (ISC_R_FAILURE);
	}

	/* allocate memory for query list */
	tql = isc_mem_get(mctx, sizeof(query_list_t));
	/* couldn't allocate memory.  Problem!! */
	if (tql == NULL)
		return (ISC_R_NOMEMORY);

	/* initialize the query segment list */
	ISC_LIST_INIT(*tql);

	/* make a copy of query_str so we can chop it up */
	temp_str = right_str = isc_mem_strdup(mctx, query_str);
	/* couldn't make a copy, problem!! */
	if (right_str == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/* loop through the string and chop it up */
	while (right_str != NULL) {
		/* allocate memory for tseg */
		tseg = isc_mem_get(mctx, sizeof(query_segment_t));
		if (tseg  == NULL) {	/* no memory, clean everything up. */
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
		tseg->sql = NULL;
		tseg->direct = isc_boolean_false;
		/* initialize the query segment link */
		ISC_LINK_INIT(tseg, link);
		/* append the query segment to the list */
		ISC_LIST_APPEND(*tql, tseg, link);

		/*
		 * split string at the first "$". set query segment to
		 * left portion
		 */
		tseg->sql = isc_mem_strdup(mctx,
					   isc_string_separate(&right_str,
							       "$"));
		if (tseg->sql == NULL) {
			/* no memory, clean everything up. */
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
		/* tseg->sql points directly to a string. */
		tseg->direct = isc_boolean_true;
		tseg->strlen = strlen(tseg->sql);

		/* check if we encountered "$zone$" token */
		if (strcasecmp(tseg->sql, "zone") == 0) {
			/*
			 * we don't really need, or want the "zone"
			 * text, so get rid of it.
			 */
			isc_mem_free(mctx, tseg->sql);
			/* set tseg->sql to in-direct zone string */
			tseg->sql = (char**) zone;
			tseg->strlen = 0;
			/* tseg->sql points in-directly to a string */
			tseg->direct = isc_boolean_false;
			foundzone = isc_boolean_true;
			/* check if we encountered "$record$" token */
		} else if (strcasecmp(tseg->sql, "record") == 0) {
			/*
			 * we don't really need, or want the "record"
			 * text, so get rid of it.
			 */
			isc_mem_free(mctx, tseg->sql);
			/* set tseg->sql to in-direct record string */
			tseg->sql = (char**) record;
			tseg->strlen = 0;
			/* tseg->sql points in-directly poinsts to a string */
			tseg->direct = isc_boolean_false;
			foundrecord = isc_boolean_true;
			/* check if we encountered "$client$" token */
		} else if (strcasecmp(tseg->sql, "client") == 0) {
			/*
			 * we don't really need, or want the "client"
			 * text, so get rid of it.
			 */
			isc_mem_free(mctx, tseg->sql);
			/* set tseg->sql to in-direct record string */
			tseg->sql = (char**) client;
			tseg->strlen = 0;
			/* tseg->sql points in-directly poinsts to a string */
			tseg->direct = isc_boolean_false;
			foundclient = isc_boolean_true;
		}
	}

	/* we don't need temp_str any more */
	isc_mem_free(mctx, temp_str);
	/*
	 * add checks later to verify zone and record are found if
	 * necessary.
	 */

	/* if this query requires %client%, make sure we found it */
	if (((flags & SDLZH_REQUIRE_CLIENT) != 0) && (!foundclient) ) {
		/* Write error message to log */
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Required token $client$ not found.");
		result = ISC_R_FAILURE;
		goto flag_fail;
	}

	/* if this query requires %record%, make sure we found it */
	if (((flags & SDLZH_REQUIRE_RECORD) != 0) && (!foundrecord) ) {
		/* Write error message to log */
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Required token $record$ not found.");
		result = ISC_R_FAILURE;
		goto flag_fail;
	}

	/* if this query requires %zone%, make sure we found it */
	if (((flags & SDLZH_REQUIRE_ZONE) != 0) && (!foundzone) ) {
		/* Write error message to log */
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Required token $zone$ not found.");
		result = ISC_R_FAILURE;
		goto flag_fail;
	}

	/* pass back the query list */
	*querylist = (query_list_t *) tql;

	/* return success */
	return (ISC_R_SUCCESS);

 cleanup:
	/* get rid of temp_str */
	if (temp_str != NULL)
		isc_mem_free(mctx, temp_str);

 flag_fail:
	/* get rid of what was build of the query list */
	if (tql != NULL)
		destroy_querylist(mctx, &tql);
	return result;
}
int
main(int argc, char *argv[]) {
	char s[1000], *cp, *key;
	size_t len;
	isc_result_t result;
	isc_symvalue_t value;
	int trace = 0;
	int c;
	isc_symexists_t exists_policy = isc_symexists_reject;
	isc_boolean_t case_sensitive = ISC_FALSE;

	while ((c = isc_commandline_parse(argc, argv, "tarc")) != -1) {
		switch (c) {
		case 't':
			trace = 1;
			break;
		case 'a':
			exists_policy = isc_symexists_add;
			break;
		case 'r':
			exists_policy = isc_symexists_replace;
			break;
		case 'c':
			case_sensitive = ISC_TRUE;
			break;
		}
	}

	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_symtab_create(mctx, 691, undefine_action, NULL,
					case_sensitive, &st) == ISC_R_SUCCESS);

	while (fgets(s, sizeof(s), stdin) != NULL) {
		len = strlen(s);
		if (len > 0U && s[len - 1] == '\n') {
			s[len - 1] = '\0';
			len--;
		}

		cp = s;

		if (cp[0] == '!') {
			cp++;
			result = isc_symtab_undefine(st, cp, 1);
			if (trace || result != ISC_R_SUCCESS)
				printf("undefine('%s'): %s\n", cp,
				       isc_result_totext(result));
		} else {
			key = cp;
			while (*cp != '\0' && *cp != ' ' && *cp != '\t')
				cp++;
			if (*cp == '\0') {
				result = isc_symtab_lookup(st, key, 0, &value);
				if (trace || result != ISC_R_SUCCESS) {
					printf("lookup('%s'): %s", key,
					       isc_result_totext(result));
					if (result == ISC_R_SUCCESS) {
						cp = value.as_pointer;
						printf(", value == '%s'", cp);
					}
					printf("\n");
				}
			} else {
				*cp++ = '\0';
				key = isc_mem_strdup(mctx, key);
				value.as_pointer = isc_mem_strdup(mctx, cp);
				result = isc_symtab_define(st, key, 1, value,
							   exists_policy);
				if (trace || result != ISC_R_SUCCESS) {
					printf("define('%s', '%s'): %s\n",
					       key, cp,
					       isc_result_totext(result));
					if (result != ISC_R_SUCCESS)
						undefine_action(key, 1,
							value, NULL);
				}
			}
		}
	}

	isc_symtab_destroy(&st);
	isc_mem_stats(mctx, stdout);
	isc_mem_destroy(&mctx);

	return (0);
}
Пример #5
0
ATF_TC_BODY(symtab_grow, tc) {
	isc_result_t result;
	isc_symtab_t *st = NULL;
	isc_symvalue_t value;
	isc_symexists_t policy = isc_symexists_reject;
	int i;

	UNUSED(tc);

	result = isc_test_begin(NULL, ISC_TRUE);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	result = isc_symtab_create(mctx, 3, undefine, NULL, ISC_FALSE, &st);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
	ATF_REQUIRE(st != NULL);

	/* Nothing should be in the table yet */

	/*
	 * Put 1024 entries in the table (this should necessate
	 * regrowing the hash table several times
	 */
	for (i = 0; i < 1024; i++) {
		char str[16], *key;

		snprintf(str, sizeof(str), "%04x", i);
		key = isc_mem_strdup(mctx, str);
		ATF_REQUIRE(key != NULL);
		value.as_pointer = isc_mem_strdup(mctx, str);
		ATF_REQUIRE(value.as_pointer != NULL);
		result = isc_symtab_define(st, key, 1, value, policy);
		ATF_CHECK_EQ(result, ISC_R_SUCCESS);
		if (result != ISC_R_SUCCESS)
			undefine(key, 1, value, NULL);
	}

	/*
	 * Try to put them in again; this should fail
	 */
	for (i = 0; i < 1024; i++) {
		char str[16], *key;

		snprintf(str, sizeof(str), "%04x", i);
		key = isc_mem_strdup(mctx, str);
		ATF_REQUIRE(key != NULL);
		value.as_pointer = isc_mem_strdup(mctx, str);
		ATF_REQUIRE(value.as_pointer != NULL);
		result = isc_symtab_define(st, key, 1, value, policy);
		ATF_CHECK_EQ(result, ISC_R_EXISTS);
		undefine(key, 1, value, NULL);
	}

	/*
	 * Retrieve them; this should succeed
	 */
	for (i = 0; i < 1024; i++) {
		char str[16];

		snprintf(str, sizeof(str), "%04x", i);
		result = isc_symtab_lookup(st, str, 0, &value);
		ATF_CHECK_EQ(result, ISC_R_SUCCESS);
		ATF_CHECK_STREQ(str, value.as_pointer);
	}

	/*
	 * Undefine them
	 */
	for (i = 0; i < 1024; i++) {
		char str[16];

		snprintf(str, sizeof(str), "%04x", i);
		result = isc_symtab_undefine(st, str, 1);
		ATF_CHECK_EQ(result, ISC_R_SUCCESS);
	}

	/*
	 * Retrieve them again; this should fail
	 */
	for (i = 0; i < 1024; i++) {
		char str[16];

		snprintf(str, sizeof(str), "%04x", i);
		result = isc_symtab_lookup(st, str, 0, &value);
		ATF_CHECK_EQ(result, ISC_R_NOTFOUND);
	}

	isc_symtab_destroy(&st);
	isc_test_end();
}
Пример #6
0
isc_result_t
dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
		const char *name, dns_view_t **viewp)
{
	dns_view_t *view;
	isc_result_t result;

	/*
	 * Create a view.
	 */

	REQUIRE(name != NULL);
	REQUIRE(viewp != NULL && *viewp == NULL);

	view = isc_mem_get(mctx, sizeof(*view));
	if (view == NULL)
		return (ISC_R_NOMEMORY);
	view->name = isc_mem_strdup(mctx, name);
	if (view->name == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup_view;
	}
	result = isc_mutex_init(&view->lock);
	if (result != ISC_R_SUCCESS)
		goto cleanup_name;

#ifdef BIND9
	view->zonetable = NULL;
	result = dns_zt_create(mctx, rdclass, &view->zonetable);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "dns_zt_create() failed: %s",
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
		goto cleanup_mutex;
	}
#endif
	view->secroots_priv = NULL;
	view->fwdtable = NULL;
	result = dns_fwdtable_create(mctx, &view->fwdtable);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "dns_fwdtable_create() failed: %s",
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
		goto cleanup_zt;
	}

	view->acache = NULL;
	view->cache = NULL;
	view->cachedb = NULL;
	view->dlzdatabase = NULL;
	view->hints = NULL;
	view->resolver = NULL;
	view->adb = NULL;
	view->requestmgr = NULL;
	view->mctx = mctx;
	view->rdclass = rdclass;
	view->frozen = ISC_FALSE;
	view->task = NULL;
	result = isc_refcount_init(&view->references, 1);
	if (result != ISC_R_SUCCESS)
		goto cleanup_fwdtable;
	view->weakrefs = 0;
	view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
			    DNS_VIEWATTR_REQSHUTDOWN);
	view->statickeys = NULL;
	view->dynamickeys = NULL;
	view->matchclients = NULL;
	view->matchdestinations = NULL;
	view->matchrecursiveonly = ISC_FALSE;
	result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
	if (result != ISC_R_SUCCESS)
		goto cleanup_references;
	view->peers = NULL;
	view->order = NULL;
	view->delonly = NULL;
	view->rootdelonly = ISC_FALSE;
	view->rootexclude = NULL;
	view->resstats = NULL;
	view->resquerystats = NULL;
	view->cacheshared = ISC_FALSE;
	ISC_LIST_INIT(view->dns64);
	view->dns64cnt = 0;

	/*
	 * Initialize configuration data with default values.
	 */
	view->recursion = ISC_TRUE;
	view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */
	view->additionalfromcache = ISC_TRUE;
	view->additionalfromauth = ISC_TRUE;
	view->enablednssec = ISC_TRUE;
	view->enablevalidation = ISC_TRUE;
	view->acceptexpired = ISC_FALSE;
	view->minimalresponses = ISC_FALSE;
	view->transfer_format = dns_one_answer;
	view->cacheacl = NULL;
	view->cacheonacl = NULL;
	view->queryacl = NULL;
	view->queryonacl = NULL;
	view->recursionacl = NULL;
	view->recursiononacl = NULL;
	view->sortlist = NULL;
	view->transferacl = NULL;
	view->notifyacl = NULL;
	view->updateacl = NULL;
	view->upfwdacl = NULL;
	view->denyansweracl = NULL;
	view->answeracl_exclude = NULL;
	view->denyanswernames = NULL;
	view->answernames_exclude = NULL;
	view->requestixfr = ISC_TRUE;
	view->provideixfr = ISC_TRUE;
	view->maxcachettl = 7 * 24 * 3600;
	view->maxncachettl = 3 * 3600;
	view->dstport = 53;
	view->preferred_glue = 0;
	view->flush = ISC_FALSE;
	view->dlv = NULL;
	view->maxudp = 0;
	view->v4_aaaa = dns_v4_aaaa_ok;
	view->v4_aaaa_acl = NULL;
	ISC_LIST_INIT(view->rpz_zones);
	view->rpz_recursive_only = ISC_TRUE;
	view->rpz_break_dnssec = ISC_FALSE;
	dns_fixedname_init(&view->dlv_fixed);
	view->managed_keys = NULL;
#ifdef BIND9
	view->new_zone_file = NULL;
	view->new_zone_config = NULL;
	view->cfg_destroy = NULL;

	result = dns_order_create(view->mctx, &view->order);
	if (result != ISC_R_SUCCESS)
		goto cleanup_dynkeys;
#endif

	result = dns_peerlist_new(view->mctx, &view->peers);
	if (result != ISC_R_SUCCESS)
		goto cleanup_order;

	result = dns_aclenv_init(view->mctx, &view->aclenv);
	if (result != ISC_R_SUCCESS)
		goto cleanup_peerlist;

	ISC_LINK_INIT(view, link);
	ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
		       DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown,
		       view, NULL, NULL, NULL);
	ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
		       DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown,
		       view, NULL, NULL, NULL);
	ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
		       DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown,
		       view, NULL, NULL, NULL);
	view->magic = DNS_VIEW_MAGIC;

	*viewp = view;

	return (ISC_R_SUCCESS);

 cleanup_peerlist:
	dns_peerlist_detach(&view->peers);

 cleanup_order:
#ifdef BIND9
	dns_order_detach(&view->order);

 cleanup_dynkeys:
#endif
	dns_tsigkeyring_detach(&view->dynamickeys);

 cleanup_references:
	isc_refcount_destroy(&view->references);

 cleanup_fwdtable:
	dns_fwdtable_destroy(&view->fwdtable);

 cleanup_zt:
#ifdef BIND9
	dns_zt_detach(&view->zonetable);

 cleanup_mutex:
#endif
	DESTROYLOCK(&view->lock);

 cleanup_name:
	isc_mem_free(mctx, view->name);

 cleanup_view:
	isc_mem_put(mctx, view, sizeof(*view));

	return (result);
}
Пример #7
0
static isc_result_t
pkcs11ecdsa_fetch(dst_key_t *key, const char *engine, const char *label,
		  dst_key_t *pub)
{
	CK_RV rv;
	CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
	CK_KEY_TYPE keyType = CKK_EC;
	CK_ATTRIBUTE searchTemplate[] =
	{
		{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
		{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
		{ CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
		{ CKA_LABEL, NULL, 0 }
	};
	CK_ULONG cnt;
	CK_ATTRIBUTE *attr;
	CK_ATTRIBUTE *pubattr;
	pk11_object_t *ec;
	pk11_object_t *pubec;
	pk11_context_t *pk11_ctx = NULL;
	isc_result_t ret;

	if (label == NULL)
		return (DST_R_NOENGINE);

	ec = key->keydata.pkey;
	pubec = pub->keydata.pkey;

	ec->object = CK_INVALID_HANDLE;
	ec->ontoken = ISC_TRUE;
	ec->reqlogon = ISC_TRUE;
	ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
	if (ec->repr == NULL)
		return (ISC_R_NOMEMORY);
	memset(ec->repr, 0, sizeof(*attr) * 2);
	ec->attrcnt = 2;
	attr = ec->repr;

	attr->type = CKA_EC_PARAMS;
	pubattr = pk11_attribute_bytype(pubec, CKA_EC_PARAMS);
	attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
	if (attr->pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
	attr->ulValueLen = pubattr->ulValueLen;
	attr++;

	attr->type = CKA_EC_POINT;
	pubattr = pk11_attribute_bytype(pubec, CKA_EC_POINT);
	attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
	if (attr->pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
	attr->ulValueLen = pubattr->ulValueLen;

	ret = pk11_parse_uri(ec, label, key->mctx, OP_EC);
	if (ret != ISC_R_SUCCESS)
		goto err;

	pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
						  sizeof(*pk11_ctx));
	if (pk11_ctx == NULL)
		DST_RET(ISC_R_NOMEMORY);
	ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE,
			       ec->reqlogon, NULL, ec->slot);
	if (ret != ISC_R_SUCCESS)
		goto err;

	attr = pk11_attribute_bytype(ec, CKA_LABEL);
	if (attr == NULL) {
		attr = pk11_attribute_bytype(ec, CKA_ID);
		INSIST(attr != NULL);
		searchTemplate[3].type = CKA_ID;
	}
	searchTemplate[3].pValue = attr->pValue;
	searchTemplate[3].ulValueLen = attr->ulValueLen;

	PK11_RET(pkcs_C_FindObjectsInit,
		 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
		 DST_R_CRYPTOFAILURE);
	PK11_RET(pkcs_C_FindObjects,
		 (pk11_ctx->session, &ec->object, (CK_ULONG) 1, &cnt),
		 DST_R_CRYPTOFAILURE);
	(void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
	if (cnt == 0)
		DST_RET(ISC_R_NOTFOUND);
	if (cnt > 1)
		DST_RET(ISC_R_EXISTS);

	if (engine != NULL) {
		key->engine = isc_mem_strdup(key->mctx, engine);
		if (key->engine == NULL)
			DST_RET(ISC_R_NOMEMORY);
	}

	key->label = isc_mem_strdup(key->mctx, label);
	if (key->label == NULL)
		DST_RET(ISC_R_NOMEMORY);

	pk11_return_session(pk11_ctx);
	memset(pk11_ctx, 0, sizeof(*pk11_ctx));
	isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
	return (ISC_R_SUCCESS);

 err:
	if (pk11_ctx != NULL) {
		pk11_return_session(pk11_ctx);
		memset(pk11_ctx, 0, sizeof(*pk11_ctx));
		isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
	}
	return (ret);
}
Пример #8
0
isc_result_t
dns_dlzcreate(isc_mem_t *mctx, const char *dlzname, const char *drivername,
	      unsigned int argc, char *argv[], dns_dlzdb_t **dbp)
{
	dns_dlzimplementation_t *impinfo;
	isc_result_t result;
	dns_dlzdb_t *db = NULL;

	/*
	 * initialize the dlz_implementations list, this is guaranteed
	 * to only really happen once.
	 */
	RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);

	/*
	 * Performs checks to make sure data is as we expect it to be.
	 */
	REQUIRE(dbp != NULL && *dbp == NULL);
	REQUIRE(dlzname != NULL);
	REQUIRE(drivername != NULL);
	REQUIRE(mctx != NULL);

	/* write log message */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
		      "Loading '%s' using driver %s", dlzname, drivername);

	/* lock the dlz_implementations list so we can search it. */
	RWLOCK(&dlz_implock, isc_rwlocktype_read);

	/* search for the driver implementation	 */
	impinfo = dlz_impfind(drivername);
	if (impinfo == NULL) {
		RWUNLOCK(&dlz_implock, isc_rwlocktype_read);

		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "unsupported DLZ database driver '%s'."
			      "  %s not loaded.",
			      drivername, dlzname);

		return (ISC_R_NOTFOUND);
	}

	/* Allocate memory to hold the DLZ database driver */
	db = isc_mem_get(mctx, sizeof(dns_dlzdb_t));
	if (db == NULL) {
		RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
		return (ISC_R_NOMEMORY);
	}

	/* Make sure memory region is set to all 0's */
	memset(db, 0, sizeof(dns_dlzdb_t));

	ISC_LINK_INIT(db, link);
	db->implementation = impinfo;
	if (dlzname != NULL)
		db->dlzname = isc_mem_strdup(mctx, dlzname);

	/* Create a new database using implementation 'drivername'. */
	result = ((impinfo->methods->create)(mctx, dlzname, argc, argv,
					     impinfo->driverarg,
					     &db->dbdata));

	/* mark the DLZ driver as valid */
	if (result == ISC_R_SUCCESS) {
		RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
		db->magic = DNS_DLZ_MAGIC;
		isc_mem_attach(mctx, &db->mctx);
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
			      "DLZ driver loaded successfully.");
		*dbp = db;
		return (ISC_R_SUCCESS);
	} else {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "DLZ driver failed to load.");
	}

	/* impinfo->methods->create failed. */
	RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
	isc_mem_put(mctx, db, sizeof(dns_dlzdb_t));
	return (result);
}
Пример #9
0
static isc_result_t
ldap_process_results(LDAP *dbc, LDAPMessage *msg, char ** attrs,
		     void *ptr, isc_boolean_t allnodes)
{
	isc_result_t result = ISC_R_SUCCESS;
	int i = 0;
	int j;
	int len;
	char *attribute = NULL;
	LDAPMessage *entry;
	char *endp = NULL;
	char *host = NULL;
	char *type = NULL;
	char *data = NULL;
	char **vals = NULL;
	int ttl;

	/* make sure there are at least some attributes to process. */
	REQUIRE(attrs != NULL || attrs[0] != NULL);

	/* get the first entry to process */
	entry = ldap_first_entry(dbc, msg);
	if (entry == NULL) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
			      "LDAP no entries to process.");
		return (ISC_R_FAILURE);
	}

	/* loop through all entries returned */
	while (entry != NULL) {
		/* reset for this loop */
		ttl = 0;
		len = 0;
		i = 0;
		attribute = attrs[i];

		/* determine how much space we need for data string */
		for (j = 0; attrs[j] != NULL; j++) {
			/* get the list of values for this attribute. */
			vals = ldap_get_values(dbc, entry, attrs[j]);
			/* skip empty attributes. */
			if (vals == NULL || ldap_count_values(vals) < 1)
				continue;
			/*
			 * we only use the first value.  this driver
			 * does not support multi-valued attributes.
			 */
			len = len + strlen(vals[0]) + 1;
			/* free vals for next loop */
			ldap_value_free(vals);
		} /* end for (j = 0; attrs[j] != NULL, j++) loop */

		/* allocate memory for data string */
		data = isc_mem_allocate(ns_g_mctx, len + 1);
		if (data == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver unable to allocate memory "
				      "while processing results");
			result = ISC_R_FAILURE;
			goto cleanup;
		}

		/*
		 * Make sure data is null termed at the beginning so
		 * we can check if any data was stored to it later.
		 */
		data[0] = '\0';

		/* reset j to re-use below */
		j = 0;

		/* loop through the attributes in the order specified. */
		while (attribute != NULL) {
			/* get the list of values for this attribute. */
			vals = ldap_get_values(dbc, entry, attribute);

			/* skip empty attributes. */
			if (vals == NULL || vals[0] == NULL) {
				/* increment attibute pointer */
				attribute = attrs[++i];
				/* start loop over */
				continue;
			}

			/*
			 * j initially = 0.  Increment j each time we
			 * set a field that way next loop will set
			 * next field.
			 */
			switch(j) {
			case 0:
				j++;
				/*
				 * convert text to int, make sure it
				 * worked right
				 */
				ttl = strtol(vals[0], &endp, 10);
				if (*endp != '\0' || ttl < 0) {
					isc_log_write(dns_lctx,
						      DNS_LOGCATEGORY_DATABASE,
						      DNS_LOGMODULE_DLZ,
						      ISC_LOG_ERROR,
						      "LDAP driver ttl must "
						      "be a postive number");
					goto cleanup;
				}
				break;
			case 1:
				j++;
				type = isc_mem_strdup(ns_g_mctx, vals[0]);
				break;
			case 2:
				j++;
				if (allnodes == isc_boolean_true) {
					host = isc_mem_strdup(ns_g_mctx,
							      vals[0]);
				} else {
					strcpy(data, vals[0]);
				}
				break;
			case 3:
				j++;
				if (allnodes == isc_boolean_true) {
					strcpy(data, vals[0]);
				} else {
					strcat(data, " ");
					strcat(data, vals[0]);
				}
				break;
			default:
				strcat(data, " ");
				strcat(data, vals[0]);
				break;
			} /* end switch(j) */

			/* free values */
			ldap_value_free(vals);
			vals = NULL;

			/* increment attibute pointer */
			attribute = attrs[++i];
		}	/* end while (attribute != NULL) */

		if (type == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver unable "
				      "to retrieve DNS type");
			result = ISC_R_FAILURE;
			goto cleanup;
		}

		if (strlen(data) < 1) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver unable "
				      "to retrieve DNS data");
			result = ISC_R_FAILURE;
			goto cleanup;
		}

		if (allnodes == isc_boolean_true) {
			if (strcasecmp(host, "~") == 0)
				result = dns_sdlz_putnamedrr(
						(dns_sdlzallnodes_t *) ptr,
						"*", type, ttl, data);
			else
				result = dns_sdlz_putnamedrr(
						(dns_sdlzallnodes_t *) ptr,
						host, type, ttl, data);
			if (result != ISC_R_SUCCESS)
				isc_log_write(dns_lctx,
					DNS_LOGCATEGORY_DATABASE,
					DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
					"dlz-ldap: putnamedrr failed "
					"for \"%s %s %u %s\", %s",
					host, type, ttl, data,
					isc_result_totext(result));
		} else {
			result = dns_sdlz_putrr((dns_sdlzlookup_t *) ptr,
						type, ttl, data);
			if (result != ISC_R_SUCCESS)
				isc_log_write(dns_lctx,
					DNS_LOGCATEGORY_DATABASE,
					DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
					"dlz-ldap: putrr failed "
					"for \"%s %u %s\", %s",
					type, ttl, data,
					isc_result_totext(result));
		}

		if (result != ISC_R_SUCCESS) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver failed "
				      "while sending data to BIND.");
			goto cleanup;
		}

		/* free memory for type, data and host for next loop */
		isc_mem_free(ns_g_mctx, type);
		isc_mem_free(ns_g_mctx, data);
		if (host != NULL)
			isc_mem_free(ns_g_mctx, host);

		/* get the next entry to process */
		entry = ldap_next_entry(dbc, entry);
	} /* end while (entry != NULL) */

 cleanup:
	/* de-allocate memory */
	if (vals != NULL)
		ldap_value_free(vals);
	if (host != NULL)
		isc_mem_free(ns_g_mctx, host);
	if (type != NULL)
		isc_mem_free(ns_g_mctx, type);
	if (data != NULL)
		isc_mem_free(ns_g_mctx, data);

	return (result);
}
Пример #10
0
static void
plus_option(char *option) {
	isc_result_t result;
	char option_store[256];
	char *cmd, *value, *ptr;
	isc_boolean_t state = ISC_TRUE;

	strlcpy(option_store, option, sizeof(option_store));
	ptr = option_store;
	cmd = next_token(&ptr,"=");
	if (cmd == NULL) {
		printf(";; Invalid option %s\n", option_store);
		return;
	}
	value = ptr;
	if (strncasecmp(cmd, "no", 2)==0) {
		cmd += 2;
		state = ISC_FALSE;
	}

#define FULLCHECK(A) \
	do { \
		size_t _l = strlen(cmd); \
		if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \
			goto invalid_option; \
	} while (/*CONSTCOND*/0)

	switch (cmd[0]) {
	case 'a': /* all */
		FULLCHECK("all");
		showcomments = state;
		rrcomments = state;
		showtrust = state;
		break;
	case 'c':
		switch (cmd[1]) {
		case 'd': /* cdflag */
			FULLCHECK("cdflag");
			cdflag = state;
			break;
		case 'l': /* class */
			FULLCHECK("class");
			noclass = ISC_TF(!state);
			break;
		case 'o': /* comments */
			FULLCHECK("comments");
			showcomments = state;
			break;
		case 'r': /* crypto */
			FULLCHECK("crypto");
			nocrypto = ISC_TF(!state);
			break;
		default:
			goto invalid_option;
		}
		break;
	case 'd':
		switch (cmd[1]) {
		case 'l': /* dlv */
			FULLCHECK("dlv");
			if (state && no_sigs)
				break;
			dlv_validation = state;
			if (value != NULL) {
				dlv_anchor = isc_mem_strdup(mctx, value);
				if (dlv_anchor == NULL)
					fatal("out of memory");
			}
			break;
		case 'n': /* dnssec */
			FULLCHECK("dnssec");
			showdnssec = state;
			break;
		default:
			goto invalid_option;
		}
		break;
	case 'm':
		switch (cmd[1]) {
		case 't': /* mtrace */
			message_trace = state;
			if (state)
				resolve_trace = state;
			break;
		case 'u': /* multiline */
			FULLCHECK("multiline");
			multiline = state;
			break;
		default:
			goto invalid_option;
		}
		break;
	case 'r':
		switch (cmd[1]) {
		case 'o': /* root */
			FULLCHECK("root");
			if (state && no_sigs)
				break;
			root_validation = state;
			if (value != NULL) {
				trust_anchor = isc_mem_strdup(mctx, value);
				if (trust_anchor == NULL)
					fatal("out of memory");
			}
			break;
		case 'r': /* rrcomments */
			FULLCHECK("rrcomments");
			rrcomments = state;
			break;
		case 't': /* rtrace */
			FULLCHECK("rtrace");
			resolve_trace = state;
			break;
		default:
			goto invalid_option;
		}
		break;
	case 's':
		switch (cmd[1]) {
		case 'h': /* short */
			FULLCHECK("short");
			short_form = state;
			if (short_form) {
				multiline = ISC_FALSE;
				showcomments = ISC_FALSE;
				showtrust = ISC_FALSE;
				showdnssec = ISC_FALSE;
			}
			break;
		case 'p': /* split */
			FULLCHECK("split");
			if (value != NULL && !state)
				goto invalid_option;
			if (!state) {
				splitwidth = 0;
				break;
			} else if (value == NULL)
				break;

			result = parse_uint(&splitwidth, value,
					    1023, "split");
			if (splitwidth % 4 != 0) {
				splitwidth = ((splitwidth + 3) / 4) * 4;
				warn("split must be a multiple of 4; "
				     "adjusting to %d", splitwidth);
			}
			/*
			 * There is an adjustment done in the
			 * totext_<rrtype>() functions which causes
			 * splitwidth to shrink.  This is okay when we're
			 * using the default width but incorrect in this
			 * case, so we correct for it
			 */
			if (splitwidth)
				splitwidth += 3;
			if (result != ISC_R_SUCCESS)
				fatal("Couldn't parse split");
			break;
		default:
			goto invalid_option;
		}
		break;
	case 't':
		switch (cmd[1]) {
		case 'r': /* trust */
			FULLCHECK("trust");
			showtrust = state;
			break;
		case 't': /* ttl */
			FULLCHECK("ttl");
			nottl = ISC_TF(!state);
			break;
		default:
			goto invalid_option;
		}
		break;
	case 'v': /* vtrace */
		FULLCHECK("vtrace");
		validator_trace = state;
		if (state)
			resolve_trace = state;
		break;
	default:
	invalid_option:
		/*
		 * We can also add a "need_value:" case here if we ever
		 * add a plus-option that requires a specified value
		 */
		fprintf(stderr, "Invalid option: +%s\n", option);
		usage();
	}
	return;
}
Пример #11
0
static isc_result_t
opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
		     const char *pin)
{
#ifdef USE_ENGINE
	ENGINE *e = NULL;
	isc_result_t ret;
	EVP_PKEY *pkey = NULL;
	RSA *rsa = NULL, *pubrsa = NULL;
	char *colon;

	UNUSED(pin);

	if (engine == NULL)
		DST_RET(DST_R_NOENGINE);
	e = dst__openssl_getengine(engine);
	if (e == NULL)
		DST_RET(DST_R_NOENGINE);
	pkey = ENGINE_load_public_key(e, label, NULL, NULL);
	if (pkey != NULL) {
		pubrsa = EVP_PKEY_get1_RSA(pkey);
		EVP_PKEY_free(pkey);
		if (pubrsa == NULL)
			DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
	}
	pkey = ENGINE_load_private_key(e, label, NULL, NULL);
	if (pkey == NULL)
		DST_RET(dst__openssl_toresult2("ENGINE_load_private_key",
					       ISC_R_NOTFOUND));
	if (engine != NULL) {
		key->engine = isc_mem_strdup(key->mctx, engine);
		if (key->engine == NULL)
			DST_RET(ISC_R_NOMEMORY);
	} else {
		key->engine = isc_mem_strdup(key->mctx, label);
		if (key->engine == NULL)
			DST_RET(ISC_R_NOMEMORY);
		colon = strchr(key->engine, ':');
		if (colon != NULL)
			*colon = '\0';
	}
	key->label = isc_mem_strdup(key->mctx, label);
	if (key->label == NULL)
		DST_RET(ISC_R_NOMEMORY);
	rsa = EVP_PKEY_get1_RSA(pkey);
	if (rsa == NULL)
		DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
	if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
		DST_RET(DST_R_INVALIDPRIVATEKEY);
	if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS)
		DST_RET(ISC_R_RANGE);
	if (pubrsa != NULL)
		RSA_free(pubrsa);
	key->key_size = EVP_PKEY_bits(pkey);
#if USE_EVP
	key->keydata.pkey = pkey;
	RSA_free(rsa);
#else
	key->keydata.rsa = rsa;
	EVP_PKEY_free(pkey);
#endif
	return (ISC_R_SUCCESS);

 err:
	if (rsa != NULL)
		RSA_free(rsa);
	if (pubrsa != NULL)
		RSA_free(pubrsa);
	if (pkey != NULL)
		EVP_PKEY_free(pkey);
	return (ret);
#else
	UNUSED(key);
	UNUSED(engine);
	UNUSED(label);
	UNUSED(pin);
	return(DST_R_NOENGINE);
#endif
}
Пример #12
0
static isc_result_t
setup_dnsseckeys(dns_client_t *client) {
	isc_result_t result;
	cfg_parser_t *parser = NULL;
	const cfg_obj_t *keys = NULL;
	const cfg_obj_t *managed_keys = NULL;
	cfg_obj_t *bindkeys = NULL;
	const char *filename = anchorfile;

	if (!root_validation && !dlv_validation)
		return (ISC_R_SUCCESS);

	if (filename == NULL) {
#ifndef WIN32
		filename = NS_SYSCONFDIR "/bind.keys";
#else
		static char buf[MAX_PATH];
		strlcpy(buf, isc_ntpaths_get(SYS_CONF_DIR), sizeof(buf));
		strlcat(buf, "\\bind.keys", sizeof(buf));
		filename = buf;
#endif
	}

	if (trust_anchor == NULL) {
		trust_anchor = isc_mem_strdup(mctx, ".");
		if (trust_anchor == NULL)
			fatal("out of memory");
	}

	if (trust_anchor != NULL)
		CHECK(convert_name(&afn, &anchor_name, trust_anchor));
	if (dlv_anchor != NULL)
		CHECK(convert_name(&dfn, &dlv_name, dlv_anchor));

	CHECK(cfg_parser_create(mctx, dns_lctx, &parser));

	if (access(filename, R_OK) != 0) {
		if (anchorfile != NULL)
			fatal("Unable to read key file '%s'", anchorfile);
	} else {
		result = cfg_parse_file(parser, filename,
					&cfg_type_bindkeys, &bindkeys);
		if (result != ISC_R_SUCCESS)
			if (anchorfile != NULL)
				fatal("Unable to load keys from '%s'",
				      anchorfile);
	}

	if (bindkeys == NULL) {
		isc_buffer_t b;

		isc_buffer_init(&b, anchortext, sizeof(anchortext) - 1);
		isc_buffer_add(&b, sizeof(anchortext) - 1);
		result = cfg_parse_buffer(parser, &b, &cfg_type_bindkeys,
					  &bindkeys);
		if (result != ISC_R_SUCCESS)
			fatal("Unable to parse built-in keys");
	}

	INSIST(bindkeys != NULL);
	cfg_map_get(bindkeys, "trusted-keys", &keys);
	cfg_map_get(bindkeys, "managed-keys", &managed_keys);

	if (keys != NULL)
		CHECK(load_keys(keys, client));
	if (managed_keys != NULL)
		CHECK(load_keys(managed_keys, client));
	result = ISC_R_SUCCESS;

	if (trusted_keys == 0)
		fatal("No trusted keys were loaded");

	if (dlv_validation)
		dns_client_setdlv(client, dns_rdataclass_in, dlv_anchor);

 cleanup:
	if (result != ISC_R_SUCCESS)
		delv_log(ISC_LOG_ERROR, "setup_dnsseckeys: %s",
			  isc_result_totext(result));
	return (result);
}
Пример #13
0
/*
 * Argument parsing is based on dig, but simplified: only one
 * QNAME/QCLASS/QTYPE tuple can be specified, and options have
 * been removed that aren't applicable to delv. The interface
 * should be familiar to dig users, however.
 */
static void
parse_args(int argc, char **argv) {
	isc_result_t result;
	isc_textregion_t tr;
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	isc_boolean_t open_type_class = ISC_TRUE;

	for (; argc > 0; argc--, argv++) {
		if (argv[0][0] == '@') {
			server = &argv[0][1];
		} else if (argv[0][0] == '+') {
			plus_option(&argv[0][1]);
		} else if (argv[0][0] == '-') {
			if (argc <= 1) {
				if (dash_option(&argv[0][1], NULL,
						&open_type_class))
				{
					argc--;
					argv++;
				}
			} else {
				if (dash_option(&argv[0][1], argv[1],
						&open_type_class))
				{
					argc--;
					argv++;
				}
			}
		} else {
			/*
			 * Anything which isn't an option
			 */
			if (open_type_class) {
				tr.base = argv[0];
				tr.length = strlen(argv[0]);
				result = dns_rdatatype_fromtext(&rdtype,
					(isc_textregion_t *)&tr);
				if (result == ISC_R_SUCCESS) {
					if (typeset)
						warn("extra query type");
					if (rdtype == dns_rdatatype_ixfr ||
					    rdtype == dns_rdatatype_axfr)
						fatal("Transfer not supported");
					qtype = rdtype;
					typeset = ISC_TRUE;
					continue;
				}
				result = dns_rdataclass_fromtext(&rdclass,
						     (isc_textregion_t *)&tr);
				if (result == ISC_R_SUCCESS) {
					if (classset)
						warn("extra query class");
					else if (rdclass != dns_rdataclass_in)
						warn("ignoring non-IN "
						     "query class");
					continue;
				}
			}

			if (curqname == NULL) {
				curqname = isc_mem_strdup(mctx, argv[0]);
				if (curqname == NULL)
					fatal("out of memory");
			}
		}
	}

	/*
	 * If no qname or qtype specified, search for root/NS
	 * If no qtype specified, use A
	 */
	if (!typeset)
		qtype = dns_rdatatype_a;

	if (curqname == NULL) {
		qname = isc_mem_strdup(mctx, ".");
		if (qname == NULL)
			fatal("out of memory");

		if (!typeset)
			qtype = dns_rdatatype_ns;
	} else
		qname = curqname;
}
Пример #14
0
static isc_boolean_t
dash_option(char *option, char *next, isc_boolean_t *open_type_class) {
	char opt, *value;
	isc_result_t result;
	isc_boolean_t value_from_next;
	isc_textregion_t tr;
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	char textname[MAXNAME];
	struct in_addr in4;
	struct in6_addr in6;
	in_port_t srcport;
	isc_uint32_t num;
	char *hash;

	while (strpbrk(option, single_dash_opts) == &option[0]) {
		/*
		 * Since the -[46himv] options do not take an argument,
		 * account for them (in any number and/or combination)
		 * if they appear as the first character(s) of a q-opt.
		 */
		opt = option[0];
		switch (opt) {
		case '4':
			if (isc_net_probeipv4() != ISC_R_SUCCESS)
				fatal("IPv4 networking not available");
			if (use_ipv6) {
				isc_net_disableipv6();
				use_ipv6 = ISC_FALSE;
			}
			break;
		case '6':
			if (isc_net_probeipv6() != ISC_R_SUCCESS)
				fatal("IPv6 networking not available");
			if (use_ipv4) {
				isc_net_disableipv4();
				use_ipv4 = ISC_FALSE;
			}
			break;
		case 'h':
			usage();
			exit(0);
			/* NOTREACHED */
		case 'i':
			no_sigs = ISC_TRUE;
			dlv_validation = ISC_FALSE;
			root_validation = ISC_FALSE;
			break;
		case 'm':
			/* handled in preparse_args() */
			break;
		case 'v':
			fputs("delv " VERSION "\n", stderr);
			exit(0);
			/* NOTREACHED */
		default:
			INSIST(0);
		}
		if (strlen(option) > 1U)
			option = &option[1];
		else
			return (ISC_FALSE);
	}
	opt = option[0];
	if (strlen(option) > 1U) {
		value_from_next = ISC_FALSE;
		value = &option[1];
	} else {
		value_from_next = ISC_TRUE;
		value = next;
	}
	if (value == NULL)
		goto invalid_option;
	switch (opt) {
	case 'a':
		anchorfile = isc_mem_strdup(mctx, value);
		if (anchorfile == NULL)
			fatal("out of memory");
		return (value_from_next);
	case 'b':
		hash = strchr(value, '#');
		if (hash != NULL) {
			result = parse_uint(&num, hash + 1, 0xffff, "port");
			if (result != ISC_R_SUCCESS)
				fatal("Couldn't parse port number");
			srcport = num;
			*hash = '\0';
		} else
			srcport = 0;

		if (inet_pton(AF_INET, value, &in4) == 1) {
			if (srcaddr4 != NULL)
				fatal("Only one local address per family "
				      "can be specified\n");
			isc_sockaddr_fromin(&a4, &in4, srcport);
			srcaddr4 = &a4;
		} else if (inet_pton(AF_INET6, value, &in6) == 1) {
			if (srcaddr6 != NULL)
				fatal("Only one local address per family "
				      "can be specified\n");
			isc_sockaddr_fromin6(&a6, &in6, srcport);
			srcaddr6 = &a6;
		} else {
			if (hash != NULL)
				*hash = '#';
			fatal("Invalid address %s", value);
		}
		if (hash != NULL)
			*hash = '#';
		return (value_from_next);
	case 'c':
		if (classset)
			warn("extra query class");

		*open_type_class = ISC_FALSE;
		tr.base = value;
		tr.length = strlen(value);
		result = dns_rdataclass_fromtext(&rdclass,
						 (isc_textregion_t *)&tr);
		if (result == ISC_R_SUCCESS)
			classset = ISC_TRUE;
		else if (rdclass != dns_rdataclass_in)
			warn("ignoring non-IN query class");
		else
			warn("ignoring invalid class");
		return (value_from_next);
	case 'd':
		result = parse_uint(&num, value, 99, "debug level");
		if (result != ISC_R_SUCCESS)
			fatal("Couldn't parse debug level");
		loglevel = num;
		return (value_from_next);
	case 'p':
		port = value;
		return (value_from_next);
	case 'q':
		if (curqname != NULL) {
			warn("extra query name");
			isc_mem_free(mctx, curqname);
		}
		curqname = isc_mem_strdup(mctx, value);
		if (curqname == NULL)
			fatal("out of memory");
		return (value_from_next);
	case 't':
		*open_type_class = ISC_FALSE;
		tr.base = value;
		tr.length = strlen(value);
		result = dns_rdatatype_fromtext(&rdtype,
					(isc_textregion_t *)&tr);
		if (result == ISC_R_SUCCESS) {
			if (typeset)
				warn("extra query type");
			if (rdtype == dns_rdatatype_ixfr ||
			    rdtype == dns_rdatatype_axfr)
				fatal("Transfer not supported");
			qtype = rdtype;
			typeset = ISC_TRUE;
		} else
			warn("ignoring invalid type");
		return (value_from_next);
	case 'x':
		result = get_reverse(textname, sizeof(textname), value,
				     ISC_FALSE);
		if (result == ISC_R_SUCCESS) {
			if (curqname != NULL) {
				isc_mem_free(mctx, curqname);
				warn("extra query name");
			}
			curqname = isc_mem_strdup(mctx, textname);
			if (curqname == NULL)
				fatal("out of memory");
			if (typeset)
				warn("extra query type");
			qtype = dns_rdatatype_ptr;
			typeset = ISC_TRUE;
		} else {
			fprintf(stderr, "Invalid IP address %s\n", value);
			exit(1);
		}
		return (value_from_next);
	invalid_option:
	default:
		fprintf(stderr, "Invalid option: -%s\n", option);
		usage();
	}
	/* NOTREACHED */
	return (ISC_FALSE);
}
/*
 * Called at startup for each dlopen zone in named.conf
 */
static isc_result_t
dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
		  void *driverarg, void **dbdata)
{
	dlopen_data_t *cd;
	isc_mem_t *mctx = NULL;
	isc_result_t result = ISC_R_FAILURE;
	int dlopen_flags = 0;

	UNUSED(driverarg);

	if (argc < 2) {
		dlopen_log(ISC_LOG_ERROR,
			   "dlz_dlopen driver for '%s' needs a path to "
			   "the shared library", dlzname);
		return (ISC_R_FAILURE);
	}

	result = isc_mem_create(0, 0, &mctx);
	if (result != ISC_R_SUCCESS)
		return (result);

	cd = isc_mem_get(mctx, sizeof(*cd));
	if (cd == NULL) {
		isc_mem_destroy(&mctx);
		return (ISC_R_NOMEMORY);
	}
	memset(cd, 0, sizeof(*cd));

	cd->mctx = mctx;

	cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]);
	if (cd->dl_path == NULL) {
		result = ISC_R_NOMEMORY;
		goto failed;
	}

	cd->dlzname = isc_mem_strdup(cd->mctx, dlzname);
	if (cd->dlzname == NULL) {
		result = ISC_R_NOMEMORY;
		goto failed;
	}

	/* Initialize the lock */
	result = isc_mutex_init(&cd->lock);
	if (result != ISC_R_SUCCESS)
		goto failed;

	/* Open the library */
	dlopen_flags = RTLD_NOW|RTLD_GLOBAL;

#ifdef RTLD_DEEPBIND
	/*
	 * If RTLD_DEEPBIND is available then use it. This can avoid
	 * issues with a module using a different version of a system
	 * library than one that bind9 uses. For example, bind9 may link
	 * to MIT kerberos, but the module may use Heimdal. If we don't
	 * use RTLD_DEEPBIND then we could end up with Heimdal functions
	 * calling MIT functions, which leads to bizarre results (usually
	 * a segfault).
	 */
	dlopen_flags |= RTLD_DEEPBIND;
#endif

	cd->dl_handle = dlopen(cd->dl_path, dlopen_flags);
	if (cd->dl_handle == NULL) {
		dlopen_log(ISC_LOG_ERROR,
			   "dlz_dlopen failed to open library '%s' - %s",
			   cd->dl_path, dlerror());
		result = ISC_R_FAILURE;
		goto failed;
	}

	/* Find the symbols */
	cd->dlz_version = (dlz_dlopen_version_t *)
		dl_load_symbol(cd, "dlz_version", ISC_TRUE);
	cd->dlz_create = (dlz_dlopen_create_t *)
		dl_load_symbol(cd, "dlz_create", ISC_TRUE);
	cd->dlz_lookup = (dlz_dlopen_lookup_t *)
		dl_load_symbol(cd, "dlz_lookup", ISC_TRUE);
	cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *)
		dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);

	if (cd->dlz_create == NULL ||
	    cd->dlz_version == NULL ||
	    cd->dlz_lookup == NULL ||
	    cd->dlz_findzonedb == NULL)
	{
		/* We're missing a required symbol */
		result = ISC_R_FAILURE;
		goto failed;
	}

	cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *)
		dl_load_symbol(cd, "dlz_allowzonexfr", ISC_FALSE);
	cd->dlz_allnodes = (dlz_dlopen_allnodes_t *)
		dl_load_symbol(cd, "dlz_allnodes",
			       ISC_TF(cd->dlz_allowzonexfr != NULL));
	cd->dlz_authority = (dlz_dlopen_authority_t *)
		dl_load_symbol(cd, "dlz_authority", ISC_FALSE);
	cd->dlz_newversion = (dlz_dlopen_newversion_t *)
		dl_load_symbol(cd, "dlz_newversion", ISC_FALSE);
	cd->dlz_closeversion = (dlz_dlopen_closeversion_t *)
		dl_load_symbol(cd, "dlz_closeversion",
			       ISC_TF(cd->dlz_newversion != NULL));
	cd->dlz_configure = (dlz_dlopen_configure_t *)
		dl_load_symbol(cd, "dlz_configure", ISC_FALSE);
	cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *)
		dl_load_symbol(cd, "dlz_ssumatch", ISC_FALSE);
	cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *)
		dl_load_symbol(cd, "dlz_addrdataset", ISC_FALSE);
	cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *)
		dl_load_symbol(cd, "dlz_subrdataset", ISC_FALSE);
	cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *)
		dl_load_symbol(cd, "dlz_delrdataset", ISC_FALSE);
	cd->dlz_destroy = (dlz_dlopen_destroy_t *)
		dl_load_symbol(cd, "dlz_destroy", ISC_FALSE);

	/* Check the version of the API is the same */
	cd->version = cd->dlz_version(&cd->flags);
	if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) ||
	    cd->version > DLZ_DLOPEN_VERSION)
	{
		dlopen_log(ISC_LOG_ERROR,
			   "dlz_dlopen: %s: incorrect driver API version %d, "
			   "requires %d",
			   cd->dl_path, cd->version, DLZ_DLOPEN_VERSION);
		result = ISC_R_FAILURE;
		goto failed;
	}

	/*
	 * Call the library's create function. Note that this is an
	 * extended version of dlz create, with the addition of
	 * named function pointers for helper functions that the
	 * driver will need. This avoids the need for the backend to
	 * link the BIND9 libraries
	 */
	MAYBE_LOCK(cd);
	result = cd->dlz_create(dlzname, argc-1, argv+1,
				&cd->dbdata,
				"log", dlopen_log,
				"putrr", dns_sdlz_putrr,
				"putnamedrr", dns_sdlz_putnamedrr,
				"writeable_zone", dns_dlz_writeablezone,
				NULL);
	MAYBE_UNLOCK(cd);
	if (result != ISC_R_SUCCESS)
		goto failed;

	*dbdata = cd;

	return (ISC_R_SUCCESS);

failed:
	dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname);
	if (cd->dl_path != NULL)
		isc_mem_free(mctx, cd->dl_path);
	if (cd->dlzname != NULL)
		isc_mem_free(mctx, cd->dlzname);
	if (dlopen_flags != 0)
		(void) isc_mutex_destroy(&cd->lock);
#ifdef HAVE_DLCLOSE
	if (cd->dl_handle)
		dlclose(cd->dl_handle);
#endif
	isc_mem_put(mctx, cd, sizeof(*cd));
	isc_mem_destroy(&mctx);
	return (result);
}
Пример #16
0
/*%
 * This function is the real core of the driver.   Zone, record
 * and client strings are passed in (or NULL is passed if the
 * string is not available).  The type of query we want to run
 * is indicated by the query flag, and the dbdata object is passed
 * passed in to.  dbdata really holds either:
 *		1) a list of database instances (in multithreaded mode) OR
 *		2) a single database instance (in single threaded mode)
 * The function will construct the query and obtain an available
 * database instance (DBI).  It will then run the query and hopefully
 * obtain a result set.
 */
static isc_result_t
ldap_get_results(const char *zone, const char *record,
		 const char *client, unsigned int query,
		 void *dbdata, void *ptr)
{
	isc_result_t result;
	dbinstance_t *dbi = NULL;
	char *querystring = NULL;
	LDAPURLDesc *ldap_url = NULL;
	int ldap_result = 0;
	LDAPMessage *ldap_msg = NULL;
	int i;
	int entries;

	/* get db instance / connection */
#ifdef ISC_PLATFORM_USETHREADS

	/* find an available DBI from the list */
	dbi = ldap_find_avail_conn((db_list_t *)
				   ((ldap_instance_t *)dbdata)->db);

#else /* ISC_PLATFORM_USETHREADS */

	/*
	 * only 1 DBI - no need to lock instance lock either
	 * only 1 thread in the whole process, no possible contention.
	 */
	dbi =  (dbinstance_t *) ((ldap_instance_t *)dbdata)->db;

#endif /* ISC_PLATFORM_USETHREADS */

	/* if DBI is null, can't do anything else */
	if (dbi == NULL)
		return (ISC_R_FAILURE);

	/* set fields */
	if (zone != NULL) {
		dbi->zone = isc_mem_strdup(ns_g_mctx, zone);
		if (dbi->zone == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {
		dbi->zone = NULL;
	}
	if (record != NULL) {
		dbi->record = isc_mem_strdup(ns_g_mctx, record);
		if (dbi->record == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {
		dbi->record = NULL;
	}
	if (client != NULL) {
		dbi->client = isc_mem_strdup(ns_g_mctx, client);
		if (dbi->client == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {
		dbi->client = NULL;
	}

	/* what type of query are we going to run? */
	switch(query) {
	case ALLNODES:
		/*
		 * if the query was not passed in from the config file
		 * then we can't run it.  return not_implemented, so
		 * it's like the code for that operation was never
		 * built into the driver.... AHHH flexibility!!!
		 */
		if (dbi->allnodes_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		} else {
			querystring = build_querystring(ns_g_mctx,
			dbi->allnodes_q);
		}
		break;
	case ALLOWXFR:
		/* same as comments as ALLNODES */
		if (dbi->allowxfr_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		} else {
			querystring = build_querystring(ns_g_mctx,
			dbi->allowxfr_q);
		}
		break;
	case AUTHORITY:
		/* same as comments as ALLNODES */
		if (dbi->authority_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		} else {
			querystring = build_querystring(ns_g_mctx,
			dbi->authority_q);
		}
		break;
	case FINDZONE:
		/* this is required.  It's the whole point of DLZ! */
		if (dbi->findzone_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for findzone.  "
				      "Findzone requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		} else {
			querystring = build_querystring(ns_g_mctx,
			dbi->findzone_q);
		}
		break;
	case LOOKUP:
		/* this is required.  It's also a major point of DLZ! */
		if (dbi->lookup_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for lookup.  "
				      "Lookup requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		} else {
			querystring = build_querystring(ns_g_mctx,
							dbi->lookup_q);
		}
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "ldap_get_results");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}

	/* if the querystring is null, Bummer, outta RAM.  UPGRADE TIME!!!   */
	if (querystring  == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/*
	 * output the full query string during debug so we can see
	 * what lame error the query has.
	 */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "\nQuery String: %s\n", querystring);

        /* break URL down into it's component parts, if error cleanup */
	ldap_result = ldap_url_parse(querystring, &ldap_url);
	if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	for (i = 0; i < 3; i++) {

		/*
		 * dbi->dbconn may be null if trying to reconnect on a
		 * previous query failed.
		 */
		if (dbi->dbconn == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
				      "LDAP driver attempting to re-connect");

			result = dlz_ldap_connect((ldap_instance_t *) dbdata,
						  dbi);
			if (result != ISC_R_SUCCESS) {
				result = ISC_R_FAILURE;
				continue;
			}
		}

		/* perform ldap search syncronously */
		ldap_result = ldap_search_s((LDAP *) dbi->dbconn,
					    ldap_url->lud_dn,
					    ldap_url->lud_scope,
					    ldap_url->lud_filter,
					    ldap_url->lud_attrs, 0, &ldap_msg);

		/*
		 * check return code.  No such object is ok, just
		 * didn't find what we wanted
		 */
		switch(ldap_result) {
		case LDAP_NO_SUCH_OBJECT:
    			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
				      "No object found matching "
				      "query requirements");
			result = ISC_R_NOTFOUND;
			goto cleanup;
			break;
		case LDAP_SUCCESS:	/* on success do nothing */
			result = ISC_R_SUCCESS;
			i = 3;
			break;
		case LDAP_SERVER_DOWN:
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
				      "LDAP driver attempting to re-connect");
			result = dlz_ldap_connect((ldap_instance_t *) dbdata,
						  dbi);
			if (result != ISC_R_SUCCESS)
				result = ISC_R_FAILURE;
			break;
		default:
			/*
			 * other errors not ok.  Log error message and
			 * get out
			 */
    			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP error: %s",
				      ldap_err2string(ldap_result));
			result = ISC_R_FAILURE;
			goto cleanup;
			break;
		} /* close switch(ldap_result) */
	} /* end for (int i = 0 i < 3; i++) */

	if (result != ISC_R_SUCCESS)
		goto cleanup;

	switch(query) {
	case ALLNODES:
		result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg,
					      ldap_url->lud_attrs,
					      ptr, isc_boolean_true);
		break;
	case AUTHORITY:
	case LOOKUP:
		result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg,
					      ldap_url->lud_attrs,
					      ptr, isc_boolean_false);
		break;
	case ALLOWXFR:
		entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
		if (entries == 0)
			result = ISC_R_NOPERM;
		else if (entries > 0)
			result = ISC_R_SUCCESS;
		else
			result = ISC_R_FAILURE;
		break;
	case FINDZONE:
		entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
		if (entries == 0)
			result = ISC_R_NOTFOUND;
		else if (entries > 0)
			result = ISC_R_SUCCESS;
		else
			result = ISC_R_FAILURE;
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "ldap_get_results");
		result = ISC_R_UNEXPECTED;
	}

 cleanup:
	/* it's always good to cleanup after yourself */

        /* if we retrieved results, free them */
	if (ldap_msg != NULL)
		ldap_msgfree(ldap_msg);

	if (ldap_url != NULL)
		ldap_free_urldesc(ldap_url);

	/* cleanup */
	if (dbi->zone != NULL)
		isc_mem_free(ns_g_mctx, dbi->zone);
	if (dbi->record != NULL)
		isc_mem_free(ns_g_mctx, dbi->record);
	if (dbi->client != NULL)
		isc_mem_free(ns_g_mctx, dbi->client);

#ifdef ISC_PLATFORM_USETHREADS

	/* release the lock so another thread can use this dbi */
	isc_mutex_unlock(&dbi->instance_lock);

#endif /* ISC_PLATFORM_USETHREADS */

        /* release query string */
	if (querystring  != NULL)
		isc_mem_free(ns_g_mctx, querystring );

	/* return result */
	return (result);
}
Пример #17
0
isc_result_t
ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
		      isc_entropy_t *ectx, dns_tkeyctx_t **tctxp)
{
	isc_result_t result;
	dns_tkeyctx_t *tctx = NULL;
	const char *s;
	isc_uint32_t n;
	dns_fixedname_t fname;
	dns_name_t *name;
	isc_buffer_t b;
	const cfg_obj_t *obj;
	int type;

	result = dns_tkeyctx_create(mctx, ectx, &tctx);
	if (result != ISC_R_SUCCESS)
		return (result);

	obj = NULL;
	result = cfg_map_get(options, "tkey-dhkey", &obj);
	if (result == ISC_R_SUCCESS) {
		s = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
		n = cfg_obj_asuint32(cfg_tuple_get(obj, "keyid"));
		isc_buffer_constinit(&b, s, strlen(s));
		isc_buffer_add(&b, strlen(s));
		dns_fixedname_init(&fname);
		name = dns_fixedname_name(&fname);
		RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
		type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY;
		RETERR(dst_key_fromfile(name, (dns_keytag_t) n, DNS_KEYALG_DH,
					type, NULL, mctx, &tctx->dhkey));
	}

	obj = NULL;
	result = cfg_map_get(options, "tkey-domain", &obj);
	if (result == ISC_R_SUCCESS) {
		s = cfg_obj_asstring(obj);
		isc_buffer_constinit(&b, s, strlen(s));
		isc_buffer_add(&b, strlen(s));
		dns_fixedname_init(&fname);
		name = dns_fixedname_name(&fname);
		RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
		tctx->domain = isc_mem_get(mctx, sizeof(dns_name_t));
		if (tctx->domain == NULL) {
			result = ISC_R_NOMEMORY;
			goto failure;
		}
		dns_name_init(tctx->domain, NULL);
		RETERR(dns_name_dup(name, mctx, tctx->domain));
	}

	obj = NULL;
	result = cfg_map_get(options, "tkey-gssapi-credential", &obj);
	if (result == ISC_R_SUCCESS) {
		s = cfg_obj_asstring(obj);

		isc_buffer_constinit(&b, s, strlen(s));
		isc_buffer_add(&b, strlen(s));
		dns_fixedname_init(&fname);
		name = dns_fixedname_name(&fname);
		RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
		RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, &tctx->gsscred));
	}

	obj = NULL;
	result = cfg_map_get(options, "tkey-gssapi-keytab", &obj);
	if (result == ISC_R_SUCCESS) {
		s = cfg_obj_asstring(obj);
		tctx->gssapi_keytab = isc_mem_strdup(mctx, s);
		if (tctx->gssapi_keytab == NULL) {
			result = ISC_R_NOMEMORY;
			goto failure;
		}
	}


	*tctxp = tctx;
	return (ISC_R_SUCCESS);

 failure:
	dns_tkeyctx_destroy(&tctx);
	return (result);
}
Пример #18
0
static isc_result_t
dlz_ldap_create(const char *dlzname, unsigned int argc, char *argv[],
		void *driverarg, void **dbdata)
{
	isc_result_t result;
	ldap_instance_t *ldap_inst = NULL;
	dbinstance_t *dbi = NULL;
	int protocol;
	int method;

#ifdef ISC_PLATFORM_USETHREADS
	/* if multi-threaded, we need a few extra variables. */
	int dbcount;
	char *endp;
/* db_list_t *dblist = NULL; */
	int i;

#endif /* ISC_PLATFORM_USETHREADS */

	UNUSED(dlzname);
	UNUSED(driverarg);

#ifdef ISC_PLATFORM_USETHREADS
	/* if debugging, let user know we are multithreaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "LDAP driver running multithreaded");
#else /* ISC_PLATFORM_USETHREADS */
	/* if debugging, let user know we are single threaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "LDAP driver running single threaded");
#endif /* ISC_PLATFORM_USETHREADS */

	if (argc < 9) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver requires at least "
			      "8 command line args.");
		return (ISC_R_FAILURE);
	}

	/* no more than 13 arg's should be passed to the driver */
	if (argc > 12) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver cannot accept more than "
			      "11 command line args.");
		return (ISC_R_FAILURE);
	}

	/* determine protocol version. */
	if (strncasecmp(argv[2], V2, strlen(V2)) == 0) {
		protocol = 2;
	} else if (strncasecmp(argv[2], V3, strlen(V3)) == 0) {
		protocol = 3;
	} else {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver protocol must be either %s or %s",
			      V2, V3);
		return (ISC_R_FAILURE);
	}

	/* determine connection method. */
	if (strncasecmp(argv[3], SIMPLE, strlen(SIMPLE)) == 0) {
		method = LDAP_AUTH_SIMPLE;
	} else if (strncasecmp(argv[3], KRB41, strlen(KRB41)) == 0) {
		method = LDAP_AUTH_KRBV41;
	} else if (strncasecmp(argv[3], KRB42, strlen(KRB42)) == 0) {
		method = LDAP_AUTH_KRBV42;
	} else {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver authentication method must be "
			      "one of %s, %s or %s",
			      SIMPLE, KRB41, KRB42);
		return (ISC_R_FAILURE);
	}

	/* multithreaded build can have multiple DB connections */
#ifdef ISC_PLATFORM_USETHREADS

	/* check how many db connections we should create */
	dbcount = strtol(argv[1], &endp, 10);
	if (*endp != '\0' || dbcount < 0) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver database connection count "
			      "must be positive.");
		return (ISC_R_FAILURE);
	}
#endif

	/* check that LDAP URL parameters make sense */
	switch(argc) {
	case 12:
		result = dlz_ldap_checkURL(argv[11], 0, "allow zone transfer");
		if (result != ISC_R_SUCCESS)
			return (result);
	case 11:
		result = dlz_ldap_checkURL(argv[10], 3, "all nodes");
		if (result != ISC_R_SUCCESS)
			return (result);
	case 10:
		if (strlen(argv[9]) > 0) {
			result = dlz_ldap_checkURL(argv[9], 3, "authority");
			if (result != ISC_R_SUCCESS)
				return (result);
		}
	case 9:
		result = dlz_ldap_checkURL(argv[8], 3, "lookup");
		if (result != ISC_R_SUCCESS)
			return (result);
		result = dlz_ldap_checkURL(argv[7], 0, "find zone");
		if (result != ISC_R_SUCCESS)
			return (result);
		break;
	default:
		/* not really needed, should shut up compiler. */
		result = ISC_R_FAILURE;
	}

	/* allocate memory for LDAP instance */
	ldap_inst = isc_mem_get(ns_g_mctx, sizeof(ldap_instance_t));
	if (ldap_inst == NULL)
		return (ISC_R_NOMEMORY);
	memset(ldap_inst, 0, sizeof(ldap_instance_t));

	/* store info needed to automatically re-connect. */
	ldap_inst->protocol = protocol;
	ldap_inst->method = method;
	ldap_inst->hosts = isc_mem_strdup(ns_g_mctx, argv[6]);
	if (ldap_inst->hosts == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}
	ldap_inst->user = isc_mem_strdup(ns_g_mctx, argv[4]);
	if (ldap_inst->user == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}
	ldap_inst->cred = isc_mem_strdup(ns_g_mctx, argv[5]);
	if (ldap_inst->cred == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

#ifdef ISC_PLATFORM_USETHREADS
	/* allocate memory for database connection list */
	ldap_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
	if (ldap_inst->db == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/* initialize DB connection list */
	ISC_LIST_INIT(*(ldap_inst->db));

	/*
	 * create the appropriate number of database instances (DBI)
	 * append each new DBI to the end of the list
	 */
	for (i = 0; i < dbcount; i++) {

#endif /* ISC_PLATFORM_USETHREADS */

		/* how many queries were passed in from config file? */
		switch(argc) {
		case 9:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     NULL, argv[7], argv[8],
						     NULL, &dbi);
			break;
		case 10:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     argv[9], argv[7], argv[8],
						     NULL, &dbi);
			break;
		case 11:
			result = build_sqldbinstance(ns_g_mctx, argv[10], NULL,
						     argv[9], argv[7], argv[8],
						     NULL, &dbi);
			break;
		case 12:
			result = build_sqldbinstance(ns_g_mctx, argv[10],
						     argv[11], argv[9],
						     argv[7], argv[8],
						     NULL, &dbi);
			break;
		default:
			/* not really needed, should shut up compiler. */
			result = ISC_R_FAILURE;
		}

		if (result == ISC_R_SUCCESS) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "LDAP driver created "
				      "database instance object.");
		} else { /* unsuccessful?, log err msg and cleanup. */
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not create "
				      "database instance object.");
			goto cleanup;
		}

#ifdef ISC_PLATFORM_USETHREADS
		/* when multithreaded, build a list of DBI's */
		ISC_LINK_INIT(dbi, link);
		ISC_LIST_APPEND(*(ldap_inst->db), dbi, link);
#else
		/*
		 * when single threaded, hold onto the one connection
		 * instance.
		 */
		ldap_inst->db = dbi;

#endif
		/* attempt to connect */
		result = dlz_ldap_connect(ldap_inst, dbi);

		/*
		 * if db connection cannot be created, log err msg and
		 * cleanup.
		 */
		switch(result) {
			/* success, do nothing */
		case ISC_R_SUCCESS:
			break;
			/*
			 * no memory means ldap_init could not
			 * allocate memory
			 */
		case ISC_R_NOMEMORY:
#ifdef ISC_PLATFORM_USETHREADS
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not allocate memory "
				      "for connection number %u",
				      i+1);
#else
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not allocate memory "
				      "for connection");
#endif
			goto cleanup;
			break;
			/*
			 * no perm means ldap_set_option could not set
			 * protocol version
			 */
		case ISC_R_NOPERM:
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not "
				      "set protocol version.");
			result = ISC_R_FAILURE;
			goto cleanup;
			break;
			/* failure means couldn't connect to ldap server */
		case ISC_R_FAILURE:
#ifdef ISC_PLATFORM_USETHREADS
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not "
				      "bind connection number %u to server.",
				      i+1);
#else
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not "
				      "bind connection to server.");
#endif
			goto cleanup;
			break;
			/*
			 * default should never happen.  If it does,
			 * major errors.
			 */
		default:
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "dlz_ldap_create() failed: %s",
					 isc_result_totext(result));
			result = ISC_R_UNEXPECTED;
			goto cleanup;
			break;
		} /* end switch(result) */


#ifdef ISC_PLATFORM_USETHREADS

		/* set DBI = null for next loop through. */
		dbi = NULL;
	}	/* end for loop */

#endif /* ISC_PLATFORM_USETHREADS */


	/* set dbdata to the ldap_instance we created. */
	*dbdata = ldap_inst;

	/* hey, we got through all of that ok, return success. */
	return(ISC_R_SUCCESS);

 cleanup:
	dlz_ldap_destroy(NULL, ldap_inst);

	return(ISC_R_FAILURE);
}
Пример #19
0
static isc_result_t
pkcs11ecdsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
		      const char *pin)
{
	CK_RV rv;
	CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
	CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
	CK_KEY_TYPE keyType = CKK_EC;
	CK_ATTRIBUTE searchTemplate[] =
	{
		{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
		{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
		{ CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
		{ CKA_LABEL, NULL, 0 }
	};
	CK_ULONG cnt;
	CK_ATTRIBUTE *attr;
	pk11_object_t *ec;
	pk11_context_t *pk11_ctx = NULL;
	isc_result_t ret;
	unsigned int i;

	UNUSED(pin);

	ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
	if (ec == NULL)
		return (ISC_R_NOMEMORY);
	memset(ec, 0, sizeof(*ec));
	ec->object = CK_INVALID_HANDLE;
	ec->ontoken = ISC_TRUE;
	ec->reqlogon = ISC_TRUE;
	key->keydata.pkey = ec;

	ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
	if (ec->repr == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memset(ec->repr, 0, sizeof(*attr) * 2);
	ec->attrcnt = 2;
	attr = ec->repr;
	attr[0].type = CKA_EC_PARAMS;
	attr[1].type = CKA_EC_POINT;

	ret = pk11_parse_uri(ec, label, key->mctx, OP_EC);
	if (ret != ISC_R_SUCCESS)
		goto err;

	pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
						  sizeof(*pk11_ctx));
	if (pk11_ctx == NULL)
		DST_RET(ISC_R_NOMEMORY);
	ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE,
			       ec->reqlogon, NULL, ec->slot);
	if (ret != ISC_R_SUCCESS)
		goto err;

	attr = pk11_attribute_bytype(ec, CKA_LABEL);
	if (attr == NULL) {
		attr = pk11_attribute_bytype(ec, CKA_ID);
		INSIST(attr != NULL);
		searchTemplate[3].type = CKA_ID;
	}
	searchTemplate[3].pValue = attr->pValue;
	searchTemplate[3].ulValueLen = attr->ulValueLen;

	PK11_RET(pkcs_C_FindObjectsInit,
		 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
		 DST_R_CRYPTOFAILURE);
	PK11_RET(pkcs_C_FindObjects,
		 (pk11_ctx->session, &hKey, (CK_ULONG) 1, &cnt),
		 DST_R_CRYPTOFAILURE);
	(void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
	if (cnt == 0)
		DST_RET(ISC_R_NOTFOUND);
	if (cnt > 1)
		DST_RET(ISC_R_EXISTS);

	attr = ec->repr;
	PK11_RET(pkcs_C_GetAttributeValue,
		 (pk11_ctx->session, hKey, attr, 2),
		 DST_R_CRYPTOFAILURE);
	for (i = 0; i <= 1; i++) {
		attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
		if (attr[i].pValue == NULL)
			DST_RET(ISC_R_NOMEMORY);
		memset(attr[i].pValue, 0, attr[i].ulValueLen);
	}
	PK11_RET(pkcs_C_GetAttributeValue,
		 (pk11_ctx->session, hKey, attr, 2),
		 DST_R_CRYPTOFAILURE);

	keyClass = CKO_PRIVATE_KEY;
	PK11_RET(pkcs_C_FindObjectsInit,
		 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
		 DST_R_CRYPTOFAILURE);
	PK11_RET(pkcs_C_FindObjects,
		 (pk11_ctx->session, &ec->object, (CK_ULONG) 1, &cnt),
		 DST_R_CRYPTOFAILURE);
	(void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
	if (cnt == 0)
		DST_RET(ISC_R_NOTFOUND);
	if (cnt > 1)
		DST_RET(ISC_R_EXISTS);

	if (engine != NULL) {
		key->engine = isc_mem_strdup(key->mctx, engine);
		if (key->engine == NULL)
			DST_RET(ISC_R_NOMEMORY);
	}

	key->label = isc_mem_strdup(key->mctx, label);
	if (key->label == NULL)
		DST_RET(ISC_R_NOMEMORY);
	if (key->key_alg == DST_ALG_ECDSA256)
		key->key_size = DNS_KEY_ECDSA256SIZE * 4;
	else
		key->key_size = DNS_KEY_ECDSA384SIZE * 4;

	pk11_return_session(pk11_ctx);
	memset(pk11_ctx, 0, sizeof(*pk11_ctx));
	isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
	return (ISC_R_SUCCESS);

 err:
	pkcs11ecdsa_destroy(key);
	if (pk11_ctx != NULL) {
		pk11_return_session(pk11_ctx);
		memset(pk11_ctx, 0, sizeof(*pk11_ctx));
		isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
	}
	return (ret);
}
Пример #20
0
int
main(int argc, char **argv) {
	isc_result_t	result;
#ifdef USE_PKCS11
	const char	*engine = "pkcs11";
#else
	const char	*engine = NULL;
#endif
	char		*filename = NULL, *directory = NULL;
	char		newname[1024];
	char		keystr[DST_KEY_FORMATSIZE];
	char		*endp, *p;
	int		ch;
	isc_entropy_t	*ectx = NULL;
	const char	*predecessor = NULL;
	dst_key_t	*prevkey = NULL;
	dst_key_t	*key = NULL;
	isc_buffer_t	buf;
	dns_name_t	*name = NULL;
	dns_secalg_t 	alg = 0;
	unsigned int 	size = 0;
	isc_uint16_t	flags = 0;
	int		prepub = -1;
	dns_ttl_t	ttl = 0;
	isc_stdtime_t	now;
	isc_stdtime_t	pub = 0, act = 0, rev = 0, inact = 0, del = 0;
	isc_boolean_t	setpub = ISC_FALSE, setact = ISC_FALSE;
	isc_boolean_t	setrev = ISC_FALSE, setinact = ISC_FALSE;
	isc_boolean_t	setdel = ISC_FALSE, setttl = ISC_FALSE;
	isc_boolean_t	unsetpub = ISC_FALSE, unsetact = ISC_FALSE;
	isc_boolean_t	unsetrev = ISC_FALSE, unsetinact = ISC_FALSE;
	isc_boolean_t	unsetdel = ISC_FALSE;
	isc_boolean_t	printcreate = ISC_FALSE, printpub = ISC_FALSE;
	isc_boolean_t	printact = ISC_FALSE,  printrev = ISC_FALSE;
	isc_boolean_t	printinact = ISC_FALSE, printdel = ISC_FALSE;
	isc_boolean_t	force = ISC_FALSE;
	isc_boolean_t   epoch = ISC_FALSE;
	isc_boolean_t   changed = ISC_FALSE;
	isc_log_t       *log = NULL;

	isc__mem_register();
	if (argc == 1)
		usage();

	result = isc_mem_create(0, 0, &mctx);
	if (result != ISC_R_SUCCESS)
		fatal("Out of memory");

	setup_logging(verbose, mctx, &log);

	dns_result_register();

	isc_commandline_errprint = ISC_FALSE;

	isc_stdtime_get(&now);

#define CMDLINE_FLAGS "A:D:E:fhI:i:K:L:P:p:R:S:uv:"
	while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
		switch (ch) {
		case 'E':
			engine = isc_commandline_argument;
			break;
		case 'f':
			force = ISC_TRUE;
			break;
		case 'p':
			p = isc_commandline_argument;
			if (!strcasecmp(p, "all")) {
				printcreate = ISC_TRUE;
				printpub = ISC_TRUE;
				printact = ISC_TRUE;
				printrev = ISC_TRUE;
				printinact = ISC_TRUE;
				printdel = ISC_TRUE;
				break;
			}

			do {
				switch (*p++) {
				case 'C':
					printcreate = ISC_TRUE;
					break;
				case 'P':
					printpub = ISC_TRUE;
					break;
				case 'A':
					printact = ISC_TRUE;
					break;
				case 'R':
					printrev = ISC_TRUE;
					break;
				case 'I':
					printinact = ISC_TRUE;
					break;
				case 'D':
					printdel = ISC_TRUE;
					break;
				case ' ':
					break;
				default:
					usage();
					break;
				}
			} while (*p != '\0');
			break;
		case 'u':
			epoch = ISC_TRUE;
			break;
		case 'K':
			/*
			 * We don't have to copy it here, but do it to
			 * simplify cleanup later
			 */
			directory = isc_mem_strdup(mctx,
						   isc_commandline_argument);
			if (directory == NULL) {
				fatal("Failed to allocate memory for "
				      "directory");
			}
			break;
		case 'L':
			if (strcmp(isc_commandline_argument, "none") == 0)
				ttl = 0;
			else
				ttl = strtottl(isc_commandline_argument);
			setttl = ISC_TRUE;
			break;
		case 'v':
			verbose = strtol(isc_commandline_argument, &endp, 0);
			if (*endp != '\0')
				fatal("-v must be followed by a number");
			break;
		case 'P':
			if (setpub || unsetpub)
				fatal("-P specified more than once");

			changed = ISC_TRUE;
			if (!strcasecmp(isc_commandline_argument, "none")) {
				unsetpub = ISC_TRUE;
			} else {
				setpub = ISC_TRUE;
				pub = strtotime(isc_commandline_argument,
						now, now);
			}
			break;
		case 'A':
			if (setact || unsetact)
				fatal("-A specified more than once");

			changed = ISC_TRUE;
			if (!strcasecmp(isc_commandline_argument, "none")) {
				unsetact = ISC_TRUE;
			} else {
				setact = ISC_TRUE;
				act = strtotime(isc_commandline_argument,
						now, now);
			}
			break;
		case 'R':
			if (setrev || unsetrev)
				fatal("-R specified more than once");

			changed = ISC_TRUE;
			if (!strcasecmp(isc_commandline_argument, "none")) {
				unsetrev = ISC_TRUE;
			} else {
				setrev = ISC_TRUE;
				rev = strtotime(isc_commandline_argument,
						now, now);
			}
			break;
		case 'I':
			if (setinact || unsetinact)
				fatal("-I specified more than once");

			changed = ISC_TRUE;
			if (!strcasecmp(isc_commandline_argument, "none")) {
				unsetinact = ISC_TRUE;
			} else {
				setinact = ISC_TRUE;
				inact = strtotime(isc_commandline_argument,
						now, now);
			}
			break;
		case 'D':
			if (setdel || unsetdel)
				fatal("-D specified more than once");

			changed = ISC_TRUE;
			if (!strcasecmp(isc_commandline_argument, "none")) {
				unsetdel = ISC_TRUE;
			} else {
				setdel = ISC_TRUE;
				del = strtotime(isc_commandline_argument,
						now, now);
			}
			break;
		case 'S':
			predecessor = isc_commandline_argument;
			break;
		case 'i':
			prepub = strtottl(isc_commandline_argument);
			break;
		case '?':
			if (isc_commandline_option != '?')
				fprintf(stderr, "%s: invalid argument -%c\n",
					program, isc_commandline_option);
			/* Falls into */
		case 'h':
			usage();

		default:
			fprintf(stderr, "%s: unhandled option -%c\n",
				program, isc_commandline_option);
			exit(1);
		}
	}

	if (argc < isc_commandline_index + 1 ||
	    argv[isc_commandline_index] == NULL)
		fatal("The key file name was not specified");
	if (argc > isc_commandline_index + 1)
		fatal("Extraneous arguments");

	if (ectx == NULL)
		setup_entropy(mctx, NULL, &ectx);
	result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
	if (result != ISC_R_SUCCESS)
		fatal("Could not initialize hash");
	result = dst_lib_init2(mctx, ectx, engine,
			       ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
	if (result != ISC_R_SUCCESS)
		fatal("Could not initialize dst: %s",
		      isc_result_totext(result));
	isc_entropy_stopcallbacksources(ectx);

	if (predecessor != NULL) {
		char keystr[DST_KEY_FORMATSIZE];
		isc_stdtime_t when;
		int major, minor;

		if (prepub == -1)
			prepub = (30 * 86400);

		if (setpub || unsetpub)
			fatal("-S and -P cannot be used together");
		if (setact || unsetact)
			fatal("-S and -A cannot be used together");

		result = dst_key_fromnamedfile(predecessor, directory,
					       DST_TYPE_PUBLIC |
					       DST_TYPE_PRIVATE,
					       mctx, &prevkey);
		if (result != ISC_R_SUCCESS)
			fatal("Invalid keyfile %s: %s",
			      filename, isc_result_totext(result));
		if (!dst_key_isprivate(prevkey))
			fatal("%s is not a private key", filename);

		name = dst_key_name(prevkey);
		alg = dst_key_alg(prevkey);
		size = dst_key_size(prevkey);
		flags = dst_key_flags(prevkey);

		dst_key_format(prevkey, keystr, sizeof(keystr));
		dst_key_getprivateformat(prevkey, &major, &minor);
		if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION)
			fatal("Predecessor has incompatible format "
			      "version %d.%d\n\t", major, minor);

		result = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when);
		if (result != ISC_R_SUCCESS)
			fatal("Predecessor has no activation date. "
			      "You must set one before\n\t"
			      "generating a successor.");

		result = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &act);
		if (result != ISC_R_SUCCESS)
			fatal("Predecessor has no inactivation date. "
			      "You must set one before\n\t"
			      "generating a successor.");

		pub = act - prepub;
		if (pub < now && prepub != 0)
			fatal("Predecessor will become inactive before the\n\t"
			      "prepublication period ends.  Either change "
			      "its inactivation date,\n\t"
			      "or use the -i option to set a shorter "
			      "prepublication interval.");

		result = dst_key_gettime(prevkey, DST_TIME_DELETE, &when);
		if (result != ISC_R_SUCCESS)
			fprintf(stderr, "%s: WARNING: Predecessor has no "
					"removal date;\n\t"
					"it will remain in the zone "
					"indefinitely after rollover.\n",
					program);

		changed = setpub = setact = ISC_TRUE;
		dst_key_free(&prevkey);
	} else {
		if (prepub < 0)
			prepub = 0;

		if (prepub > 0) {
			if (setpub && setact && (act - prepub) < pub)
				fatal("Activation and publication dates "
				      "are closer together than the\n\t"
				      "prepublication interval.");

			if (setpub && !setact) {
				setact = ISC_TRUE;
				act = pub + prepub;
			} else if (setact && !setpub) {
				setpub = ISC_TRUE;
				pub = act - prepub;
			}

			if ((act - prepub) < now)
				fatal("Time until activation is shorter "
				      "than the\n\tprepublication interval.");
		}
	}

	if (directory != NULL) {
		filename = argv[isc_commandline_index];
	} else {
		result = isc_file_splitpath(mctx, argv[isc_commandline_index],
					    &directory, &filename);
		if (result != ISC_R_SUCCESS)
			fatal("cannot process filename %s: %s",
			      argv[isc_commandline_index],
			      isc_result_totext(result));
	}

	result = dst_key_fromnamedfile(filename, directory,
				       DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
				       mctx, &key);
	if (result != ISC_R_SUCCESS)
		fatal("Invalid keyfile %s: %s",
		      filename, isc_result_totext(result));

	if (!dst_key_isprivate(key))
		fatal("%s is not a private key", filename);

	dst_key_format(key, keystr, sizeof(keystr));

	if (predecessor != NULL) {
		if (!dns_name_equal(name, dst_key_name(key)))
			fatal("Key name mismatch");
		if (alg != dst_key_alg(key))
			fatal("Key algorithm mismatch");
		if (size != dst_key_size(key))
			fatal("Key size mismatch");
		if (flags != dst_key_flags(key))
			fatal("Key flags mismatch");
	}

	if (force)
		set_keyversion(key);
	else
		check_keyversion(key, keystr);

	if (verbose > 2)
		fprintf(stderr, "%s: %s\n", program, keystr);

	/*
	 * Set time values.
	 */
	if (setpub)
		dst_key_settime(key, DST_TIME_PUBLISH, pub);
	else if (unsetpub)
		dst_key_unsettime(key, DST_TIME_PUBLISH);

	if (setact)
		dst_key_settime(key, DST_TIME_ACTIVATE, act);
	else if (unsetact)
		dst_key_unsettime(key, DST_TIME_ACTIVATE);

	if (setrev) {
		if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0)
			fprintf(stderr, "%s: warning: Key %s is already "
					"revoked; changing the revocation date "
					"will not affect this.\n",
					program, keystr);
		if ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0)
			fprintf(stderr, "%s: warning: Key %s is not flagged as "
					"a KSK, but -R was used.  Revoking a "
					"ZSK is legal, but undefined.\n",
					program, keystr);
		dst_key_settime(key, DST_TIME_REVOKE, rev);
	} else if (unsetrev) {
		if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0)
			fprintf(stderr, "%s: warning: Key %s is already "
					"revoked; removing the revocation date "
					"will not affect this.\n",
					program, keystr);
		dst_key_unsettime(key, DST_TIME_REVOKE);
	}

	if (setinact)
		dst_key_settime(key, DST_TIME_INACTIVE, inact);
	else if (unsetinact)
		dst_key_unsettime(key, DST_TIME_INACTIVE);

	if (setdel)
		dst_key_settime(key, DST_TIME_DELETE, del);
	else if (unsetdel)
		dst_key_unsettime(key, DST_TIME_DELETE);

	if (setttl)
		dst_key_setttl(key, ttl);

	/*
	 * No metadata changes were made but we're forcing an upgrade
	 * to the new format anyway: use "-P now -A now" as the default
	 */
	if (force && !changed) {
		dst_key_settime(key, DST_TIME_PUBLISH, now);
		dst_key_settime(key, DST_TIME_ACTIVATE, now);
		changed = ISC_TRUE;
	}

	if (!changed && setttl)
		changed = ISC_TRUE;

	/*
	 * Print out time values, if -p was used.
	 */
	if (printcreate)
		printtime(key, DST_TIME_CREATED, "Created", epoch, stdout);

	if (printpub)
		printtime(key, DST_TIME_PUBLISH, "Publish", epoch, stdout);

	if (printact)
		printtime(key, DST_TIME_ACTIVATE, "Activate", epoch, stdout);

	if (printrev)
		printtime(key, DST_TIME_REVOKE, "Revoke", epoch, stdout);

	if (printinact)
		printtime(key, DST_TIME_INACTIVE, "Inactive", epoch, stdout);

	if (printdel)
		printtime(key, DST_TIME_DELETE, "Delete", epoch, stdout);

	if (changed) {
		isc_buffer_init(&buf, newname, sizeof(newname));
		result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory,
					       &buf);
		if (result != ISC_R_SUCCESS) {
			fatal("Failed to build public key filename: %s",
			      isc_result_totext(result));
		}

		result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
					directory);
		if (result != ISC_R_SUCCESS) {
			dst_key_format(key, keystr, sizeof(keystr));
			fatal("Failed to write key %s: %s", keystr,
			      isc_result_totext(result));
		}

		printf("%s\n", newname);

		isc_buffer_clear(&buf);
		result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory,
					       &buf);
		if (result != ISC_R_SUCCESS) {
			fatal("Failed to build private key filename: %s",
			      isc_result_totext(result));
		}
		printf("%s\n", newname);
	}

	dst_key_free(&key);
	dst_lib_destroy();
	isc_hash_destroy();
	cleanup_entropy(&ectx);
	if (verbose > 10)
		isc_mem_stats(mctx, stdout);
	cleanup_logging(&log);
	isc_mem_free(mctx, directory);
	isc_mem_destroy(&mctx);

	return (0);
}
Пример #21
0
/*
 * Called at startup for each dlopen zone in named.conf
 */
static isc_result_t
dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
		  void *driverarg, void **dbdata)
{
	dlopen_data_t *cd;
	isc_mem_t *mctx = NULL;
	isc_result_t result = ISC_R_FAILURE;
	isc_boolean_t triedload = ISC_FALSE;

	UNUSED(driverarg);

	if (argc < 2) {
		dlopen_log(ISC_LOG_ERROR,
			   "dlz_dlopen driver for '%s' needs a path to "
			   "the shared library", dlzname);
		return (ISC_R_FAILURE);
	}

	isc_mem_create(0, 0, &mctx);

	cd = isc_mem_get(mctx, sizeof(*cd));
	if (cd == NULL) {
		isc_mem_destroy(&mctx);
		return (ISC_R_NOMEMORY);
	}
	memset(cd, 0, sizeof(*cd));

	cd->mctx = mctx;

	cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]);
	if (cd->dl_path == NULL) {
		goto failed;
	}

	cd->dlzname = isc_mem_strdup(cd->mctx, dlzname);
	if (cd->dlzname == NULL) {
		goto failed;
	}

	triedload = ISC_TRUE;

	/* Initialize the lock */
	isc_mutex_init(&cd->lock);

	/* Open the library */
	cd->dl_handle = LoadLibraryA(cd->dl_path);
	if (cd->dl_handle == NULL) {
		unsigned int error = GetLastError();

		dlopen_log(ISC_LOG_ERROR,
			   "dlz_dlopen failed to open library '%s' - %u",
			   cd->dl_path, error);
		goto failed;
	}

	/* Find the symbols */
	cd->dlz_version = (dlz_dlopen_version_t *)
		dl_load_symbol(cd, "dlz_version", ISC_TRUE);
	cd->dlz_create = (dlz_dlopen_create_t *)
		dl_load_symbol(cd, "dlz_create", ISC_TRUE);
	cd->dlz_lookup = (dlz_dlopen_lookup_t *)
		dl_load_symbol(cd, "dlz_lookup", ISC_TRUE);
	cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *)
		dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);

	if (cd->dlz_create == NULL ||
	    cd->dlz_lookup == NULL ||
	    cd->dlz_findzonedb == NULL)
	{
		/* We're missing a required symbol */
		goto failed;
	}

	cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *)
		dl_load_symbol(cd, "dlz_allowzonexfr", ISC_FALSE);
	cd->dlz_allnodes = (dlz_dlopen_allnodes_t *)
		dl_load_symbol(cd, "dlz_allnodes",
			       ISC_TF(cd->dlz_allowzonexfr != NULL));
	cd->dlz_authority = (dlz_dlopen_authority_t *)
		dl_load_symbol(cd, "dlz_authority", ISC_FALSE);
	cd->dlz_newversion = (dlz_dlopen_newversion_t *)
		dl_load_symbol(cd, "dlz_newversion", ISC_FALSE);
	cd->dlz_closeversion = (dlz_dlopen_closeversion_t *)
		dl_load_symbol(cd, "dlz_closeversion",
			       ISC_TF(cd->dlz_newversion != NULL));
	cd->dlz_configure = (dlz_dlopen_configure_t *)
		dl_load_symbol(cd, "dlz_configure", ISC_FALSE);
	cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *)
		dl_load_symbol(cd, "dlz_ssumatch", ISC_FALSE);
	cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *)
		dl_load_symbol(cd, "dlz_addrdataset", ISC_FALSE);
	cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *)
		dl_load_symbol(cd, "dlz_subrdataset", ISC_FALSE);
	cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *)
		dl_load_symbol(cd, "dlz_delrdataset", ISC_FALSE);

	/* Check the version of the API is the same */
	cd->version = cd->dlz_version(&cd->flags);
	if (cd->version != DLZ_DLOPEN_VERSION) {
		dlopen_log(ISC_LOG_ERROR,
			   "dlz_dlopen: incorrect version %d "
			   "should be %d in '%s'",
			   cd->version, DLZ_DLOPEN_VERSION, cd->dl_path);
		goto failed;
	}

	/*
	 * Call the library's create function. Note that this is an
	 * extended version of dlz create, with the addition of
	 * named function pointers for helper functions that the
	 * driver will need. This avoids the need for the backend to
	 * link the BIND9 libraries
	 */
	MAYBE_LOCK(cd);
	result = cd->dlz_create(dlzname, argc-1, argv+1,
				&cd->dbdata,
				"log", dlopen_log,
				"putrr", dns_sdlz_putrr,
				"putnamedrr", dns_sdlz_putnamedrr,
				"writeable_zone", dns_dlz_writeablezone,
				NULL);
	MAYBE_UNLOCK(cd);
	if (result != ISC_R_SUCCESS)
		goto failed;

	*dbdata = cd;

	return (ISC_R_SUCCESS);

failed:
	dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname);
	if (cd->dl_path)
		isc_mem_free(mctx, cd->dl_path);
	if (cd->dlzname)
		isc_mem_free(mctx, cd->dlzname);
	if (triedload)
		(void) isc_mutex_destroy(&cd->lock);
	if (cd->dl_handle)
		FreeLibrary(cd->dl_handle);
	isc_mem_put(mctx, cd, sizeof(*cd));
	isc_mem_destroy(&mctx);
	return (result);
}
Пример #22
0
static isc_result_t
get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) {
	isc_result_t result;
	cfg_parser_t *pctx = NULL;
	cfg_obj_t *config = NULL;
	const cfg_obj_t *key = NULL;
	const cfg_obj_t *algobj = NULL;
	const cfg_obj_t *secretobj = NULL;
	const char *algstr = NULL;
	const char *secretstr = NULL;
	controlkey_t *keyid = NULL;
	char secret[1024];
	unsigned int algtype;
	isc_buffer_t b;

	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
		      NS_LOGMODULE_CONTROL, ISC_LOG_INFO,
		      "configuring command channel from '%s'",
		      ns_g_keyfile);
	if (! isc_file_exists(ns_g_keyfile))
		return (ISC_R_FILENOTFOUND);

	CHECK(cfg_parser_create(mctx, ns_g_lctx, &pctx));
	CHECK(cfg_parse_file(pctx, ns_g_keyfile, &cfg_type_rndckey, &config));
	CHECK(cfg_map_get(config, "key", &key));

	keyid = isc_mem_get(mctx, sizeof(*keyid));
	if (keyid == NULL)
		CHECK(ISC_R_NOMEMORY);
	keyid->keyname = isc_mem_strdup(mctx,
					cfg_obj_asstring(cfg_map_getname(key)));
	keyid->secret.base = NULL;
	keyid->secret.length = 0;
	keyid->algorithm = DST_ALG_UNKNOWN;
	ISC_LINK_INIT(keyid, link);
	if (keyid->keyname == NULL)
		CHECK(ISC_R_NOMEMORY);

	CHECK(bind9_check_key(key, ns_g_lctx));

	(void)cfg_map_get(key, "algorithm", &algobj);
	(void)cfg_map_get(key, "secret", &secretobj);
	INSIST(algobj != NULL && secretobj != NULL);

	algstr = cfg_obj_asstring(algobj);
	secretstr = cfg_obj_asstring(secretobj);

	if (ns_config_getkeyalgorithm2(algstr, NULL,
				       &algtype, NULL) != ISC_R_SUCCESS) {
		cfg_obj_log(key, ns_g_lctx,
			    ISC_LOG_WARNING,
			    "unsupported algorithm '%s' in "
			    "key '%s' for use with command "
			    "channel",
			    algstr, keyid->keyname);
		goto cleanup;
	}

	keyid->algorithm = algtype;
	isc_buffer_init(&b, secret, sizeof(secret));
	result = isc_base64_decodestring(secretstr, &b);

	if (result != ISC_R_SUCCESS) {
		cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
			    "secret for key '%s' on command channel: %s",
			    keyid->keyname, isc_result_totext(result));
		goto cleanup;
	}

	keyid->secret.length = isc_buffer_usedlength(&b);
	keyid->secret.base = isc_mem_get(mctx,
					 keyid->secret.length);
	if (keyid->secret.base == NULL) {
		cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
			   "couldn't register key '%s': "
			   "out of memory", keyid->keyname);
		CHECK(ISC_R_NOMEMORY);
	}
	memmove(keyid->secret.base, isc_buffer_base(&b),
		keyid->secret.length);
	ISC_LIST_APPEND(*keyids, keyid, link);
	keyid = NULL;
	result = ISC_R_SUCCESS;

  cleanup:
	if (keyid != NULL)
		free_controlkey(keyid, mctx);
	if (config != NULL)
		cfg_obj_destroy(pctx, &config);
	if (pctx != NULL)
		cfg_parser_destroy(&pctx);
	return (result);
}
Пример #23
0
isc_result_t
ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
		  const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
		  dns_zone_t *zone)
{
	isc_result_t result;
	const char *zname;
	dns_rdataclass_t zclass;
	dns_rdataclass_t vclass;
	const cfg_obj_t *maps[5];
	const cfg_obj_t *zoptions = NULL;
	const cfg_obj_t *options = NULL;
	const cfg_obj_t *obj;
	const char *filename = NULL;
	dns_notifytype_t notifytype = dns_notifytype_yes;
	isc_sockaddr_t *addrs;
	dns_name_t **keynames;
	isc_uint32_t count;
	char *cpval;
	unsigned int dbargc;
	char **dbargv;
	static char default_dbtype[] = "rbt";
	isc_mem_t *mctx = dns_zone_getmctx(zone);
	dns_dialuptype_t dialup = dns_dialuptype_no;
	dns_zonetype_t ztype;
	int i;
	isc_int32_t journal_size;
	isc_boolean_t multi;
	isc_boolean_t alt;
	dns_view_t *view;
	isc_boolean_t check = ISC_FALSE, fail = ISC_FALSE;
	isc_boolean_t warn = ISC_FALSE, ignore = ISC_FALSE;
	isc_boolean_t ixfrdiff;
	dns_masterformat_t masterformat;
	isc_stats_t *zoneqrystats;
	isc_boolean_t zonestats_on;
	int seconds;

	i = 0;
	if (zconfig != NULL) {
		zoptions = cfg_tuple_get(zconfig, "options");
		maps[i++] = zoptions;
	}
	if (vconfig != NULL)
		maps[i++] = cfg_tuple_get(vconfig, "options");
	if (config != NULL) {
		(void)cfg_map_get(config, "options", &options);
		if (options != NULL)
			maps[i++] = options;
	}
	maps[i++] = ns_g_defaults;
	maps[i] = NULL;

	if (vconfig != NULL)
		RETERR(ns_config_getclass(cfg_tuple_get(vconfig, "class"),
					  dns_rdataclass_in, &vclass));
	else
		vclass = dns_rdataclass_in;

	/*
	 * Configure values common to all zone types.
	 */

	zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));

	RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
				  vclass, &zclass));
	dns_zone_setclass(zone, zclass);

	ztype = zonetype_fromconfig(zoptions);
	dns_zone_settype(zone, ztype);

	obj = NULL;
	result = cfg_map_get(zoptions, "database", &obj);
	if (result == ISC_R_SUCCESS)
		cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
	else
		cpval = default_dbtype;

	if (cpval == NULL)
		return(ISC_R_NOMEMORY);

	result = strtoargv(mctx, cpval, &dbargc, &dbargv);
	if (result != ISC_R_SUCCESS && cpval != default_dbtype) {
		isc_mem_free(mctx, cpval);
		return (result);
	}

	/*
	 * ANSI C is strange here.  There is no logical reason why (char **)
	 * cannot be promoted automatically to (const char * const *) by the
	 * compiler w/o generating a warning.
	 */
	result = dns_zone_setdbtype(zone, dbargc, (const char * const *)dbargv);
	isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv));
	if (cpval != default_dbtype)
		isc_mem_free(mctx, cpval);
	if (result != ISC_R_SUCCESS)
		return (result);

	obj = NULL;
	result = cfg_map_get(zoptions, "file", &obj);
	if (result == ISC_R_SUCCESS)
		filename = cfg_obj_asstring(obj);

	/*
	 * Unless we're using some alternative database, a master zone
	 * will be needing a master file.
	 */
	if (ztype == dns_zone_master && cpval == default_dbtype &&
	    filename == NULL) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
			      "zone '%s': 'file' not specified",
			      zname);
		return (ISC_R_FAILURE);
	}

	masterformat = dns_masterformat_text;
	obj = NULL;
	result= ns_config_get(maps, "masterfile-format", &obj);
	if (result == ISC_R_SUCCESS) {
		const char *masterformatstr = cfg_obj_asstring(obj);

		if (strcasecmp(masterformatstr, "text") == 0)
			masterformat = dns_masterformat_text;
		else if (strcasecmp(masterformatstr, "raw") == 0)
			masterformat = dns_masterformat_raw;
		else
			INSIST(0);
	}
	RETERR(dns_zone_setfile2(zone, filename, masterformat));

	obj = NULL;
	result = cfg_map_get(zoptions, "journal", &obj);
	if (result == ISC_R_SUCCESS)
		RETERR(dns_zone_setjournal(zone, cfg_obj_asstring(obj)));

	if (ztype == dns_zone_slave)
		RETERR(configure_zone_acl(zconfig, vconfig, config,
					  allow_notify, ac, zone,
					  dns_zone_setnotifyacl,
					  dns_zone_clearnotifyacl));
	/*
	 * XXXAG This probably does not make sense for stubs.
	 */
	RETERR(configure_zone_acl(zconfig, vconfig, config,
				  allow_query, ac, zone,
				  dns_zone_setqueryacl,
				  dns_zone_clearqueryacl));

	obj = NULL;
	result = ns_config_get(maps, "dialup", &obj);
	INSIST(result == ISC_R_SUCCESS && obj != NULL);
	if (cfg_obj_isboolean(obj)) {
		if (cfg_obj_asboolean(obj))
			dialup = dns_dialuptype_yes;
		else
			dialup = dns_dialuptype_no;
	} else {
		const char *dialupstr = cfg_obj_asstring(obj);
		if (strcasecmp(dialupstr, "notify") == 0)
			dialup = dns_dialuptype_notify;
		else if (strcasecmp(dialupstr, "notify-passive") == 0)
			dialup = dns_dialuptype_notifypassive;
		else if (strcasecmp(dialupstr, "refresh") == 0)
			dialup = dns_dialuptype_refresh;
		else if (strcasecmp(dialupstr, "passive") == 0)
			dialup = dns_dialuptype_passive;
		else
			INSIST(0);
	}
	dns_zone_setdialup(zone, dialup);

	obj = NULL;
	result = ns_config_get(maps, "zone-statistics", &obj);
	INSIST(result == ISC_R_SUCCESS && obj != NULL);
	zonestats_on = cfg_obj_asboolean(obj);
	zoneqrystats = NULL;
	if (zonestats_on) {
		RETERR(isc_stats_create(mctx, &zoneqrystats,
					dns_nsstatscounter_max));
	}
	dns_zone_setrequeststats(zone, zoneqrystats);
	if (zoneqrystats != NULL)
		isc_stats_detach(&zoneqrystats);

	/*
	 * Configure master functionality.  This applies
	 * to primary masters (type "master") and slaves
	 * acting as masters (type "slave"), but not to stubs.
	 */
	if (ztype != dns_zone_stub && ztype != dns_zone_staticstub) {
		obj = NULL;
		result = ns_config_get(maps, "notify", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (cfg_obj_isboolean(obj)) {
			if (cfg_obj_asboolean(obj))
				notifytype = dns_notifytype_yes;
			else
				notifytype = dns_notifytype_no;
		} else {
			const char *notifystr = cfg_obj_asstring(obj);
			if (strcasecmp(notifystr, "explicit") == 0)
				notifytype = dns_notifytype_explicit;
			else if (strcasecmp(notifystr, "master-only") == 0)
				notifytype = dns_notifytype_masteronly;
			else
				INSIST(0);
		}
		dns_zone_setnotifytype(zone, notifytype);

		obj = NULL;
		result = ns_config_get(maps, "also-notify", &obj);
		if (result == ISC_R_SUCCESS) {
			isc_sockaddr_t *addrs = NULL;
			isc_uint32_t addrcount;
			result = ns_config_getiplist(config, obj, 0, mctx,
						     &addrs, &addrcount);
			if (result != ISC_R_SUCCESS)
				return (result);
			result = dns_zone_setalsonotify(zone, addrs,
							addrcount);
			ns_config_putiplist(mctx, &addrs, addrcount);
			if (result != ISC_R_SUCCESS)
				return (result);
		} else
			RETERR(dns_zone_setalsonotify(zone, NULL, 0));

		obj = NULL;
		result = ns_config_get(maps, "notify-source", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));

		obj = NULL;
		result = ns_config_get(maps, "notify-source-v6", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));

		obj = NULL;
		result = ns_config_get(maps, "notify-to-soa", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA,
				   cfg_obj_asboolean(obj));

		dns_zone_setisself(zone, ns_client_isself, NULL);

		RETERR(configure_zone_acl(zconfig, vconfig, config,
					  allow_transfer, ac, zone,
					  dns_zone_setxfracl,
					  dns_zone_clearxfracl));

		obj = NULL;
		result = ns_config_get(maps, "max-transfer-time-out", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60);

		obj = NULL;
		result = ns_config_get(maps, "max-transfer-idle-out", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60);

		obj = NULL;
		result =  ns_config_get(maps, "max-journal-size", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setjournalsize(zone, -1);
		if (cfg_obj_isstring(obj)) {
			const char *str = cfg_obj_asstring(obj);
			INSIST(strcasecmp(str, "unlimited") == 0);
			journal_size = ISC_UINT32_MAX / 2;
		} else {
			isc_resourcevalue_t value;
			value = cfg_obj_asuint64(obj);
			if (value > ISC_UINT32_MAX / 2) {
				cfg_obj_log(obj, ns_g_lctx,
					    ISC_LOG_ERROR,
					    "'max-journal-size "
					    "%" ISC_PRINT_QUADFORMAT "d' "
					    "is too large",
					    value);
				RETERR(ISC_R_RANGE);
			}
			journal_size = (isc_uint32_t)value;
		}
		dns_zone_setjournalsize(zone, journal_size);

		obj = NULL;
		result = ns_config_get(maps, "ixfr-from-differences", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (cfg_obj_isboolean(obj))
			ixfrdiff = cfg_obj_asboolean(obj);
		else if (!strcasecmp(cfg_obj_asstring(obj), "master") &&
			 ztype == dns_zone_master)
			ixfrdiff = ISC_TRUE;
		else if (!strcasecmp(cfg_obj_asstring(obj), "slave") &&
			ztype == dns_zone_slave)
			ixfrdiff = ISC_TRUE;
		else
			ixfrdiff = ISC_FALSE;
		dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, ixfrdiff);

		checknames(ztype, maps, &obj);
		INSIST(obj != NULL);
		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
			fail = ISC_FALSE;
			check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
			fail = check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
			fail = check = ISC_FALSE;
		} else
			INSIST(0);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, fail);

		obj = NULL;
		result = ns_config_get(maps, "notify-delay", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "check-sibling", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING,
				   cfg_obj_asboolean(obj));

		obj = NULL;
		result = ns_config_get(maps, "zero-no-soa-ttl", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj));

		obj = NULL;
		result = ns_config_get(maps, "nsec3-test-zone", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE,
				   cfg_obj_asboolean(obj));
	}

	/*
	 * Configure update-related options.  These apply to
	 * primary masters only.
	 */
	if (ztype == dns_zone_master) {
		dns_acl_t *updateacl;

		RETERR(configure_zone_acl(zconfig, vconfig, config,
					  allow_update, ac, zone,
					  dns_zone_setupdateacl,
					  dns_zone_clearupdateacl));

		updateacl = dns_zone_getupdateacl(zone);
		if (updateacl != NULL  && dns_acl_isinsecure(updateacl))
			isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
				      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
				      "zone '%s' allows updates by IP "
				      "address, which is insecure",
				      zname);

		RETERR(configure_zone_ssutable(zoptions, zone, zname));

		obj = NULL;
		result = ns_config_get(maps, "sig-validity-interval", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		{
			const cfg_obj_t *validity, *resign;

			validity = cfg_tuple_get(obj, "validity");
			seconds = cfg_obj_asuint32(validity) * 86400;
			dns_zone_setsigvalidityinterval(zone, seconds);

			resign = cfg_tuple_get(obj, "re-sign");
			if (cfg_obj_isvoid(resign)) {
				seconds /= 4;
			} else {
				if (seconds > 7 * 86400)
					seconds = cfg_obj_asuint32(resign) *
							86400;
				else
					seconds = cfg_obj_asuint32(resign) *
							3600;
			}
			dns_zone_setsigresigninginterval(zone, seconds);
		}

		obj = NULL;
		result = ns_config_get(maps, "key-directory", &obj);
		if (result == ISC_R_SUCCESS) {
			filename = cfg_obj_asstring(obj);
			RETERR(dns_zone_setkeydirectory(zone, filename));
		}

		obj = NULL;
		result = ns_config_get(maps, "sig-signing-signatures", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setsignatures(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "sig-signing-nodes", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setnodes(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "sig-signing-type", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "update-check-ksk", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK,
				   cfg_obj_asboolean(obj));

		obj = NULL;
		result = ns_config_get(maps, "dnssec-dnskey-kskonly", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY,
				   cfg_obj_asboolean(obj));
	} else if (ztype == dns_zone_slave) {
		RETERR(configure_zone_acl(zconfig, vconfig, config,
					  allow_update_forwarding, ac, zone,
					  dns_zone_setforwardacl,
					  dns_zone_clearforwardacl));
	}

	/*%
	 * Primary master functionality.
	 */
	if (ztype == dns_zone_master) {
		isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE;

		obj = NULL;
		result = ns_config_get(maps, "check-wildcard", &obj);
		if (result == ISC_R_SUCCESS)
			check = cfg_obj_asboolean(obj);
		else
			check = ISC_FALSE;
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKWILDCARD, check);

		obj = NULL;
		result = ns_config_get(maps, "check-dup-records", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
			fail = ISC_FALSE;
			check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
			fail = check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
			fail = check = ISC_FALSE;
		} else
			INSIST(0);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRR, check);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRRFAIL, fail);

		obj = NULL;
		result = ns_config_get(maps, "check-mx", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
			fail = ISC_FALSE;
			check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
			fail = check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
			fail = check = ISC_FALSE;
		} else
			INSIST(0);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMX, check);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMXFAIL, fail);

		obj = NULL;
		result = ns_config_get(maps, "check-integrity", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKINTEGRITY,
				   cfg_obj_asboolean(obj));

		obj = NULL;
		result = ns_config_get(maps, "check-mx-cname", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
			warn = ISC_TRUE;
			ignore = ISC_FALSE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
			warn = ignore = ISC_FALSE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
			warn = ignore = ISC_TRUE;
		} else
			INSIST(0);
		dns_zone_setoption(zone, DNS_ZONEOPT_WARNMXCNAME, warn);
		dns_zone_setoption(zone, DNS_ZONEOPT_IGNOREMXCNAME, ignore);

		obj = NULL;
		result = ns_config_get(maps, "check-srv-cname", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
			warn = ISC_TRUE;
			ignore = ISC_FALSE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
			warn = ignore = ISC_FALSE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
			warn = ignore = ISC_TRUE;
		} else
			INSIST(0);
		dns_zone_setoption(zone, DNS_ZONEOPT_WARNSRVCNAME, warn);
		dns_zone_setoption(zone, DNS_ZONEOPT_IGNORESRVCNAME, ignore);

		obj = NULL;
		result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_SECURETOINSECURE,
				   cfg_obj_asboolean(obj));

		obj = NULL;
		result = cfg_map_get(zoptions, "auto-dnssec", &obj);
		if (result == ISC_R_SUCCESS) {
			const char *arg = cfg_obj_asstring(obj);
			if (strcasecmp(arg, "allow") == 0)
				allow = ISC_TRUE;
			else if (strcasecmp(arg, "maintain") == 0)
				allow = maint = ISC_TRUE;
			else if (strcasecmp(arg, "off") == 0)
				;
			else
				INSIST(0);
			dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
			dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
		}
	}

	/*
	 * Configure slave functionality.
	 */
	switch (ztype) {
	case dns_zone_slave:
	case dns_zone_stub:
		count = 0;
		obj = NULL;
		(void)cfg_map_get(zoptions, "masters", &obj);
		if (obj != NULL) {
			addrs = NULL;
			keynames = NULL;
			RETERR(ns_config_getipandkeylist(config, obj, mctx,
							 &addrs, &keynames,
							 &count));
			result = dns_zone_setmasterswithkeys(zone, addrs,
							     keynames, count);
			ns_config_putipandkeylist(mctx, &addrs, &keynames,
						  count);
		} else
			result = dns_zone_setmasters(zone, NULL, 0);
		RETERR(result);

		multi = ISC_FALSE;
		if (count > 1) {
			obj = NULL;
			result = ns_config_get(maps, "multi-master", &obj);
			INSIST(result == ISC_R_SUCCESS && obj != NULL);
			multi = cfg_obj_asboolean(obj);
		}
		dns_zone_setoption(zone, DNS_ZONEOPT_MULTIMASTER, multi);

		obj = NULL;
		result = ns_config_get(maps, "max-transfer-time-in", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setmaxxfrin(zone, cfg_obj_asuint32(obj) * 60);

		obj = NULL;
		result = ns_config_get(maps, "max-transfer-idle-in", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setidlein(zone, cfg_obj_asuint32(obj) * 60);

		obj = NULL;
		result = ns_config_get(maps, "max-refresh-time", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setmaxrefreshtime(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "min-refresh-time", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setminrefreshtime(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "max-retry-time", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setmaxretrytime(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "min-retry-time", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setminretrytime(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "transfer-source", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setxfrsource4(zone, cfg_obj_assockaddr(obj)));
		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));

		obj = NULL;
		result = ns_config_get(maps, "transfer-source-v6", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setxfrsource6(zone, cfg_obj_assockaddr(obj)));
		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));

		obj = NULL;
		result = ns_config_get(maps, "alt-transfer-source", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setaltxfrsource4(zone, cfg_obj_assockaddr(obj)));

		obj = NULL;
		result = ns_config_get(maps, "alt-transfer-source-v6", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setaltxfrsource6(zone, cfg_obj_assockaddr(obj)));

		obj = NULL;
		(void)ns_config_get(maps, "use-alt-transfer-source", &obj);
		if (obj == NULL) {
			/*
			 * Default off when views are in use otherwise
			 * on for BIND 8 compatibility.
			 */
			view = dns_zone_getview(zone);
			if (view != NULL && strcmp(view->name, "_default") == 0)
				alt = ISC_TRUE;
			else
				alt = ISC_FALSE;
		} else
			alt = cfg_obj_asboolean(obj);
		dns_zone_setoption(zone, DNS_ZONEOPT_USEALTXFRSRC, alt);

		obj = NULL;
		(void)ns_config_get(maps, "try-tcp-refresh", &obj);
		dns_zone_setoption(zone, DNS_ZONEOPT_TRYTCPREFRESH,
				   cfg_obj_asboolean(obj));
		break;

	case dns_zone_staticstub:
		RETERR(configure_staticstub(zoptions, zone, zname,
					    default_dbtype));
		break;

	default:
		break;
	}

	return (ISC_R_SUCCESS);
}
int
main(int argc, char **argv) {
	isc_result_t result;
#ifdef USE_PKCS11
	const char *engine = PKCS11_ENGINE;
#else
	const char *engine = NULL;
#endif
	char *filename = NULL, *dir = NULL;
	char newname[1024], oldname[1024];
	char keystr[DST_KEY_FORMATSIZE];
	char *endp;
	int ch;
	isc_entropy_t *ectx = NULL;
	dst_key_t *key = NULL;
	isc_uint32_t flags;
	isc_buffer_t buf;
	isc_boolean_t force = ISC_FALSE;
	isc_boolean_t remove = ISC_FALSE;
	isc_boolean_t id = ISC_FALSE;

	if (argc == 1)
		usage();

	result = isc_mem_create(0, 0, &mctx);
	if (result != ISC_R_SUCCESS)
		fatal("Out of memory");

#ifdef PKCS11CRYPTO
	pk11_result_register();
#endif
	dns_result_register();

	isc_commandline_errprint = ISC_FALSE;

	while ((ch = isc_commandline_parse(argc, argv, "E:fK:rRhv:V")) != -1) {
		switch (ch) {
		    case 'E':
			engine = isc_commandline_argument;
			break;
		    case 'f':
			force = ISC_TRUE;
			break;
		    case 'K':
			/*
			 * We don't have to copy it here, but do it to
			 * simplify cleanup later
			 */
			dir = isc_mem_strdup(mctx, isc_commandline_argument);
			if (dir == NULL) {
				fatal("Failed to allocate memory for "
				      "directory");
			}
			break;
		    case 'r':
			remove = ISC_TRUE;
			break;
		    case 'R':
			id = ISC_TRUE;
			break;
		    case 'v':
			verbose = strtol(isc_commandline_argument, &endp, 0);
			if (*endp != '\0')
				fatal("-v must be followed by a number");
			break;
		    case '?':
			if (isc_commandline_option != '?')
				fprintf(stderr, "%s: invalid argument -%c\n",
					program, isc_commandline_option);
			/* Falls into */
		    case 'h':
			/* Does not return. */
			usage();

		    case 'V':
			/* Does not return. */
			version(program);

		    default:
			fprintf(stderr, "%s: unhandled option -%c\n",
				program, isc_commandline_option);
			exit(1);
		}
	}

	if (argc < isc_commandline_index + 1 ||
	    argv[isc_commandline_index] == NULL)
		fatal("The key file name was not specified");
	if (argc > isc_commandline_index + 1)
		fatal("Extraneous arguments");

	if (dir != NULL) {
		filename = argv[isc_commandline_index];
	} else {
		result = isc_file_splitpath(mctx, argv[isc_commandline_index],
					    &dir, &filename);
		if (result != ISC_R_SUCCESS)
			fatal("cannot process filename %s: %s",
			      argv[isc_commandline_index],
			      isc_result_totext(result));
		if (strcmp(dir, ".") == 0) {
			isc_mem_free(mctx, dir);
			dir = NULL;
		}
	}

	if (ectx == NULL)
		setup_entropy(mctx, NULL, &ectx);
	result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
	if (result != ISC_R_SUCCESS)
		fatal("Could not initialize hash");
	result = dst_lib_init2(mctx, ectx, engine,
			       ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
	if (result != ISC_R_SUCCESS)
		fatal("Could not initialize dst: %s",
		      isc_result_totext(result));
	isc_entropy_stopcallbacksources(ectx);

	result = dst_key_fromnamedfile(filename, dir,
				       DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
				       mctx, &key);
	if (result != ISC_R_SUCCESS)
		fatal("Invalid keyfile name %s: %s",
		      filename, isc_result_totext(result));

	if (id) {
		fprintf(stdout, "%u\n", dst_key_rid(key));
		goto cleanup;
	}
	dst_key_format(key, keystr, sizeof(keystr));

	if (verbose > 2)
		fprintf(stderr, "%s: %s\n", program, keystr);

	if (force)
		set_keyversion(key);
	else
		check_keyversion(key, keystr);


	flags = dst_key_flags(key);
	if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
		isc_stdtime_t now;

		if ((flags & DNS_KEYFLAG_KSK) == 0)
			fprintf(stderr, "%s: warning: Key is not flagged "
					"as a KSK. Revoking a ZSK is "
					"legal, but undefined.\n",
					program);

		isc_stdtime_get(&now);
		dst_key_settime(key, DST_TIME_REVOKE, now);

		dst_key_setflags(key, flags | DNS_KEYFLAG_REVOKE);

		isc_buffer_init(&buf, newname, sizeof(newname));
		dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);

		if (access(newname, F_OK) == 0 && !force) {
			fatal("Key file %s already exists; "
			      "use -f to force overwrite", newname);
		}

		result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
					dir);
		if (result != ISC_R_SUCCESS) {
			dst_key_format(key, keystr, sizeof(keystr));
			fatal("Failed to write key %s: %s", keystr,
			      isc_result_totext(result));
		}

		isc_buffer_clear(&buf);
		dst_key_buildfilename(key, 0, dir, &buf);
		printf("%s\n", newname);

		/*
		 * Remove old key file, if told to (and if
		 * it isn't the same as the new file)
		 */
		if (remove && dst_key_alg(key) != DST_ALG_RSAMD5) {
			isc_buffer_init(&buf, oldname, sizeof(oldname));
			dst_key_setflags(key, flags & ~DNS_KEYFLAG_REVOKE);
			dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf);
			if (strcmp(oldname, newname) == 0)
				goto cleanup;
			(void)unlink(oldname);
			isc_buffer_clear(&buf);
			dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);
			(void)unlink(oldname);
		}
	} else {
		dst_key_format(key, keystr, sizeof(keystr));
		fatal("Key %s is already revoked", keystr);
	}

cleanup:
	dst_key_free(&key);
	dst_lib_destroy();
	isc_hash_destroy();
	cleanup_entropy(&ectx);
	if (verbose > 10)
		isc_mem_stats(mctx, stdout);
	if (dir != NULL)
		isc_mem_free(mctx, dir);
	isc_mem_destroy(&mctx);

	return (0);
}
Пример #25
0
static isc_result_t
opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
	dst_private_t priv;
	isc_result_t ret;
	int i;
	RSA *rsa = NULL, *pubrsa = NULL;
#ifdef USE_ENGINE
	ENGINE *e = NULL;
#endif
	isc_mem_t *mctx = key->mctx;
	const char *engine = NULL, *label = NULL;
#if defined(USE_ENGINE) || USE_EVP
	EVP_PKEY *pkey = NULL;
#endif

#if USE_EVP
	if (pub != NULL && pub->keydata.pkey != NULL)
		pubrsa = EVP_PKEY_get1_RSA(pub->keydata.pkey);
#else
	if (pub != NULL && pub->keydata.rsa != NULL) {
		pubrsa = pub->keydata.rsa;
		pub->keydata.rsa = NULL;
	}
#endif

	/* read private key file */
	ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
	if (ret != ISC_R_SUCCESS)
		goto err;

	for (i = 0; i < priv.nelements; i++) {
		switch (priv.elements[i].tag) {
		case TAG_RSA_ENGINE:
			engine = (char *)priv.elements[i].data;
			break;
		case TAG_RSA_LABEL:
			label = (char *)priv.elements[i].data;
			break;
		default:
			break;
		}
	}
	/*
	 * Is this key is stored in a HSM?
	 * See if we can fetch it.
	 */
	if (label != NULL) {
#ifdef USE_ENGINE
		if (engine == NULL)
			DST_RET(DST_R_NOENGINE);
		e = dst__openssl_getengine(engine);
		if (e == NULL)
			DST_RET(DST_R_NOENGINE);
		pkey = ENGINE_load_private_key(e, label, NULL, NULL);
		if (pkey == NULL)
			DST_RET(dst__openssl_toresult2(
					"ENGINE_load_private_key",
					ISC_R_NOTFOUND));
		key->engine = isc_mem_strdup(key->mctx, engine);
		if (key->engine == NULL)
			DST_RET(ISC_R_NOMEMORY);
		key->label = isc_mem_strdup(key->mctx, label);
		if (key->label == NULL)
			DST_RET(ISC_R_NOMEMORY);
		rsa = EVP_PKEY_get1_RSA(pkey);
		if (rsa == NULL)
			DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
		if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
			DST_RET(DST_R_INVALIDPRIVATEKEY);
		if (pubrsa != NULL)
			RSA_free(pubrsa);
		key->key_size = EVP_PKEY_bits(pkey);
#if USE_EVP
		key->keydata.pkey = pkey;
		RSA_free(rsa);
#else
		key->keydata.rsa = rsa;
		EVP_PKEY_free(pkey);
#endif
		dst__privstruct_free(&priv, mctx);
		memset(&priv, 0, sizeof(priv));
		return (ISC_R_SUCCESS);
#else
		DST_RET(DST_R_NOENGINE);
#endif
	}

	rsa = RSA_new();
	if (rsa == NULL)
		DST_RET(ISC_R_NOMEMORY);
	SET_FLAGS(rsa);

#if USE_EVP
	pkey = EVP_PKEY_new();
	if (pkey == NULL)
		DST_RET(ISC_R_NOMEMORY);
	if (!EVP_PKEY_set1_RSA(pkey, rsa))
		DST_RET(ISC_R_FAILURE);
	key->keydata.pkey = pkey;
#else
	key->keydata.rsa = rsa;
#endif

	for (i = 0; i < priv.nelements; i++) {
		BIGNUM *bn;
		switch (priv.elements[i].tag) {
		case TAG_RSA_ENGINE:
			continue;
		case TAG_RSA_LABEL:
			continue;
		case TAG_RSA_PIN:
			continue;
		default:
			bn = BN_bin2bn(priv.elements[i].data,
				       priv.elements[i].length, NULL);
			if (bn == NULL)
				DST_RET(ISC_R_NOMEMORY);
		}

		switch (priv.elements[i].tag) {
			case TAG_RSA_MODULUS:
				rsa->n = bn;
				break;
			case TAG_RSA_PUBLICEXPONENT:
				rsa->e = bn;
				break;
			case TAG_RSA_PRIVATEEXPONENT:
				rsa->d = bn;
				break;
			case TAG_RSA_PRIME1:
				rsa->p = bn;
				break;
			case TAG_RSA_PRIME2:
				rsa->q = bn;
				break;
			case TAG_RSA_EXPONENT1:
				rsa->dmp1 = bn;
				break;
			case TAG_RSA_EXPONENT2:
				rsa->dmq1 = bn;
				break;
			case TAG_RSA_COEFFICIENT:
				rsa->iqmp = bn;
				break;
		}
	}
	dst__privstruct_free(&priv, mctx);
	memset(&priv, 0, sizeof(priv));

	if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
		DST_RET(DST_R_INVALIDPRIVATEKEY);
	key->key_size = BN_num_bits(rsa->n);
	if (pubrsa != NULL)
		RSA_free(pubrsa);
#if USE_EVP
	RSA_free(rsa);
#endif

	return (ISC_R_SUCCESS);

 err:
#if USE_EVP
	if (pkey != NULL)
		EVP_PKEY_free(pkey);
#endif
	if (rsa != NULL)
		RSA_free(rsa);
	if (pubrsa != NULL)
		RSA_free(pubrsa);
	opensslrsa_destroy(key);
	dst__privstruct_free(&priv, mctx);
	memset(&priv, 0, sizeof(priv));
	return (ret);
}
Пример #26
0
static isc_result_t
opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
	dst_private_t priv;
	isc_result_t ret;
	int i;
	RSA *rsa = NULL, *pubrsa = NULL;
#ifdef USE_ENGINE
	ENGINE *ep = NULL;
	const BIGNUM *ex = NULL;
#endif
	isc_mem_t *mctx = key->mctx;
	const char *engine = NULL, *label = NULL;
#if defined(USE_ENGINE) || USE_EVP
	EVP_PKEY *pkey = NULL;
#endif
	BIGNUM *n = NULL, *e = NULL, *d = NULL;
	BIGNUM *p = NULL, *q = NULL;
	BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;

	/* read private key file */
	ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
	if (ret != ISC_R_SUCCESS)
		goto err;

	if (key->external) {
		if (priv.nelements != 0)
			DST_RET(DST_R_INVALIDPRIVATEKEY);
		if (pub == NULL)
			DST_RET(DST_R_INVALIDPRIVATEKEY);
		key->keydata.pkey = pub->keydata.pkey;
		pub->keydata.pkey = NULL;
		key->key_size = pub->key_size;
		dst__privstruct_free(&priv, mctx);
		memset(&priv, 0, sizeof(priv));
		return (ISC_R_SUCCESS);
	}

#if USE_EVP
	if (pub != NULL && pub->keydata.pkey != NULL)
		pubrsa = EVP_PKEY_get1_RSA(pub->keydata.pkey);
#else
	if (pub != NULL && pub->keydata.rsa != NULL) {
		pubrsa = pub->keydata.rsa;
		pub->keydata.rsa = NULL;
	}
#endif

	for (i = 0; i < priv.nelements; i++) {
		switch (priv.elements[i].tag) {
		case TAG_RSA_ENGINE:
			engine = (char *)priv.elements[i].data;
			break;
		case TAG_RSA_LABEL:
			label = (char *)priv.elements[i].data;
			break;
		default:
			break;
		}
	}

	/*
	 * Is this key is stored in a HSM?
	 * See if we can fetch it.
	 */
	if (label != NULL) {
#ifdef USE_ENGINE
		if (engine == NULL)
			DST_RET(DST_R_NOENGINE);
		ep = dst__openssl_getengine(engine);
		if (ep == NULL)
			DST_RET(DST_R_NOENGINE);
		pkey = ENGINE_load_private_key(ep, label, NULL, NULL);
		if (pkey == NULL)
			DST_RET(dst__openssl_toresult2(
					"ENGINE_load_private_key",
					ISC_R_NOTFOUND));
		key->engine = isc_mem_strdup(key->mctx, engine);
		if (key->engine == NULL)
			DST_RET(ISC_R_NOMEMORY);
		key->label = isc_mem_strdup(key->mctx, label);
		if (key->label == NULL)
			DST_RET(ISC_R_NOMEMORY);
		rsa = EVP_PKEY_get1_RSA(pkey);
		if (rsa == NULL)
			DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
		if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
			DST_RET(DST_R_INVALIDPRIVATEKEY);
		RSA_get0_key(rsa, NULL, &ex, NULL);
		if (BN_num_bits(ex) > RSA_MAX_PUBEXP_BITS)
			DST_RET(ISC_R_RANGE);
		if (pubrsa != NULL)
			RSA_free(pubrsa);
		key->key_size = EVP_PKEY_bits(pkey);
#if USE_EVP
		key->keydata.pkey = pkey;
		RSA_free(rsa);
#else
		key->keydata.rsa = rsa;
		EVP_PKEY_free(pkey);
#endif
		dst__privstruct_free(&priv, mctx);
		memset(&priv, 0, sizeof(priv));
		return (ISC_R_SUCCESS);
#else
		DST_RET(DST_R_NOENGINE);
#endif
	}

	rsa = RSA_new();
	if (rsa == NULL)
		DST_RET(ISC_R_NOMEMORY);
	SET_FLAGS(rsa);

#if USE_EVP
	pkey = EVP_PKEY_new();
	if (pkey == NULL)
		DST_RET(ISC_R_NOMEMORY);
	if (!EVP_PKEY_set1_RSA(pkey, rsa))
		DST_RET(ISC_R_FAILURE);
	key->keydata.pkey = pkey;
#else
	key->keydata.rsa = rsa;
#endif

	for (i = 0; i < priv.nelements; i++) {
		BIGNUM *bn;
		switch (priv.elements[i].tag) {
		case TAG_RSA_ENGINE:
			continue;
		case TAG_RSA_LABEL:
			continue;
		default:
			bn = BN_bin2bn(priv.elements[i].data,
				       priv.elements[i].length, NULL);
			if (bn == NULL)
				DST_RET(ISC_R_NOMEMORY);
			switch (priv.elements[i].tag) {
			case TAG_RSA_MODULUS:
				n = bn;
				break;
			case TAG_RSA_PUBLICEXPONENT:
				e = bn;
				break;
			case TAG_RSA_PRIVATEEXPONENT:
				d = bn;
				break;
			case TAG_RSA_PRIME1:
				p = bn;
				break;
			case TAG_RSA_PRIME2:
				q = bn;
				break;
			case TAG_RSA_EXPONENT1:
				dmp1 = bn;
				break;
			case TAG_RSA_EXPONENT2:
				dmq1 = bn;
				break;
			case TAG_RSA_COEFFICIENT:
				iqmp = bn;
				break;
			}
		}
	}
	dst__privstruct_free(&priv, mctx);
	memset(&priv, 0, sizeof(priv));

	if (RSA_set0_key(rsa, n, e, d) == 0) {
		if (n != NULL) BN_free(n);
		if (e != NULL) BN_free(e);
		if (d != NULL) BN_free(d);
	}
	if (RSA_set0_factors(rsa, p, q) == 0) {
		if (p != NULL) BN_free(p);
		if (q != NULL) BN_free(q);
	}
	if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0) {
		if (dmp1 != NULL) BN_free(dmp1);
		if (dmq1 != NULL) BN_free(dmq1);
		if (iqmp != NULL) BN_free(iqmp);
	}

	if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
		DST_RET(DST_R_INVALIDPRIVATEKEY);
	if (BN_num_bits(e) > RSA_MAX_PUBEXP_BITS)
		DST_RET(ISC_R_RANGE);
	key->key_size = BN_num_bits(n);
	if (pubrsa != NULL)
		RSA_free(pubrsa);
#if USE_EVP
	RSA_free(rsa);
#endif

	return (ISC_R_SUCCESS);

 err:
#if USE_EVP
	if (pkey != NULL)
		EVP_PKEY_free(pkey);
#endif
	if (rsa != NULL)
		RSA_free(rsa);
	if (pubrsa != NULL)
		RSA_free(pubrsa);
	key->keydata.generic = NULL;
	dst__privstruct_free(&priv, mctx);
	memset(&priv, 0, sizeof(priv));
	return (ret);
}