Winapi 查找给定SID是否属于由SID标识的组

Winapi 查找给定SID是否属于由SID标识的组,winapi,Winapi,我正在编写一个windows服务,它根据不同的规则执行操作,其中一个规则基于请求的用户身份 因此,它接收请求用户SID,然后将其与内部SID列表进行比较,以决定将执行什么操作。使用EqualSIDAPI函数可以使这非常容易 然而,我现在面临的情况是,服务清单中的一些小岛屿发展中国家是集团小岛屿发展中国家,而不是用户小岛屿发展中国家 这意味着我必须找到一种方法来测试接收到的SID是否等于列表中的SID,或者是否属于列表中由SID表示的组 我环顾四周,看看有哪些API可用,并找到了关于需要令牌句柄的

我正在编写一个windows服务,它根据不同的规则执行操作,其中一个规则基于请求的用户身份

因此,它接收请求用户SID,然后将其与内部SID列表进行比较,以决定将执行什么操作。使用
EqualSID
API函数可以使这非常容易

然而,我现在面临的情况是,服务清单中的一些小岛屿发展中国家是集团小岛屿发展中国家,而不是用户小岛屿发展中国家

这意味着我必须找到一种方法来测试接收到的SID是否等于列表中的SID,或者是否属于列表中由SID表示的组

我环顾四周,看看有哪些API可用,并找到了关于需要令牌句柄的
CheckTokenMembership
。这就是我有点迷茫的地方,因为服务不一定位于同一台机器上,所以我似乎找不到从收到的SID创建有效令牌句柄的方法

服务本身在默认的“NT服务”帐户下运行,我更希望它能保持这种状态

您建议我使用什么API


目标语言是Delphi,但我能理解纯C语言中的示例。

在查看了其他各种内容后,我终于找到了实现这一点的方法。简而言之,答案是
Active Directory服务接口
也称为
ADSI

如果其他人正在查看,请提供更多详细信息,以下是在Delphi中实现此目的的一系列步骤:

  • 活动DS类型库
    对象集导入Delphi。这将创建带有所有必要接口的
    ActiveDs\u TLB
    单元
  • 像这样声明AdsGetObject

    function ADsGetObject(lpszPathName: WideString; const riid: TGUID; out ppObject): HRESULT; safecall;
    
  • 使用SID语法检索IADSUser实例:

    var
      SIDUser: IADSUser;
      User: IADSUser;
    
      SIDGroup: IADSGroup;
      Group: IADSGroup;
    begin
      // Bind using the SID
      AdsGetObject('LDAP://<SID=S-1-5-7>', IADSUser, SIDUser);
    
      // rebind using the distinguished name as suggested by MSDN
      AdsGetObject('LDAP://' + SIDUser.Get('distinguishedName'), IADSUser, User);
    
      // Use the User instance
      ShowMessage(User.FullName);
    
      // Same method for group 
      AdsGetObject('LDAP://<SID=S-1-5-32-545>', IADSGroup, SIDGroup);
      AdsGetObject('LDAP://' + SIDGroup.Get('distinguishedName'), IADSGroup, Group);
    
      // IsMember does not seem to work with LDAP
      // https://groups.google.com/forum/#!topic/microsoft.public.adsi.general/2d-e4HPXGfA
      // http://www.rlmueller.net/Programs/IsMember4.txt
    //  if Group.IsMember(User.ADsPath) then
      if AdsIsMember(User, 'S-1-5-32-545') then
        ShowMessage('InGroup');
    end;
    
    有了这些,我现在可以检查给定的SID是否属于由其SID定义的组

    function ADsIsMember(const User: IADSUser; const GroupSID: string): Boolean;
    const
      TokenGroupsId = 'tokenGroups';
    var
      PropNames: array of OleVariant;
      TokenGroups: OleVariant;
      TokenGroupLow: Integer;
      TokenGroupHigh: Integer;
      TokenGroupIndex: Integer;
      SIDBytes: array of Byte;
      SIDAsString: PChar;
    begin
      Result := False;
      SetLength(PropNames, 1);
      PropNames[0] := TokenGroupsId;
      User.GetInfoEx(PropNames, 0);
      TokenGroups := User.Get(TokenGroupsId);
      TokenGroupLow := VarArrayLowBound(TokenGroups, 1);
      TokenGroupHigh := VarArrayHighBound(TokenGroups, 1);
      for TokenGroupIndex := TokenGroupLow to TokenGroupHigh do
      begin
        SIDBytes := TokenGroups[TokenGroupIndex];
        ConvertSidToStringSid(@SIDBytes[0], SIDAsString);
        if GroupSID = SIDAsString then
          Exit(True);
      end;
    end;