示例#1
0
文件: lookup.c 项目: crossbuild/bind
static void
lookup_find(dns_lookup_t *lookup, dns_fetchevent_t *event) {
	isc_result_t result;
	isc_boolean_t want_restart;
	isc_boolean_t send_event;
	dns_name_t *name, *fname, *prefix;
	dns_fixedname_t foundname, fixed;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	unsigned int nlabels;
	int order;
	dns_namereln_t namereln;
	dns_rdata_cname_t cname;
	dns_rdata_dname_t dname;

	REQUIRE(VALID_LOOKUP(lookup));

	LOCK(&lookup->lock);

	result = ISC_R_SUCCESS;
	name = dns_fixedname_name(&lookup->name);

	do {
		lookup->restarts++;
		want_restart = ISC_FALSE;
		send_event = ISC_TRUE;

		if (event == NULL && !lookup->canceled) {
			dns_fixedname_init(&foundname);
			fname = dns_fixedname_name(&foundname);
			INSIST(!dns_rdataset_isassociated(&lookup->rdataset));
			INSIST(!dns_rdataset_isassociated
						(&lookup->sigrdataset));
			/*
			 * If we have restarted then clear the old node.				 */
			if  (lookup->event->node != NULL) {
				INSIST(lookup->event->db != NULL);
				dns_db_detachnode(lookup->event->db,
						 &lookup->event->node);
			}
			if (lookup->event->db != NULL)
				dns_db_detach(&lookup->event->db);
			result = view_find(lookup, fname);
			if (result == ISC_R_NOTFOUND) {
				/*
				 * We don't know anything about the name.
				 * Launch a fetch.
				 */
				if  (lookup->event->node != NULL) {
					INSIST(lookup->event->db != NULL);
					dns_db_detachnode(lookup->event->db,
							 &lookup->event->node);
				}
				if (lookup->event->db != NULL)
					dns_db_detach(&lookup->event->db);
				result = start_fetch(lookup);
				if (result == ISC_R_SUCCESS)
					send_event = ISC_FALSE;
				goto done;
			}
		} else if (event != NULL) {
			result = event->result;
			fname = dns_fixedname_name(&event->foundname);
			dns_resolver_destroyfetch(&lookup->fetch);
			INSIST(event->rdataset == &lookup->rdataset);
			INSIST(event->sigrdataset == &lookup->sigrdataset);
		} else
			fname = NULL;	/* Silence compiler warning. */

		/*
		 * If we've been canceled, forget about the result.
		 */
		if (lookup->canceled)
			result = ISC_R_CANCELED;

		switch (result) {
		case ISC_R_SUCCESS:
			result = build_event(lookup);
			if (event == NULL)
				break;
			if (event->db != NULL)
				dns_db_attach(event->db, &lookup->event->db);
			if (event->node != NULL)
				dns_db_attachnode(lookup->event->db,
						  event->node,
						  &lookup->event->node);
			break;
		case DNS_R_CNAME:
			/*
			 * Copy the CNAME's target into the lookup's
			 * query name and start over.
			 */
			result = dns_rdataset_first(&lookup->rdataset);
			if (result != ISC_R_SUCCESS)
				break;
			dns_rdataset_current(&lookup->rdataset, &rdata);
			result = dns_rdata_tostruct(&rdata, &cname, NULL);
			dns_rdata_reset(&rdata);
			if (result != ISC_R_SUCCESS)
				break;
			result = dns_name_copy(&cname.cname, name, NULL);
			dns_rdata_freestruct(&cname);
			if (result == ISC_R_SUCCESS) {
				want_restart = ISC_TRUE;
				send_event = ISC_FALSE;
			}
			break;
		case DNS_R_DNAME:
			namereln = dns_name_fullcompare(name, fname, &order,
							&nlabels);
			INSIST(namereln == dns_namereln_subdomain);
			/*
			 * Get the target name of the DNAME.
			 */
			result = dns_rdataset_first(&lookup->rdataset);
			if (result != ISC_R_SUCCESS)
				break;
			dns_rdataset_current(&lookup->rdataset, &rdata);
			result = dns_rdata_tostruct(&rdata, &dname, NULL);
			dns_rdata_reset(&rdata);
			if (result != ISC_R_SUCCESS)
				break;
			/*
			 * Construct the new query name and start over.
			 */
			dns_fixedname_init(&fixed);
			prefix = dns_fixedname_name(&fixed);
			dns_name_split(name, nlabels, prefix, NULL);
			result = dns_name_concatenate(prefix, &dname.dname,
						      name, NULL);
			dns_rdata_freestruct(&dname);
			if (result == ISC_R_SUCCESS) {
				want_restart = ISC_TRUE;
				send_event = ISC_FALSE;
			}
			break;
		default:
			send_event = ISC_TRUE;
		}

		if (dns_rdataset_isassociated(&lookup->rdataset))
			dns_rdataset_disassociate(&lookup->rdataset);
		if (dns_rdataset_isassociated(&lookup->sigrdataset))
			dns_rdataset_disassociate(&lookup->sigrdataset);

	done:
		if (event != NULL) {
			if (event->node != NULL)
				dns_db_detachnode(event->db, &event->node);
			if (event->db != NULL)
				dns_db_detach(&event->db);
			isc_event_free(ISC_EVENT_PTR(&event));
		}

		/*
		 * Limit the number of restarts.
		 */
		if (want_restart && lookup->restarts == MAX_RESTARTS) {
			want_restart = ISC_FALSE;
			result = ISC_R_QUOTA;
			send_event = ISC_TRUE;
		}

	} while (want_restart);

	if (send_event) {
		lookup->event->result = result;
		lookup->event->ev_sender = lookup;
		isc_task_sendanddetach(&lookup->task,
				       (isc_event_t **)&lookup->event);
		dns_view_detach(&lookup->view);
	}

	UNLOCK(&lookup->lock);
}
示例#2
0
static isc_result_t
rsa_check(pk11_object_t *rsa, pk11_object_t *pubrsa) {
    CK_ATTRIBUTE *pubattr, *privattr;
    CK_BYTE *priv_exp = NULL, *priv_mod = NULL;
    CK_BYTE *pub_exp = NULL, *pub_mod = NULL;
    unsigned int priv_explen = 0, priv_modlen = 0;
    unsigned int pub_explen = 0, pub_modlen = 0;

    REQUIRE(rsa != NULL && pubrsa != NULL);

    privattr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
    INSIST(privattr != NULL);
    priv_exp = privattr->pValue;
    priv_explen = privattr->ulValueLen;

    pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT);
    INSIST(pubattr != NULL);
    pub_exp = pubattr->pValue;
    pub_explen = pubattr->ulValueLen;

    if (priv_exp != NULL) {
        if (priv_explen != pub_explen)
            return (DST_R_INVALIDPRIVATEKEY);
        if (memcmp(priv_exp, pub_exp, pub_explen) != 0)
            return (DST_R_INVALIDPRIVATEKEY);
    } else {
        privattr->pValue = pub_exp;
        privattr->ulValueLen = pub_explen;
        pubattr->pValue = NULL;
        pubattr->ulValueLen = 0;
    }

    if (privattr->pValue == NULL)
        return (DST_R_INVALIDPRIVATEKEY);

    privattr = pk11_attribute_bytype(rsa, CKA_MODULUS);
    INSIST(privattr != NULL);
    priv_mod = privattr->pValue;
    priv_modlen = privattr->ulValueLen;

    pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS);
    INSIST(pubattr != NULL);
    pub_mod = pubattr->pValue;
    pub_modlen = pubattr->ulValueLen;

    if (priv_mod != NULL) {
        if (priv_modlen != pub_modlen)
            return (DST_R_INVALIDPRIVATEKEY);
        if (memcmp(priv_mod, pub_mod, pub_modlen) != 0)
            return (DST_R_INVALIDPRIVATEKEY);
    } else {
        privattr->pValue = pub_mod;
        privattr->ulValueLen = pub_modlen;
        pubattr->pValue = NULL;
        pubattr->ulValueLen = 0;
    }

    if (privattr->pValue == NULL)
        return (DST_R_INVALIDPRIVATEKEY);

    return (ISC_R_SUCCESS);
}
示例#3
0
static isc_result_t
pkcs11rsa_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_RSA;
    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 *rsa;
    pk11_context_t *pk11_ctx = NULL;
    isc_result_t ret;
    unsigned int i;

    UNUSED(pin);

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

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

    ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA);
    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_RSA, ISC_TRUE, ISC_FALSE,
                           rsa->reqlogon, NULL, rsa->slot);
    if (ret != ISC_R_SUCCESS)
        goto err;

    attr = pk11_attribute_bytype(rsa, CKA_LABEL);
    if (attr == NULL) {
        attr = pk11_attribute_bytype(rsa, 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 = rsa->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, &rsa->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);

    attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
    INSIST(attr != NULL);
    if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
        DST_RET(ISC_R_RANGE);

    attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
    INSIST(attr != NULL);
    key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);

    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:
    pkcs11rsa_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);
}
示例#4
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);
	}
	if (isc_mutex_init(&manager->lock) != ISC_R_SUCCESS) {
		isc_heap_destroy(&manager->heap);
		isc_mem_put(mctx, manager, sizeof(*manager));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_mutex_init() %s",
				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
						ISC_MSG_FAILED, "failed"));
		return (ISC_R_UNEXPECTED);
	}
	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);
}
isc_result_t
isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) {
	isc_result_t result;
	isc_netaddr_t netaddr;
	char pbuf[sizeof("65000")];
	unsigned int plen;
	isc_region_t avail;

	REQUIRE(sockaddr != NULL);

	/*
	 * Do the port first, giving us the opportunity to check for
	 * unsupported address families before calling
	 * isc_netaddr_fromsockaddr().
	 */
	switch (sockaddr->type.sa.sa_family) {
	case AF_INET:
		snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port));
		break;
	case AF_INET6:
		snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port));
		break;
#ifdef ISC_PLAFORM_HAVESYSUNH
	case AF_UNIX:
		plen = strlen(sockaddr->type.sunix.sun_path);
		if (plen >= isc_buffer_availablelength(target))
			return (ISC_R_NOSPACE);

		isc_buffer_putmem(target, sockaddr->type.sunix.sun_path, plen);

		/*
		 * Null terminate after used region.
		 */
		isc_buffer_availableregion(target, &avail);
		INSIST(avail.length >= 1);
		avail.base[0] = '\0';

		return (ISC_R_SUCCESS);
