在Cassini-dev的NTLM身份验证类中的此代码块中,对SECUR32.DLL(通过Interop)进行了调用,以对HTTP请求的Authorization标头中的base64编码数据进行身份验证。这很有道理,当AcceptSecurityContext()和QuerySecurityContextToken()都返回0时,客户端已被授权。最后,从安全上下文令牌中提取了一个SecurityIdentifier(_sid变量)。 (有关common Security IDs的一些知识)

这是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;


Request Class中,在使用NtlmAuth的TryNtlmAuthenticate()方法中,成功完成NTLM身份验证的3个步骤之后,在返回最终的403或满足请求之前,将进行一次最终检查:

if (_host.GetProcessSid() != auth.SID)
{
    _connection.WriteErrorAndClose(0x193);
    return false;
}


在这里,_host.GetProcessSid()是Cassini进程(me)的所有者的SecurityIndentifier,而auth.SID是已通过身份验证的用户的cc(上述NtlmAuth类的_sid)。如果这两个SID不相同,则返回403并停止身份验证,否则将请求提供给浏览器。



我的问题是:


为什么需要比较2个不同用户的SecurityIndentifiers?当我尝试使用不是拥有Cassini进程用户的用户/密码进行NTLM身份验证时,此操作将失败(返回403)。
如果这确实是预期的行为,并且如果Cassini将作为Windows服务运行,则由于主机SID为S-1-5-18(或可能类似,具体取决于操作系统版本)而无法登录。没有人可以登录为操作系统。这仅仅是Cassini NTLM身份验证实现的一部分,而我没有正确使用Cassini吗?
如果这显然不是预期的行为,那么SecurityIndentifiers在此上下文中扮演什么角色?是否需要进行额外的检查以确保主机SID必须属于某个类别或组,才能接受特定类别/组的客户端SID?处理主机/客户端SID时是否有OS版本(XP / Vista / 7)?
还是在这里没有安全标识符的适用用途,因为它们没有被存储或传递,也没有被用来进一步识别用户/客户端?




更新:似乎在2010年的cassinidev论坛proposed a patch which removes this SID check(补丁#6604)有人,但是它仍在评估中。

最佳答案

这不是一个答案,但我只是注意到一个类似的问题,只是一个略有不同的表现形式:当托管在Windows服务中并且Cassini-dev配置为使用Windows身份验证时,HttpContext.Current.User是服务正在运行的帐户在下面,而不是发出请求的用户。

在我看来,这似乎是卡西尼开发版中的错误。

关于c# - Cassini-dev的NTLM身份验证中的SecurityIdentifiers,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8241320/

10-12 17:35