Пример #1
0
static void
ratelimiter_free(isc_ratelimiter_t *rl) {
	DESTROYLOCK(&rl->lock);
	isc_mem_put(rl->mctx, rl, sizeof(*rl));
}
Пример #2
0
isc_result_t
dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
			  dst_key_t *dstkey, isc_boolean_t generated,
			  dns_name_t *creator, isc_stdtime_t inception,
			  isc_stdtime_t expire, isc_mem_t *mctx,
			  dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
{
	dns_tsigkey_t *tkey;
	isc_result_t ret;
	unsigned int refs = 0;

	REQUIRE(key == NULL || *key == NULL);
	REQUIRE(name != NULL);
	REQUIRE(algorithm != NULL);
	REQUIRE(mctx != NULL);
	REQUIRE(key != NULL || ring != NULL);

	tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
	if (tkey == NULL)
		return (ISC_R_NOMEMORY);

	dns_name_init(&tkey->name, NULL);
	ret = dns_name_dup(name, mctx, &tkey->name);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_key;
	(void)dns_name_downcase(&tkey->name, &tkey->name, NULL);

	if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
		tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else {
		if (dstkey != NULL) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
		tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
		if (tkey->algorithm == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_name;
		}
		dns_name_init(tkey->algorithm, NULL);
		ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_algorithm;
		(void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
					NULL);
	}

	if (creator != NULL) {
		tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
		if (tkey->creator == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_algorithm;
		}
		dns_name_init(tkey->creator, NULL);
		ret = dns_name_dup(creator, mctx, tkey->creator);
		if (ret != ISC_R_SUCCESS) {
			isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
			goto cleanup_algorithm;
		}
	} else
		tkey->creator = NULL;

	tkey->key = NULL;
	if (dstkey != NULL)
		dst_key_attach(dstkey, &tkey->key);
	tkey->ring = ring;

	if (key != NULL)
		refs = 1;
	if (ring != NULL)
		refs++;
	ret = isc_refcount_init(&tkey->refs, refs);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_creator;

	tkey->generated = generated;
	tkey->inception = inception;
	tkey->expire = expire;
	tkey->mctx = NULL;
	isc_mem_attach(mctx, &tkey->mctx);
	ISC_LINK_INIT(tkey, link);

	tkey->magic = TSIG_MAGIC;

	if (ring != NULL) {
		ret = keyring_add(ring, name, tkey);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_refs;
	}

	/*
	 * Ignore this if it's a GSS key, since the key size is meaningless.
	 */
	if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
	    !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
	    !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		char namestr[DNS_NAME_FORMATSIZE];
		dns_name_format(name, namestr, sizeof(namestr));
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
			      DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
			      "the key '%s' is too short to be secure",
			      namestr);
	}

	if (key != NULL)
		*key = tkey;

	return (ISC_R_SUCCESS);

 cleanup_refs:
	tkey->magic = 0;
	while (refs-- > 0)
		isc_refcount_decrement(&tkey->refs, NULL);
	isc_refcount_destroy(&tkey->refs);
 cleanup_creator:
	if (tkey->key != NULL)
		dst_key_free(&tkey->key);
	if (tkey->creator != NULL) {
		dns_name_free(tkey->creator, mctx);
		isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
	}
 cleanup_algorithm:
	if (algname_is_allocated(tkey->algorithm)) {
		if (dns_name_dynamic(tkey->algorithm))
			dns_name_free(tkey->algorithm, mctx);
		isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
	}
 cleanup_name:
	dns_name_free(&tkey->name, mctx);
 cleanup_key:
	isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));

	return (ret);
}
Пример #3
0
isc_result_t
isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
		    isc_httpdclientok_t *client_ok,
		    isc_httpdondestroy_t *ondestroy, void *cb_arg,
		    isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdp)
{
	isc_result_t result;
	isc_httpdmgr_t *httpd;

	REQUIRE(mctx != NULL);
	REQUIRE(sock != NULL);
	REQUIRE(task != NULL);
	REQUIRE(tmgr != NULL);
	REQUIRE(httpdp != NULL && *httpdp == NULL);

	httpd = isc_mem_get(mctx, sizeof(isc_httpdmgr_t));
	if (httpd == NULL)
		return (ISC_R_NOMEMORY);

	result = isc_mutex_init(&httpd->lock);
	if (result != ISC_R_SUCCESS) {
		isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t));
		return (result);
	}
	httpd->mctx = NULL;
	isc_mem_attach(mctx, &httpd->mctx);
	httpd->sock = NULL;
	isc_socket_attach(sock, &httpd->sock);
	httpd->task = NULL;
	isc_task_attach(task, &httpd->task);
	httpd->timermgr = tmgr; /* XXXMLG no attach function? */
	httpd->client_ok = client_ok;
	httpd->ondestroy = ondestroy;
	httpd->cb_arg = cb_arg;

	ISC_LIST_INIT(httpd->running);
	ISC_LIST_INIT(httpd->urls);

	/* XXXMLG ignore errors on isc_socket_listen() */
	result = isc_socket_listen(sock, SOMAXCONN);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_socket_listen() failed: %s",
				 isc_result_totext(result));
		goto cleanup;
	}

	(void)isc_socket_filter(sock, "httpready");

	result = isc_socket_accept(sock, task, isc_httpd_accept, httpd);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	httpd->render_404 = render_404;
	httpd->render_500 = render_500;

	*httpdp = httpd;
	return (ISC_R_SUCCESS);

  cleanup:
	isc_task_detach(&httpd->task);
	isc_socket_detach(&httpd->sock);
	isc_mem_detach(&httpd->mctx);
	(void)isc_mutex_destroy(&httpd->lock);
	isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t));
	return (result);
}
Пример #4
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->dampening = 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->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->maxbits = 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;
	view->redirect = 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);
}
Пример #5
0
void
dns_stats_freecounters(isc_mem_t *mctx, isc_uint64_t **ctrp) {
	isc_mem_put(mctx, *ctrp, DNS_STATS_NCOUNTERS * sizeof(isc_uint64_t));
	*ctrp = NULL;
}
Пример #6
0
void
isc_timermgr_destroy(isc_timermgr_t **managerp) {
	isc_timermgr_t *manager;
	isc_mem_t *mctx;

	/*
	 * Destroy a timer manager.
	 */

	REQUIRE(managerp != NULL);
	manager = *managerp;
	REQUIRE(VALID_MANAGER(manager));

	LOCK(&manager->lock);

#ifndef ISC_PLATFORM_USETHREADS
	if (manager->refs > 1) {
		manager->refs--;
		UNLOCK(&manager->lock);
		*managerp = NULL;
		return;
	}

	isc__timermgr_dispatch();
#endif /* ISC_PLATFORM_USETHREADS */

	REQUIRE(EMPTY(manager->timers));
	manager->done = ISC_TRUE;

#ifdef ISC_PLATFORM_USETHREADS
	XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
			      ISC_MSG_SIGNALDESTROY, "signal (destroy)"));
	SIGNAL(&manager->wakeup);
#endif /* ISC_PLATFORM_USETHREADS */

	UNLOCK(&manager->lock);

#ifdef ISC_PLATFORM_USETHREADS
	/*
	 * Wait for thread to exit.
	 */
	if (isc_thread_join(manager->thread, NULL) != ISC_R_SUCCESS)
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_thread_join() %s",
				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
						ISC_MSG_FAILED, "failed"));
#endif /* ISC_PLATFORM_USETHREADS */

	/*
	 * Clean up.
	 */
#ifdef ISC_PLATFORM_USETHREADS
	(void)isc_condition_destroy(&manager->wakeup);
#endif /* ISC_PLATFORM_USETHREADS */
	DESTROYLOCK(&manager->lock);
	isc_heap_destroy(&manager->heap);
	manager->magic = 0;
	mctx = manager->mctx;
	isc_mem_put(mctx, manager, sizeof(*manager));
	isc_mem_detach(&mctx);

	*managerp = NULL;
}
Пример #7
0
isc_result_t
ns_lwdclientmgr_create(ns_lwreslistener_t *listener, unsigned int nclients,
		    isc_taskmgr_t *taskmgr)
{
	ns_lwresd_t *lwresd = listener->manager;
	ns_lwdclientmgr_t *cm;
	ns_lwdclient_t *client;
	unsigned int i;
	isc_result_t result = ISC_R_FAILURE;

	cm = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclientmgr_t));
	if (cm == NULL)
		return (ISC_R_NOMEMORY);

	cm->listener = NULL;
	ns_lwreslistener_attach(listener, &cm->listener);
	cm->mctx = lwresd->mctx;
	cm->sock = NULL;
	isc_socket_attach(listener->sock, &cm->sock);
	cm->view = lwresd->view;
	cm->lwctx = NULL;
	cm->task = NULL;
	cm->flags = 0;
	ISC_LINK_INIT(cm, link);
	ISC_LIST_INIT(cm->idle);
	ISC_LIST_INIT(cm->running);

	if (lwres_context_create(&cm->lwctx, cm->mctx,
				 ns__lwresd_memalloc, ns__lwresd_memfree,
				 LWRES_CONTEXT_SERVERMODE)
	    != ISC_R_SUCCESS)
		goto errout;

	for (i = 0; i < nclients; i++) {
		client = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclient_t));
		if (client != NULL) {
			ns_lwdclient_log(50, "created client %p, manager %p",
					 client, cm);
			ns_lwdclient_initialize(client, cm);
		}
	}

	/*
	 * If we could create no clients, clean up and return.
	 */
	if (ISC_LIST_EMPTY(cm->idle))
		goto errout;

	result = isc_task_create(taskmgr, 0, &cm->task);
	if (result != ISC_R_SUCCESS)
		goto errout;

	/*
	 * This MUST be last, since there is no way to cancel an onshutdown...
	 */
	result = isc_task_onshutdown(cm->task, lwdclientmgr_shutdown_callback,
				     cm);
	if (result != ISC_R_SUCCESS)
		goto errout;

	ns_lwreslistener_linkcm(listener, cm);

	return (ISC_R_SUCCESS);

 errout:
	client = ISC_LIST_HEAD(cm->idle);
	while (client != NULL) {
		ISC_LIST_UNLINK(cm->idle, client, link);
		isc_mem_put(lwresd->mctx, client, sizeof(*client));
		client = ISC_LIST_HEAD(cm->idle);
	}

	if (cm->task != NULL)
		isc_task_detach(&cm->task);

	if (cm->lwctx != NULL)
		lwres_context_destroy(&cm->lwctx);

	isc_mem_put(lwresd->mctx, cm, sizeof(*cm));
	return (result);
}
Пример #8
0
static isc_result_t
getbuf6(isc_interfaceiter_t *iter) {
	char strbuf[ISC_STRERRORSIZE];
	isc_result_t result;

	iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;

	for (;;) {
		iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
		if (iter->buf6 == NULL)
			return (ISC_R_NOMEMORY);

		memset(&iter->lifc, 0, sizeof(iter->lifc));
#ifdef ISC_HAVE_LIFC_FAMILY
		iter->lifc.lifc_family = AF_INET6;
#endif
#ifdef ISC_HAVE_LIFC_FLAGS
		iter->lifc.lifc_flags = 0;
#endif
		iter->lifc.lifc_len = iter->bufsize6;
		iter->lifc.lifc_buf = iter->buf6;
		/*
		 * Ignore the HP/UX warning about "integer overflow during
		 * conversion".  It comes from its own macro definition,
		 * and is really hard to shut up.
		 */
		if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
		    == -1) {
#ifdef __hpux
			/*
			 * IPv6 interface scanning is not available on all
			 * kernels w/ IPv6 sockets.
			 */
			if (errno == ENOENT) {
				isc__strerror(errno, strbuf, sizeof(strbuf));
				isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
					      ISC_LOGMODULE_INTERFACE,
					      ISC_LOG_DEBUG(1),
					      isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_IFITERIOCTL,
							ISC_MSG_GETIFCONFIG,
							"get interface "
							"configuration: %s"),
					       strbuf);
				result = ISC_R_FAILURE;
				goto cleanup;
			}
#endif
			if (errno != EINVAL) {
				isc__strerror(errno, strbuf, sizeof(strbuf));
				UNEXPECTED_ERROR(__FILE__, __LINE__,
						 isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_IFITERIOCTL,
							ISC_MSG_GETIFCONFIG,
							"get interface "
							"configuration: %s"),
						 strbuf);
				result = ISC_R_UNEXPECTED;
				goto cleanup;
			}
			/*
			 * EINVAL.  Retry with a bigger buffer.
			 */
		} else {
			/*
			 * The ioctl succeeded.
			 * Some OS's just return what will fit rather
			 * than set EINVAL if the buffer is too small
			 * to fit all the interfaces in.  If
			 * ifc.ifc_len is too near to the end of the
			 * buffer we will grow it just in case and
			 * retry.
			 */
			if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
			    < iter->bufsize6)
				break;
		}
		if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_IFITERIOCTL,
							ISC_MSG_BUFFERMAX,
							"get interface "
							"configuration: "
							"maximum buffer "
							"size exceeded"));
			result = ISC_R_UNEXPECTED;
			goto cleanup;
		}
		isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);

		iter->bufsize6 *= 2;
	}

	if (iter->lifc.lifc_len != 0)
		iter->mode = 6;
	return (ISC_R_SUCCESS);

 cleanup:
	isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
	iter->buf6 = NULL;
	return (result);
}
Пример #9
0
isc_result_t
isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
	isc_interfaceiter_t *iter;
	isc_result_t result;
	char strbuf[ISC_STRERRORSIZE];

	REQUIRE(mctx != NULL);
	REQUIRE(iterp != NULL);
	REQUIRE(*iterp == NULL);

	iter = isc_mem_get(mctx, sizeof(*iter));
	if (iter == NULL)
		return (ISC_R_NOMEMORY);

	iter->mctx = mctx;
	iter->mode = 4;
	iter->buf = NULL;
	iter->pos = (unsigned int) -1;
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
	iter->buf6 = NULL;
	iter->pos6 = (unsigned int) -1;
	iter->result6 = ISC_R_NOMORE;
	iter->socket6 = -1;
	iter->first6 = ISC_FALSE;
#endif

	/*
	 * Get the interface configuration, allocating more memory if
	 * necessary.
	 */

#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
	result = isc_net_probeipv6();
	if (result == ISC_R_SUCCESS) {
		/*
		 * Create an unbound datagram socket to do the SIOCGLIFCONF
		 * ioctl on.  HP/UX requires an AF_INET6 socket for
		 * SIOCGLIFCONF to get IPv6 addresses.
		 */
		if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
			isc__strerror(errno, strbuf, sizeof(strbuf));
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_IFITERIOCTL,
							ISC_MSG_MAKESCANSOCKET,
							"making interface "
							"scan socket: %s"),
					 strbuf);
			result = ISC_R_UNEXPECTED;
			goto socket6_failure;
		}
		result = iter->result6 = getbuf6(iter);
		if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
			goto ioctl6_failure;
	}
#endif
	if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 isc_msgcat_get(isc_msgcat,
						ISC_MSGSET_IFITERIOCTL,
						ISC_MSG_MAKESCANSOCKET,
						"making interface "
						"scan socket: %s"),
				 strbuf);
		result = ISC_R_UNEXPECTED;
		goto socket_failure;
	}
	result = getbuf4(iter);
	if (result != ISC_R_SUCCESS)
		goto ioctl_failure;

	/*
	 * A newly created iterator has an undefined position
	 * until isc_interfaceiter_first() is called.
	 */
#ifdef HAVE_TRUCLUSTER
	iter->clua_context = -1;
	iter->clua_done = ISC_TRUE;
#endif
#ifdef __linux
	iter->proc = fopen("/proc/net/if_inet6", "r");
	iter->valid = ISC_R_FAILURE;
#endif
	iter->result = ISC_R_FAILURE;

	iter->magic = IFITER_MAGIC;
	*iterp = iter;
	return (ISC_R_SUCCESS);

 ioctl_failure:
	if (iter->buf != NULL)
		isc_mem_put(mctx, iter->buf, iter->bufsize);
	(void) close(iter->socket);

 socket_failure:
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
	if (iter->buf6 != NULL)
		isc_mem_put(mctx, iter->buf6, iter->bufsize6);
  ioctl6_failure:
	if (iter->socket6 != -1)
		(void) close(iter->socket6);
  socket6_failure:
#endif

	isc_mem_put(mctx, iter, sizeof(*iter));
	return (result);
}
Пример #10
0
ISC_TASKFUNC_SCOPE isc_result_t
isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
		    unsigned int default_quantum, isc_taskmgr_t **managerp)
{
	isc_result_t result;
	unsigned int i, started = 0;
	isc__taskmgr_t *manager;

	/*
	 * Create a new task manager.
	 */

	REQUIRE(workers > 0);
	REQUIRE(managerp != NULL && *managerp == NULL);

#ifndef USE_WORKER_THREADS
	UNUSED(i);
	UNUSED(started);
#endif

#ifdef USE_SHARED_MANAGER
	if (taskmgr != NULL) {
		if (taskmgr->refs == 0)
			return (ISC_R_SHUTTINGDOWN);
		taskmgr->refs++;
		*managerp = (isc_taskmgr_t *)taskmgr;
		return (ISC_R_SUCCESS);
	}
#endif /* USE_SHARED_MANAGER */

	manager = isc_mem_get(mctx, sizeof(*manager));
	if (manager == NULL)
		return (ISC_R_NOMEMORY);
	manager->common.methods = &taskmgrmethods;
	manager->common.impmagic = TASK_MANAGER_MAGIC;
	manager->common.magic = ISCAPI_TASKMGR_MAGIC;
	manager->mode = isc_taskmgrmode_normal;
	manager->mctx = NULL;
	result = isc_mutex_init(&manager->lock);
	if (result != ISC_R_SUCCESS)
		goto cleanup_mgr;

#ifdef USE_WORKER_THREADS
	manager->workers = 0;
	manager->threads = isc_mem_allocate(mctx,
					    workers * sizeof(isc_thread_t));
	if (manager->threads == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup_lock;
	}
	if (isc_condition_init(&manager->work_available) != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_condition_init() %s",
				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
						ISC_MSG_FAILED, "failed"));
		result = ISC_R_UNEXPECTED;
		goto cleanup_threads;
	}
	if (isc_condition_init(&manager->exclusive_granted) != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_condition_init() %s",
				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
						ISC_MSG_FAILED, "failed"));
		result = ISC_R_UNEXPECTED;
		goto cleanup_workavailable;
	}
	if (isc_condition_init(&manager->paused) != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_condition_init() %s",
				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
						ISC_MSG_FAILED, "failed"));
		result = ISC_R_UNEXPECTED;
		goto cleanup_exclusivegranted;
	}
#endif /* USE_WORKER_THREADS */
	if (default_quantum == 0)
		default_quantum = DEFAULT_DEFAULT_QUANTUM;
	manager->default_quantum = default_quantum;
	INIT_LIST(manager->tasks);
	INIT_LIST(manager->ready_tasks);
	INIT_LIST(manager->ready_priority_tasks);
	manager->tasks_running = 0;
	manager->exclusive_requested = ISC_FALSE;
	manager->pause_requested = ISC_FALSE;
	manager->exiting = ISC_FALSE;
	manager->excl = NULL;

	isc_mem_attach(mctx, &manager->mctx);

#ifdef USE_WORKER_THREADS
	LOCK(&manager->lock);
	/*
	 * Start workers.
	 */
	for (i = 0; i < workers; i++) {
		if (isc_thread_create(run, manager,
				      &manager->threads[manager->workers]) ==
		    ISC_R_SUCCESS) {
			manager->workers++;
			started++;
		}
	}
	UNLOCK(&manager->lock);

	if (started == 0) {
		manager_free(manager);
		return (ISC_R_NOTHREADS);
	}
	isc_thread_setconcurrency(workers);
#endif /* USE_WORKER_THREADS */
#ifdef USE_SHARED_MANAGER
	manager->refs = 1;
	taskmgr = manager;
#endif /* USE_SHARED_MANAGER */

	*managerp = (isc_taskmgr_t *)manager;

	return (ISC_R_SUCCESS);

#ifdef USE_WORKER_THREADS
 cleanup_exclusivegranted:
	(void)isc_condition_destroy(&manager->exclusive_granted);
 cleanup_workavailable:
	(void)isc_condition_destroy(&manager->work_available);
 cleanup_threads:
	isc_mem_free(mctx, manager->threads);
 cleanup_lock:
	DESTROYLOCK(&manager->lock);
#endif
 cleanup_mgr:
	isc_mem_put(mctx, manager, sizeof(*manager));
	return (result);
}
Пример #11
0
static isc_result_t
getbuf4(isc_interfaceiter_t *iter) {
	char strbuf[ISC_STRERRORSIZE];

	iter->bufsize = IFCONF_BUFSIZE_INITIAL;

	for (;;) {
		iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
		if (iter->buf == NULL)
			return (ISC_R_NOMEMORY);

		memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
		iter->ifc.ifc_len = iter->bufsize;
		iter->ifc.ifc_buf = iter->buf;
		/*
		 * Ignore the HP/UX warning about "integer overflow during
		 * conversion".  It comes from its own macro definition,
		 * and is really hard to shut up.
		 */
		if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
		    == -1) {
			if (errno != EINVAL) {
				isc__strerror(errno, strbuf, sizeof(strbuf));
				UNEXPECTED_ERROR(__FILE__, __LINE__,
						 isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_IFITERIOCTL,
							ISC_MSG_GETIFCONFIG,
							"get interface "
							"configuration: %s"),
						 strbuf);
				goto unexpected;
			}
			/*
			 * EINVAL.  Retry with a bigger buffer.
			 */
		} else {
			/*
			 * The ioctl succeeded.
			 * Some OS's just return what will fit rather
			 * than set EINVAL if the buffer is too small
			 * to fit all the interfaces in.  If
			 * ifc.lifc_len is too near to the end of the
			 * buffer we will grow it just in case and
			 * retry.
			 */
			if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
			    < iter->bufsize)
				break;
		}
		if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_IFITERIOCTL,
							ISC_MSG_BUFFERMAX,
							"get interface "
							"configuration: "
							"maximum buffer "
							"size exceeded"));
			goto unexpected;
		}
		isc_mem_put(iter->mctx, iter->buf, iter->bufsize);

		iter->bufsize *= 2;
	}
	return (ISC_R_SUCCESS);

 unexpected:
	isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
	iter->buf = NULL;
	return (ISC_R_UNEXPECTED);
}
Пример #12
0
static isc_result_t
opensslrsa_tofile(const dst_key_t *key, const char *directory) {
	int i;
	RSA *rsa;
	dst_private_t priv;
	unsigned char *bufs[8];
	isc_result_t result;

#if USE_EVP
	if (key->keydata.pkey == NULL)
		return (DST_R_NULLKEY);
	rsa = EVP_PKEY_get1_RSA(key->keydata.pkey);
	if (rsa == NULL)
		return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
#else
	if (key->keydata.rsa == NULL)
		return (DST_R_NULLKEY);
	rsa = key->keydata.rsa;
#endif

	for (i = 0; i < 8; i++) {
		bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(rsa->n));
		if (bufs[i] == NULL) {
			result = ISC_R_NOMEMORY;
			goto fail;
		}
	}

	i = 0;

	priv.elements[i].tag = TAG_RSA_MODULUS;
	priv.elements[i].length = BN_num_bytes(rsa->n);
	BN_bn2bin(rsa->n, bufs[i]);
	priv.elements[i].data = bufs[i];
	i++;

	priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT;
	priv.elements[i].length = BN_num_bytes(rsa->e);
	BN_bn2bin(rsa->e, bufs[i]);
	priv.elements[i].data = bufs[i];
	i++;

	if (rsa->d != NULL) {
		priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
		priv.elements[i].length = BN_num_bytes(rsa->d);
		BN_bn2bin(rsa->d, bufs[i]);
		priv.elements[i].data = bufs[i];
		i++;
	}

	if (rsa->p != NULL) {
		priv.elements[i].tag = TAG_RSA_PRIME1;
		priv.elements[i].length = BN_num_bytes(rsa->p);
		BN_bn2bin(rsa->p, bufs[i]);
		priv.elements[i].data = bufs[i];
		i++;
	}

	if (rsa->q != NULL) {
		priv.elements[i].tag = TAG_RSA_PRIME2;
		priv.elements[i].length = BN_num_bytes(rsa->q);
		BN_bn2bin(rsa->q, bufs[i]);
		priv.elements[i].data = bufs[i];
		i++;
	}

	if (rsa->dmp1 != NULL) {
		priv.elements[i].tag = TAG_RSA_EXPONENT1;
		priv.elements[i].length = BN_num_bytes(rsa->dmp1);
		BN_bn2bin(rsa->dmp1, bufs[i]);
		priv.elements[i].data = bufs[i];
		i++;
	}

	if (rsa->dmq1 != NULL) {
		priv.elements[i].tag = TAG_RSA_EXPONENT2;
		priv.elements[i].length = BN_num_bytes(rsa->dmq1);
		BN_bn2bin(rsa->dmq1, bufs[i]);
		priv.elements[i].data = bufs[i];
		i++;
	}

	if (rsa->iqmp != NULL) {
		priv.elements[i].tag = TAG_RSA_COEFFICIENT;
		priv.elements[i].length = BN_num_bytes(rsa->iqmp);
		BN_bn2bin(rsa->iqmp, bufs[i]);
		priv.elements[i].data = bufs[i];
		i++;
	}

	if (key->engine != NULL) {
		priv.elements[i].tag = TAG_RSA_ENGINE;
		priv.elements[i].length = strlen(key->engine) + 1;
		priv.elements[i].data = (unsigned char *)key->engine;
		i++;
	}

	if (key->label != NULL) {
		priv.elements[i].tag = TAG_RSA_LABEL;
		priv.elements[i].length = strlen(key->label) + 1;
		priv.elements[i].data = (unsigned char *)key->label;
		i++;
	}


	priv.nelements = i;
	result = dst__privstruct_writefile(key, &priv, directory);
 fail:
#if USE_EVP
	RSA_free(rsa);
#endif
	for (i = 0; i < 8; i++) {
		if (bufs[i] == NULL)
			break;
		isc_mem_put(key->mctx, bufs[i], BN_num_bytes(rsa->n));
	}
	return (result);
}
Пример #13
0
static void
opensslrsa_destroyctx(dst_context_t *dctx) {
#if USE_EVP
	EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
#endif

	REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
		dctx->key->key_alg == DST_ALG_RSASHA1 ||
		dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 ||
		dctx->key->key_alg == DST_ALG_RSASHA256 ||
		dctx->key->key_alg == DST_ALG_RSASHA512);

#if USE_EVP
	if (evp_md_ctx != NULL) {
		EVP_MD_CTX_destroy(evp_md_ctx);
		dctx->ctxdata.evp_md_ctx = NULL;
	}
#else
	switch (dctx->key->key_alg) {
	case DST_ALG_RSAMD5:
		{
			isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;

			if (md5ctx != NULL) {
				isc_md5_invalidate(md5ctx);
				isc_mem_put(dctx->mctx, md5ctx,
					    sizeof(isc_md5_t));
				dctx->ctxdata.md5ctx = NULL;
			}
		}
		break;
	case DST_ALG_RSASHA1:
	case DST_ALG_NSEC3RSASHA1:
		{
			isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;

			if (sha1ctx != NULL) {
				isc_sha1_invalidate(sha1ctx);
				isc_mem_put(dctx->mctx, sha1ctx,
					    sizeof(isc_sha1_t));
				dctx->ctxdata.sha1ctx = NULL;
			}
		}
		break;
	case DST_ALG_RSASHA256:
		{
			isc_sha256_t *sha256ctx = dctx->ctxdata.sha256ctx;

			if (sha256ctx != NULL) {
				isc_sha256_invalidate(sha256ctx);
				isc_mem_put(dctx->mctx, sha256ctx,
					    sizeof(isc_sha256_t));
				dctx->ctxdata.sha256ctx = NULL;
			}
		}
		break;
	case DST_ALG_RSASHA512:
		{
			isc_sha512_t *sha512ctx = dctx->ctxdata.sha512ctx;

			if (sha512ctx != NULL) {
				isc_sha512_invalidate(sha512ctx);
				isc_mem_put(dctx->mctx, sha512ctx,
					    sizeof(isc_sha512_t));
				dctx->ctxdata.sha512ctx = NULL;
			}
		}
		break;
	default:
		INSIST(0);
	}
#endif
}
Пример #14
0
int
main(int argc, char **argv) {
	isc_boolean_t show_final_mem = ISC_FALSE;
	isc_result_t result = ISC_R_SUCCESS;
	isc_taskmgr_t *taskmgr = NULL;
	isc_task_t *task = NULL;
	isc_log_t *log = NULL;
	isc_logconfig_t *logconfig = NULL;
	isc_logdestination_t logdest;
	cfg_parser_t *pctx = NULL;
	cfg_obj_t *config = NULL;
	const char *keyname = NULL;
	struct in_addr in;
	struct in6_addr in6;
	char *p;
	size_t argslen;
	int ch;
	int i;

	result = isc_file_progname(*argv, program, sizeof(program));
	if (result != ISC_R_SUCCESS)
		memcpy(program, "rndc", 5);
	progname = program;

	admin_conffile = RNDC_CONFFILE;
	admin_keyfile = RNDC_KEYFILE;

	isc_sockaddr_any(&local4);
	isc_sockaddr_any6(&local6);

	result = isc_app_start();
	if (result != ISC_R_SUCCESS)
		fatal("isc_app_start() failed: %s", isc_result_totext(result));

	isc_commandline_errprint = ISC_FALSE;

	while ((ch = isc_commandline_parse(argc, argv, "b:c:hk:Mmp:s:Vy:"))
	       != -1) {
		switch (ch) {
		case 'b':
			if (inet_pton(AF_INET, isc_commandline_argument,
				      &in) == 1) {
				isc_sockaddr_fromin(&local4, &in, 0);
				local4set = ISC_TRUE;
			} else if (inet_pton(AF_INET6, isc_commandline_argument,
					     &in6) == 1) {
				isc_sockaddr_fromin6(&local6, &in6, 0);
				local6set = ISC_TRUE;
			}
			break;

		case 'c':
			admin_conffile = isc_commandline_argument;
			break;

		case 'k':
			admin_keyfile = isc_commandline_argument;
			break;

		case 'M':
			isc_mem_debugging = ISC_MEM_DEBUGTRACE;
			break;

		case 'm':
			show_final_mem = ISC_TRUE;
			break;

		case 'p':
			remoteport = atoi(isc_commandline_argument);
			if (remoteport > 65535 || remoteport == 0)
				fatal("port '%s' out of range",
				      isc_commandline_argument);
			break;

		case 's':
			servername = isc_commandline_argument;
			break;

		case 'V':
			verbose = ISC_TRUE;
			break;

		case 'y':
			keyname = isc_commandline_argument;
			break;

		case '?':
			if (isc_commandline_option != '?') {
				fprintf(stderr, "%s: invalid argument -%c\n",
					program, isc_commandline_option);
				usage(1);
			}
		case 'h':
			usage(0);
			break;
		default:
			fprintf(stderr, "%s: unhandled option -%c\n",
				program, isc_commandline_option);
			exit(1);
		}
	}

	argc -= isc_commandline_index;
	argv += isc_commandline_index;

	if (argc < 1)
		usage(1);

	isc_random_get(&serial);

	DO("create memory context", isc_mem_create(0, 0, &mctx));
	DO("create socket manager", isc_socketmgr_create(mctx, &socketmgr));
	DO("create task manager", isc_taskmgr_create(mctx, 1, 0, &taskmgr));
	DO("create task", isc_task_create(taskmgr, 0, &task));

	DO("create logging context", isc_log_create(mctx, &log, &logconfig));
	isc_log_setcontext(log);
	DO("setting log tag", isc_log_settag(logconfig, progname));
	logdest.file.stream = stderr;
	logdest.file.name = NULL;
	logdest.file.versions = ISC_LOG_ROLLNEVER;
	logdest.file.maximum_size = 0;
	DO("creating log channel",
	   isc_log_createchannel(logconfig, "stderr",
				 ISC_LOG_TOFILEDESC, ISC_LOG_INFO, &logdest,
				 ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL));
	DO("enabling log channel", isc_log_usechannel(logconfig, "stderr",
						      NULL, NULL));

	parse_config(mctx, log, keyname, &pctx, &config);

	isccc_result_register();

	command = *argv;

	/*
	 * Convert argc/argv into a space-delimited command string
	 * similar to what the user might enter in interactive mode
	 * (if that were implemented).
	 */
	argslen = 0;
	for (i = 0; i < argc; i++)
		argslen += strlen(argv[i]) + 1;

	args = isc_mem_get(mctx, argslen);
	if (args == NULL)
		DO("isc_mem_get", ISC_R_NOMEMORY);

	p = args;
	for (i = 0; i < argc; i++) {
		size_t len = strlen(argv[i]);
		memcpy(p, argv[i], len);
		p += len;
		*p++ = ' ';
	}

	p--;
	*p++ = '\0';
	INSIST(p == args + argslen);

	notify("%s", command);

	if (strcmp(command, "restart") == 0)
		fatal("'%s' is not implemented", command);

	if (nserveraddrs == 0)
		get_addresses(servername, (in_port_t) remoteport);

	DO("post event", isc_app_onrun(mctx, task, rndc_start, NULL));

	result = isc_app_run();
	if (result != ISC_R_SUCCESS)
		fatal("isc_app_run() failed: %s", isc_result_totext(result));

	if (connects > 0 || sends > 0 || recvs > 0)
		isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);

	isc_task_detach(&task);
	isc_taskmgr_destroy(&taskmgr);
	isc_socketmgr_destroy(&socketmgr);
	isc_log_destroy(&log);
	isc_log_setcontext(NULL);

	cfg_obj_destroy(pctx, &config);
	cfg_parser_destroy(&pctx);

	isc_mem_put(mctx, args, argslen);
	isccc_ccmsg_invalidate(&ccmsg);

	dns_name_destroy();

	if (show_final_mem)
		isc_mem_stats(mctx, stderr);

	isc_mem_destroy(&mctx);

	if (failed)
		return (1);

	return (0);
}
Пример #15
0
isc_result_t
isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
		 isc_time_t *expires, isc_interval_t *interval,
		 isc_task_t *task, isc_taskaction_t action, const void *arg,
		 isc_timer_t **timerp)
{
	isc_timer_t *timer;
	isc_result_t result;
	isc_time_t now;

	/*
	 * Create a new 'type' timer managed by 'manager'.  The timers
	 * parameters are specified by 'expires' and 'interval'.  Events
	 * will be posted to 'task' and when dispatched 'action' will be
	 * called with 'arg' as the arg value.  The new timer is returned
	 * in 'timerp'.
	 */

	REQUIRE(VALID_MANAGER(manager));
	REQUIRE(task != NULL);
	REQUIRE(action != NULL);
	if (expires == NULL)
		expires = isc_time_epoch;
	if (interval == NULL)
		interval = isc_interval_zero;
	REQUIRE(type == isc_timertype_inactive ||
		!(isc_time_isepoch(expires) && isc_interval_iszero(interval)));
	REQUIRE(timerp != NULL && *timerp == NULL);
	REQUIRE(type != isc_timertype_limited ||
		!(isc_time_isepoch(expires) || isc_interval_iszero(interval)));

	/*
	 * Get current time.
	 */
	if (type != isc_timertype_inactive) {
		TIME_NOW(&now);
	} else {
		/*
		 * We don't have to do this, but it keeps the compiler from
		 * complaining about "now" possibly being used without being
		 * set, even though it will never actually happen.
		 */
		isc_time_settoepoch(&now);
	}


	timer = isc_mem_get(manager->mctx, sizeof(*timer));
	if (timer == NULL)
		return (ISC_R_NOMEMORY);

	timer->manager = manager;
	timer->references = 1;

	if (type == isc_timertype_once && !isc_interval_iszero(interval)) {
		result = isc_time_add(&now, interval, &timer->idle);
		if (result != ISC_R_SUCCESS) {
			isc_mem_put(manager->mctx, timer, sizeof(*timer));
			return (result);
		}
	} else
		isc_time_settoepoch(&timer->idle);

	timer->type = type;
	timer->expires = *expires;
	timer->interval = *interval;
	timer->task = NULL;
	isc_task_attach(task, &timer->task);
	timer->action = action;
	/*
	 * Removing the const attribute from "arg" is the best of two
	 * evils here.  If the timer->arg member is made const, then
	 * it affects a great many recipients of the timer event
	 * which did not pass in an "arg" that was truly const.
	 * Changing isc_timer_create() to not have "arg" prototyped as const,
	 * though, can cause compilers warnings for calls that *do*
	 * have a truly const arg.  The caller will have to carefully
	 * keep track of whether arg started as a true const.
	 */
	DE_CONST(arg, timer->arg);
	timer->index = 0;
	result = isc_mutex_init(&timer->lock);
	if (result != ISC_R_SUCCESS) {
		isc_task_detach(&timer->task);
		isc_mem_put(manager->mctx, timer, sizeof(*timer));
		return (result);
	}
	ISC_LINK_INIT(timer, link);
	timer->magic = TIMER_MAGIC;

	LOCK(&manager->lock);

	/*
	 * Note we don't have to lock the timer like we normally would because
	 * there are no external references to it yet.
	 */

	if (type != isc_timertype_inactive)
		result = schedule(timer, &now, ISC_TRUE);
	else
		result = ISC_R_SUCCESS;
	if (result == ISC_R_SUCCESS)
		APPEND(manager->timers, timer, link);

	UNLOCK(&manager->lock);

	if (result != ISC_R_SUCCESS) {
		timer->magic = 0;
		DESTROYLOCK(&timer->lock);
		isc_task_detach(&timer->task);
		isc_mem_put(manager->mctx, timer, sizeof(*timer));
		return (result);
	}

	*timerp = timer;

	return (ISC_R_SUCCESS);
}
Пример #16
0
isc_result_t
isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
	isc_interfaceiter_t *iter;
	isc_result_t result;
	size_t bufsize;
	size_t bufused;
	char strbuf[ISC_STRERRORSIZE];

	REQUIRE(mctx != NULL);
	REQUIRE(iterp != NULL);
	REQUIRE(*iterp == NULL);

	iter = isc_mem_get(mctx, sizeof(*iter));
	if (iter == NULL)
		return (ISC_R_NOMEMORY);

	iter->mctx = mctx;
	iter->buf = 0;

	/*
	 * Determine the amount of memory needed.
	 */
	bufsize = 0;
	if (sysctl(mib, 6, NULL, &bufsize, NULL, (size_t) 0) < 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 isc_msgcat_get(isc_msgcat,
						ISC_MSGSET_IFITERSYSCTL,
						ISC_MSG_GETIFLISTSIZE,
						"getting interface "
						"list size: sysctl: %s"),
				 strbuf);
		result = ISC_R_UNEXPECTED;
		goto failure;
	}
	iter->bufsize = bufsize;

	iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
	if (iter->buf == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}

	bufused = bufsize;
	if (sysctl(mib, 6, iter->buf, &bufused, NULL, (size_t) 0) < 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 isc_msgcat_get(isc_msgcat,
						ISC_MSGSET_IFITERSYSCTL,
						ISC_MSG_GETIFLIST,
						"getting interface list: "
						"sysctl: %s"),
				 strbuf);
		result = ISC_R_UNEXPECTED;
		goto failure;
	}
	iter->bufused = bufused;
	INSIST(iter->bufused <= iter->bufsize);

	/*
	 * A newly created iterator has an undefined position
	 * until isc_interfaceiter_first() is called.
	 */
	iter->pos = (unsigned int) -1;
	iter->result = ISC_R_FAILURE;

	iter->magic = IFITER_MAGIC;
	*iterp = iter;
	return (ISC_R_SUCCESS);

 failure:
	if (iter->buf != NULL)
		isc_mem_put(mctx, iter->buf, iter->bufsize);
	isc_mem_put(mctx, iter, sizeof(*iter));
	return (result);
}
Пример #17
0
isc_result_t
isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
	isc_timermgr_t *manager;
	isc_result_t result;

	/*
	 * Create a timer manager.
	 */

	REQUIRE(managerp != NULL && *managerp == NULL);

#ifndef ISC_PLATFORM_USETHREADS
	if (timermgr != NULL) {
		timermgr->refs++;
		*managerp = timermgr;
		return (ISC_R_SUCCESS);
	}
#endif /* ISC_PLATFORM_USETHREADS */

	manager = isc_mem_get(mctx, sizeof(*manager));
	if (manager == NULL)
		return (ISC_R_NOMEMORY);

	manager->magic = TIMER_MANAGER_MAGIC;
	manager->mctx = NULL;
	manager->done = ISC_FALSE;
	INIT_LIST(manager->timers);
	manager->nscheduled = 0;
	isc_time_settoepoch(&manager->due);
	manager->heap = NULL;
	result = isc_heap_create(mctx, sooner, set_index, 0, &manager->heap);
	if (result != ISC_R_SUCCESS) {
		INSIST(result == ISC_R_NOMEMORY);
		isc_mem_put(mctx, manager, sizeof(*manager));
		return (ISC_R_NOMEMORY);
	}
	result = isc_mutex_init(&manager->lock);
	if (result != ISC_R_SUCCESS) {
		isc_heap_destroy(&manager->heap);
		isc_mem_put(mctx, manager, sizeof(*manager));
		return (result);
	}
	isc_mem_attach(mctx, &manager->mctx);
