C++ 如何为AD组使用AllocateAndInitializeSid?

C++ 如何为AD组使用AllocateAndInitializeSid?,c++,winapi,visual-c++,active-directory,C++,Winapi,Visual C++,Active Directory,我想为域管理员组创建一个SID,并将其传递给CheckTokenMembership,以确定给定的AD用户是否属于该组。但是,我不太确定应该将什么标识符权限和子权限与AllocateAndInitializeSid一起使用。到目前为止,我看到的所有“有效”例子都只涉及当地团体 例如: SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY; PSID adminGroup; AllocateAndInitializeSid(&a

我想为域管理员组创建一个SID,并将其传递给
CheckTokenMembership
,以确定给定的AD用户是否属于该组。但是,我不太确定应该将什么标识符权限和子权限与
AllocateAndInitializeSid
一起使用。到目前为止,我看到的所有“有效”例子都只涉及当地团体

例如:

SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
PSID adminGroup;

AllocateAndInitializeSid(&ntAuthority,
                         2,
                         SECURITY_BUILTIN_DOMAIN_RID,
                         DOMAIN_ALIAS_RID_ADMINS,
                         0, 0, 0, 0, 0, 0,
                         &adminGroup);
应使用哪个权限和子权限为AD Administrators组创建SID?我尝试了
DOMAIN\u-GROUP\u-RID\u-ADMINS
DOMAIN\u-RID\u-ADMIN
SECURITY\u-NT\u-AUTHORITY
但是
CheckTokenMembership
总是报告某个给定用户不是该组的成员,这是不正确的

任何联机文档的示例和指针都将不胜感激。

您可以与
策略DNSDomainInformation
一起使用,以检索计算机主域的SID

或者,如果您知道要查询的帐户与您感兴趣的域管理员组属于同一个域,则可以使用从帐户SID中提取域SID


获得域SID后,可以使用创建域管理员组的SID。使用
WinAccountDomainAdminsId
选项。然后,正如您所建议的那样,只需调用CheckTokenMembership()。

您可以枚举令牌组,并检查您感兴趣的SID显示

volatile UCHAR guz;

ULONG IsDomainAdmin(HANDLE hToken, PBOOL IsMember)
{
    ULONG cb = 0, rcb = 0x100, err;
    PVOID stack = alloca(guz);

    union {
        PVOID buf;
        PTOKEN_GROUPS ptg;
    };

    do 
    {
        if (cb < rcb)
        {
            cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
        }

        if (GetTokenInformation(hToken, TokenGroups, buf, cb, &rcb))
        {
            *IsMember = FALSE;

            if (ULONG GroupCount = ptg->GroupCount)
            {
                PSID_AND_ATTRIBUTES Groups = ptg->Groups;
                do 
                {
                    // S-1-5-21-domain-512
                    PSID Sid = Groups++->Sid;
                    PSID_IDENTIFIER_AUTHORITY psia = GetSidIdentifierAuthority(Sid);

                    static SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;

                    if (!memcmp(psia, &ntAuthority, sizeof(SID_IDENTIFIER_AUTHORITY)))
                    {
                        ULONG n = *GetSidSubAuthorityCount(Sid);

                        if (
                            1 < n &&
                            *GetSidSubAuthority(Sid, 0) == SECURITY_NT_NON_UNIQUE &&
                            *GetSidSubAuthority(Sid, n - 1) == DOMAIN_GROUP_RID_ADMINS
                            )
                        {
                            *IsMember = TRUE;

                            return NOERROR;
                        }
                    }

                } while (--GroupCount);
            }
            return NOERROR;
        }

    } while ((err = GetLastError()) == ERROR_INSUFFICIENT_BUFFER);

    return err;
}
volatile-UCHAR-guz;
ULONG IsDomainAdmin(把手hToken,PBOOL IsMember)
{
ULONG cb=0,rcb=0x100,错误;
PVOID stack=alloca(guz);
联合{
pvoidbuf;
PTOKEN_组ptg;
};
做
{
如果(cbGroupCount)
{
PSID_和_属性组=ptg->Groups;
做
{
//S-1-5-21-domain-512
PSID Sid=组+->Sid;
PSID_IDENTIFIER_AUTHORITY psia=GetSidIdentifierAuthority(Sid);
静态SID\u标识符\u权限n权限=安全\u NT\u权限;
if(!memcmp(psia,&N权限,sizeof(SID\u标识符\u权限)))
{
ULONG n=*GetSidSubAuthorityCount(Sid);
如果(
1
但您使用哪种令牌进行检查?uac下的管理员?他拥有
S-1-5-32-544
(您使用的sid)和
SE\u GROUP\u use\u FOR\u DENY\u属性我使用从LogonUser获得的令牌。示例:LogonUser(用户名、域、密码、LOGON32\u登录\u网络、LOGON32\u私有\u默认值和hToken),但我想用户没有提升?在这种情况下,
S-1-5-32-544
(您使用的sid)与令牌中的
SE\u GROUP\u use\u FOR\u DENY\u属性一起使用。和CheckTokenMembership,并且必须返回False,该提升哪个用户?调用LogonUser的进程应该在哪个用户下运行?另外,如何确定令牌中是否存在SE_GROUP_USE_FOR_DENY_ONLY属性?@RbMm,请不要混淆本地计算机管理员和域管理员组。UAC对域组成员资格没有影响。我在获取特定域SID方面没有问题。我如何使用它来确定给定的域用户是否属于域管理员组?我已将其添加到我的答案中。CreateWellKnownSid()/CheckTokenMembership()适用于我,因此我接受此答案。RbMm的建议也有效,但这种方法对我更有效,因为我保留了域SID。这种代码在大多数情况下是错误的,应该使用CheckTokenMembership。很少将仅拒绝SID视为“有效”组条目。@Anders-可以在此处添加easy检查SID属性(是否启用了
SE\u group\u
exist和
SE\u group\u仅使用\u表示拒绝
不存在),但我不确定需要如何解释这种情况-我们想要检查访问或成员资格?在大多数情况下,
都是错误的
-这是什么意思?在大多数情况下,
DOMAIN\u GROUP\u RID\u ADMINS
在令牌中未启用?你不会把它与
域\u别名\u RID\u管理员混为一谈吧?“在大多数情况下”,我最担心的是人们在不了解拒绝属性的情况下发现并使用这段代码。访问和成员资格之间的界限可能有点模糊,如果设置了拒绝位,是谁设置的,为什么?故意限制自己或公司政策?还有更多的安全考虑。我不确定本地管理员是否能够为他们不是其成员的组创建具有拒绝SID的令牌。win32函数应该阻止您这样做,但我不确定Nt*API或内核驱动程序。@Anders-当我写这篇文章时,我也有疑问-使用或不使用SID属性。检查访问权限或成员资格。从-
函数忽略SidsToDisable数组中现有令牌中未找到的任何SID。
Nt*函数在此不更改图片。但是当然可以通过使用
ZwCreateToken
从零开始创建令牌,但是为了满足这一需要,可以说,如果用户拥有
SE_DEBUG_特权
(所有本地