Пример #1
0
static isc_result_t
process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
		dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout,
		dns_tsig_keyring_t *ring)
{
	isc_result_t result = ISC_R_SUCCESS;
	dst_key_t *dstkey = NULL;
	dns_tsigkey_t *tsigkey = NULL;
	dns_fixedname_t principal;
	isc_stdtime_t now;
	isc_region_t intoken;
	isc_buffer_t *outtoken = NULL;
	gss_ctx_id_t gss_ctx = NULL;

	/*
	 * You have to define either a gss credential (principal) to
	 * accept with tkey-gssapi-credential, or you have to
	 * configure a specific keytab (with tkey-gssapi-keytab) in
	 * order to use gsstkey
	 */
	if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) {
		tkey_log("process_gsstkey(): no tkey-gssapi-credential "
			 "or tkey-gssapi-keytab configured");
		return (ISC_R_NOPERM);
	}

	if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) &&
	    !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		tkeyout->error = dns_tsigerror_badalg;
		tkey_log("process_gsstkey(): dns_tsigerror_badalg");	/* XXXSRA */
		return (ISC_R_SUCCESS);
	}

	/*
	 * XXXDCL need to check for key expiry per 4.1.1
	 * XXXDCL need a way to check fully established, perhaps w/key_flags
	 */

	intoken.base = tkeyin->key;
	intoken.length = tkeyin->keylen;

	result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
	if (result == ISC_R_SUCCESS)
		gss_ctx = dst_key_getgssctx(tsigkey->key);

	dns_fixedname_init(&principal);

	/*
	 * Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set
	 */
	result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab,
				      &intoken,
				      &outtoken, &gss_ctx,
				      dns_fixedname_name(&principal),
				      tctx->mctx);
	if (result == DNS_R_INVALIDTKEY) {
		if (tsigkey != NULL)
			dns_tsigkey_detach(&tsigkey);
		tkeyout->error = dns_tsigerror_badkey;
		tkey_log("process_gsstkey(): dns_tsigerror_badkey");    /* XXXSRA */
		return (ISC_R_SUCCESS);
	}
	if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
		goto failure;
	/*
	 * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
	 */

	isc_stdtime_get(&now);

	if (tsigkey == NULL) {
#ifdef GSSAPI
		OM_uint32 gret, minor, lifetime;
#endif
		isc_uint32_t expire;

		RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx,
					  &dstkey, &intoken));
		/*
		 * Limit keys to 1 hour or the context's lifetime whichever
		 * is smaller.
		 */
		expire = now + 3600;
#ifdef GSSAPI
		gret = gss_context_time(&minor, gss_ctx, &lifetime);
		if (gret == GSS_S_COMPLETE && now + lifetime < expire)
			expire = now + lifetime;
#endif
		RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
						 dstkey, ISC_TRUE,
						 dns_fixedname_name(&principal),
						 now, expire, ring->mctx, ring,
						 NULL));
		dst_key_free(&dstkey);
		tkeyout->inception = now;
		tkeyout->expire = expire;
	} else {
		tkeyout->inception = tsigkey->inception;
		tkeyout->expire = tsigkey->expire;
		dns_tsigkey_detach(&tsigkey);
	}

	if (outtoken) {
		tkeyout->key = isc_mem_get(tkeyout->mctx,
					   isc_buffer_usedlength(outtoken));
		if (tkeyout->key == NULL) {
			result = ISC_R_NOMEMORY;
			goto failure;
		}
		tkeyout->keylen = isc_buffer_usedlength(outtoken);
		memmove(tkeyout->key, isc_buffer_base(outtoken),
		       isc_buffer_usedlength(outtoken));
		isc_buffer_free(&outtoken);
	} else {
		tkeyout->key = isc_mem_get(tkeyout->mctx, tkeyin->keylen);
		if (tkeyout->key == NULL) {
			result = ISC_R_NOMEMORY;
			goto failure;
		}
		tkeyout->keylen = tkeyin->keylen;
		memmove(tkeyout->key, tkeyin->key, tkeyin->keylen);
	}

	tkeyout->error = dns_rcode_noerror;

	tkey_log("process_gsstkey(): dns_tsigerror_noerror");   /* XXXSRA */

	return (ISC_R_SUCCESS);

failure:
	if (tsigkey != NULL)
		dns_tsigkey_detach(&tsigkey);

	if (dstkey != NULL)
		dst_key_free(&dstkey);

	if (outtoken != NULL)
		isc_buffer_free(&outtoken);

	tkey_log("process_gsstkey(): %s",
		isc_result_totext(result));	/* XXXSRA */

	return (result);
}
Пример #2
0
static isc_result_t
process_gsstkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
		dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx,
		dns_rdata_tkey_t *tkeyout,
		dns_tsig_keyring_t *ring, dns_namelist_t *namelist)
{
	isc_result_t result = ISC_R_SUCCESS;
	dst_key_t *dstkey = NULL;
	void *gssctx = NULL;
	isc_stdtime_t now;
	isc_region_t intoken;
	unsigned char array[1024];
	isc_buffer_t outtoken;

	UNUSED(namelist);

	if (tctx->gsscred == NULL)
		return (ISC_R_NOPERM);

	if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) &&
	    !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		tkeyout->error = dns_tsigerror_badalg;
		return (ISC_R_SUCCESS);
	}

	intoken.base = tkeyin->key;
	intoken.length = tkeyin->keylen;

	isc_buffer_init(&outtoken, array, sizeof(array));
	RETERR(dst_gssapi_acceptctx(name, tctx->gsscred, &intoken,
				    &outtoken, &gssctx));

	dstkey = NULL;
	RETERR(dst_key_fromgssapi(name, gssctx, msg->mctx, &dstkey));

	result = dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
					   dstkey, ISC_TRUE, signer,
					   tkeyin->inception, tkeyin->expire,
					   msg->mctx, ring, NULL);
#if 1
	if (result != ISC_R_SUCCESS)
		goto failure;
#else
	if (result == ISC_R_NOTFOUND) {
		tkeyout->error = dns_tsigerror_badalg;
		return (ISC_R_SUCCESS);
	}
	if (result != ISC_R_SUCCESS)
		goto failure;
#endif

	/* This key is good for a long time */
	isc_stdtime_get(&now);
	tkeyout->inception = tkeyin->inception;
	tkeyout->expire = tkeyin->expire;

	tkeyout->key = isc_mem_get(msg->mctx,
				   isc_buffer_usedlength(&outtoken));
	if (tkeyout->key == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}
	tkeyout->keylen = isc_buffer_usedlength(&outtoken);
	memcpy(tkeyout->key, isc_buffer_base(&outtoken), tkeyout->keylen);

	return (ISC_R_SUCCESS);

 failure:
	if (dstkey != NULL)
		dst_key_free(&dstkey);

	return (result);
}