Closed valorl closed 5 years ago
That exception occurs when the server has not yet seen an AcceptToken
call that results in a status of SecurityStatus.OK
and you try to perform some action that requires a fully initialized context. That means that the authentication cycle is not complete. Check the return value from AcceptToken
, and do not use the context before it returns SecurityStatus.OK
.
This snippit from Context.cs
shows how the exception occurs when init isn't done:
public string ContextUserName
{
get
{
CheckLifecycle(); // <------------------
return QueryContextString( ContextQueryAttrib.Names );
}
}
protected void Initialize( DateTime expiry )
{
this.Expiry = expiry;
this.Initialized = true; // <------------------
}
private void CheckLifecycle()
{
if( this.Initialized == false ) // <------------------
{
throw new InvalidOperationException( "The context is not yet fully formed." );
}
else if( this.Disposed )
{
throw new ObjectDisposedException( "Context" );
}
}
This snippit from ServerContext.cs
shows when init is called, which would disable the exception:
public SecurityStatus AcceptToken( byte[] clientToken, out byte[] nextToken )
{
...
if( this.ContextHandle.IsInvalid )
{
status = ContextNativeMethods.AcceptSecurityContext_1( ... );
}
else
{
status = ContextNativeMethods.AcceptSecurityContext_2( ... );
}
}
}
if( status == SecurityStatus.OK )
{
nextToken = null;
base.Initialize( rawExpiry.ToDateTime() ); // <-------------
...
I am accepting Kerberos tokens only, in which case AcceptToken
results in SecurityStatus.OK
on the first call. This is why I expected to not see this exception, but I figured out there were some unusual clients triggering this by sending NTLM tokens.
Thanks for the help :)
From time to time, I can see
The context is not yet fully formed.
exceptions being thrown when trying to accessServerContext.ContextUserName
property.The property is being accessed (for logging purposes) immediately after
AcceptToken
is called and successful.Interestingly, the next thing after that logging call is an
ImpersonateClient()
call which always works.Is there any hidden race condition/concurrency I'm perhaps not aware of here?
Here's an illustration of what my code is doing: