问题
In this block of code in Cassini-dev's NTLM authentication class, calls made to SECUR32.DLL (via Interop) are made to authenticate the base64 encoded data in an HTTP request's Authorization
headers. This makes sense, when both AcceptSecurityContext() and QuerySecurityContextToken() return 0
, the client has been authorized. At the end, the security context token has a SecurityIdentifier
extracted from it (the _sid variable). (A bit about common Security IDs )
Here is the relevant section of the NtlmAuth Class
int num = Interop.AcceptSecurityContext(ref _credentialsHandle, zero,
ref _inputBufferDesc, 20,
0, ref _securityContext, ref _outputBufferDesc,
ref _securityContextAttributes, ref _timestamp);
if (num == 0x90312)
{
securityContextAcquired = true;
_blob = Convert.ToBase64String(inArray, 0, (int) _outputBuffer.cbBuffer);
}
else
{
if (num != 0)
{
return false;
}
IntPtr phToken = IntPtr.Zero;
if (Interop.QuerySecurityContextToken(ref _securityContext, ref phToken) != 0)
{
return false;
}
try
{
using (WindowsIdentity identity = new WindowsIdentity(phToken))
{
_sid = identity.User;
}
}
finally
{
Interop.CloseHandle(phToken);
}
_completed = true;
In the Request Class, in the TryNtlmAuthenticate()
method where NtlmAuth is being used, after successfully completing the 3 steps of the NTLM authentication, before returning either a final 403 or fulfilling the request, one final check is being made:
if (_host.GetProcessSid() != auth.SID)
{
_connection.WriteErrorAndClose(0x193);
return false;
}
Here, the _host.GetProcessSid() is the SecurityIndentifier
of the owner of the Cassini process (me) and auth.SID is the SecurityIdentifier
of the user that was authenticated (_sid from the NtlmAuth class above). If these 2 SID's are not the same, a 403 is returned and authentication stops, otherwise the request is served to the browser.
My questions are:
- Why would you need to compare the SecurityIndentifiers of 2 different users? This fails (returns a 403) when I attempt to NTLM authenticate with a user/password that isn't the user that owns the Cassini process.
- If this really is the intended behavior, if Cassini is to run as a Windows service, nobody would be able to log in because the host SID would be S-1-5-18 (or maybe something similar depending on the OS version) and nobody can log in as the operating system. Is this just part of Cassini's NTLM authentication implementation and I'm not using Cassini correctly?
- If this is clearly not the intended behavior, what role does SecurityIndentifiers play in this context? Does extra checks need to be made to ensure host SID's need to be of a certain class or group in order to accept client SID's of certain class/group? Are there OS version (XP/Vista/7) implications when dealing with host/client SID's?
- Or are there no applicable uses of SecurityIdentifiers here since they are not being stored nor passed around, nor are they being used to further identify the user/client?
Update: It seems that someone at the cassinidev forums proposed a patch which removes this SID check (patch #6604) back in 2010 but it's still being evaluated.
回答1:
Not an answer, but I'm just noticing a similar problem, but a slightly different manifestation: when hosted in a windows service and Cassini-dev is configured to use Windows authentication, the HttpContext.Current.User is the account the service is running under, not the user who made the request.
This seems like a bug in cassini-dev to me.
来源:https://stackoverflow.com/questions/8241320/securityidentifiers-in-cassini-devs-ntlm-authentication