#endif
	default:
		return (ISC_R_FAILURE);
	}

	plen = strlen(pbuf);
	INSIST(plen < sizeof(pbuf));

	isc_netaddr_fromsockaddr(&netaddr, sockaddr);
	result = isc_netaddr_totext(&netaddr, target);
	if (result != ISC_R_SUCCESS)
		return (result);

	if (1 + plen + 1 > isc_buffer_availablelength(target))
		return (ISC_R_NOSPACE);

	isc_buffer_putmem(target, (const unsigned char *)"#", 1);
	isc_buffer_putmem(target, (const unsigned char *)pbuf, plen);

	/*
	 * Null terminate after used region.
	 */
	isc_buffer_availableregion(target, &avail);
	INSIST(avail.length >= 1);
	avail.base[0] = '\0';

	return (ISC_R_SUCCESS);
}
示例#6
0
static isc_result_t
internal_current(isc_interfaceiter_t *iter) {
	struct ifa_msghdr *ifam, *ifam_end;

	REQUIRE(VALID_IFITER(iter));
	REQUIRE (iter->pos < (unsigned int) iter->bufused);

	ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos);
	ifam_end = (struct ifa_msghdr *) ((char *) iter->buf + iter->bufused);

	// Skip wrong RTM version headers
	if (ifam->ifam_version != RTM_VERSION)
		return (ISC_R_IGNORE);

	if (ifam->ifam_type == RTM_IFINFO) {
		struct if_msghdr *ifm = (struct if_msghdr *) ifam;
		struct sockaddr_dl *sdl = (struct sockaddr_dl *) (ifm + 1);
		unsigned int namelen;

		memset(&iter->current, 0, sizeof(iter->current));

		iter->current.ifindex = sdl->sdl_index;
		namelen = sdl->sdl_nlen;
		if (namelen > sizeof(iter->current.name) - 1)
			namelen = sizeof(iter->current.name) - 1;

		memset(iter->current.name, 0, sizeof(iter->current.name));
		memcpy(iter->current.name, sdl->sdl_data, namelen);

		iter->current.flags = 0;

		if ((ifam->ifam_flags & IFF_UP) != 0)
			iter->current.flags |= INTERFACE_F_UP;

		if ((ifam->ifam_flags & IFF_POINTOPOINT) != 0)
			iter->current.flags |= INTERFACE_F_POINTTOPOINT;

		if ((ifam->ifam_flags & IFF_LOOPBACK) != 0)
			iter->current.flags |= INTERFACE_F_LOOPBACK;

		if ((ifam->ifam_flags & IFF_BROADCAST) != 0)
			iter->current.flags |= INTERFACE_F_BROADCAST;

#ifdef IFF_MULTICAST
		if ((ifam->ifam_flags & IFF_MULTICAST) != 0)
			iter->current.flags |= INTERFACE_F_MULTICAST;
#endif

		/*
		 * This is not an interface address.
		 * Force another iteration.
		 */
		return (ISC_R_IGNORE);
	} else if (ifam->ifam_type == RTM_NEWADDR) {
		int i;
		int family;
		struct sockaddr *mask_sa = NULL;
		struct sockaddr *addr_sa = NULL;
		struct sockaddr *dst_sa = NULL;

		struct sockaddr *sa = (struct sockaddr *)(ifam + 1);
		family = sa->sa_family;

		for (i = 0; i < RTAX_MAX; i++)
		{
			if ((ifam->ifam_addrs & (1 << i)) == 0)
				continue;

			INSIST(sa < (struct sockaddr *) ifam_end);

			switch (i) {
			case RTAX_NETMASK: /* Netmask */
				mask_sa = sa;
				break;
			case RTAX_IFA: /* Interface address */
				addr_sa = sa;
				break;
			case RTAX_BRD: /* Broadcast or destination address */
				dst_sa = sa;
				break;
			}
#ifdef ISC_PLATFORM_HAVESALEN
			sa = (struct sockaddr *)((char*)(sa)
					 + ROUNDUP(sa->sa_len));
#else
#ifdef sgi
			/*
			 * Do as the contributed SGI code does.
			 */
			sa = (struct sockaddr *)((char*)(sa)
					 + ROUNDUP(_FAKE_SA_LEN_DST(sa)));
#else
			/* XXX untested. */
			sa = (struct sockaddr *)((char*)(sa)
					 + ROUNDUP(sizeof(struct sockaddr)));
#endif
#endif
		}

		if (addr_sa == NULL)
			return (ISC_R_IGNORE);

		family = addr_sa->sa_family;
		if (family != AF_INET && family != AF_INET6)
			return (ISC_R_IGNORE);

		iter->current.af = family;

		get_addr(family, &iter->current.address, addr_sa,
			 iter->current.name);

		if (mask_sa != NULL)
			get_addr(family, &iter->current.netmask, mask_sa,
				 iter->current.name);

		if (dst_sa != NULL &&
		    (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
			get_addr(family, &iter->current.dstaddress, dst_sa,
				 iter->current.name);

		if (dst_sa != NULL &&
		    (iter->current.flags & INTERFACE_F_BROADCAST) != 0)
			get_addr(family, &iter->current.broadcast, dst_sa,
				 iter->current.name);

		return (ISC_R_SUCCESS);
	} else {
		printf("%s", isc_msgcat_get(isc_msgcat,
					    ISC_MSGSET_IFITERSYSCTL,
					    ISC_MSG_UNEXPECTEDTYPE,
					    "warning: unexpected interface "
					    "list message type\n"));
		return (ISC_R_IGNORE);
	}
}
示例#7
0
static inline isc_result_t
schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
	isc_result_t result;
	isc_timermgr_t *manager;
	isc_time_t due;
	int cmp;
#ifdef ISC_PLATFORM_USETHREADS
	isc_boolean_t timedwait;
#endif

	/*
	 * Note: the caller must ensure locking.
	 */

	REQUIRE(timer->type != isc_timertype_inactive);

#ifndef ISC_PLATFORM_USETHREADS
	UNUSED(signal_ok);
#endif /* ISC_PLATFORM_USETHREADS */

	manager = timer->manager;

#ifdef ISC_PLATFORM_USETHREADS
	/*
	 * If the manager was timed wait, we may need to signal the
	 * manager to force a wakeup.
	 */
	timedwait = ISC_TF(manager->nscheduled > 0 &&
			   isc_time_seconds(&manager->due) != 0);
#endif

	/*
	 * Compute the new due time.
	 */
	if (timer->type != isc_timertype_once) {
		result = isc_time_add(now, &timer->interval, &due);
		if (result != ISC_R_SUCCESS)
			return (result);
		if (timer->type == isc_timertype_limited &&
		    isc_time_compare(&timer->expires, &due) < 0)
			due = timer->expires;
	} else {
		if (isc_time_isepoch(&timer->idle))
			due = timer->expires;
		else if (isc_time_isepoch(&timer->expires))
			due = timer->idle;
		else if (isc_time_compare(&timer->idle, &timer->expires) < 0)
			due = timer->idle;
		else
			due = timer->expires;
	}

	/*
	 * Schedule the timer.
	 */

	if (timer->index > 0) {
		/*
		 * Already scheduled.
		 */
		cmp = isc_time_compare(&due, &timer->due);
		timer->due = due;
		switch (cmp) {
		case -1:
			isc_heap_increased(manager->heap, timer->index);
			break;
		case 1:
			isc_heap_decreased(manager->heap, timer->index);
			break;
		case 0:
			/* Nothing to do. */
			break;
		}
	} else {
		timer->due = due;
		result = isc_heap_insert(manager->heap, timer);
		if (result != ISC_R_SUCCESS) {
			INSIST(result == ISC_R_NOMEMORY);
			return (ISC_R_NOMEMORY);
		}
		manager->nscheduled++;
	}

	XTRACETIMER(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
				   ISC_MSG_SCHEDULE, "schedule"), timer, due);

	/*
	 * If this timer is at the head of the queue, we need to ensure
	 * that we won't miss it if it has a more recent due time than
	 * the current "next" timer.  We do this either by waking up the
	 * run thread, or explicitly setting the value in the manager.
	 */
#ifdef ISC_PLATFORM_USETHREADS

	/*
	 * This is a temporary (probably) hack to fix a bug on tru64 5.1
	 * and 5.1a.  Sometimes, pthread_cond_timedwait() doesn't actually
	 * return when the time expires, so here, we check to see if
	 * we're 15 seconds or more behind, and if we are, we signal
	 * the dispatcher.  This isn't such a bad idea as a general purpose
	 * watchdog, so perhaps we should just leave it in here.
	 */
	if (signal_ok && timedwait) {
		isc_interval_t fifteen;
		isc_time_t then;

		isc_interval_set(&fifteen, 15, 0);
		isc_time_add(&manager->due, &fifteen, &then);

		if (isc_time_compare(&then, now) < 0) {
			SIGNAL(&manager->wakeup);
			signal_ok = ISC_FALSE;
			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
				      ISC_LOGMODULE_TIMER, ISC_LOG_WARNING,
				      "*** POKED TIMER ***");
		}
	}
		
	if (timer->index == 1 && signal_ok) {
		XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
				      ISC_MSG_SIGNALSCHED,
				      "signal (schedule)"));
		SIGNAL(&manager->wakeup);
	}
#else /* ISC_PLATFORM_USETHREADS */
	if (timer->index == 1 &&
	    isc_time_compare(&timer->due, &manager->due) < 0)
		manager->due = timer->due;
#endif /* ISC_PLATFORM_USETHREADS */

	return (ISC_R_SUCCESS);
}
示例#8
0
static void
fork_blocking_child(
    blocking_child *	c
)
{
    static int	atexit_installed;
    static int	blocking_pipes[4] = { -1, -1, -1, -1 };
    int		rc;
    int		was_pipe;
    int		is_pipe;
    int		saved_errno = 0;
    int		childpid;
    int		keep_fd;
    int		fd;

    /*
     * parent and child communicate via a pair of pipes.
     *
     * 0 child read request
     * 1 parent write request
     * 2 parent read response
     * 3 child write response
     */
    if (-1 == c->req_write_pipe) {
        rc = pipe_socketpair(&blocking_pipes[0], &was_pipe);
        if (0 != rc) {
            saved_errno = errno;
        } else {
            rc = pipe_socketpair(&blocking_pipes[2], &is_pipe);
            if (0 != rc) {
                saved_errno = errno;
                close(blocking_pipes[0]);
                close(blocking_pipes[1]);
            } else {
                INSIST(was_pipe == is_pipe);
            }
        }
        if (0 != rc) {
            errno = saved_errno;
            msyslog(LOG_ERR, "unable to create worker pipes: %m");
            exit(1);
        }

        /*
         * Move the descriptors the parent will keep open out of the
         * low descriptors preferred by C runtime buffered FILE *.
         */
        c->req_write_pipe = move_fd(blocking_pipes[1]);
        c->resp_read_pipe = move_fd(blocking_pipes[2]);
        /*
         * wake any worker child on orderly shutdown of the
         * daemon so that it can notice the broken pipes and
         * go away promptly.
         */
        if (!atexit_installed) {
            atexit(&send_worker_home_atexit);
            atexit_installed = TRUE;
        }
    }

#if defined(HAVE_DROPROOT) && !defined(NEED_EARLY_FORK)
    /* defer the fork until after root is dropped */
    if (droproot && !root_dropped)
        return;
#endif
    if (syslog_file != NULL)
        fflush(syslog_file);
    fflush(stdout);
    fflush(stderr);

    signal_no_reset(SIGCHLD, SIG_IGN);

    childpid = fork();
    if (-1 == childpid) {
        msyslog(LOG_ERR, "unable to fork worker: %m");
        exit(1);
    }

    if (childpid) {
        /* this is the parent */
        TRACE(1, ("forked worker child (pid %d)\n", childpid));
        c->pid = childpid;
        c->ispipe = is_pipe;

        /* close the child's pipe descriptors. */
        close(blocking_pipes[0]);
        close(blocking_pipes[3]);

        memset(blocking_pipes, -1, sizeof(blocking_pipes));

        /* wire into I/O loop */
        (*addremove_io_fd)(c->resp_read_pipe, is_pipe, FALSE);

        return;		/* parent returns */
    }

    /*
     * The parent gets the child pid as the return value of fork().
     * The child must work for it.
     */
    c->pid = getpid();
    worker_process = TRUE;

    /*
     * In the child, close all files except stdin, stdout, stderr,
     * and the two child ends of the pipes.
     */
    DEBUG_INSIST(-1 == c->req_read_pipe);
    DEBUG_INSIST(-1 == c->resp_write_pipe);
    c->req_read_pipe = blocking_pipes[0];
    c->resp_write_pipe = blocking_pipes[3];

    kill_asyncio(0);
    closelog();
    if (syslog_file != NULL) {
        fclose(syslog_file);
        syslog_file = NULL;
        syslogit = TRUE;
    }
    keep_fd = max(c->req_read_pipe, c->resp_write_pipe);
    for (fd = 3; fd < keep_fd; fd++)
        if (fd != c->req_read_pipe &&
                fd != c->resp_write_pipe)
            close(fd);
    close_all_beyond(keep_fd);
    /*
     * We get signals from refclock serial I/O on NetBSD in the
     * worker if we do not reset SIGIO's handler to the default.
     * It is not conditionalized for NetBSD alone because on
     * systems where it is not needed, it is harmless, and that
     * allows us to handle unknown others with NetBSD behavior.
     * [Bug 1386]
     */
#if defined(USE_SIGIO)
    signal_no_reset(SIGIO, SIG_DFL);
#elif defined(USE_SIGPOLL)
    signal_no_reset(SIGPOLL, SIG_DFL);
#endif
    signal_no_reset(SIGHUP, worker_sighup);
    init_logging("ntp_intres", 0, FALSE);
    setup_logfile(NULL);

    /*
     * And now back to the portable code
     */
    exit_worker(blocking_child_common(c));
}
示例#9
0
// MCA: ExtendedGCD
int integer_gcd_extended(integer_t gcd, integer_t U, integer_t V, integer_t A, integer_t B) {
  integer_t a, b, u, w, v, x, q, r;
  
  INSIST(gcd != U);
  INSIST(gcd != V);
  INSIST(U != V);

  a = integer_create(0);
  b = gcd;

  VERIFY(integer_absolute_value(a, A));
  VERIFY(integer_absolute_value(b, B));

  u = U;
  VERIFY(integer_set_unsigned_value(u, 1));
  w = integer_create(0);

  v = V;
  VERIFY(integer_set_unsigned_value(v, 0));
  x = integer_create(1);

  q = integer_create(0);
  r = integer_create(0);

  while(!integer_is_zero(b)) {
    VERIFY(integer_divide(q, r, a, b));
    SWAP(a, b);
    SWAP(b, r);

    VERIFY(integer_multiply(r, q, w));
    VERIFY(integer_subtract(u, u, r));
    SWAP(u, w);

    VERIFY(integer_multiply(r, q, x));
    VERIFY(integer_subtract(v, v, r));
    SWAP(v, x);
  }

  EXCHANGE(gcd, a);
  EXCHANGE(U, u);
  EXCHANGE(V, v);

  integer_destroy(q);
  /* gcd is passed between a, b, and r */
  if(b == gcd) {
    integer_destroy(a);
    integer_destroy(r);
  }
  else if(a == gcd) {
    integer_destroy(b);
    integer_destroy(r);
  }
  else {
    integer_destroy(a);
    integer_destroy(b);
  }
  
  /* U and V are passed between u, w and v, x respectively */
  if(u == U) {
    integer_destroy(w);
    integer_destroy(x);
  }
  else {
    integer_destroy(u);
    integer_destroy(v);
  }
  
  return 0;
}
示例#10
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);
}
示例#11
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);
}
示例#12
0
/*
 * Create a writeable DLZ zone. This can be called by DLZ drivers
 * during configure() to create a zone that can be updated. The zone
 * type is set to dns_zone_dlz, which is equivalent to a master zone
 *
 * This function uses a callback setup in dns_dlzconfigure() to call
 * into the server zone code to setup the remaining pieces of server
 * specific functionality on the zone
 */
isc_result_t
dns_dlz_writeablezone(dns_view_t *view, const char *zone_name) {
	dns_zone_t *zone = NULL;
	dns_zone_t *dupzone = NULL;
	isc_result_t result;
	isc_buffer_t buffer;
	dns_fixedname_t fixorigin;
	dns_name_t *origin;
	dns_dlzdb_t *dlzdatabase;

	REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));

	dlzdatabase = view->dlzdatabase;

	REQUIRE(dlzdatabase->configure_callback != NULL);

	isc_buffer_init(&buffer, zone_name, strlen(zone_name));
	isc_buffer_add(&buffer, strlen(zone_name));
	dns_fixedname_init(&fixorigin);
	result = dns_name_fromtext(dns_fixedname_name(&fixorigin),
				   &buffer, dns_rootname, 0, NULL);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	origin = dns_fixedname_name(&fixorigin);

	/* See if the zone already exists */
	result = dns_view_findzone(view, origin, &dupzone);
	if (result == ISC_R_SUCCESS) {
		dns_zone_detach(&dupzone);
		result = ISC_R_EXISTS;
		goto cleanup;
	}
	INSIST(dupzone == NULL);

	/* Create it */
	result = dns_zone_create(&zone, view->mctx);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	result = dns_zone_setorigin(zone, origin);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	dns_zone_setview(zone, view);

	dns_zone_setadded(zone, ISC_TRUE);

	if (dlzdatabase->ssutable == NULL) {
		result = dns_ssutable_createdlz(dlzdatabase->mctx,
						&dlzdatabase->ssutable,
						view->dlzdatabase);
		if (result != ISC_R_SUCCESS)
			goto cleanup;
	}
	dns_zone_setssutable(zone, dlzdatabase->ssutable);

	result = dlzdatabase->configure_callback(view, zone);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	/*
	 * Add the zone to its view in the new view list.
	 */
	result = dns_view_addzone(view, zone);

 cleanup:
	if (zone != NULL)
		dns_zone_detach(&zone);

	return (result);
}
示例#13
0
int
ns_sign2(u_char *msg, int *msglen, int msgsize, int error, void *k,
	 const u_char *querysig, int querysiglen, u_char *sig, int *siglen,
	 time_t in_timesigned, u_char **dnptrs, u_char **lastdnptr)
{
	HEADER *hp = (HEADER *)msg;
	DST_KEY *key = (DST_KEY *)k;
	u_char *cp = msg + *msglen, *eob = msg + msgsize;
	u_char *lenp;
	u_char *alg;
	int n;
	time_t timesigned;
        u_char name[NS_MAXCDNAME];

	dst_init();
	if (msg == NULL || msglen == NULL || sig == NULL || siglen == NULL)
		return (-1);

	/* Name. */
	if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
		n = ns_name_pton(key->dk_key_name, name, sizeof name);
		if (n != -1)
			n = ns_name_pack(name, cp, eob - cp,
					 (const u_char **)dnptrs,
					 (const u_char **)lastdnptr);

	} else {
		n = ns_name_pton("", name, sizeof name);
		if (n != -1)
			n = ns_name_pack(name, cp, eob - cp, NULL, NULL);
	}
	if (n < 0)
		return (NS_TSIG_ERROR_NO_SPACE);
	cp += n;

	/* Type, class, ttl, length (not filled in yet). */
	BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ);
	PUTSHORT(ns_t_tsig, cp);
	PUTSHORT(ns_c_any, cp);
	PUTLONG(0, cp);		/* TTL */
	lenp = cp;
	cp += 2;

	/* Alg. */
	if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
		if (key->dk_alg != KEY_HMAC_MD5)
			return (-ns_r_badkey);
		n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL);
	}
	else
		n = dn_comp("", cp, eob - cp, NULL, NULL);
	if (n < 0)
		return (NS_TSIG_ERROR_NO_SPACE);
	alg = cp;
	cp += n;
	
	/* Time. */
	BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
	PUTSHORT(0, cp);
	timesigned = time(NULL);
	if (error != ns_r_badtime)
		PUTLONG(timesigned, cp);
	else
		PUTLONG(in_timesigned, cp);
	PUTSHORT(NS_TSIG_FUDGE, cp);

	/* Compute the signature. */
	if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
		void *ctx;
		u_char buf[NS_MAXCDNAME], *cp2;
		int n;

		dst_sign_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0);

		/* Digest the query signature, if this is a response. */
		if (querysiglen > 0 && querysig != NULL) {
			u_int16_t len_n = htons(querysiglen);
			dst_sign_data(SIG_MODE_UPDATE, key, &ctx,
				      (u_char *)&len_n, INT16SZ, NULL, 0);
			dst_sign_data(SIG_MODE_UPDATE, key, &ctx,
				      querysig, querysiglen, NULL, 0);
		}

		/* Digest the message. */
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, msg, *msglen,
			      NULL, 0);

		/* Digest the key name. */
		n = ns_name_ntol(name, buf, sizeof(buf));
		INSIST(n > 0);
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);

		/* Digest the class and TTL. */
		cp2 = buf;
		PUTSHORT(ns_c_any, cp2);
		PUTLONG(0, cp2);
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf,
			      NULL, 0);

		/* Digest the algorithm. */
		n = ns_name_ntol(alg, buf, sizeof(buf));
		INSIST(n > 0);
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);

		/* Digest the time signed, fudge, error, and other data */
		cp2 = buf;
		PUTSHORT(0, cp2);	/* Top 16 bits of time */
		if (error != ns_r_badtime)
			PUTLONG(timesigned, cp2);
		else
			PUTLONG(in_timesigned, cp2);
		PUTSHORT(NS_TSIG_FUDGE, cp2);
		PUTSHORT(error, cp2);	/* Error */
		if (error != ns_r_badtime)
			PUTSHORT(0, cp2);	/* Other data length */
		else {
			PUTSHORT(INT16SZ+INT32SZ, cp2);	/* Other data length */
			PUTSHORT(0, cp2);	/* Top 16 bits of time */
			PUTLONG(timesigned, cp2);
		}
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf,
			      NULL, 0);

		n = dst_sign_data(SIG_MODE_FINAL, key, &ctx, NULL, 0,
				  sig, *siglen);
		if (n < 0)
			return (-ns_r_badkey);
		*siglen = n;
	} else
		*siglen = 0;

	/* Add the signature. */
	BOUNDS_CHECK(cp, INT16SZ + (*siglen));
	PUTSHORT(*siglen, cp);
	memcpy(cp, sig, *siglen);
	cp += (*siglen);

	/* The original message ID & error. */
	BOUNDS_CHECK(cp, INT16SZ + INT16SZ);
	PUTSHORT(ntohs(hp->id), cp);	/* already in network order */
	PUTSHORT(error, cp);

	/* Other data. */
	BOUNDS_CHECK(cp, INT16SZ);
	if (error != ns_r_badtime)
		PUTSHORT(0, cp);	/* Other data length */
	else {
		PUTSHORT(INT16SZ+INT32SZ, cp);	/* Other data length */
		BOUNDS_CHECK(cp, INT32SZ+INT16SZ);
		PUTSHORT(0, cp);	/* Top 16 bits of time */
		PUTLONG(timesigned, cp);
	}

	/* Go back and fill in the length. */
	PUTSHORT(cp - lenp - INT16SZ, lenp);

	hp->arcount = htons(ntohs(hp->arcount) + 1);
	*msglen = (cp - msg);
	return (0);
}
示例#14
0
static isc_result_t
add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring,
		 isc_mem_t *mctx)
{
	dns_tsigkey_t *tsigkey = NULL;
	const cfg_listelt_t *element;
	const cfg_obj_t *key = NULL;
	const char *keyid = NULL;
	unsigned char *secret = NULL;
	int secretalloc = 0;
	int secretlen = 0;
	isc_result_t ret;
	isc_stdtime_t now;
	isc_uint16_t bits;

	for (element = cfg_list_first(list);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const cfg_obj_t *algobj = NULL;
		const cfg_obj_t *secretobj = NULL;
		dns_name_t keyname;
		dns_name_t *alg;
		const char *algstr;
		char keynamedata[1024];
		isc_buffer_t keynamesrc, keynamebuf;
		const char *secretstr;
		isc_buffer_t secretbuf;

		key = cfg_listelt_value(element);
		keyid = cfg_obj_asstring(cfg_map_getname(key));

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

		/*
		 * Create the key name.
		 */
		dns_name_init(&keyname, NULL);
		isc_buffer_init(&keynamesrc, keyid, strlen(keyid));
		isc_buffer_add(&keynamesrc, strlen(keyid));
		isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata));
		ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname,
					DNS_NAME_DOWNCASE, &keynamebuf);
		if (ret != ISC_R_SUCCESS)
			goto failure;

		/*
		 * Create the algorithm.
		 */
		algstr = cfg_obj_asstring(algobj);
		if (ns_config_getkeyalgorithm(algstr, &alg, &bits)
		    != ISC_R_SUCCESS) {
			cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR,
				    "key '%s': has a unsupported algorithm '%s'",
				    keyid, algstr);
			ret = DNS_R_BADALG;
			goto failure;
		}

		secretstr = cfg_obj_asstring(secretobj);
		secretalloc = secretlen = strlen(secretstr) * 3 / 4;
		secret = isc_mem_get(mctx, secretlen);
		if (secret == NULL) {
			ret = ISC_R_NOMEMORY;
			goto failure;
		}
		isc_buffer_init(&secretbuf, secret, secretlen);
		ret = isc_base64_decodestring(secretstr, &secretbuf);
		if (ret != ISC_R_SUCCESS)
			goto failure;
		secretlen = isc_buffer_usedlength(&secretbuf);

		isc_stdtime_get(&now);
		ret = dns_tsigkey_create(&keyname, alg, secret, secretlen,
					 ISC_FALSE, NULL, now, now,
					 mctx, ring, &tsigkey);
		isc_mem_put(mctx, secret, secretalloc);
		secret = NULL;
		if (ret != ISC_R_SUCCESS)
			goto failure;
		/*
		 * Set digest bits.
		 */
		dst_key_setbits(tsigkey->key, bits);
		dns_tsigkey_detach(&tsigkey);
	}

	return (ISC_R_SUCCESS);

 failure:
	cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
		    "configuring key '%s': %s", keyid,
		    isc_result_totext(ret));

	if (secret != NULL)
		isc_mem_put(mctx, secret, secretalloc);
	return (ret);
}
示例#15
0
文件: print.c 项目: OPSF/uClinux
int
lwres__print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
	int h;
	int l;
	int q;
	int alt;
	int zero;
	int left;
	int plus;
	int space;
	long long tmpi;
	unsigned long long tmpui;
	unsigned long width;
	unsigned long precision;
	unsigned int length;
	char buf[1024];
	char c;
	void *v;
	char *save = str;
	const char *cp;
	const char *head;
	int count = 0;
	int pad;
	int zeropad;
	int dot;
	double dbl;
#ifdef HAVE_LONG_DOUBLE
	long double ldbl;
#endif
	char fmt[32];

	INSIST(str != NULL);
	INSIST(format != NULL);

	while (*format != '\0') {
		if (*format != '%') {
			if (size > 1U) {
				*str++ = *format;
				size--;
			}
			count++;
			format++;
			continue;
		}
		format++;

		/*
		 * Reset flags.
		 */
		dot = space = plus = left = zero = alt = h = l = q = 0;
		width = precision = 0;
		head = "";
		length = pad = zeropad = 0;

		do {
			if (*format == '#') {
				alt = 1;
				format++;
			} else if (*format == '-') {
				left = 1;
				zero = 0;
				format++;
			} else if (*format == ' ') {
				if (!plus)
					space = 1;
				format++;
			} else if (*format == '+') {
				plus = 1;
				space = 0;
				format++;
			} else if (*format == '0') {
				if (!left)
					zero = 1;
				format++;
			} else
				break;
		} while (1);

		/*
		 * Width.
		 */
		if (*format == '*') {
			width = va_arg(ap, int);
			format++;
		} else if (isdigit((unsigned char)*format)) {
示例#16
0
static isc_result_t
value_towire(isccc_sexpr_t *elt, isccc_region_t *target)
{
	size_t len;
	unsigned char *lenp;
	isccc_region_t *vr;
	isc_result_t result;

	if (isccc_sexpr_binaryp(elt)) {
		vr = isccc_sexpr_tobinary(elt);
		len = REGION_SIZE(*vr);
		if (REGION_SIZE(*target) < 1 + 4 + len)
			return (ISC_R_NOSPACE);
		PUT8(ISCCC_CCMSGTYPE_BINARYDATA, target->rstart);
		PUT32(len, target->rstart);
		if (REGION_SIZE(*target) < len)
			return (ISC_R_NOSPACE);
		PUT_MEM(vr->rstart, len, target->rstart);
	} else if (isccc_alist_alistp(elt)) {
		if (REGION_SIZE(*target) < 1 + 4)
			return (ISC_R_NOSPACE);
		PUT8(ISCCC_CCMSGTYPE_TABLE, target->rstart);
		/*
		 * Emit a placeholder length.
		 */
		lenp = target->rstart;
		PUT32(0, target->rstart);
		/*
		 * Emit the table.
		 */
		result = table_towire(elt, target);
		if (result != ISC_R_SUCCESS)
			return (result);
		len = (size_t)(target->rstart - lenp);
		/*
		 * 'len' is 4 bytes too big, since it counts
		 * the placeholder length too.  Adjust and
		 * emit.
		 */
		INSIST(len >= 4U);
		len -= 4;
		PUT32(len, lenp);
	} else if (isccc_sexpr_listp(elt)) {
		if (REGION_SIZE(*target) < 1 + 4)
			return (ISC_R_NOSPACE);
		PUT8(ISCCC_CCMSGTYPE_LIST, target->rstart);
		/*
		 * Emit a placeholder length and count.
		 */
		lenp = target->rstart;
		PUT32(0, target->rstart);
		/*
		 * Emit the list.
		 */
		result = list_towire(elt, target);
		if (result != ISC_R_SUCCESS)
			return (result);
		len = (size_t)(target->rstart - lenp);
		/*
		 * 'len' is 4 bytes too big, since it counts
		 * the placeholder length.  Adjust and emit.
		 */
		INSIST(len >= 4U);
		len -= 4;
		PUT32(len, lenp);
	}

	return (ISC_R_SUCCESS);
}
示例#17
0
static inline isc_result_t
tostruct_naptr(ARGS_TOSTRUCT) {
	dns_rdata_naptr_t *naptr = target;
	isc_region_t r;
	isc_result_t result;
	dns_name_t name;

	REQUIRE(rdata->type == 35);
	REQUIRE(target != NULL);
	REQUIRE(rdata->length != 0);

	naptr->common.rdclass = rdata->rdclass;
	naptr->common.rdtype = rdata->type;
	ISC_LINK_INIT(&naptr->common, link);

	naptr->flags = NULL;
	naptr->service = NULL;
	naptr->regexp = NULL;

	dns_rdata_toregion(rdata, &r);

	naptr->order = uint16_fromregion(&r);
	isc_region_consume(&r, 2);

	naptr->preference = uint16_fromregion(&r);
	isc_region_consume(&r, 2);

	naptr->flags_len = uint8_fromregion(&r);
	isc_region_consume(&r, 1);
	INSIST(naptr->flags_len <= r.length);
	naptr->flags = mem_maybedup(mctx, r.base, naptr->flags_len);
	if (naptr->flags == NULL)
		goto cleanup;
	isc_region_consume(&r, naptr->flags_len);

	naptr->service_len = uint8_fromregion(&r);
	isc_region_consume(&r, 1);
	INSIST(naptr->service_len <= r.length);
	naptr->service = mem_maybedup(mctx, r.base, naptr->service_len);
	if (naptr->service == NULL)
		goto cleanup;
	isc_region_consume(&r, naptr->service_len);

	naptr->regexp_len = uint8_fromregion(&r);
	isc_region_consume(&r, 1);
	INSIST(naptr->regexp_len <= r.length);
	naptr->regexp = mem_maybedup(mctx, r.base, naptr->regexp_len);
	if (naptr->regexp == NULL)
		goto cleanup;
	isc_region_consume(&r, naptr->regexp_len);

	dns_name_init(&name, NULL);
	dns_name_fromregion(&name, &r);
	dns_name_init(&naptr->replacement, NULL);
	result = name_duporclone(&name, mctx, &naptr->replacement);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	naptr->mctx = mctx;
	return (ISC_R_SUCCESS);

 cleanup:
	if (mctx != NULL && naptr->flags != NULL)
		isc_mem_free(mctx, naptr->flags);
	if (mctx != NULL && naptr->service != NULL)
		isc_mem_free(mctx, naptr->service);
	if (mctx != NULL && naptr->regexp != NULL)
		isc_mem_free(mctx, naptr->regexp);
	return (ISC_R_NOMEMORY);
}
示例#18
0
static isc_result_t
towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
             dns_compress_t *cctx, isc_buffer_t *target,
             dns_rdatasetorderfunc_t order, const void *order_arg,
             isc_boolean_t partial, unsigned int options,
             unsigned int *countp, void **state)
{
    dns_rdata_t rdata = DNS_RDATA_INIT;
    isc_region_t r;
    isc_result_t result;
    unsigned int i, count, added, choice;
    isc_buffer_t savedbuffer, rdlen, rrbuffer;
    unsigned int headlen;
    isc_boolean_t question = ISC_FALSE;
    isc_boolean_t shuffle = ISC_FALSE;
    dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE];
    struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE];

    UNUSED(state);

    /*
     * Convert 'rdataset' to wire format, compressing names as specified
     * in cctx, and storing the result in 'target'.
     */

    REQUIRE(DNS_RDATASET_VALID(rdataset));
    REQUIRE(countp != NULL);
    REQUIRE((order == NULL) == (order_arg == NULL));
    REQUIRE(cctx != NULL && cctx->mctx != NULL);

    count = 0;
    if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
        question = ISC_TRUE;
        count = 1;
        result = dns_rdataset_first(rdataset);
        INSIST(result == ISC_R_NOMORE);
    } else if (rdataset->type == 0) {
        /*
         * This is a negative caching rdataset.
         */
        unsigned int ncache_opts = 0;
        if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0)
            ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC;
        return (dns_ncache_towire(rdataset, cctx, target, ncache_opts,
                                  countp));
    } else {
        count = (rdataset->methods->count)(rdataset);
        result = dns_rdataset_first(rdataset);
        if (result == ISC_R_NOMORE)
            return (ISC_R_SUCCESS);
        if (result != ISC_R_SUCCESS)
            return (result);
    }

    /*
     * Do we want to shuffle this anwer?
     */
    if (!question && count > 1 &&
            (!WANT_FIXED(rdataset) || order != NULL) &&
            rdataset->type != dns_rdatatype_rrsig)
        shuffle = ISC_TRUE;

    if (shuffle && count > MAX_SHUFFLE) {
        shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled));
        sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted));
        if (shuffled == NULL || sorted == NULL)
            shuffle = ISC_FALSE;
    } else {
        shuffled = shuffled_fixed;
        sorted = sorted_fixed;
    }

    if (shuffle) {
        /*
         * First we get handles to all of the rdata.
         */
        i = 0;
        do {
            INSIST(i < count);
            dns_rdata_init(&shuffled[i]);
            dns_rdataset_current(rdataset, &shuffled[i]);
            i++;
            result = dns_rdataset_next(rdataset);
        } while (result == ISC_R_SUCCESS);
        if (result != ISC_R_NOMORE)
            goto cleanup;
        INSIST(i == count);

        /*
         * Now we shuffle.
         */
        if (WANT_FIXED(rdataset)) {
            /*
             * 'Fixed' order.
             */
            INSIST(order != NULL);
            for (i = 0; i < count; i++) {
                sorted[i].key = (*order)(&shuffled[i],
                                         order_arg);
                sorted[i].rdata = &shuffled[i];
            }
        } else if (WANT_RANDOM(rdataset)) {
            /*
             * 'Random' order.
             */
            for (i = 0; i < count; i++) {
                dns_rdata_t rdata;
                isc_uint32_t val;

                isc_random_get(&val);
                choice = i + (val % (count - i));
                rdata = shuffled[i];
                shuffled[i] = shuffled[choice];
                shuffled[choice] = rdata;
                if (order != NULL)
                    sorted[i].key = (*order)(&shuffled[i],
                                             order_arg);
                else
                    sorted[i].key = 0; /* Unused */
                sorted[i].rdata = &shuffled[i];
            }
        } else {
            /*
             * "Cyclic" order.
             */
            isc_uint32_t val;
            unsigned int j;

            val = rdataset->count;
            if (val == ISC_UINT32_MAX)
                isc_random_get(&val);
            j = val % count;
            for (i = 0; i < count; i++) {
                if (order != NULL)
                    sorted[j].key = (*order)(&shuffled[i],
                                             order_arg);
                else
                    sorted[j].key = 0; /* Unused */
                sorted[j].rdata = &shuffled[i];
                j++;
                if (j == count)
                    j = 0; /* Wrap around. */
            }
        }

        /*
         * Sorted order.
         */
        if (order != NULL)
            qsort(sorted, count, sizeof(sorted[0]),
                  towire_compare);
    }

    savedbuffer = *target;
    i = 0;
    added = 0;

    do {
        /*
         * Copy out the name, type, class, ttl.
         */

        rrbuffer = *target;
        dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
        result = dns_name_towire(owner_name, cctx, target);
        if (result != ISC_R_SUCCESS)
            goto rollback;
        headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t);
        if (!question)
            headlen += sizeof(dns_ttl_t)
                       + 2;  /* XXX 2 for rdata len */
        isc_buffer_availableregion(target, &r);
        if (r.length < headlen) {
            result = ISC_R_NOSPACE;
            goto rollback;
        }
        isc_buffer_putuint16(target, rdataset->type);
        isc_buffer_putuint16(target, rdataset->rdclass);
        if (!question) {
            isc_buffer_putuint32(target, rdataset->ttl);

            /*
             * Save space for rdlen.
             */
            rdlen = *target;
            isc_buffer_add(target, 2);

            /*
             * Copy out the rdata
             */
            if (shuffle)
                rdata = *(sorted[i].rdata);
            else {
                dns_rdata_reset(&rdata);
                dns_rdataset_current(rdataset, &rdata);
            }
            result = dns_rdata_towire(&rdata, cctx, target);
            if (result != ISC_R_SUCCESS)
                goto rollback;
            INSIST((target->used >= rdlen.used + 2) &&
                   (target->used - rdlen.used - 2 < 65536));
            isc_buffer_putuint16(&rdlen,
                                 (isc_uint16_t)(target->used -
                                                rdlen.used - 2));
            added++;
        }

        if (shuffle) {
            i++;
            if (i == count)
                result = ISC_R_NOMORE;
            else
                result = ISC_R_SUCCESS;
        } else {
            result = dns_rdataset_next(rdataset);
        }
    } while (result == ISC_R_SUCCESS);

    if (result != ISC_R_NOMORE)
        goto rollback;

    *countp += count;

    result = ISC_R_SUCCESS;
    goto cleanup;

rollback:
    if (partial && result == ISC_R_NOSPACE) {
        INSIST(rrbuffer.used < 65536);
        dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used);
        *countp += added;
        *target = rrbuffer;
        goto cleanup;
    }
    INSIST(savedbuffer.used < 65536);
    dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
    *countp = 0;
    *target = savedbuffer;

cleanup:
    if (sorted != NULL && sorted != sorted_fixed)
        isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted));
    if (shuffled != NULL && shuffled != shuffled_fixed)
        isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled));
    return (result);
}
示例#19
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);
}
示例#20
0
/*% parses a file and fills in the data structure. */
isc_result_t
irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp)
{
	FILE *fp = NULL;
	char word[256];
	isc_result_t rval, ret = ISC_R_SUCCESS;
	irs_resconf_t *conf;
	unsigned int i;
	int stopchar;

	REQUIRE(mctx != NULL);
	REQUIRE(filename != NULL);
	REQUIRE(strlen(filename) > 0U);
	REQUIRE(confp != NULL && *confp == NULL);

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

	conf->mctx = mctx;
	ISC_LIST_INIT(conf->nameservers);
	conf->numns = 0;
	conf->domainname = NULL;
	conf->searchnxt = 0;
	conf->sortlistnxt = 0;
	conf->resdebug = 0;
	conf->ndots = 1;
	for (i = 0; i < RESCONFMAXSEARCH; i++)
		conf->search[i] = NULL;

	errno = 0;
	if ((fp = fopen(filename, "r")) != NULL) {
		do {
			stopchar = getword(fp, word, sizeof(word));
			if (stopchar == EOF) {
				rval = ISC_R_SUCCESS;
				POST(rval);
				break;
			}

			if (strlen(word) == 0U)
				rval = ISC_R_SUCCESS;
			else if (strcmp(word, "nameserver") == 0)
				rval = resconf_parsenameserver(conf, fp);
			else if (strcmp(word, "domain") == 0)
				rval = resconf_parsedomain(conf, fp);
			else if (strcmp(word, "search") == 0)
				rval = resconf_parsesearch(conf, fp);
			else if (strcmp(word, "sortlist") == 0)
				rval = resconf_parsesortlist(conf, fp);
			else if (strcmp(word, "options") == 0)
				rval = resconf_parseoption(conf, fp);
			else {
				/* unrecognised word. Ignore entire line */
				rval = ISC_R_SUCCESS;
				stopchar = eatline(fp);
				if (stopchar == EOF) {
					break;
				}
			}
			if (ret == ISC_R_SUCCESS && rval != ISC_R_SUCCESS)
				ret = rval;
		} while (1);

		fclose(fp);
	} else {
		switch (errno) {
		case ENOENT:
			break;
		default:
			isc_mem_put(mctx, conf, sizeof(*conf));
			return (ISC_R_INVALIDFILE);
		}
	}

	/* If we don't find a nameserver fall back to localhost */
	if (conf->numns == 0U) {
		INSIST(ISC_LIST_EMPTY(conf->nameservers));

		/* XXX: should we catch errors? */
		(void)add_server(conf->mctx, "127.0.0.1", &conf->nameservers);
		(void)add_server(conf->mctx, "::1", &conf->nameservers);
	}

	/*
	 * Construct unified search list from domain or configured
	 * search list
	 */
	ISC_LIST_INIT(conf->searchlist);
	if (conf->domainname != NULL) {
		ret = add_search(conf, conf->domainname);
	} else if (conf->searchnxt > 0) {
		for (i = 0; i < conf->searchnxt; i++) {
			ret = add_search(conf, conf->search[i]);
			if (ret != ISC_R_SUCCESS)
				break;
		}
	}

	conf->magic = IRS_RESCONF_MAGIC;

	if (ret != ISC_R_SUCCESS)
		irs_resconf_destroy(&conf);
	else {
		if (fp == NULL)
			ret = ISC_R_FILENOTFOUND;
		*confp = conf;
	}

	return (ret);
}
示例#21
0
static void
dispatch(isc_timermgr_t *manager, isc_time_t *now) {
	isc_boolean_t done = ISC_FALSE, post_event, need_schedule;
	isc_event_t *event;
	isc_eventtype_t type = 0;
	isc_timer_t *timer;
	isc_result_t result;

	/*
	 * The caller must be holding the manager lock.
	 */

	while (manager->nscheduled > 0 && !done) {
		timer = isc_heap_element(manager->heap, 1);
		INSIST(timer->type != isc_timertype_inactive);
		if (isc_time_compare(now, &timer->due) >= 0) {
			if (timer->type == isc_timertype_ticker) {
				type = ISC_TIMEREVENT_TICK;
				post_event = ISC_TRUE;
				need_schedule = ISC_TRUE;
			} else if (timer->type == isc_timertype_limited) {
				int cmp;
				cmp = isc_time_compare(now, &timer->expires);
				if (cmp >= 0) {
					type = ISC_TIMEREVENT_LIFE;
					post_event = ISC_TRUE;
					need_schedule = ISC_FALSE;
				} else {
					type = ISC_TIMEREVENT_TICK;
					post_event = ISC_TRUE;
					need_schedule = ISC_TRUE;
				}
			} else if (!isc_time_isepoch(&timer->expires) &&
				   isc_time_compare(now,
						    &timer->expires) >= 0) {
				type = ISC_TIMEREVENT_LIFE;
				post_event = ISC_TRUE;
				need_schedule = ISC_FALSE;
			} else if (!isc_time_isepoch(&timer->idle) &&
				   isc_time_compare(now,
						    &timer->idle) >= 0) {
				type = ISC_TIMEREVENT_IDLE;
				post_event = ISC_TRUE;
				need_schedule = ISC_FALSE;
			} else {
				/*
				 * Idle timer has been touched; reschedule.
				 */
				XTRACEID(isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_TIMER,
							ISC_MSG_IDLERESCHED,
							"idle reschedule"),
					 timer);
				post_event = ISC_FALSE;
				need_schedule = ISC_TRUE;
			}

			if (post_event) {
				XTRACEID(isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_TIMER,
							ISC_MSG_POSTING,
							"posting"), timer);
				/*
				 * XXX We could preallocate this event.
				 */
				event = isc_event_allocate(manager->mctx,
							   timer,
							   type,
							   timer->action,
							   timer->arg,
							   sizeof(*event));

				if (event != NULL)
					isc_task_send(timer->task, &event);
				else
					UNEXPECTED_ERROR(__FILE__, __LINE__,
						 isc_msgcat_get(isc_msgcat,
							 ISC_MSGSET_TIMER,
							 ISC_MSG_EVENTNOTALLOC,
							 "couldn't "
							 "allocate event"));
			}

			timer->index = 0;
			isc_heap_delete(manager->heap, 1);
			manager->nscheduled--;

			if (need_schedule) {
				result = schedule(timer, now, ISC_FALSE);
				if (result != ISC_R_SUCCESS)
					UNEXPECTED_ERROR(__FILE__, __LINE__,
						isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_TIMER,
							ISC_MSG_SCHEDFAIL,
							"couldn't "
							"schedule timer: %u"),
							 result);
			}
		} else {
			manager->due = timer->due;
			done = ISC_TRUE;
		}
	}
}
示例#22
0
isc_result_t
isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
	isc_int32_t cntflag;

	REQUIRE(VALID_RWLOCK(rwl));

#ifdef ISC_RWLOCK_TRACE
	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
				  ISC_MSG_PRELOCK, "prelock"), rwl, type);
#endif

	if (type == isc_rwlocktype_read) {
		if (rwl->write_requests != rwl->write_completions) {
			/* there is a waiting or active writer */
			LOCK(&rwl->lock);
			if (rwl->write_requests != rwl->write_completions) {
				rwl->readers_waiting++;
				WAIT(&rwl->readable, &rwl->lock);
				rwl->readers_waiting--;
			}
			UNLOCK(&rwl->lock);
		}

		cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
		while (1) {
			if ((rwl->cnt_and_flag & WRITER_ACTIVE) == 0)
				break;

			/* A writer is still working */
			LOCK(&rwl->lock);
			rwl->readers_waiting++;
			if ((rwl->cnt_and_flag & WRITER_ACTIVE) != 0)
				WAIT(&rwl->readable, &rwl->lock);
			rwl->readers_waiting--;
			UNLOCK(&rwl->lock);

			/*
			 * Typically, the reader should be able to get a lock
			 * at this stage:
			 *   (1) there should have been no pending writer when
			 *       the reader was trying to increment the
			 *       counter; otherwise, the writer should be in
			 *       the waiting queue, preventing the reader from
			 *       proceeding to this point.
			 *   (2) once the reader increments the counter, no
			 *       more writer can get a lock.
			 * Still, it is possible another writer can work at
			 * this point, e.g. in the following scenario:
			 *   A previous writer unlocks the writer lock.
			 *   This reader proceeds to point (1).
			 *   A new writer appears, and gets a new lock before
			 *   the reader increments the counter.
			 *   The reader then increments the counter.
			 *   The previous writer notices there is a waiting
			 *   reader who is almost ready, and wakes it up.
			 * So, the reader needs to confirm whether it can now
			 * read explicitly (thus we loop).  Note that this is
			 * not an infinite process, since the reader has
			 * incremented the counter at this point.
			 */
		}

		/*
		 * If we are temporarily preferred to writers due to the writer
		 * quota, reset the condition (race among readers doesn't
		 * matter).
		 */
		rwl->write_granted = 0;
	} else {
		isc_int32_t prev_writer;

		/* enter the waiting queue, and wait for our turn */
		prev_writer = isc_atomic_xadd(&rwl->write_requests, 1);
		while (rwl->write_completions != prev_writer) {
			LOCK(&rwl->lock);
			if (rwl->write_completions != prev_writer) {
				WAIT(&rwl->writeable, &rwl->lock);
				UNLOCK(&rwl->lock);
				continue;
			}
			UNLOCK(&rwl->lock);
			break;
		}

		while (1) {
			cntflag = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
						     WRITER_ACTIVE);
			if (cntflag == 0)
				break;

			/* Another active reader or writer is working. */
			LOCK(&rwl->lock);
			if (rwl->cnt_and_flag != 0)
				WAIT(&rwl->writeable, &rwl->lock);
			UNLOCK(&rwl->lock);
		}

		INSIST((rwl->cnt_and_flag & WRITER_ACTIVE) != 0);
		rwl->write_granted++;
	}

#ifdef ISC_RWLOCK_TRACE
	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
				  ISC_MSG_POSTLOCK, "postlock"), rwl, type);
