确定用户是否属于本地管理员组
我的问题
我正在使用 PInvoked Windows API 函数来验证用户是否属于本地管理员组。我正在利用 GetCurrentProcess
、OpenProcessToken
、GetTokenInformation
和 LookupAccountSid
来验证用户是否是本地管理员。
GetTokenInformation
返回一个 TOKEN_GROUPS
结构,其中包含 SID_AND_ATTRIBUTES
结构数组。我迭代该集合并比较由 LookupAccountSid
返回的用户名。
我的问题是,在本地(或更普遍地在我们的内部域上),这按预期工作。 builtin\Administrators 位于当前进程令牌的组成员身份内,我的方法返回 true。在另一个开发人员的另一个域上,该函数返回 false。
LookupAccountSid
在 TOKEN_GROUPS
结构的前 2 次迭代中正常运行,返回 None 和Everyone,然后抱怨“参数不正确”。
什么会导致只有两个组正常工作?
TOKEN_GROUPS
结构表明有 14 个组。我假设 SID 无效。
我 PInvoked 的所有内容均取自 PInvoke 网站 上的示例。唯一的区别是,使用 LookupAccountSid 时,我已将 Sid
参数从 byte[]
更改为 IntPtr
因为 SID_AND_ATTRIBUTES
也是用 IntPtr
定义的。由于 LookupAccountSid
是使用 PSID 定义的,这样可以吗?
LookupAccountSid PInvoke
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool LookupAccountSid(
string lpSystemName,
IntPtr Sid,
StringBuilder lpName,
ref uint cchName,
StringBuilder ReferencedDomainName,
ref uint cchReferencedDomainName,
out SID_NAME_USE peUse);
代码失败的位置
for (int i = 0; i < usize; i++)
{
accountCount = 0;
domainCount = 0;
//Get Sizes
LookupAccountSid(null, tokenGroups.Groups[i].SID, null, ref accountCount, null,
ref domainCount, out snu);
accountName2.EnsureCapacity((int) accountCount);
domainName.EnsureCapacity((int) domainCount);
if (!LookupAccountSid(null, tokenGroups.Groups[i].SID, accountName2, ref accountCount, domainName,
ref domainCount, out snu))
{
//Finds its way here after 2 iterations
//But only in a different developers domain
var error = Marshal.GetLastWin32Error();
_log.InfoFormat("Failed to look up SID's account name. {0}", new Win32Exception(error).Message);
continue;
}
如果需要更多代码,请告诉我。任何帮助将不胜感激。
My Problem
I'm using PInvoked Windows API functions to verify if a user is part of the local administrators group. I'm utilizing GetCurrentProcess
, OpenProcessToken
, GetTokenInformation
and LookupAccountSid
to verify if the user is a local admin.
GetTokenInformation
returns a TOKEN_GROUPS
struct with an array of SID_AND_ATTRIBUTES
structs. I iterate over the collection and compare the user names returned by LookupAccountSid
.
My problem is that, locally (or more generally on our in-house domain), this works as expected. The builtin\Administrators is located within the group membership of the current process token and my method returns true. On another domain of another developer the function returns false.
The LookupAccountSid
functions properly for the first 2 iterations of the TOKEN_GROUPS
struct, returning None and Everyone, and then craps out complaining that "A Parameter is incorrect."
What would cause only two groups to work correctly?
The TOKEN_GROUPS
struct indicates that there are 14 groups. I'm assuming it's the SID that is invalid.
Everything that I have PInvoked I have taken from an example on the PInvoke website. The only difference is that with the LookupAccountSid
I have changed the Sid
parameter from a byte[]
to a IntPtr
because SID_AND_ATTRIBUTES
is also defined with an IntPtr
. Is this ok since LookupAccountSid
is defined with a PSID?
LookupAccountSid PInvoke
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool LookupAccountSid(
string lpSystemName,
IntPtr Sid,
StringBuilder lpName,
ref uint cchName,
StringBuilder ReferencedDomainName,
ref uint cchReferencedDomainName,
out SID_NAME_USE peUse);
Where the code falls over
for (int i = 0; i < usize; i++)
{
accountCount = 0;
domainCount = 0;
//Get Sizes
LookupAccountSid(null, tokenGroups.Groups[i].SID, null, ref accountCount, null,
ref domainCount, out snu);
accountName2.EnsureCapacity((int) accountCount);
domainName.EnsureCapacity((int) domainCount);
if (!LookupAccountSid(null, tokenGroups.Groups[i].SID, accountName2, ref accountCount, domainName,
ref domainCount, out snu))
{
//Finds its way here after 2 iterations
//But only in a different developers domain
var error = Marshal.GetLastWin32Error();
_log.InfoFormat("Failed to look up SID's account name. {0}", new Win32Exception(error).Message);
continue;
}
If more code is needed let me know. Any help would be greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
听起来您正在尝试复制 的功能
NetUserGetLocalGroups
。您还可以使用NetUserGetInfo
信息级别为 1,并检查USER_INFO_1
用于USER_PRIV_ADMIN
。It sounds like you're trying to duplicate the functionality of
NetUserGetLocalGroups
. You can also useNetUserGetInfo
with an information level of 1, and check the value ofusri1_priv
in theUSER_INFO_1
forUSER_PRIV_ADMIN
.我不确定 NetUserGetLocalGroups 是否知道拒绝 SID(如果您需要验证当前进程(不是用户帐户!)是否在管理组中,则必须处理拒绝 SID)
如果您只需要支持 2000 及更高版本, PInvoke CheckTokenMembership (该 MSDN 页面有一个IsUserAdmin 示例函数)
在 NT4 上,您需要从 GetTokenInformation 获取 TokenGroups 数组,但您不调用 LookupAccountSid,您只需对每个项目调用 EqualSid 并将其与使用 AllocateAndInitializeSid(...,SECURITY_BUILTIN_DOMAIN_RID, ...)
I'm not sure if NetUserGetLocalGroups knows about deny SIDs (If you need to verify if the current process (not the user account!) is in the admin group, you have to handle deny SIDs)
If you only need to support 2000 and later, PInvoke CheckTokenMembership (That MSDN page has a IsUserAdmin example function)
On NT4 you need to get a TokenGroups array from GetTokenInformation, but you don't call LookupAccountSid, you just call EqualSid on every item and compare it to a admin group SID you create with AllocateAndInitializeSid(...,SECURITY_BUILTIN_DOMAIN_RID,...)