GSS_SPNEGO_MECHANISM, flags, 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",
CHECK(isc_buffer_copyregion(outtoken, &r));
}
- if (gret == GSS_S_COMPLETE) {
- result = ISC_R_SUCCESS;
- } else {
- result = DNS_R_CONTINUE;
- }
-
cleanup:
if (gouttoken.length != 0U) {
(void)gss_release_buffer(&minor, &gouttoken);
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 HAVE_GSSAPI_GSSAPI_KRB5_H || HAVE_GSSAPI_KRB5_H
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)));
- CLEANUP(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)));
+ CLEANUP(ISC_R_FAILURE);
+ }
- 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);
- CHECK(dns_name_fromtext(principal, &namebuf, dns_rootname, 0));
- } else {
- result = DNS_R_CONTINUE;
- }
+ GBUFFER_TO_REGION(gnamebuf, r);
+ isc_buffer_init(&namebuf, r.base, r.length);
+ isc_buffer_add(&namebuf, r.length);
+
+ CHECK(dns_name_fromtext(principal, &namebuf, dns_rootname, 0));
*ctxout = context;
cleanup:
+ 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) {
intoken = (isc_region_t){ tkeyin->key, tkeyin->keylen };
result = dst_gssapi_acceptctx(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);
}
tkey_log("process_gsstkey(): dns_tsigerror_badkey");
return ISC_R_SUCCESS;
}
- if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) {
- CHECK(result);
- }
/*
- * 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.
*/
if (dns_name_countlabels(principal) == 0U) {
if (tsigkey != NULL) {
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.
*/
CHECK(dns_tsigkey_createfromkey(tkeyname, DST_ALG_GSSAPI, dstkey, true,
false, NULL, rtkey.inception,