0, NULL, gintokenp,
NULL, &gouttoken, &ret_flags, NULL);
- if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) {
+ switch (gret) {
+ case GSS_S_COMPLETE:
+ result = ISC_R_SUCCESS;
+ break;
+ case GSS_S_CONTINUE_NEEDED:
+ result = DNS_R_CONTINUE;
+ break;
+ default:
gss_err_message(mctx, gret, minor, err_message);
if (err_message != NULL && *err_message != NULL)
gss_log(3, "Failure initiating security context: %s",
RETERR(isc_buffer_copyregion(outtoken, &r));
}
- if (gret == GSS_S_COMPLETE)
- result = ISC_R_SUCCESS;
- else
- result = DNS_R_CONTINUE;
-
- out:
- if (gouttoken.length != 0U)
+out:
+ if (gouttoken.length != 0U) {
(void)gss_release_buffer(&minor, &gouttoken);
+ }
(void)gss_release_name(&minor, &gname);
return (result);
}
char buf[1024];
REQUIRE(outtoken != NULL && *outtoken == NULL);
+ REQUIRE(*ctxout == NULL);
REGION_TO_GBUFFER(*intoken, gintoken);
- if (*ctxout == NULL)
- context = GSS_C_NO_CONTEXT;
- else
- context = *ctxout;
-
if (gssapi_keytab != NULL) {
#if defined(ISC_PLATFORM_GSSAPI_KRB5_HEADER) || defined(WIN32)
gret = gsskrb5_register_acceptor_identity(gssapi_keytab);
switch (gret) {
case GSS_S_COMPLETE:
- case GSS_S_CONTINUE_NEEDED:
break;
+ /*
+ * RFC 3645 4.1.3: we don't handle GSS_S_CONTINUE_NEEDED
+ * Multi-round GSS-API negotiation is not supported.
+ */
+ case GSS_S_CONTINUE_NEEDED:
+ gss_log(3, "multi-round GSS-API negotiation not supported");
+ (void)gss_delete_sec_context(&minor, &context, NULL);
+ /* FALLTHROUGH */
case GSS_S_DEFECTIVE_TOKEN:
case GSS_S_DEFECTIVE_CREDENTIAL:
case GSS_S_BAD_SIG:
case GSS_S_BAD_MECH:
case GSS_S_FAILURE:
result = DNS_R_INVALIDTKEY;
- /* fall through */
+ /* FALLTHROUGH */
default:
gss_log(3, "failed gss_accept_sec_context: %s",
gss_error_tostring(gret, minor, buf, sizeof(buf)));
(void)gss_release_buffer(&minor, &gouttoken);
}
- if (gret == GSS_S_COMPLETE) {
- gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
- if (gret != GSS_S_COMPLETE) {
- gss_log(3, "failed gss_display_name: %s",
- gss_error_tostring(gret, minor,
- buf, sizeof(buf)));
- RETERR(ISC_R_FAILURE);
- }
+ INSIST(gret == GSS_S_COMPLETE);
- /*
- * Compensate for a bug in Solaris8's implementation
- * of gss_display_name(). Should be harmless in any
- * case, since principal names really should not
- * contain null characters.
- */
- if (gnamebuf.length > 0U &&
- ((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
- gnamebuf.length--;
+ gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed gss_display_name: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ result = ISC_R_FAILURE;
+ goto out;
+ }
- gss_log(3, "gss-api source name (accept) is %.*s",
- (int)gnamebuf.length, (char *)gnamebuf.value);
+ /*
+ * Compensate for a bug in Solaris8's implementation
+ * of gss_display_name(). Should be harmless in any
+ * case, since principal names really should not
+ * contain null characters.
+ */
+ if (gnamebuf.length > 0U &&
+ ((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
+ {
+ gnamebuf.length--;
+ }
- GBUFFER_TO_REGION(gnamebuf, r);
- isc_buffer_init(&namebuf, r.base, r.length);
- isc_buffer_add(&namebuf, r.length);
+ gss_log(3, "gss-api source name (accept) is %.*s", (int)gnamebuf.length,
+ (char *)gnamebuf.value);
- RETERR(dns_name_fromtext(principal, &namebuf, dns_rootname,
- 0, NULL));
+ GBUFFER_TO_REGION(gnamebuf, r);
+ isc_buffer_init(&namebuf, r.base, r.length);
+ isc_buffer_add(&namebuf, r.length);
- if (gnamebuf.length != 0U) {
- gret = gss_release_buffer(&minor, &gnamebuf);
- if (gret != GSS_S_COMPLETE)
- gss_log(3, "failed gss_release_buffer: %s",
- gss_error_tostring(gret, minor, buf,
- sizeof(buf)));
- }
- } else
- result = DNS_R_CONTINUE;
+ result = dns_name_fromtext(principal, &namebuf, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ goto out;
+ }
*ctxout = context;
- out:
+out:
+ if (result != ISC_R_SUCCESS && context != GSS_C_NO_CONTEXT) {
+ (void)gss_delete_sec_context(&minor, &context, NULL);
+ }
+
+ if (gnamebuf.length != 0U) {
+ gret = gss_release_buffer(&minor, &gnamebuf);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed gss_release_buffer: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ }
+ }
+
if (gname != NULL) {
gret = gss_release_name(&minor, &gname);
if (gret != GSS_S_COMPLETE)
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);
-
principal = dns_fixedname_initname(&fixed);
/*
result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab,
&intoken, &outtoken, &gss_ctx,
principal, tctx->mctx);
- if (result == DNS_R_INVALIDTKEY) {
+ if (result != ISC_R_SUCCESS) {
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.
+ * Multi-round GSS-API negotiation (GSS_S_CONTINUE_NEEDED) is
+ * rejected in dst_gssapi_acceptctx(), so if we reach here the
+ * negotiation is complete and the principal must be set.
*/
isc_stdtime_get(&now);
return (ISC_R_SUCCESS);
failure:
+ if (dstkey == NULL && gss_ctx != NULL) {
+ dst_gssapi_deletectx(tctx->mctx, &gss_ctx);
+ }
+
if (tsigkey != NULL)
dns_tsigkey_detach(&tsigkey);
&dstkey, NULL));
/*
- * XXXSRA This seems confused. If we got CONTINUE from initctx,
- * the GSS negotiation hasn't completed yet, so we can't sign
- * anything yet.
+ * GSS negotiation is complete (CONTINUE returned earlier).
+ * Create the TSIG key from the established context.
*/
RETERR(dns_tsigkey_createfromkey(tkeyname,