2015-03-16 5 views
0

Я пишу службу Windows, которая выполняет операции в соответствии с различными правилами, одна из которых основана на запрашивающем идентификаторе пользователя.Найти, если данный идентификатор SID принадлежит к группе, идентифицированной SID

Таким образом, он получает запрашивающий идентификатор пользователя SID и затем сравнивает его со своим внутренним списком идентификаторов безопасности, чтобы решить, какую операцию он будет выполнять. Использование функции API EqualSID делает это очень простым.

Однако теперь я столкнулся с ситуацией, когда некоторые идентификаторы SID в списке услуг являются идентификаторами группы, а не идентификаторами SID пользователя.

Это означает, что я должен найти способ проверить, соответствует ли полученный SID тому, который указан в списке, или принадлежит группе, которая представлена ​​SID в списке.

Я осмотрелся, чтобы узнать, какие API-интерфейсы будут доступны и что будет найдено около CheckTokenMembership, для чего требуется маркер маркера. Вот где я немного потерялся, потому что, поскольку служба не обязательно находится на одной машине, я не могу найти способ создать правильный дескриптор маркера из SID, который я получил.

Служба сама работает под учетной записью «Служба NT» по умолчанию, и я предпочел бы, чтобы она оставалась таким образом.

Какой API вы бы предложили использовать?

Целевой язык Delphi, но я могу понять примеры в простом C.

ответ

0

Ну, осмотрев на различных других вещей, которые я, наконец, удалось найти способ для достижения этой цели. Короче говоря, ответ Active Directory Service Interfaces также известный как ADSI

Чтобы дать немного больше деталей должен кто-то будет смотреть на что, здесь есть ряд шагов для достижения этой цели в Delphi:

  1. Импорт Active DS Type Library набор объектов в Delphi. Это создаст ActiveDs_TLB блок со всеми необходимыми интерфейсами
  2. Declare AdsGetObject как так

    function ADsGetObject(lpszPathName: WideString; const riid: TGUID; out ppObject): HRESULT; safecall; 
    
  3. Получить экземпляр IADsUser с синтаксисом SID:

    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; 
    

Как вы можете видеть , хотелось бы использовать метод IsMember для IADSGroup, но ясно, что он не работает, потому что он должен вернуть True в приведенном выше случае (S-1-5-32-545 is t он мировой группы). Так как это было предложено дать ссылку в комментариях, я написал свой собственный IsMember так:

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; 

При всем этом, я могу проверить, является ли данный SID принадлежит к группе определяется его SID.

Смежные вопросы