[Auth] Only set GSS_C_DELEG_FLAG flag when we confirm server supports delegation.

This commit is contained in:
Moonchild 2026-01-14 21:50:24 +01:00 • committed by OwnedByWuigi
commit 20dcff60d6
2 changed files with 44 additions and 6 deletions

View file

@ -288,8 +288,6 @@ nsAuthGSSAPI::nsAuthGSSAPI(pType package)
LOG(("entering nsAuthGSSAPI::nsAuthGSSAPI()\n")); LOG(("entering nsAuthGSSAPI::nsAuthGSSAPI()\n"));
mComplete = false;
if (!gssLibrary && NS_FAILED(gssInit())) if (!gssLibrary && NS_FAILED(gssInit()))
return; return;
@ -340,6 +338,8 @@ nsAuthGSSAPI::Reset()
} }
mCtx = GSS_C_NO_CONTEXT; mCtx = GSS_C_NO_CONTEXT;
mComplete = false; mComplete = false;
mDelegationRequested = false;
mDelegationSupported = false;
} }
/* static */ void /* static */ void
@ -386,6 +386,7 @@ nsAuthGSSAPI::GetNextToken(const void *inToken,
{ {
OM_uint32 major_status, minor_status; OM_uint32 major_status, minor_status;
OM_uint32 req_flags = 0; OM_uint32 req_flags = 0;
OM_uint32 ret_flags = 0;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
gss_buffer_t in_token_ptr = GSS_C_NO_BUFFER; gss_buffer_t in_token_ptr = GSS_C_NO_BUFFER;
@ -402,8 +403,22 @@ nsAuthGSSAPI::GetNextToken(const void *inToken,
if (mComplete) if (mComplete)
Reset(); Reset();
if (mServiceFlags & REQ_DELEGATE) // Two-phase delegation logic
// Phase 1: Try authentication without delegation first
// Phase 2: Only retry with delegation if server supports it (ret_flags)
bool delegationConfigured = (mServiceFlags & REQ_DELEGATE) != 0;
if (delegationConfigured) {
if (!mDelegationRequested) {
// First attempt: don't request delegation yet
LOG(("First auth attempt without delegation"));
mDelegationRequested = true;
} else if (mDelegationSupported) {
// Second attempt: server supports delegation, now request it
LOG(("Retrying auth with delegation - server supports it"));
req_flags |= GSS_C_DELEG_FLAG; req_flags |= GSS_C_DELEG_FLAG;
}
}
if (mServiceFlags & REQ_MUTUAL_AUTH) if (mServiceFlags & REQ_MUTUAL_AUTH)
req_flags |= GSS_C_MUTUAL_FLAG; req_flags |= GSS_C_MUTUAL_FLAG;
@ -469,7 +484,7 @@ nsAuthGSSAPI::GetNextToken(const void *inToken,
in_token_ptr, in_token_ptr,
nullptr, nullptr,
&output_token, &output_token,
nullptr, &ret_flags,
nullptr); nullptr);
if (GSS_ERROR(major_status)) { if (GSS_ERROR(major_status)) {
@ -478,6 +493,27 @@ nsAuthGSSAPI::GetNextToken(const void *inToken,
rv = NS_ERROR_FAILURE; rv = NS_ERROR_FAILURE;
goto end; goto end;
} }
// Check if server supports delegation (OK-AS-DELEGATE equivalent)
if (delegationConfigured && !mDelegationSupported &&
(ret_flags & GSS_C_DELEG_FLAG)) {
LOG(("Server supports delegation (GSS_C_DELEG_FLAG in ret_flags)"));
// If we completed without requesting delegation, but server supports it,
// we need to restart with delegation
if (major_status == GSS_S_COMPLETE && !(req_flags & GSS_C_DELEG_FLAG)) {
LOG(("Restarting authentication to request delegation"));
Reset();
// These flags get cleared by Reset().
// Set them again to make sure the next call sets GSS_C_DELEG_FLAG
mDelegationRequested = true;
mDelegationSupported = true;
gss_release_name_ptr(&minor_status, &server);
return GetNextToken(inToken, inTokenLen, outToken, outTokenLen);
}
}
if (major_status == GSS_S_COMPLETE) { if (major_status == GSS_S_COMPLETE) {
// Mark ourselves as being complete, so that if we're called again // Mark ourselves as being complete, so that if we're called again
// we know to start afresh. // we know to start afresh.

View file

@ -54,9 +54,11 @@ private:
gss_ctx_id_t mCtx; gss_ctx_id_t mCtx;
gss_OID mMechOID; gss_OID mMechOID;
nsCString mServiceName; nsCString mServiceName;
uint32_t mServiceFlags; uint32_t mServiceFlags = REQ_DEFAULT;
nsString mUsername; nsString mUsername;
bool mComplete; bool mComplete = false;
bool mDelegationRequested = false;
bool mDelegationSupported = false;
}; };
#endif /* nsAuthGSSAPI_h__ */ #endif /* nsAuthGSSAPI_h__ */