#endif

	return (ISC_R_SUCCESS);
}
示例#23
0
文件: nsec3.c 项目: KaiToTo/freebsd
isc_result_t
dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
		     dns_dbnode_t *node, unsigned int hashalg,
		     unsigned int flags, unsigned int iterations,
		     const unsigned char *salt, size_t salt_length,
		     const unsigned char *nexthash, size_t hash_length,
		     unsigned char *buffer, dns_rdata_t *rdata)
{
	isc_result_t result;
	dns_rdataset_t rdataset;
	isc_region_t r;
	unsigned int i, window;
	int octet;
	isc_boolean_t found;
	isc_boolean_t found_ns;
	isc_boolean_t need_rrsig;

	unsigned char *nsec_bits, *bm;
	unsigned int max_type;
	dns_rdatasetiter_t *rdsiter;
	unsigned char *p;

	REQUIRE(salt_length < 256U);
	REQUIRE(hash_length < 256U);
	REQUIRE(flags <= 0xffU);
	REQUIRE(hashalg <= 0xffU);
	REQUIRE(iterations <= 0xffffU);

	switch (hashalg) {
	case dns_hash_sha1:
		REQUIRE(hash_length == ISC_SHA1_DIGESTLENGTH);
		break;
	}

	memset(buffer, 0, DNS_NSEC3_BUFFERSIZE);

	p = buffer;

	*p++ = hashalg;
	*p++ = flags;

	*p++ = iterations >> 8;
	*p++ = iterations;

	*p++ = salt_length;
	memcpy(p, salt, salt_length);
	p += salt_length;

	*p++ = hash_length;
	memcpy(p, nexthash, hash_length);
	p += hash_length;

	r.length = p - buffer;
	r.base = buffer;

	/*
	 * Use the end of the space for a raw bitmap leaving enough
	 * space for the window identifiers and length octets.
	 */
	bm = r.base + r.length + 512;
	nsec_bits = r.base + r.length;
	max_type = 0;
	if (node == NULL)
		goto collapse_bitmap;
	dns_rdataset_init(&rdataset);
	rdsiter = NULL;
	result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
	if (result != ISC_R_SUCCESS)
		return (result);
	found = found_ns = need_rrsig = ISC_FALSE;
	for (result = dns_rdatasetiter_first(rdsiter);
	     result == ISC_R_SUCCESS;
	     result = dns_rdatasetiter_next(rdsiter))
	{
		dns_rdatasetiter_current(rdsiter, &rdataset);
		if (rdataset.type != dns_rdatatype_nsec &&
		    rdataset.type != dns_rdatatype_nsec3 &&
		    rdataset.type != dns_rdatatype_rrsig) {
			if (rdataset.type > max_type)
				max_type = rdataset.type;
			set_bit(bm, rdataset.type, 1);
			/*
			 * Work out if we need to set the RRSIG bit for
			 * this node.  We set the RRSIG bit if either of
			 * the following conditions are met:
			 * 1) We have a SOA or DS then we need to set
			 *    the RRSIG bit as both always will be signed.
			 * 2) We set the RRSIG bit if we don't have
			 *    a NS record but do have other data.
			 */
			if (rdataset.type == dns_rdatatype_soa ||
			    rdataset.type == dns_rdatatype_ds)
				need_rrsig = ISC_TRUE;
			else if (rdataset.type == dns_rdatatype_ns)
				found_ns = ISC_TRUE;
			else
				found = ISC_TRUE;
		}
		dns_rdataset_disassociate(&rdataset);
	}
	if ((found && !found_ns) || need_rrsig) {
		if (dns_rdatatype_rrsig > max_type)
			max_type = dns_rdatatype_rrsig;
		set_bit(bm, dns_rdatatype_rrsig, 1);
	}

	/*
	 * At zone cuts, deny the existence of glue in the parent zone.
	 */
	if (bit_isset(bm, dns_rdatatype_ns) &&
	    ! bit_isset(bm, dns_rdatatype_soa)) {
		for (i = 0; i <= max_type; i++) {
			if (bit_isset(bm, i) &&
			    ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
				set_bit(bm, i, 0);
		}
	}

	dns_rdatasetiter_destroy(&rdsiter);
	if (result != ISC_R_NOMORE)
		return (result);

 collapse_bitmap:
	for (window = 0; window < 256; window++) {
		if (window * 256 > max_type)
			break;
		for (octet = 31; octet >= 0; octet--)
			if (bm[window * 32 + octet] != 0)
				break;
		if (octet < 0)
			continue;
		nsec_bits[0] = window;
		nsec_bits[1] = octet + 1;
		/*
		 * Note: potentially overlapping move.
		 */
		memmove(&nsec_bits[2], &bm[window * 32], octet + 1);
		nsec_bits += 3 + octet;
	}
	r.length = nsec_bits - r.base;
	INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
	dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);

	return (ISC_R_SUCCESS);
}
示例#24
0
static isc_result_t
xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
		  dns_name_t *qname, dns_rdatatype_t qtype,
		  dns_rdataclass_t qclass, dns_zone_t *zone,
		  dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
		  rrstream_t *stream, dns_tsigkey_t *tsigkey,
		  isc_buffer_t *lasttsig, unsigned int maxtime,
		  unsigned int idletime, isc_boolean_t many_answers,
		  xfrout_ctx_t **xfrp)
{
	xfrout_ctx_t *xfr;
	isc_result_t result;
	unsigned int len;
	void *mem;

	INSIST(xfrp != NULL && *xfrp == NULL);
	xfr = isc_mem_get(mctx, sizeof(*xfr));
	if (xfr == NULL)
		return (ISC_R_NOMEMORY);
	xfr->mctx = NULL;
	isc_mem_attach(mctx, &xfr->mctx);
	xfr->client = NULL;
	ns_client_attach(client, &xfr->client);
	xfr->id = id;
	xfr->qname = qname;
	xfr->qtype = qtype;
	xfr->qclass = qclass;
	xfr->zone = NULL;
	xfr->db = NULL;
	xfr->ver = NULL;
	if (zone != NULL)	/* zone will be NULL if it's DLZ */
		dns_zone_attach(zone, &xfr->zone);
	dns_db_attach(db, &xfr->db);
	dns_db_attachversion(db, ver, &xfr->ver);
	xfr->end_of_stream = ISC_FALSE;
	xfr->tsigkey = tsigkey;
	xfr->lasttsig = lasttsig;
	xfr->txmem = NULL;
	xfr->txmemlen = 0;
	xfr->nmsg = 0;
	xfr->many_answers = many_answers,
	xfr->sends = 0;
	xfr->shuttingdown = ISC_FALSE;
	xfr->mnemonic = NULL;
	xfr->buf.base = NULL;
	xfr->buf.length = 0;
	xfr->txmem = NULL;
	xfr->txmemlen = 0;
	xfr->stream = NULL;
	xfr->quota = NULL;

	/*
	 * Allocate a temporary buffer for the uncompressed response
	 * message data.  The size should be no more than 65535 bytes
	 * so that the compressed data will fit in a TCP message,
	 * and no less than 65535 bytes so that an almost maximum-sized
	 * RR will fit.  Note that although 65535-byte RRs are allowed
	 * in principle, they cannot be zone-transferred (at least not
	 * if uncompressible), because the message and RR headers would
	 * push the size of the TCP message over the 65536 byte limit.
	 */
	len = 65535;
	mem = isc_mem_get(mctx, len);
	if (mem == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}
	isc_buffer_init(&xfr->buf, mem, len);

	/*
	 * Allocate another temporary buffer for the compressed
	 * response message and its TCP length prefix.
	 */
	len = 2 + 65535;
	mem = isc_mem_get(mctx, len);
	if (mem == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}
	isc_buffer_init(&xfr->txlenbuf, mem, 2);
	isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
	xfr->txmem = mem;
	xfr->txmemlen = len;

	CHECK(dns_timer_setidle(xfr->client->timer,
				maxtime, idletime, ISC_FALSE));

	/*
	 * Register a shutdown callback with the client, so that we
	 * can stop the transfer immediately when the client task
	 * gets a shutdown event.
	 */
	xfr->client->shutdown = xfrout_client_shutdown;
	xfr->client->shutdown_arg = xfr;
	/*
	 * These MUST be after the last "goto failure;" / CHECK to
	 * prevent a double free by the caller.
	 */
	xfr->quota = quota;
	xfr->stream = stream;

	*xfrp = xfr;
	return (ISC_R_SUCCESS);

failure:
	xfrout_ctx_destroy(&xfr);
	return (result);
}
示例#25
0
static isc_result_t
pkcs11rsa_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_RSA;
    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 *rsa;
    pk11_object_t *pubrsa;
    pk11_context_t *pk11_ctx = NULL;
    isc_result_t ret;

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

    rsa = key->keydata.pkey;
    pubrsa = pub->keydata.pkey;

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

    attr->type = CKA_MODULUS;
    pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS);
    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_PUBLIC_EXPONENT;
    pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT);
    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(rsa, label, key->mctx, OP_RSA);
    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_RSA, ISC_TRUE, ISC_FALSE,
                           rsa->reqlogon, NULL, rsa->slot);
    if (ret != ISC_R_SUCCESS)
        goto err;

    attr = pk11_attribute_bytype(rsa, CKA_LABEL);
    if (attr == NULL) {
        attr = pk11_attribute_bytype(rsa, 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, &rsa->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));

    attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
    INSIST(attr != NULL);
    key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);

    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);
}
示例#26
0
/*
 * Arrange to send as much as we can of "stream" without blocking.
 *
 * Requires:
 *	The stream iterator is initialized and points at an RR,
 *      or possibly at the end of the stream (that is, the
 *      _first method of the iterator has been called).
 */
static void
sendstream(xfrout_ctx_t *xfr) {
	dns_message_t *tcpmsg = NULL;
	dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
	isc_result_t result;
	isc_region_t used;
	isc_region_t region;
	dns_rdataset_t *qrdataset;
	dns_name_t *msgname = NULL;
	dns_rdata_t *msgrdata = NULL;
	dns_rdatalist_t *msgrdl = NULL;
	dns_rdataset_t *msgrds = NULL;
	dns_compress_t cctx;
	isc_boolean_t cleanup_cctx = ISC_FALSE;

	int n_rrs;

	isc_buffer_clear(&xfr->buf);
	isc_buffer_clear(&xfr->txlenbuf);
	isc_buffer_clear(&xfr->txbuf);

	if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) {
		/*
		 * In the UDP case, we put the response data directly into
		 * the client message.
		 */
		msg = xfr->client->message;
		CHECK(dns_message_reply(msg, ISC_TRUE));
	} else {
		/*
		 * TCP. Build a response dns_message_t, temporarily storing
		 * the raw, uncompressed owner names and RR data contiguously
		 * in xfr->buf.  We know that if the uncompressed data fits
		 * in xfr->buf, the compressed data will surely fit in a TCP
		 * message.
		 */

		CHECK(dns_message_create(xfr->mctx,
					 DNS_MESSAGE_INTENTRENDER, &tcpmsg));
		msg = tcpmsg;

		msg->id = xfr->id;
		msg->rcode = dns_rcode_noerror;
		msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
		if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
			msg->flags |= DNS_MESSAGEFLAG_RA;
		CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
		CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
		if (xfr->lasttsig != NULL)
			isc_buffer_free(&xfr->lasttsig);

		/*
		 * Account for reserved space.
		 */
		if (xfr->tsigkey != NULL)
			INSIST(msg->reserved != 0U);
		isc_buffer_add(&xfr->buf, msg->reserved);

		/*
		 * Include a question section in the first message only.
		 * BIND 8.2.1 will not recognize an IXFR if it does not
		 * have a question section.
		 */
		if (xfr->nmsg == 0) {
			dns_name_t *qname = NULL;
			isc_region_t r;

			/*
			 * Reserve space for the 12-byte message header
			 * and 4 bytes of question.
			 */
			isc_buffer_add(&xfr->buf, 12 + 4);

			qrdataset = NULL;
			result = dns_message_gettemprdataset(msg, &qrdataset);
			if (result != ISC_R_SUCCESS)
				goto failure;
			dns_rdataset_init(qrdataset);
			dns_rdataset_makequestion(qrdataset,
					xfr->client->message->rdclass,
					xfr->qtype);

			result = dns_message_gettempname(msg, &qname);
			if (result != ISC_R_SUCCESS)
				goto failure;
			dns_name_init(qname, NULL);
			isc_buffer_availableregion(&xfr->buf, &r);
			INSIST(r.length >= xfr->qname->length);
			r.length = xfr->qname->length;
			isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
					  xfr->qname->length);
			dns_name_fromregion(qname, &r);
			ISC_LIST_INIT(qname->list);
			ISC_LIST_APPEND(qname->list, qrdataset, link);

			dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
		} else {
			/*
			 * Reserve space for the 12-byte message header
			 */
			isc_buffer_add(&xfr->buf, 12);
			msg->tcp_continuation = 1;
		}
	}

	/*
	 * Try to fit in as many RRs as possible, unless "one-answer"
	 * format has been requested.
	 */
	for (n_rrs = 0; ; n_rrs++) {
		dns_name_t *name = NULL;
		isc_uint32_t ttl;
		dns_rdata_t *rdata = NULL;

		unsigned int size;
		isc_region_t r;

		msgname = NULL;
		msgrdata = NULL;
		msgrdl = NULL;
		msgrds = NULL;

		xfr->stream->methods->current(xfr->stream,
					      &name, &ttl, &rdata);
		size = name->length + 10 + rdata->length;
		isc_buffer_availableregion(&xfr->buf, &r);
		if (size >= r.length) {
			/*
			 * RR would not fit.  If there are other RRs in the
			 * buffer, send them now and leave this RR to the
			 * next message.  If this RR overflows the buffer
			 * all by itself, fail.
			 *
			 * In theory some RRs might fit in a TCP message
			 * when compressed even if they do not fit when
			 * uncompressed, but surely we don't want
			 * to send such monstrosities to an unsuspecting
			 * slave.
			 */
			if (n_rrs == 0) {
				xfrout_log(xfr, ISC_LOG_WARNING,
					   "RR too large for zone transfer "
					   "(%d bytes)", size);
				/* XXX DNS_R_RRTOOLARGE? */
				result = ISC_R_NOSPACE;
				goto failure;
			}
			break;
		}

		if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
			log_rr(name, rdata, ttl); /* XXX */

		result = dns_message_gettempname(msg, &msgname);
		if (result != ISC_R_SUCCESS)
			goto failure;
		dns_name_init(msgname, NULL);
		isc_buffer_availableregion(&xfr->buf, &r);
		INSIST(r.length >= name->length);
		r.length = name->length;
		isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
		dns_name_fromregion(msgname, &r);

		/* Reserve space for RR header. */
		isc_buffer_add(&xfr->buf, 10);

		result = dns_message_gettemprdata(msg, &msgrdata);
		if (result != ISC_R_SUCCESS)
			goto failure;
		isc_buffer_availableregion(&xfr->buf, &r);
		r.length = rdata->length;
		isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
		dns_rdata_init(msgrdata);
		dns_rdata_fromregion(msgrdata,
				     rdata->rdclass, rdata->type, &r);

		result = dns_message_gettemprdatalist(msg, &msgrdl);
		if (result != ISC_R_SUCCESS)
			goto failure;
		msgrdl->type = rdata->type;
		msgrdl->rdclass = rdata->rdclass;
		msgrdl->ttl = ttl;
		if (rdata->type == dns_rdatatype_sig ||
		    rdata->type == dns_rdatatype_rrsig)
			msgrdl->covers = dns_rdata_covers(rdata);
		else
			msgrdl->covers = dns_rdatatype_none;
		ISC_LINK_INIT(msgrdl, link);
		ISC_LIST_INIT(msgrdl->rdata);
		ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);

		result = dns_message_gettemprdataset(msg, &msgrds);
		if (result != ISC_R_SUCCESS)
			goto failure;
		dns_rdataset_init(msgrds);
		result = dns_rdatalist_tordataset(msgrdl, msgrds);
		INSIST(result == ISC_R_SUCCESS);

		ISC_LIST_APPEND(msgname->list, msgrds, link);

		dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
		msgname = NULL;

		result = xfr->stream->methods->next(xfr->stream);
		if (result == ISC_R_NOMORE) {
			xfr->end_of_stream = ISC_TRUE;
			break;
		}
		CHECK(result);

		if (! xfr->many_answers)
			break;
	}

	if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) {
		CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
		dns_compress_setsensitive(&cctx, ISC_TRUE);
		cleanup_cctx = ISC_TRUE;
		CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
		CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
		CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
		CHECK(dns_message_renderend(msg));
		dns_compress_invalidate(&cctx);
		cleanup_cctx = ISC_FALSE;

		isc_buffer_usedregion(&xfr->txbuf, &used);
		isc_buffer_putuint16(&xfr->txlenbuf,
				     (isc_uint16_t)used.length);
		region.base = xfr->txlenbuf.base;
		region.length = 2 + used.length;
		xfrout_log(xfr, ISC_LOG_DEBUG(8),
			   "sending TCP message of %d bytes",
			   used.length);
		CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
				      &region, xfr->client->task,
				      xfrout_senddone,
				      xfr));
		xfr->sends++;
	} else {
		xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
		ns_client_send(xfr->client);
		xfr->stream->methods->pause(xfr->stream);
		xfrout_ctx_destroy(&xfr);
		return;
	}

	/* Advance lasttsig to be the last TSIG generated */
	CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));

	xfr->nmsg++;

 failure:
	if (msgname != NULL) {
		if (msgrds != NULL) {
			if (dns_rdataset_isassociated(msgrds))
				dns_rdataset_disassociate(msgrds);
			dns_message_puttemprdataset(msg, &msgrds);
		}
		if (msgrdl != NULL) {
			ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
			dns_message_puttemprdatalist(msg, &msgrdl);
		}
		if (msgrdata != NULL)
			dns_message_puttemprdata(msg, &msgrdata);
		dns_message_puttempname(msg, &msgname);
	}

	if (tcpmsg != NULL)
		dns_message_destroy(&tcpmsg);

	if (cleanup_cctx)
		dns_compress_invalidate(&cctx);
	/*
	 * Make sure to release any locks held by database
	 * iterators before returning from the event handler.
	 */
	xfr->stream->methods->pause(xfr->stream);

	if (result == ISC_R_SUCCESS)
		return;

	xfrout_fail(xfr, result, "sending zone data");
}
示例#27
0
static isc_result_t
pkcs11rsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
    dst_private_t priv;
    isc_result_t ret;
    int i;
    pk11_object_t *rsa;
    CK_ATTRIBUTE *attr;
    isc_mem_t *mctx = key->mctx;
    const char *engine = NULL, *label = NULL;

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

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

    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;
        }
    }
    rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
    if (rsa == NULL)
        DST_RET(ISC_R_NOMEMORY);
    memset(rsa, 0, sizeof(*rsa));
    key->keydata.pkey = rsa;

    /* Is this key is stored in a HSM? See if we can fetch it. */
    if ((label != NULL) || (engine != NULL)) {
        ret = pkcs11rsa_fetch(key, engine, label, pub);
        if (ret != ISC_R_SUCCESS)
            goto err;
        dst__privstruct_free(&priv, mctx);
        memset(&priv, 0, sizeof(priv));
        return (ret);
    }

    rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8);
    if (rsa->repr == NULL)
        DST_RET(ISC_R_NOMEMORY);
    memset(rsa->repr, 0, sizeof(*attr) * 8);
    rsa->attrcnt = 8;
    attr = rsa->repr;
    attr[0].type = CKA_MODULUS;
    attr[1].type = CKA_PUBLIC_EXPONENT;
    attr[2].type = CKA_PRIVATE_EXPONENT;
    attr[3].type = CKA_PRIME_1;
    attr[4].type = CKA_PRIME_2;
    attr[5].type = CKA_EXPONENT_1;
    attr[6].type = CKA_EXPONENT_2;
    attr[7].type = CKA_COEFFICIENT;

    for (i = 0; i < priv.nelements; i++) {
        CK_BYTE *bn;

        switch (priv.elements[i].tag) {
        case TAG_RSA_ENGINE:
            continue;
        case TAG_RSA_LABEL:
            continue;
        default:
            bn = isc_mem_get(key->mctx, priv.elements[i].length);
            if (bn == NULL)
                DST_RET(ISC_R_NOMEMORY);
            memmove(bn, priv.elements[i].data,
                    priv.elements[i].length);
        }

        switch (priv.elements[i].tag) {
        case TAG_RSA_MODULUS:
            attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
            INSIST(attr != NULL);
            attr->pValue = bn;
            attr->ulValueLen = priv.elements[i].length;
            break;
        case TAG_RSA_PUBLICEXPONENT:
            attr = pk11_attribute_bytype(rsa,
                                         CKA_PUBLIC_EXPONENT);
            INSIST(attr != NULL);
            attr->pValue = bn;
            attr->ulValueLen = priv.elements[i].length;
            break;
        case TAG_RSA_PRIVATEEXPONENT:
            attr = pk11_attribute_bytype(rsa,
                                         CKA_PRIVATE_EXPONENT);
            INSIST(attr != NULL);
            attr->pValue = bn;
            attr->ulValueLen = priv.elements[i].length;
            break;
        case TAG_RSA_PRIME1:
            attr = pk11_attribute_bytype(rsa, CKA_PRIME_1);
            INSIST(attr != NULL);
            attr->pValue = bn;
            attr->ulValueLen = priv.elements[i].length;
            break;
        case TAG_RSA_PRIME2:
            attr = pk11_attribute_bytype(rsa, CKA_PRIME_2);
            INSIST(attr != NULL);
            attr->pValue = bn;
            attr->ulValueLen = priv.elements[i].length;
            break;
        case TAG_RSA_EXPONENT1:
            attr = pk11_attribute_bytype(rsa,
                                         CKA_EXPONENT_1);
            INSIST(attr != NULL);
            attr->pValue = bn;
            attr->ulValueLen = priv.elements[i].length;
            break;
        case TAG_RSA_EXPONENT2:
            attr = pk11_attribute_bytype(rsa,
                                         CKA_EXPONENT_2);
            INSIST(attr != NULL);
            attr->pValue = bn;
            attr->ulValueLen = priv.elements[i].length;
            break;
        case TAG_RSA_COEFFICIENT:
            attr = pk11_attribute_bytype(rsa,
                                         CKA_COEFFICIENT);
            INSIST(attr != NULL);
            attr->pValue = bn;
            attr->ulValueLen = priv.elements[i].length;
            break;
        }
    }

    if (rsa_check(rsa, pub->keydata.pkey) != ISC_R_SUCCESS)
        DST_RET(DST_R_INVALIDPRIVATEKEY);

    attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
    INSIST(attr != NULL);
    key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);

    attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
    INSIST(attr != NULL);
    if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
        DST_RET(ISC_R_RANGE);

    dst__privstruct_free(&priv, mctx);
    memset(&priv, 0, sizeof(priv));

    return (ISC_R_SUCCESS);

