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 错误。他们都在同一个电话上抛出。
- From the github vanara project and my discussion with the author
- 我目前找不到源的第二个 SO 实现。
它们都抛出相同的异常,所以这可能是 api 中的一个普遍问题。可能是因为名称中的元音变音 Ä
?
SO
的类似问题
听起来很相似,但这不是我面临的问题。
我在早期项目中的经验
我在 Windodws 7 / Server 2008 环境中使用 (2.) 年前的实现没有任何问题,但不幸的是我目前没有这样的系统来验证我最近的代码。
报告的类似问题
上找到了关于类似行为的帖子
我目前的解决方法是
ntAccountName = realSid.Translate(typeof(NTAccount)).ToString();
AdvApi32.LookupAccountName(systemName, ntAccountName, out foundSid, out domainName, out sidNameUse)
但是 sid.Translate(..) 在传递外国委托人时会抛出异常,我不知道它在其他情况下的可靠性如何。
问题
- 此 api 是否存在任何已知问题以及如何解决?
- 还有其他解决方法吗? (
LsaLookupSids
不能使用,因为没有 return SID_NAME_USE 标志)
我使用 Vanara libraries 和@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 包 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:
return LookupAccountSid2(lpSystemName, lpSid, out samAccountName, out domainName, out useFlags);
}
}
我在托管 C# 代码中使用 LookupAccountSid
的 pinvoke 实现多年。
在 German Windows Server 2016
上,它在解析 S-1-5-11
(经过身份验证的用户)时开始抛出 System.AccessViolationException
,其中德语名称为:“NT-Authorität\Authentifizierte Benutzer”。
我测试了 3 种不同的实现 来排除 pinvoke 错误。他们都在同一个电话上抛出。
- From the github vanara project and my discussion with the author
- 我目前找不到源的第二个 SO 实现。
它们都抛出相同的异常,所以这可能是 api 中的一个普遍问题。可能是因为名称中的元音变音 Ä
?
SO
的类似问题我在早期项目中的经验
我在 Windodws 7 / Server 2008 环境中使用 (2.) 年前的实现没有任何问题,但不幸的是我目前没有这样的系统来验证我最近的代码。
报告的类似问题
上找到了关于类似行为的帖子我目前的解决方法是
ntAccountName = realSid.Translate(typeof(NTAccount)).ToString();
AdvApi32.LookupAccountName(systemName, ntAccountName, out foundSid, out domainName, out sidNameUse)
但是 sid.Translate(..) 在传递外国委托人时会抛出异常,我不知道它在其他情况下的可靠性如何。
问题
- 此 api 是否存在任何已知问题以及如何解决?
- 还有其他解决方法吗? (
LsaLookupSids
不能使用,因为没有 return SID_NAME_USE 标志)
我使用 Vanara libraries 和@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
指针的人,这里是 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:
return LookupAccountSid2(lpSystemName, lpSid, out samAccountName, out domainName, out useFlags);
}
}