#ifdef ISC_PLATFORM_USETHREADS
	if (isc_condition_init(&manager->wakeup) != ISC_R_SUCCESS) {
		isc_mem_detach(&manager->mctx);
		DESTROYLOCK(&manager->lock);
		isc_heap_destroy(&manager->heap);
		isc_mem_put(mctx, manager, sizeof(*manager));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_condition_init() %s",
				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
						ISC_MSG_FAILED, "failed"));
		return (ISC_R_UNEXPECTED);
	}
	if (isc_thread_create(run, manager, &manager->thread) !=
	    ISC_R_SUCCESS) {
		isc_mem_detach(&manager->mctx);
		(void)isc_condition_destroy(&manager->wakeup);
		DESTROYLOCK(&manager->lock);
		isc_heap_destroy(&manager->heap);
		isc_mem_put(mctx, manager, sizeof(*manager));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_thread_create() %s",
				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
						ISC_MSG_FAILED, "failed"));
		return (ISC_R_UNEXPECTED);
	}
#else /* ISC_PLATFORM_USETHREADS */
	manager->refs = 1;
	timermgr = manager;
#endif /* ISC_PLATFORM_USETHREADS */

	*managerp = manager;

	return (ISC_R_SUCCESS);
}
Пример #18
0
static isc_result_t
create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
	isc_stats_t *stats;
	isc_result_t result = ISC_R_SUCCESS;

	REQUIRE(statsp != NULL && *statsp == NULL);

	stats = isc_mem_get(mctx, sizeof(*stats));
	if (stats == NULL)
		return (ISC_R_NOMEMORY);

	result = isc_mutex_init(&stats->lock);
	if (result != ISC_R_SUCCESS)
		goto clean_stats;

	stats->counters = isc_mem_get(mctx, sizeof(isc_stat_t) * ncounters);
	if (stats->counters == NULL) {
		result = ISC_R_NOMEMORY;
		goto clean_mutex;
	}
	stats->copiedcounters = isc_mem_get(mctx,
					    sizeof(isc_uint64_t) * ncounters);
	if (stats->copiedcounters == NULL) {
		result = ISC_R_NOMEMORY;
		goto clean_counters;
	}

#ifdef ISC_RWLOCK_USEATOMIC
	result = isc_rwlock_init(&stats->counterlock, 0, 0);
	if (result != ISC_R_SUCCESS)
		goto clean_copiedcounters;
#endif

	stats->references = 1;
	memset(stats->counters, 0, sizeof(isc_stat_t) * ncounters);
	stats->mctx = NULL;
	isc_mem_attach(mctx, &stats->mctx);
	stats->ncounters = ncounters;
	stats->magic = ISC_STATS_MAGIC;

	*statsp = stats;

	return (result);

clean_counters:
	isc_mem_put(mctx, stats->counters, sizeof(isc_stat_t) * ncounters);

#ifdef ISC_RWLOCK_USEATOMIC
clean_copiedcounters:
	isc_mem_put(mctx, stats->copiedcounters,
		    sizeof(isc_stat_t) * ncounters);
#endif

clean_mutex:
	DESTROYLOCK(&stats->lock);

clean_stats:
	isc_mem_put(mctx, stats, sizeof(*stats));

	return (result);
}
Пример #19
0
isc_result_t
dns_tsec_create(isc_mem_t *mctx, dns_tsectype_t type, dst_key_t *key,
		dns_tsec_t **tsecp)
{
	isc_result_t result;
	dns_tsec_t *tsec;
	dns_tsigkey_t *tsigkey = NULL;
	dns_name_t *algname;

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

	tsec = isc_mem_get(mctx, sizeof(*tsec));
	if (tsec == NULL)
		return (ISC_R_NOMEMORY);

	tsec->type = type;
	tsec->mctx = mctx;

	switch (type) {
	case dns_tsectype_tsig:
		switch (dst_key_alg(key)) {
		case DST_ALG_HMACMD5:
			algname = dns_tsig_hmacmd5_name;
			break;
		case DST_ALG_HMACSHA1:
			algname = dns_tsig_hmacsha1_name;
			break;
		case DST_ALG_HMACSHA224:
			algname = dns_tsig_hmacsha224_name;
			break;
		case DST_ALG_HMACSHA256:
			algname = dns_tsig_hmacsha256_name;
			break;
		case DST_ALG_HMACSHA384:
			algname = dns_tsig_hmacsha384_name;
			break;
		case DST_ALG_HMACSHA512:
			algname = dns_tsig_hmacsha512_name;
			break;
		default:
			isc_mem_put(mctx, tsec, sizeof(*tsec));
			return (DNS_R_BADALG);
		}
		result = dns_tsigkey_createfromkey(dst_key_name(key),
						   algname, key, ISC_FALSE,
						   NULL, 0, 0, mctx, NULL,
						   &tsigkey);
		if (result != ISC_R_SUCCESS) {
			isc_mem_put(mctx, tsec, sizeof(*tsec));
			return (result);
		}
		tsec->ukey.tsigkey = tsigkey;
		break;
	case dns_tsectype_sig0:
		tsec->ukey.key = key;
		break;
	default:
		INSIST(0);
	}

	tsec->magic = DNS_TSEC_MAGIC;

	*tsecp = tsec;
	return (ISC_R_SUCCESS);
}
Пример #20
0
isc_result_t
dst_key_fromnamedfile(const char *filename, const char *dirname,
		      int type, isc_mem_t *mctx, dst_key_t **keyp)
{
	isc_result_t result;
	dst_key_t *pubkey = NULL, *key = NULL;
	char *newfilename = NULL;
	int newfilenamelen = 0;
	isc_lex_t *lex = NULL;

	REQUIRE(dst_initialized == ISC_TRUE);
	REQUIRE(filename != NULL);
	REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
	REQUIRE(mctx != NULL);
	REQUIRE(keyp != NULL && *keyp == NULL);

	/* If an absolute path is specified, don't use the key directory */
#ifndef WIN32
	if (filename[0] == '/')
		dirname = NULL;
#else /* WIN32 */
	if (filename[0] == '/' || filename[0] == '\\')
		dirname = NULL;
#endif

	newfilenamelen = strlen(filename) + 5;
	if (dirname != NULL)
		newfilenamelen += strlen(dirname) + 1;
	newfilename = isc_mem_get(mctx, newfilenamelen);
	if (newfilename == NULL)
		return (ISC_R_NOMEMORY);
	result = addsuffix(newfilename, newfilenamelen,
			   dirname, filename, ".key");
	INSIST(result == ISC_R_SUCCESS);

	result = dst_key_read_public(newfilename, type, mctx, &pubkey);
	isc_mem_put(mctx, newfilename, newfilenamelen);
	newfilename = NULL;
	RETERR(result);

	if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC ||
	    (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
		result = computeid(pubkey);
		if (result != ISC_R_SUCCESS) {
			dst_key_free(&pubkey);
			return (result);
		}

		*keyp = pubkey;
		return (ISC_R_SUCCESS);
	}

	result = algorithm_status(pubkey->key_alg);
	if (result != ISC_R_SUCCESS) {
		dst_key_free(&pubkey);
		return (result);
	}

	key = get_key_struct(pubkey->key_name, pubkey->key_alg,
			     pubkey->key_flags, pubkey->key_proto, 0,
			     pubkey->key_class, pubkey->key_ttl, mctx);
	if (key == NULL) {
		dst_key_free(&pubkey);
		return (ISC_R_NOMEMORY);
	}

	if (key->func->parse == NULL)
		RETERR(DST_R_UNSUPPORTEDALG);

	newfilenamelen = strlen(filename) + 9;
	if (dirname != NULL)
		newfilenamelen += strlen(dirname) + 1;
	newfilename = isc_mem_get(mctx, newfilenamelen);
	if (newfilename == NULL)
		RETERR(ISC_R_NOMEMORY);
	result = addsuffix(newfilename, newfilenamelen,
			   dirname, filename, ".private");
	INSIST(result == ISC_R_SUCCESS);

	RETERR(isc_lex_create(mctx, 1500, &lex));
	RETERR(isc_lex_openfile(lex, newfilename));
	isc_mem_put(mctx, newfilename, newfilenamelen);

	RETERR(key->func->parse(key, lex, pubkey));
	isc_lex_destroy(&lex);

	RETERR(computeid(key));

	if (pubkey->key_id != key->key_id)
		RETERR(DST_R_INVALIDPRIVATEKEY);
	dst_key_free(&pubkey);

	*keyp = key;
	return (ISC_R_SUCCESS);

 out:
	if (pubkey != NULL)
		dst_key_free(&pubkey);
	if (newfilename != NULL)
		isc_mem_put(mctx, newfilename, newfilenamelen);
	if (lex != NULL)
		isc_lex_destroy(&lex);
	if (key != NULL)
		dst_key_free(&key);
	return (result);
}
Пример #21
0
isc_result_t
dns_diff_print(dns_diff_t *diff, FILE *file) {
	isc_result_t result;
	dns_difftuple_t *t;
	char *mem = NULL;
	unsigned int size = 2048;

	REQUIRE(DNS_DIFF_VALID(diff));

	mem = isc_mem_get(diff->mctx, size);
	if (mem == NULL)
		return (ISC_R_NOMEMORY);

	for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;
	     t = ISC_LIST_NEXT(t, link))
	{
		isc_buffer_t buf;
		isc_region_t r;

		dns_rdatalist_t rdl;
		dns_rdataset_t rds;
		dns_rdata_t rd = DNS_RDATA_INIT;

		result = diff_tuple_tordataset(t, &rd, &rdl, &rds);
		if (result != ISC_R_SUCCESS) {
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "diff_tuple_tordataset failed: %s",
					 dns_result_totext(result));
			result =  ISC_R_UNEXPECTED;
			goto cleanup;
		}
 again:
		isc_buffer_init(&buf, mem, size);
		result = dns_rdataset_totext(&rds, &t->name,
					     ISC_FALSE, ISC_FALSE, &buf);

		if (result == ISC_R_NOSPACE) {
			isc_mem_put(diff->mctx, mem, size);
			size += 1024;
			mem = isc_mem_get(diff->mctx, size);
			if (mem == NULL) {
				result = ISC_R_NOMEMORY;
				goto cleanup;
			}
			goto again;
		}

		if (result != ISC_R_SUCCESS)
			goto cleanup;
		/*
		 * Get rid of final newline.
		 */
		INSIST(buf.used >= 1 &&
		       ((char *) buf.base)[buf.used-1] == '\n');
		buf.used--;

		isc_buffer_usedregion(&buf, &r);
		if (file != NULL)
			fprintf(file, "%s %.*s\n",
				t->op == DNS_DIFFOP_ADD ?  "add" : "del",
				(int) r.length, (char *) r.base);
		else
			isc_log_write(DIFF_COMMON_LOGARGS, ISC_LOG_DEBUG(7),
				      "%s %.*s",
				      t->op == DNS_DIFFOP_ADD ?  "add" : "del",
				      (int) r.length, (char *) r.base);
	}
	result = ISC_R_SUCCESS;
 cleanup:
	if (mem != NULL)
		isc_mem_put(diff->mctx, mem, size);
	return (result);
}
Пример #22
0
static void
destroy(isc_event_t *event) {
	isc_mem_t *mctx = event->ev_destroy_arg;

	isc_mem_put(mctx, event, event->ev_size);
}
Пример #23
0
int
main(void) {
	isc_mem_t *mctx = NULL;
	isc_entropy_t *ectx = NULL;
	isc_buffer_t b;
	dns_fixedname_t fname;
	dns_name_t *name;
	isc_result_t result;

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

	current = isc_mem_get(mctx, 256);
	if (current == NULL)
		return (1);
	if (getcwd(current, 256) == NULL) {
		perror("getcwd");
		return (1);
	}

	dns_result_register();

	result = isc_entropy_create(mctx, &ectx);
	if (result != ISC_R_SUCCESS)
		return (1);
	result = isc_entropy_createfilesource(ectx, "randomfile");
	if (result != ISC_R_SUCCESS)
		return (1);
	dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING|ISC_ENTROPY_GOODONLY);

	dns_fixedname_init(&fname);
	name = dns_fixedname_name(&fname);
	isc_buffer_init(&b, "test.", 5);
	isc_buffer_add(&b, 5);
	result = dns_name_fromtext(name, &b, NULL, 0, NULL);
	if (result != ISC_R_SUCCESS)
		return (1);
	io(name, 23616, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx);
	io(name, 54622, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC,
	   mctx);

	io(name, 49667, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx);
	io(name, 2, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx);

	isc_buffer_init(&b, "dh.", 3);
	isc_buffer_add(&b, 3);
	result = dns_name_fromtext(name, &b, NULL, 0, NULL);
	if (result != ISC_R_SUCCESS)
		return (1);
	dh(name, 18602, name, 48957, mctx);

	generate(DST_ALG_RSAMD5, mctx);
	generate(DST_ALG_DH, mctx);
	generate(DST_ALG_DSA, mctx);
	generate(DST_ALG_HMACMD5, mctx);

	dst_lib_destroy();
	isc_entropy_detach(&ectx);

	isc_mem_put(mctx, current, 256);
