繁体   English   中英

LookupAccountSid() 在 Server 2016 上引发 System.AccessViolationException

[英]LookupAccountSid() throws System.AccessViolationException on Server 2016

几年来,我在托管的 C# 代码中使用了LookupAccountSid的 pinvoke 实现。

German Windows Server 2016上,它在解析S-1-5-11 (经过身份验证的用户)时开始抛出System.AccessViolationException ,其中德国名称为:“NT-Authorität\Authentifizierte Benutzer”。

我测试了 3 种不同的实现以排除 pinvoke 错误。 他们都在同一个电话中抛出。

  1. 来自 github vanara 项目和我与作者的讨论
  2. 第一个 SO 实现
  3. 我目前找不到源的第二个 SO 实现。

它们都抛出相同的异常,因此这可能是 api 中的一般问题。 可能是因为名称中的变音符号Ä

SO的类似问题

这个问题听起来很相似,但这不是我面临的问题。

我在早期项目中的经验

我在(2.)年前在 Windodws 7 / Server 2008 环境中使用了实现,没有任何问题,但不幸的是我目前没有这样的系统来验证我最近的代码。

类似报告的问题

我发现这个线程关于法语系统上的类似行为

我目前的解决方法是

ntAccountName = realSid.Translate(typeof(NTAccount)).ToString();
AdvApi32.LookupAccountName(systemName, ntAccountName, out foundSid, out domainName, out sidNameUse)

但是 sid.Translate(..) 在传递外国委托人时抛出,我不知道在其他情况下它有多可靠。

问题

  • 这个 api 是否有任何已知问题以及如何解决?
  • 还有其他解决方法吗? (不能使用LsaLookupSids ,因为它不返回 SID_NAME_USE 标志)

我使用Vanara 库和 @RbMm 的注释编写了以下内容,以使用LsaLookupSids来模仿LookupAccountSid功能。

private static NTStatus LookupAccountSid2([Optional] string lpSystemName, PSID lpSid, out string lpName,
   out string lpReferencedDomainName, out SID_NAME_USE peUse)
{
   lpName = lpReferencedDomainName = null;
   peUse = default;
   using var pol = LsaOpenPolicy(LsaPolicyRights.POLICY_LOOKUP_NAMES, lpSystemName);
   var ret = LsaLookupSids2(pol, LsaLookupSidsFlags.LSA_LOOKUP_RETURN_LOCAL_NAMES, 1, new[] { lpSid }, out var refDom, out var names);
   if (ret.Failed) return ret;
   using (refDom)
   using (names)
   {
      lpReferencedDomainName = refDom.ToStructure<LSA_REFERENCED_DOMAIN_LIST>().DomainList.First().Name;
      var name = names.ToArray<LSA_TRANSLATED_NAME>(1)[0];
      lpName = name.Name;
      peUse = name.Use;
   }
   return ret;
}

对于那些不熟悉 vanara 库以及如何将SecurityIdentifier转换为PSID指针的人,这里是已接受答案的包装器。 要使用该库,只需获取 nuget package Vanara.AdvApi32

using Vanara.PInvoke;

public static bool LookupAccountSid2(string lpSystemName, SecurityIdentifier sid, out string samAccountName,
       out string domainName, out AdvApi32.SID_NAME_USE useFlags)
{
    using (AdvApi32.SafePSID safePSID = new AdvApi32.SafePSID(sid))
    {
        PSID lpSid = new PSID(safePSID);

        /// call the actual implementation from: https://stackoverflow.com/a/65202841/1574221
        return LookupAccountSid2(lpSystemName, lpSid, out samAccountName, out domainName, out useFlags);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM