EdZava / VCL-ActiveDirectory4Delphi

Delphi basic library for validation and authentication of LDAP users in Active Directory.
MIT License
82 stars 14 forks source link

Add the possibility to enumerate the Users #3

Open gliden opened 1 year ago

gliden commented 1 year ago

it would be really helpful if you can enumerate over the users of a specific group

EdZava commented 1 year ago

I think it could be done. Right now, I don't have the means to test anything related to DA as I no longer have access to a DA server.

However, I'll share an example code that I believe could work. It would need to be tested and adjusted accordingly.

procedure GetGroupMembers(const groupName: string);
var
  group: IADsGroup;
  members: IADsMembers;
  member: IUnknown;
  enumVar: IEnumVariant;
  count: LongWord;
  userName, fullName: WideString;
begin
  group := ADsGetObject('LDAP://CN=' + groupName + ',OU=UnidadOrganizativa,DC=dominio,DC=com') as IADsGroup;

  if Assigned(group) then
  begin
    members := group.Members as IADsMembers;
    members._NewEnum(EnumVar);
    EnumVar.Reset;

    while EnumVar.Next(1, member, Count) = S_OK do
    begin
      if Supports(member, IADsUser) then
      begin
        userName := IADsUser(member).Name;
        fullName := IADsUser(member).FullName;
        // Add List (userName, fullName)
      end;

      member := nil;
    end;
  end;
end;

If you would like to contribute to the project, any help would be welcome.

EdZava commented 1 year ago

@gliden Could you try the example that I gave you?

gliden commented 1 year ago

@EdZava I tried it but there is an OLE-Exception GetGroupMembers = Error.Class: EOleException | Error.Message: Schnittstelle nicht unterstützt

The exception occures in this code ADsGetObject('LDAP://OU=XXX,DC=XXX,DC=local', IADsGroup, group);

EdZava commented 1 year ago

@gliden Try to try this other example method:

function TActiveDirectoryClientWinapi.GetGroupUsers(inDomainName, inGroupName: string; out outUsers: TStringList): Boolean;
var
  Path: string;
  Resultado: HRESULT;
  Group: IADsGroup;
  Enum: IEnumVariant;
  varUser: OleVariant;
  Temp: LongWord;
begin
  Result := False;
  outUsers := TStringList.Create;

  if (Trim(inDomainName) = '') then
    Exit;

  if (Trim(inGroupName) = '') then
    Exit;

  Path := TActiveDirectoryWinapiUtils.GetPathLDAP(inDomainName, 'CN=' + inGroupName);
  Resultado := ADsGetObject(Path, IADsGroup, Group);

  if (Failed(Resultado)) or (Group = nil) then
    Exit;

  Enum := Group.Members._NewEnum as IEnumVariant;

  if (Enum <> nil) then
  begin
    while (Enum.Next(1, varUser, Temp) = S_OK) do
    begin
      outUsers.Add(varUser.Name);
      VariantClear(varUser);
    end;
  end;

  Result := True;
end;

Then tell me if it worked for you.

gliden commented 1 year ago

Its not working with this error GetGroupUsers = Error.Class: EOleException | Error.Message: Es ist ein Fehler bei der Ausführung aufgetreten

In our Domain the users are organized in an organizationalUnit but also the group "CN=Builtin" is not working.

In Ldap-Admin it looks like this: image

EdZava commented 1 year ago

@gliden I'm sorry for not being able to help further, but without debugging the code, it's difficult for me to indicate what the solution could be.

When I have some free time at work, I will try to recover the VM I had with the DA configured to attempt implementing this method.

If I find anything else, I will let you know here. Thank you!