/*	isc_mem_stats(mctx, stdout);*/
	isc_mem_destroy(&mctx);

	return (0);
}
isc_result_t
isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
	char strbuf[ISC_STRERRORSIZE];
	isc_interfaceiter_t *iter;
	isc_result_t result;
	int error;
	unsigned long bytesReturned = 0;

	REQUIRE(mctx != NULL);
	REQUIRE(iterp != NULL);
	REQUIRE(*iterp == NULL);

	iter = isc_mem_get(mctx, sizeof(*iter));
	if (iter == NULL)
		return (ISC_R_NOMEMORY);

	InitSockets();

	iter->mctx = mctx;
	iter->buf4 = NULL;
	iter->buf6 = NULL;
	iter->pos4 = NULL;
	iter->pos6 = 0;
	iter->buf6size = 0;
	iter->buf4size = 0;
	iter->result = ISC_R_FAILURE;
	iter->numIF = 0;
	iter->v4IF = 0;

	/*
	 * Create an unbound datagram socket to do the
	 * SIO_GET_INTERFACE_LIST WSAIoctl on.
	 */
	iter->socket = socket(AF_INET, SOCK_DGRAM, 0);
	if (iter->socket == INVALID_SOCKET) {
		error = WSAGetLastError();
		if (error == WSAEAFNOSUPPORT)
			goto inet6_only;
		isc__strerror(error, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				"making interface scan socket: %s",
				strbuf);
		result = ISC_R_UNEXPECTED;
		goto socket_failure;
	}

	/*
	 * Get the interface configuration, allocating more memory if
	 * necessary.
	 */
	iter->buf4size = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO);

	for (;;) {
		iter->buf4 = isc_mem_get(mctx, iter->buf4size);
		if (iter->buf4 == NULL) {
			result = ISC_R_NOMEMORY;
			goto alloc_failure;
		}

		if (WSAIoctl(iter->socket, SIO_GET_INTERFACE_LIST,
			     0, 0, iter->buf4, iter->buf4size,
			     &bytesReturned, 0, 0) == SOCKET_ERROR)
		{
			error = WSAGetLastError();
			if (error != WSAEFAULT && error != WSAENOBUFS) {
				errno = error;
				isc__strerror(error, strbuf, sizeof(strbuf));
				UNEXPECTED_ERROR(__FILE__, __LINE__,
						"get interface configuration: %s",
						strbuf);
				result = ISC_R_UNEXPECTED;
				goto ioctl_failure;
			}
			/*
			 * EINVAL.  Retry with a bigger buffer.
			 */
		} else {
			/*
			 * The WSAIoctl succeeded.
			 * If the number of the returned bytes is the same
			 * as the buffer size, we will grow it just in
			 * case and retry.
			 */
			if (bytesReturned > 0 &&
			    (bytesReturned < iter->buf4size))
				break;
		}
		if (iter->buf4size >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) {
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "get interface configuration: "
					 "maximum buffer size exceeded");
			result = ISC_R_UNEXPECTED;
			goto ioctl_failure;
		}
		isc_mem_put(mctx, iter->buf4, iter->buf4size);

		iter->buf4size += IFCONF_SIZE_INCREMENT *
			sizeof(INTERFACE_INFO);
	}

	/*
	 * A newly created iterator has an undefined position
	 * until isc_interfaceiter_first() is called.
	 */
	iter->v4IF = bytesReturned/sizeof(INTERFACE_INFO);

	/* We don't need the socket any more, so close it */
	closesocket(iter->socket);

 inet6_only:
	/*
	 * Create an unbound datagram socket to do the
	 * SIO_ADDRESS_LIST_QUERY WSAIoctl on.
	 */
	iter->socket = socket(AF_INET6, SOCK_DGRAM, 0);
	if (iter->socket == INVALID_SOCKET) {
		error = WSAGetLastError();
		if (error == WSAEAFNOSUPPORT)
			goto inet_only;
		isc__strerror(error, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				"making interface scan socket: %s",
				strbuf);
		result = ISC_R_UNEXPECTED;
		goto ioctl_failure;
	}

	/*
	 * Get the interface configuration, allocating more memory if
	 * necessary.
	 */
	iter->buf6size = sizeof(SOCKET_ADDRESS_LIST) +
			 IFCONF_SIZE_INITIAL*sizeof(SOCKET_ADDRESS);

	for (;;) {
		iter->buf6 = isc_mem_get(mctx, iter->buf6size);
		if (iter->buf6 == NULL) {
			result = ISC_R_NOMEMORY;
			goto ioctl_failure;
		}

		if (WSAIoctl(iter->socket, SIO_ADDRESS_LIST_QUERY,
			     0, 0, iter->buf6, iter->buf6size,
			     &bytesReturned, 0, 0) == SOCKET_ERROR)
		{
			error = WSAGetLastError();
			if (error != WSAEFAULT && error != WSAENOBUFS) {
				errno = error;
				isc__strerror(error, strbuf, sizeof(strbuf));
				UNEXPECTED_ERROR(__FILE__, __LINE__,
						 "sio address list query: %s",
						 strbuf);
				result = ISC_R_UNEXPECTED;
				goto ioctl6_failure;
			}
			/*
			 * EINVAL.  Retry with a bigger buffer.
			 */
		} else
			break;

		if (iter->buf6size >= IFCONF_SIZE_MAX*sizeof(SOCKET_ADDRESS)) {
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "get interface configuration: "
					 "maximum buffer size exceeded");
			result = ISC_R_UNEXPECTED;
			goto ioctl6_failure;
		}
		isc_mem_put(mctx, iter->buf6, iter->buf6size);

		iter->buf6size += IFCONF_SIZE_INCREMENT *
			sizeof(SOCKET_ADDRESS);
	}

	closesocket(iter->socket);

 inet_only:
	iter->magic = IFITER_MAGIC;
	*iterp = iter;
	return (ISC_R_SUCCESS);

 ioctl6_failure:
	isc_mem_put(mctx, iter->buf6, iter->buf6size);

 ioctl_failure:
	if (iter->buf4 != NULL)
		isc_mem_put(mctx, iter->buf4, iter->buf4size);

 alloc_failure:
	if (iter->socket != INVALID_SOCKET)
		(void) closesocket(iter->socket);

 socket_failure:
	isc_mem_put(mctx, iter, sizeof(*iter));
	return (result);
}
Пример #25
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);
}
Пример #26
0
static isc_result_t
process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
	       dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx,
	       dns_rdata_tkey_t *tkeyout,
	       dns_tsig_keyring_t *ring, dns_namelist_t *namelist)
{
	isc_result_t result = ISC_R_SUCCESS;
	dns_name_t *keyname, ourname;
	dns_rdataset_t *keyset = NULL;
	dns_rdata_t keyrdata = DNS_RDATA_INIT, ourkeyrdata = DNS_RDATA_INIT;
	isc_boolean_t found_key = ISC_FALSE, found_incompatible = ISC_FALSE;
	dst_key_t *pubkey = NULL;
	isc_buffer_t ourkeybuf, *shared = NULL;
	isc_region_t r, r2, ourkeyr;
	unsigned char keydata[DST_KEY_MAXSIZE];
	unsigned int sharedsize;
	isc_buffer_t secret;
	unsigned char *randomdata = NULL, secretdata[256];
	dns_ttl_t ttl = 0;

	if (tctx->dhkey == NULL) {
		tkey_log("process_dhtkey: tkey-dhkey not defined");
		tkeyout->error = dns_tsigerror_badalg;
		return (DNS_R_REFUSED);
	}

	if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) {
		tkey_log("process_dhtkey: algorithms other than "
			 "hmac-md5 are not supported");
		tkeyout->error = dns_tsigerror_badalg;
		return (ISC_R_SUCCESS);
	}

	/*
	 * Look for a DH KEY record that will work with ours.
	 */
	for (result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL);
	     result == ISC_R_SUCCESS && !found_key;
	     result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL))
	{
		keyname = NULL;
		dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname);
		keyset = NULL;
		result = dns_message_findtype(keyname, dns_rdatatype_key, 0,
					      &keyset);
		if (result != ISC_R_SUCCESS)
			continue;

		for (result = dns_rdataset_first(keyset);
		     result == ISC_R_SUCCESS && !found_key;
		     result = dns_rdataset_next(keyset))
		{
			dns_rdataset_current(keyset, &keyrdata);
			pubkey = NULL;
			result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
							 msg->mctx, &pubkey);
			if (result != ISC_R_SUCCESS) {
				dns_rdata_reset(&keyrdata);
				continue;
			}
			if (dst_key_alg(pubkey) == DNS_KEYALG_DH) {
				if (dst_key_paramcompare(pubkey, tctx->dhkey))
				{
					found_key = ISC_TRUE;
					ttl = keyset->ttl;
					break;
				} else
					found_incompatible = ISC_TRUE;
			}
			dst_key_free(&pubkey);
			dns_rdata_reset(&keyrdata);
		}
	}

	if (!found_key) {
		if (found_incompatible) {
			tkey_log("process_dhtkey: found an incompatible key");
			tkeyout->error = dns_tsigerror_badkey;
			return (ISC_R_SUCCESS);
		} else {
			tkey_log("process_dhtkey: failed to find a key");
			return (DNS_R_FORMERR);
		}
	}

	RETERR(add_rdata_to_list(msg, keyname, &keyrdata, ttl, namelist));

	isc_buffer_init(&ourkeybuf, keydata, sizeof(keydata));
	RETERR(dst_key_todns(tctx->dhkey, &ourkeybuf));
	isc_buffer_usedregion(&ourkeybuf, &ourkeyr);
	dns_rdata_fromregion(&ourkeyrdata, dns_rdataclass_any,
			     dns_rdatatype_key, &ourkeyr);

	dns_name_init(&ourname, NULL);
	dns_name_clone(dst_key_name(tctx->dhkey), &ourname);

	/*
	 * XXXBEW The TTL should be obtained from the database, if it exists.
	 */
	RETERR(add_rdata_to_list(msg, &ourname, &ourkeyrdata, 0, namelist));

	RETERR(dst_key_secretsize(tctx->dhkey, &sharedsize));
	RETERR(isc_buffer_allocate(msg->mctx, &shared, sharedsize));

	result = dst_key_computesecret(pubkey, tctx->dhkey, shared);
	if (result != ISC_R_SUCCESS) {
		tkey_log("process_dhtkey: failed to compute shared secret: %s",
			 isc_result_totext(result));
		goto failure;
	}
	dst_key_free(&pubkey);

	isc_buffer_init(&secret, secretdata, sizeof(secretdata));

	randomdata = isc_mem_get(tkeyout->mctx, TKEY_RANDOM_AMOUNT);
	if (randomdata == NULL)
		goto failure;

	result = isc_entropy_getdata(tctx->ectx, randomdata,
				     TKEY_RANDOM_AMOUNT, NULL, 0);
	if (result != ISC_R_SUCCESS) {
		tkey_log("process_dhtkey: failed to obtain entropy: %s",
			 isc_result_totext(result));
		goto failure;
	}

	r.base = randomdata;
	r.length = TKEY_RANDOM_AMOUNT;
	r2.base = tkeyin->key;
	r2.length = tkeyin->keylen;
	RETERR(compute_secret(shared, &r2, &r, &secret));
	isc_buffer_free(&shared);

	RETERR(dns_tsigkey_create(name, &tkeyin->algorithm,
				  isc_buffer_base(&secret),
				  isc_buffer_usedlength(&secret),
				  ISC_TRUE, signer, tkeyin->inception,
				  tkeyin->expire, msg->mctx, ring, NULL));

	/* This key is good for a long time */
	tkeyout->inception = tkeyin->inception;
	tkeyout->expire = tkeyin->expire;

	tkeyout->key = randomdata;
	tkeyout->keylen = TKEY_RANDOM_AMOUNT;

	return (ISC_R_SUCCESS);

 failure:
	if (!ISC_LIST_EMPTY(*namelist))
		free_namelist(msg, namelist);
	if (shared != NULL)
		isc_buffer_free(&shared);
	if (pubkey != NULL)
		dst_key_free(&pubkey);
	if (randomdata != NULL)
		isc_mem_put(tkeyout->mctx, randomdata, TKEY_RANDOM_AMOUNT);
	return (result);
}
Пример #27
0
isc_result_t
dns_tsig_sign(dns_message_t *msg) {
	dns_tsigkey_t *key;
	dns_rdata_any_tsig_t tsig, querytsig;
	unsigned char data[128];
	isc_buffer_t databuf, sigbuf;
	isc_buffer_t *dynbuf;
	dns_name_t *owner;
	dns_rdata_t *rdata = NULL;
	dns_rdatalist_t *datalist;
	dns_rdataset_t *dataset;
	isc_region_t r;
	isc_stdtime_t now;
	isc_mem_t *mctx;
	dst_context_t *ctx = NULL;
	isc_result_t ret;
	unsigned char badtimedata[BADTIMELEN];
	unsigned int sigsize = 0;
	isc_boolean_t response = is_response(msg);

	REQUIRE(msg != NULL);
	REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg)));

	/*
	 * If this is a response, there should be a query tsig.
	 */
	if (response && msg->querytsig == NULL)
		return (DNS_R_EXPECTEDTSIG);

	dynbuf = NULL;

	mctx = msg->mctx;
	key = dns_message_gettsigkey(msg);

	tsig.mctx = mctx;
	tsig.common.rdclass = dns_rdataclass_any;
	tsig.common.rdtype = dns_rdatatype_tsig;
	ISC_LINK_INIT(&tsig.common, link);
	dns_name_init(&tsig.algorithm, NULL);
	dns_name_clone(key->algorithm, &tsig.algorithm);

	isc_stdtime_get(&now);
	tsig.timesigned = now + msg->timeadjust;
	tsig.fudge = DNS_TSIG_FUDGE;

	tsig.originalid = msg->id;

	isc_buffer_init(&databuf, data, sizeof(data));

	if (response)
		tsig.error = msg->querytsigstatus;
	else
		tsig.error = dns_rcode_noerror;

	if (tsig.error != dns_tsigerror_badtime) {
		tsig.otherlen = 0;
		tsig.other = NULL;
	} else {
		isc_buffer_t otherbuf;

		tsig.otherlen = BADTIMELEN;
		tsig.other = badtimedata;
		isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
		isc_buffer_putuint48(&otherbuf, tsig.timesigned);
	}

	if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
		unsigned char header[DNS_MESSAGE_HEADERLEN];
		isc_buffer_t headerbuf;
		isc_uint16_t digestbits;

		ret = dst_context_create3(key->key, mctx,
					  DNS_LOGCATEGORY_DNSSEC,
					  ISC_TRUE, &ctx);
		if (ret != ISC_R_SUCCESS)
			return (ret);

		/*
		 * If this is a response, digest the query signature.
		 */
		if (response) {
			dns_rdata_t querytsigrdata = DNS_RDATA_INIT;

			ret = dns_rdataset_first(msg->querytsig);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;
			dns_rdataset_current(msg->querytsig, &querytsigrdata);
			ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
						 NULL);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;
			isc_buffer_putuint16(&databuf, querytsig.siglen);
			if (isc_buffer_availablelength(&databuf) <
			    querytsig.siglen) {
				ret = ISC_R_NOSPACE;
				goto cleanup_context;
			}
			isc_buffer_putmem(&databuf, querytsig.signature,
					  querytsig.siglen);
			isc_buffer_usedregion(&databuf, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;
		}