err:
    pkcs11rsa_destroy(key);
    dst__privstruct_free(&priv, mctx);
    memset(&priv, 0, sizeof(priv));
    return (ret);
}
示例#28
0
void
ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
	isc_result_t result;
	dns_name_t *question_name;
	dns_rdataset_t *question_rdataset;
	dns_zone_t *zone = NULL;
	dns_db_t *db = NULL;
	dns_dbversion_t *ver = NULL;
	dns_rdataclass_t question_class;
	rrstream_t *soa_stream = NULL;
	rrstream_t *data_stream = NULL;
	rrstream_t *stream = NULL;
	dns_difftuple_t *current_soa_tuple = NULL;
	dns_name_t *soa_name;
	dns_rdataset_t *soa_rdataset;
	dns_rdata_t soa_rdata = DNS_RDATA_INIT;
	isc_boolean_t have_soa = ISC_FALSE;
	const char *mnemonic = NULL;
	isc_mem_t *mctx = client->mctx;
	dns_message_t *request = client->message;
	xfrout_ctx_t *xfr = NULL;
	isc_quota_t *quota = NULL;
	dns_transfer_format_t format = client->view->transfer_format;
	isc_netaddr_t na;
	dns_peer_t *peer = NULL;
	isc_buffer_t *tsigbuf = NULL;
	char *journalfile;
	char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
	char keyname[DNS_NAME_FORMATSIZE];
	isc_boolean_t is_poll = ISC_FALSE;
	isc_boolean_t is_dlz = ISC_FALSE;

	switch (reqtype) {
	case dns_rdatatype_axfr:
		mnemonic = "AXFR";
		break;
	case dns_rdatatype_ixfr:
		mnemonic = "IXFR";
		break;
	default:
		INSIST(0);
		break;
	}

	ns_client_log(client,
		      DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
		      ISC_LOG_DEBUG(6), "%s request", mnemonic);
	/*
	 * Apply quota.
	 */
	result = isc_quota_attach(&ns_g_server->xfroutquota, &quota);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
			      "%s request denied: %s", mnemonic,
			      isc_result_totext(result));
		goto failure;
	}

	/*
	 * Interpret the question section.
	 */
	result = dns_message_firstname(request, DNS_SECTION_QUESTION);
	INSIST(result == ISC_R_SUCCESS);

	/*
	 * The question section must contain exactly one question, and
	 * it must be for AXFR/IXFR as appropriate.
	 */
	question_name = NULL;
	dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
	question_rdataset = ISC_LIST_HEAD(question_name->list);
	question_class = question_rdataset->rdclass;
	INSIST(question_rdataset->type == reqtype);
	if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
		FAILC(DNS_R_FORMERR, "multiple questions");
	result = dns_message_nextname(request, DNS_SECTION_QUESTION);
	if (result != ISC_R_NOMORE)
		FAILC(DNS_R_FORMERR, "multiple questions");

	result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
			     &zone);

	if (result != ISC_R_SUCCESS) {
		/*
		 * Normal zone table does not have a match.
		 * Try the DLZ database
		 */
		if (client->view->dlzdatabase != NULL) {
			result = dns_dlzallowzonexfr(client->view,
						     question_name,
						     &client->peeraddr,
						     &db);

			if (result == ISC_R_NOPERM) {
				char _buf1[DNS_NAME_FORMATSIZE];
				char _buf2[DNS_RDATACLASS_FORMATSIZE];

				result = DNS_R_REFUSED;
				dns_name_format(question_name, _buf1,
						sizeof(_buf1));
				dns_rdataclass_format(question_class,
						      _buf2, sizeof(_buf2));
				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
					      NS_LOGMODULE_XFER_OUT,
					      ISC_LOG_ERROR,
					      "zone transfer '%s/%s' denied",
					      _buf1, _buf2);
				goto failure;
			}
			if (result != ISC_R_SUCCESS)
				FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
				      question_name, question_class);
			is_dlz = ISC_TRUE;
			/*
			 * DLZ only support full zone transfer, not incremental
			 */
			if (reqtype != dns_rdatatype_axfr) {
				mnemonic = "AXFR-style IXFR";
				reqtype = dns_rdatatype_axfr;
			}

		} else {
			/*
			 * not DLZ and not in normal zone table, we are
			 * not authoritative
			 */
			FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
			      question_name, question_class);
		}
	} else {
		/* zone table has a match */
		switch(dns_zone_gettype(zone)) {
			case dns_zone_master:
			case dns_zone_slave:
			case dns_zone_dlz:
				break;	/* Master and slave zones are OK for transfer. */
			default:
				FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class);
			}
		CHECK(dns_zone_getdb(zone, &db));
		dns_db_currentversion(db, &ver);
	}

	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
		    "%s question section OK", mnemonic);

	/*
	 * Check the authority section.  Look for a SOA record with
	 * the same name and class as the question.
	 */
	for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
	     result == ISC_R_SUCCESS;
	     result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
	{
		soa_name = NULL;
		dns_message_currentname(request, DNS_SECTION_AUTHORITY,
					&soa_name);

		/*
		 * Ignore data whose owner name is not the zone apex.
		 */
		if (! dns_name_equal(soa_name, question_name))
			continue;

		for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
		     soa_rdataset != NULL;
		     soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
		{
			/*
			 * Ignore non-SOA data.
			 */
			if (soa_rdataset->type != dns_rdatatype_soa)
				continue;
			if (soa_rdataset->rdclass != question_class)
				continue;

			CHECK(dns_rdataset_first(soa_rdataset));
			dns_rdataset_current(soa_rdataset, &soa_rdata);
			result = dns_rdataset_next(soa_rdataset);
			if (result == ISC_R_SUCCESS)
				FAILC(DNS_R_FORMERR,
				      "IXFR authority section "
				      "has multiple SOAs");
			have_soa = ISC_TRUE;
			goto got_soa;
		}
	}
 got_soa:
	if (result != ISC_R_NOMORE)
		CHECK(result);

	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
		    "%s authority section OK", mnemonic);

	/*
	 * If not a DLZ zone, decide whether to allow this transfer.
	 */
	if (!is_dlz) {
		ns_client_aclmsg("zone transfer", question_name, reqtype,
				 client->view->rdclass, msg, sizeof(msg));
		CHECK(ns_client_checkacl(client, NULL, msg,
					 dns_zone_getxfracl(zone),
					 ISC_TRUE, ISC_LOG_ERROR));
	}

	/*
	 * AXFR over UDP is not possible.
	 */
	if (reqtype == dns_rdatatype_axfr &&
	    (client->attributes & NS_CLIENTATTR_TCP) == 0)
		FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");

	/*
	 * Look up the requesting server in the peer table.
	 */
	isc_netaddr_fromsockaddr(&na, &client->peeraddr);
	(void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);

	/*
	 * Decide on the transfer format (one-answer or many-answers).
	 */
	if (peer != NULL)
		(void)dns_peer_gettransferformat(peer, &format);

	/*
	 * Get a dynamically allocated copy of the current SOA.
	 */
	if (is_dlz)
		dns_db_currentversion(db, &ver);

	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
				    &current_soa_tuple));

	if (reqtype == dns_rdatatype_ixfr) {
		isc_uint32_t begin_serial, current_serial;
		isc_boolean_t provide_ixfr;

		/*
		 * Outgoing IXFR may have been disabled for this peer
		 * or globally.
		 */
		provide_ixfr = client->view->provideixfr;
		if (peer != NULL)
			(void) dns_peer_getprovideixfr(peer, &provide_ixfr);
		if (provide_ixfr == ISC_FALSE)
			goto axfr_fallback;

		if (! have_soa)
			FAILC(DNS_R_FORMERR,
			      "IXFR request missing SOA");

		begin_serial = dns_soa_getserial(&soa_rdata);
		current_serial = dns_soa_getserial(&current_soa_tuple->rdata);

		/*
		 * RFC1995 says "If an IXFR query with the same or
		 * newer version number than that of the server
		 * is received, it is replied to with a single SOA
		 * record of the server's current version, just as
		 * in AXFR".  The claim about AXFR is incorrect,
		 * but other than that, we do as the RFC says.
		 *
		 * Sending a single SOA record is also how we refuse
		 * IXFR over UDP (currently, we always do).
		 */
		if (DNS_SERIAL_GE(begin_serial, current_serial) ||
		    (client->attributes & NS_CLIENTATTR_TCP) == 0)
		{
			CHECK(soa_rrstream_create(mctx, db, ver, &stream));
			is_poll = ISC_TRUE;
			goto have_stream;
		}
		journalfile = dns_zone_getjournal(zone);
		if (journalfile != NULL)
			result = ixfr_rrstream_create(mctx,
						      journalfile,
						      begin_serial,
						      current_serial,
						      &data_stream);
		else
			result = ISC_R_NOTFOUND;
		if (result == ISC_R_NOTFOUND ||
		    result == ISC_R_RANGE) {
			xfrout_log1(client, question_name, question_class,
				    ISC_LOG_DEBUG(4),
				    "IXFR version not in journal, "
				    "falling back to AXFR");
			mnemonic = "AXFR-style IXFR";
			goto axfr_fallback;
		}
		CHECK(result);
	} else {
	axfr_fallback:
		CHECK(axfr_rrstream_create(mctx, db, ver,
					   &data_stream));
	}

	/*
	 * Bracket the data stream with SOAs.
	 */
	CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
	CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
				       &stream));
	soa_stream = NULL;
	data_stream = NULL;

 have_stream:
	CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
	/*
	 * Create the xfrout context object.  This transfers the ownership
	 * of "stream", "db", "ver", and "quota" to the xfrout context object.
	 */



	if (is_dlz)
		CHECK(xfrout_ctx_create(mctx, client, request->id,
					question_name, reqtype, question_class,
					zone, db, ver, quota, stream,
					dns_message_gettsigkey(request),
					tsigbuf,
					3600,
					3600,
					(format == dns_many_answers) ?
					ISC_TRUE : ISC_FALSE,
					&xfr));
	else
		CHECK(xfrout_ctx_create(mctx, client, request->id,
					question_name, reqtype, question_class,
					zone, db, ver, quota, stream,
					dns_message_gettsigkey(request),
					tsigbuf,
					dns_zone_getmaxxfrout(zone),
					dns_zone_getidleout(zone),
					(format == dns_many_answers) ?
					ISC_TRUE : ISC_FALSE,
					&xfr));

	xfr->mnemonic = mnemonic;
	stream = NULL;
	quota = NULL;

	CHECK(xfr->stream->methods->first(xfr->stream));

	if (xfr->tsigkey != NULL)
		dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
	else
		keyname[0] = '\0';
	if (is_poll)
		xfrout_log1(client, question_name, question_class,
			    ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
	else
		xfrout_log1(client, question_name, question_class,
			    ISC_LOG_INFO, "%s started%s%s", mnemonic,
			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);

	/*
	 * Hand the context over to sendstream().  Set xfr to NULL;
	 * sendstream() is responsible for either passing the
	 * context on to a later event handler or destroying it.
	 */
	sendstream(xfr);
	xfr = NULL;

	result = ISC_R_SUCCESS;

 failure:
	if (result == DNS_R_REFUSED)
		inc_stats(zone, dns_nsstatscounter_xfrrej);
	if (quota != NULL)
		isc_quota_detach(&quota);
	if (current_soa_tuple != NULL)
		dns_difftuple_free(&current_soa_tuple);
	if (stream != NULL)
		stream->methods->destroy(&stream);
	if (soa_stream != NULL)
		soa_stream->methods->destroy(&soa_stream);
	if (data_stream != NULL)
		data_stream->methods->destroy(&data_stream);
	if (ver != NULL)
		dns_db_closeversion(db, &ver, ISC_FALSE);
	if (db != NULL)
		dns_db_detach(&db);
	if (zone != NULL)
		dns_zone_detach(&zone);
	/* XXX kludge */
	if (xfr != NULL) {
		xfrout_fail(xfr, result, "setting up zone transfer");
	} else if (result != ISC_R_SUCCESS) {
		ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
			      NS_LOGMODULE_XFER_OUT,
			      ISC_LOG_DEBUG(3), "zone transfer setup failed");
		ns_client_error(client, result);
	}
}
示例#29
0
static isc_result_t
pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits,
                           dst_context_t *dctx) {
    CK_RV rv;
    CK_MECHANISM mech = { 0, NULL, 0 };
    CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
    CK_KEY_TYPE keyType = CKK_RSA;
    CK_ATTRIBUTE keyTemplate[] =
    {
        { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
        { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
        { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
        { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
        { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
        { CKA_MODULUS, NULL, 0 },
        { CKA_PUBLIC_EXPONENT, NULL, 0 },
    };
    CK_ATTRIBUTE *attr;
    pk11_object_t *rsa;
    pk11_context_t *pk11_ctx;
    isc_result_t ret;
    unsigned int i;

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

    rsa = key->keydata.pkey;

    pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
               sizeof(*pk11_ctx));
    if (pk11_ctx == NULL)
        return (ISC_R_NOMEMORY);
    ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
                           rsa->reqlogon, NULL,
                           pk11_get_best_token(OP_RSA));
    if (ret != ISC_R_SUCCESS)
        goto err;

    for (attr = pk11_attribute_first(rsa);
            attr != NULL;
            attr = pk11_attribute_next(rsa, attr))
        switch (attr->type) {
        case CKA_MODULUS:
            INSIST(keyTemplate[5].type == attr->type);
            keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
                                                attr->ulValueLen);
            if (keyTemplate[5].pValue == NULL)
                DST_RET(ISC_R_NOMEMORY);
            memmove(keyTemplate[5].pValue, attr->pValue,
                    attr->ulValueLen);
            keyTemplate[5].ulValueLen = attr->ulValueLen;
            break;
        case CKA_PUBLIC_EXPONENT:
            INSIST(keyTemplate[6].type == attr->type);
            keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
                                                attr->ulValueLen);
            if (keyTemplate[6].pValue == NULL)
                DST_RET(ISC_R_NOMEMORY);
            memmove(keyTemplate[6].pValue, attr->pValue,
                    attr->ulValueLen);
            keyTemplate[6].ulValueLen = attr->ulValueLen;
            if (pk11_numbits(attr->pValue,
                             attr->ulValueLen) > maxbits &&
                    maxbits != 0)
                DST_RET(DST_R_VERIFYFAILURE);
            break;
        }
    pk11_ctx->object = CK_INVALID_HANDLE;
    pk11_ctx->ontoken = ISC_FALSE;
    PK11_RET(pkcs_C_CreateObject,
             (pk11_ctx->session,
              keyTemplate, (CK_ULONG) 7,
              &pk11_ctx->object),
             ISC_R_FAILURE);

    switch (dctx->key->key_alg) {
    case DST_ALG_RSAMD5:
        mech.mechanism = CKM_MD5_RSA_PKCS;
        break;
    case DST_ALG_RSASHA1:
    case DST_ALG_NSEC3RSASHA1:
        mech.mechanism = CKM_SHA1_RSA_PKCS;
        break;
    case DST_ALG_RSASHA256:
        mech.mechanism = CKM_SHA256_RSA_PKCS;
        break;
    case DST_ALG_RSASHA512:
        mech.mechanism = CKM_SHA512_RSA_PKCS;
        break;
    default:
        INSIST(0);
    }

    PK11_RET(pkcs_C_VerifyInit,
             (pk11_ctx->session, &mech, pk11_ctx->object),
             ISC_R_FAILURE);

    dctx->ctxdata.pk11_ctx = pk11_ctx;

    for (i = 5; i <= 6; i++)
        if (keyTemplate[i].pValue != NULL) {
            memset(keyTemplate[i].pValue, 0,
                   keyTemplate[i].ulValueLen);
            isc_mem_put(dctx->mctx,
                        keyTemplate[i].pValue,
                        keyTemplate[i].ulValueLen);
        }

    return (ISC_R_SUCCESS);

err:
    if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
        (void) pkcs_C_DestroyObject(pk11_ctx->session,
                                    pk11_ctx->object);
    for (i = 5; i <= 6; i++)
        if (keyTemplate[i].pValue != NULL) {
            memset(keyTemplate[i].pValue, 0,
                   keyTemplate[i].ulValueLen);
            isc_mem_put(dctx->mctx,
                        keyTemplate[i].pValue,
                        keyTemplate[i].ulValueLen);
        }
    pk11_return_session(pk11_ctx);
    memset(pk11_ctx, 0, sizeof(*pk11_ctx));
    isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));

    return (ret);
}
示例#30
0
ns_sortlisttype_t
ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr, void **argp) {
	unsigned int i;

	if (acl == NULL)
		goto dont_sort;

	for (i = 0; i < acl->length; i++) {
		/*
		 * 'e' refers to the current 'top level statement'
		 * in the sortlist (see ARM).
		 */
		dns_aclelement_t *e = &acl->elements[i];
		dns_aclelement_t *try_elt;
		dns_aclelement_t *order_elt = NULL;
		dns_aclelement_t *matched_elt = NULL;

		if (e->type == dns_aclelementtype_nestedacl) {
			dns_acl_t *inner = e->u.nestedacl;

			if (inner->length < 1 || inner->length > 2)
				goto dont_sort;
			if (inner->elements[0].negative)
				goto dont_sort;
			try_elt = &inner->elements[0];
			if (inner->length == 2)
				order_elt = &inner->elements[1];
		} else {
			/*
			 * BIND 8 allows bare elements at the top level
			 * as an undocumented feature.
			 */
			try_elt = e;
		}

		if (dns_aclelement_match(clientaddr, NULL, try_elt,
					 &ns_g_server->aclenv,
					 &matched_elt)) {
			if (order_elt != NULL) {
				if (order_elt->type ==
				    dns_aclelementtype_nestedacl) {
					*argp = order_elt->u.nestedacl;
					return (NS_SORTLISTTYPE_2ELEMENT);
				} else if (order_elt->type ==
					   dns_aclelementtype_localhost &&
					   ns_g_server->aclenv.localhost != NULL) {
					*argp = ns_g_server->aclenv.localhost;
					return (NS_SORTLISTTYPE_2ELEMENT);
				} else if (order_elt->type ==
					   dns_aclelementtype_localnets &&
					   ns_g_server->aclenv.localnets != NULL) {
					*argp = ns_g_server->aclenv.localnets;
					return (NS_SORTLISTTYPE_2ELEMENT);
				} else {
					/*
					 * BIND 8 allows a bare IP prefix as
					 * the 2nd element of a 2-element
					 * sortlist statement.
					 */
					*argp = order_elt;
					return (NS_SORTLISTTYPE_1ELEMENT);
				}
			} else {
				INSIST(matched_elt != NULL);
				*argp = matched_elt;
				return (NS_SORTLISTTYPE_1ELEMENT);
			}
		}
	}

	/* No match; don't sort. */
 dont_sort:
	*argp = NULL;
	return (NS_SORTLISTTYPE_NONE);
}