#if defined(__clang__)  && \
       ( __clang_major__ < 3 || \
	(__clang_major__ == 3 && __clang_minor__ < 2) || \
	(__clang_major__ == 4 && __clang_minor__ < 2))
	/* false positive: http://llvm.org/bugs/show_bug.cgi?id=14461 */
		else memset(&querytsig, 0, sizeof(querytsig));
#endif

		/*
		 * Digest the header.
		 */
		isc_buffer_init(&headerbuf, header, sizeof(header));
		dns_message_renderheader(msg, &headerbuf);
		isc_buffer_usedregion(&headerbuf, &r);
		ret = dst_context_adddata(ctx, &r);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;

		/*
		 * Digest the remainder of the message.
		 */
		isc_buffer_usedregion(msg->buffer, &r);
		isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
		ret = dst_context_adddata(ctx, &r);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;

		if (msg->tcp_continuation == 0) {
			/*
			 * Digest the name, class, ttl, alg.
			 */
			dns_name_toregion(&key->name, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

			isc_buffer_clear(&databuf);
			isc_buffer_putuint16(&databuf, dns_rdataclass_any);
			isc_buffer_putuint32(&databuf, 0); /* ttl */
			isc_buffer_usedregion(&databuf, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

			dns_name_toregion(&tsig.algorithm, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

		}
		/* Digest the timesigned and fudge */
		isc_buffer_clear(&databuf);
		if (tsig.error == dns_tsigerror_badtime) {
			INSIST(response);
			tsig.timesigned = querytsig.timesigned;
		}
		isc_buffer_putuint48(&databuf, tsig.timesigned);
		isc_buffer_putuint16(&databuf, tsig.fudge);
		isc_buffer_usedregion(&databuf, &r);
		ret = dst_context_adddata(ctx, &r);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;

		if (msg->tcp_continuation == 0) {
			/*
			 * Digest the error and other data length.
			 */
			isc_buffer_clear(&databuf);
			isc_buffer_putuint16(&databuf, tsig.error);
			isc_buffer_putuint16(&databuf, tsig.otherlen);

			isc_buffer_usedregion(&databuf, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

			/*
			 * Digest other data.
			 */
			if (tsig.otherlen > 0) {
				r.length = tsig.otherlen;
				r.base = tsig.other;
				ret = dst_context_adddata(ctx, &r);
				if (ret != ISC_R_SUCCESS)
					goto cleanup_context;
			}
		}

		ret = dst_key_sigsize(key->key, &sigsize);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;
		tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
		if (tsig.signature == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_context;
		}

		isc_buffer_init(&sigbuf, tsig.signature, sigsize);
		ret = dst_context_sign(ctx, &sigbuf);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_signature;
		dst_context_destroy(&ctx);
		digestbits = dst_key_getbits(key->key);
		if (digestbits != 0) {
			unsigned int bytes = (digestbits + 1) / 8;
			if (response && bytes < querytsig.siglen)
				bytes = querytsig.siglen;
			if (bytes > isc_buffer_usedlength(&sigbuf))
				bytes = isc_buffer_usedlength(&sigbuf);
			tsig.siglen = bytes;
		} else
			tsig.siglen = isc_buffer_usedlength(&sigbuf);
	} else {
		tsig.siglen = 0;
		tsig.signature = NULL;
	}

	ret = dns_message_gettemprdata(msg, &rdata);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_signature;
	ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_rdata;
	ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
				   dns_rdatatype_tsig, &tsig, dynbuf);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_dynbuf;

	dns_message_takebuffer(msg, &dynbuf);

	if (tsig.signature != NULL) {
		isc_mem_put(mctx, tsig.signature, sigsize);
		tsig.signature = NULL;
	}

	owner = NULL;
	ret = dns_message_gettempname(msg, &owner);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_rdata;
	dns_name_init(owner, NULL);
	ret = dns_name_dup(&key->name, msg->mctx, owner);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_owner;

	datalist = NULL;
	ret = dns_message_gettemprdatalist(msg, &datalist);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_owner;
	dataset = NULL;
	ret = dns_message_gettemprdataset(msg, &dataset);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_rdatalist;
	datalist->rdclass = dns_rdataclass_any;
	datalist->type = dns_rdatatype_tsig;
	datalist->covers = 0;
	datalist->ttl = 0;
	ISC_LIST_INIT(datalist->rdata);
	ISC_LIST_APPEND(datalist->rdata, rdata, link);
	dns_rdataset_init(dataset);
	RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
		      == ISC_R_SUCCESS);
	msg->tsig = dataset;
	msg->tsigname = owner;

	/* Windows does not like the tsig name being compressed. */
	msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;

	return (ISC_R_SUCCESS);

 cleanup_rdatalist:
	dns_message_puttemprdatalist(msg, &datalist);
 cleanup_owner:
	dns_message_puttempname(msg, &owner);
	goto cleanup_rdata;
 cleanup_dynbuf:
	isc_buffer_free(&dynbuf);
 cleanup_rdata:
	dns_message_puttemprdata(msg, &rdata);
 cleanup_signature:
	if (tsig.signature != NULL)
		isc_mem_put(mctx, tsig.signature, sigsize);
 cleanup_context:
	if (ctx != NULL)
		dst_context_destroy(&ctx);
	return (ret);
}
Пример #28
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) {
		result = ISC_R_NOMEMORY;
		goto failed;
	}

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

	triedload = ISC_TRUE;

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

	/* 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);
		result = ISC_R_FAILURE;
		goto cleanup_lock;
	}

	/* 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 cleanup_lock;
	}

	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 - 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 cleanup_lock;
	}

	/*
	 * 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 cleanup_lock;

	*dbdata = cd;

	return (ISC_R_SUCCESS);

cleanup_lock:
	DESTROYLOCK(&cd->lock);
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);
}
Пример #29
0
static void
isc_httpd_accept(isc_task_t *task, isc_event_t *ev)
{
	isc_result_t result;
	isc_httpdmgr_t *httpdmgr = ev->ev_arg;
	isc_httpd_t *httpd;
	isc_region_t r;
	isc_socket_newconnev_t *nev = (isc_socket_newconnev_t *)ev;
	isc_sockaddr_t peeraddr;

	ENTER("accept");

	LOCK(&httpdmgr->lock);
	if (MSHUTTINGDOWN(httpdmgr)) {
		NOTICE("accept shutting down, goto out");
		goto out;
	}

	if (nev->result == ISC_R_CANCELED) {
		NOTICE("accept canceled, goto out");
		goto out;
	}

	if (nev->result != ISC_R_SUCCESS) {
		/* XXXMLG log failure */
		NOTICE("accept returned failure, goto requeue");
		goto requeue;
	}

	(void)isc_socket_getpeername(nev->newsocket, &peeraddr);
	if (httpdmgr->client_ok != NULL &&
	    !(httpdmgr->client_ok)(&peeraddr, httpdmgr->cb_arg)) {
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}

	httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t));
	if (httpd == NULL) {
		/* XXXMLG log failure */
		NOTICE("accept failed to allocate memory, goto requeue");
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}

	httpd->mgr = httpdmgr;
	ISC_LINK_INIT(httpd, link);
	ISC_LIST_APPEND(httpdmgr->running, httpd, link);
	ISC_HTTPD_SETRECV(httpd);
	httpd->sock = nev->newsocket;
	isc_socket_setname(httpd->sock, "httpd", NULL);
	httpd->flags = 0;

	/*
	 * Initialize the buffer for our headers.
	 */
	httpd->headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW);
	if (httpd->headerdata == NULL) {
		isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t));
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}
	httpd->headerlen = HTTP_SENDGROW;
	isc_buffer_init(&httpd->headerbuffer, httpd->headerdata,
			httpd->headerlen);

	ISC_LIST_INIT(httpd->bufflist);

	isc_buffer_initnull(&httpd->bodybuffer);
	reset_client(httpd);

	r.base = (unsigned char *)httpd->recvbuf;
	r.length = HTTP_RECVLEN - 1;
	result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone,
				 httpd);
	/* FIXME!!! */
	POST(result);
	NOTICE("accept queued recv on socket");

 requeue:
	result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept,
				   httpdmgr);
	if (result != ISC_R_SUCCESS) {
		/* XXXMLG what to do?  Log failure... */
		NOTICE("accept could not reaccept due to failure");
	}

 out:
	UNLOCK(&httpdmgr->lock);

	httpdmgr_destroy(httpdmgr);

	isc_event_free(&ev);

	EXIT("accept");
}
Пример #30
0
static isc_result_t
pkcs11rsa_tofile(const dst_key_t *key, const char *directory) {
    int i;
    pk11_object_t *rsa;
    CK_ATTRIBUTE *attr;
    CK_ATTRIBUTE *modulus = NULL, *exponent = NULL;
    CK_ATTRIBUTE  *d = NULL, *p = NULL, *q = NULL;
    CK_ATTRIBUTE *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
    dst_private_t priv;
    unsigned char *bufs[10];
    isc_result_t result;

    if (key->keydata.pkey == NULL)
        return (DST_R_NULLKEY);

    if (key->external) {
        priv.nelements = 0;
        return (dst__privstruct_writefile(key, &priv, directory));
    }

    rsa = key->keydata.pkey;

    for (attr = pk11_attribute_first(rsa);
            attr != NULL;
            attr = pk11_attribute_next(rsa, attr))
        switch (attr->type) {
        case CKA_MODULUS:
            modulus = attr;
            break;
        case CKA_PUBLIC_EXPONENT:
            exponent = attr;
            break;
        case CKA_PRIVATE_EXPONENT:
            d = attr;
            break;
        case CKA_PRIME_1:
            p = attr;
            break;
        case CKA_PRIME_2:
            q = attr;
            break;
        case CKA_EXPONENT_1:
            dmp1 = attr;
            break;
        case CKA_EXPONENT_2:
            dmq1 = attr;
            break;
        case CKA_COEFFICIENT:
            iqmp = attr;
            break;
        }
    if ((modulus == NULL) || (exponent == NULL))
        return (DST_R_NULLKEY);

    memset(bufs, 0, sizeof(bufs));

    for (i = 0; i < 10; i++) {
        bufs[i] = isc_mem_get(key->mctx, modulus->ulValueLen);
        if (bufs[i] == NULL) {
            result = ISC_R_NOMEMORY;
            goto fail;
        }
        memset(bufs[i], 0, modulus->ulValueLen);
    }

    i = 0;

    priv.elements[i].tag = TAG_RSA_MODULUS;
    priv.elements[i].length = (unsigned short) modulus->ulValueLen;
    memmove(bufs[i], modulus->pValue, modulus->ulValueLen);
    priv.elements[i].data = bufs[i];
    i++;

    priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT;
    priv.elements[i].length = (unsigned short) exponent->ulValueLen;
    memmove(bufs[i], exponent->pValue, exponent->ulValueLen);
    priv.elements[i].data = bufs[i];
    i++;

    if (d != NULL) {
        priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
        priv.elements[i].length = (unsigned short) d->ulValueLen;
        memmove(bufs[i], d->pValue, d->ulValueLen);
        priv.elements[i].data = bufs[i];
        i++;
    }

    if (p != NULL) {
        priv.elements[i].tag = TAG_RSA_PRIME1;
        priv.elements[i].length = (unsigned short) p->ulValueLen;
        memmove(bufs[i], p->pValue, p->ulValueLen);
        priv.elements[i].data = bufs[i];
        i++;
    }

    if (q != NULL) {
        priv.elements[i].tag = TAG_RSA_PRIME2;
        priv.elements[i].length = (unsigned short) q->ulValueLen;
        memmove(bufs[i], q->pValue, q->ulValueLen);
        priv.elements[i].data = bufs[i];
        i++;
    }

    if (dmp1 != NULL) {
        priv.elements[i].tag = TAG_RSA_EXPONENT1;
        priv.elements[i].length = (unsigned short) dmp1->ulValueLen;
        memmove(bufs[i], dmp1->pValue, dmp1->ulValueLen);
        priv.elements[i].data = bufs[i];
        i++;
    }

    if (dmq1 != NULL) {
        priv.elements[i].tag = TAG_RSA_EXPONENT2;
        priv.elements[i].length = (unsigned short) dmq1->ulValueLen;
        memmove(bufs[i], dmq1->pValue, dmq1->ulValueLen);
        priv.elements[i].data = bufs[i];
        i++;
    }

    if (iqmp != NULL) {
        priv.elements[i].tag = TAG_RSA_COEFFICIENT;
        priv.elements[i].length = (unsigned short) iqmp->ulValueLen;
        memmove(bufs[i], iqmp->pValue, iqmp->ulValueLen);
        priv.elements[i].data = bufs[i];
        i++;
    }

    if (key->engine != NULL) {
        priv.elements[i].tag = TAG_RSA_ENGINE;
        priv.elements[i].length = strlen(key->engine) + 1;
        priv.elements[i].data = (unsigned char *)key->engine;
        i++;
    }

    if (key->label != NULL) {
        priv.elements[i].tag = TAG_RSA_LABEL;
        priv.elements[i].length = strlen(key->label) + 1;
        priv.elements[i].data = (unsigned char *)key->label;
        i++;
    }

    priv.nelements = i;
    result = dst__privstruct_writefile(key, &priv, directory);
fail:
    for (i = 0; i < 10; i++) {
        if (bufs[i] == NULL)
            break;
        memset(bufs[i], 0, modulus->ulValueLen);
        isc_mem_put(key->mctx, bufs[i], modulus->ulValueLen);
    }
    return (result);
}