Get users from Acctive Directory Group - active-directory

I created an Active Directory domain name 'ADDOMAIN2' having a group name "CommonUsers" having 8 users. but when I do a Directory Search for users in group "CommonUsers" it returns zero result. hers is my code
DirectorySearcher searcher = new DirectorySearcher();
DirectoryEntry directoryEntry = new DirectoryEntry(string.Format("LDAP://{0}", "ADDOMAIN2"), "Administrator", "p#S$w0rd");
string dnPath = directoryEntry.Properties["distinguishedName"].Value.ToString();
// string path = string.Format("LDAP://{0}/{1}{2}", "ADDOMAIN2", "", dnPath);
string path = "LDAP://ADDOMAIN2/CN=CommonUsers,DC=ADDomain2,DC=ADDomain01,DC=WaveDomain";
directoryEntry.Path = path;
searcher.SearchRoot = directoryEntry;
searcher.Filter = "(&(objectCategory=person)(objectClass=user))";
SearchResultCollection rs = searcher.FindAll();
Any Idea what is wrong here?
Thanx

Try using some external LDAP browser (like the old and free version 2.6 of Softerra LDAP Browser) to check whether your query string is really pointing to the correct location.

DirectorySearcher is not used to find users inside a group. It's used to find objects under a base path. Since there is no user objects placed under your AD group object, you won't find anything.
In most cases, you can find the user objects in an AD group from its member attribute. Beware that AD group can contain either group or user. So, some of the entres there may be group. In some cases, the member attribute does not contain AD group nor AD user, it's containing a Foreign Security Principal. This happens if your user is coming from another forest. The primary group is also handled differently. Even "Domain User" is primary group of most of the users in AD, its member attribute doesn't contain anything at all. There are a lot other oddities that makes enumerating an AD group object really hard.
Fortunately, in .NET 3.5, Microsoft provides some useful classes in the framework to do the dirty work for you. Check out System.DirectoryServices.AccountManagement
To get some quick examples, you can check out this codeproject article
Your code should be something like this.
PrincipalContext context = new PrincipalContext(ContextType.Domain, "yourdomain.com");
GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "Domain Users");
foreach (Principal principal in groupPrincipal.GetMembers(false))
{
Console.Out.WriteLine(principal.DistinguishedName);
}
Console.In.ReadLine();

Related

What is the proper way to get some specific user attributes from Active Directory via LDAP C API?

I am trying to get some user attributes from Active Directry using Windows LDAP API. I am using:
Active Directory Version: The one that comes with Windows Server 2012
LDAP version: 3
Wldap32.lib version: The one that comes with Windows 10 x64
Eg:
PCHAR myAttributes[4];
myAttributes[0] = "DistinguishedName";
myAttributes[1] = "DisplayName";
myAttributes[2] = "PasswordExpired";
myAttributes[3] = "mail";
ldap_search_s(
myLdapConnection, // Ldap connection
myDomain, // DN to start search
LDAP_SCOPE_SUBTREE, // Scope
myFilter, // Filter
myAttributes, // Retrieve list of attributes
0, // Get both attributes and values
&mySearchResult // [out] Search results
);
It returns DistinguishedName, DisplayName and mail attributes, but does not reuturn the PasswordExpired attribute.
I queried with some other attributes and it looks like it does not return attributes with boolean values as well as the EmailAddress attribute.
Why does it not return PasswordExpired attribute?
What about EmailAddress ?
Is there a difference between EmailAddress and mail ?
There is no PasswordExpired LDAP attribute in Active Directory. To build your query look at this URL for attribute names in standard Active Directory schema https://msdn.microsoft.com/en-us/library/ms675090(v=vs.85).aspx. To check if password for given account is expired you'll need to check userAccountControl attribute, which is actually value storing flags of different states of user account https://msdn.microsoft.com/en-us/library/ms680832(v=vs.85).aspx. There is IADsUser interface that will translate this all for you in case you don't have to stick just to LDAP https://msdn.microsoft.com/en-us/library/aa746343(v=vs.85).aspx
You will find current primary email address in mail attribute. There is no EmailAddress LDAP attribute, unless you meant E-mail-Addresses which is CN for the same schema attribute as mail, so no difference there.
See above. In general if you do not have compelling reason to stick just to C/LDAP I'd recommend you to use .Net Framework instead. Otherwise you have a lot of work ahead of you - not just interpreting bit flags like in case of password expiration but possibly also with different authentication methods, different structures capturing time and date, accounting for timezones, UTF, chasing referrals and other stuff you might need depending on complexity of what you want to achieve. You will be productive much faster in .Net Framework. See DirectoryServices https://msdn.microsoft.com/en-us/library/mt481534(v=vs.110).aspx namespace or Security namespace https://msdn.microsoft.com/en-us/library/mt481561(v=vs.110).aspx for details.

LDAP query cannot find a specific group in Active Directory

I have a macro within Excel that I periodically use to pull out details of group members within Active Directory. It works fine for every group I've tried but I've come across one group that I just do not seem able to get data for.
The relevant bit of the script is below:
Set rootDSE = GetObject("LDAP://[MyDomain.co.uk]/RootDSE")
DomainContainer = rootDSE.Get("defaultNamingContext")
Set conn = CreateObject("ADODB.Connection")
conn.Provider = "ADSDSOObject"
conn.Open "ADs Provider"
Set command = CreateObject("ADODB.Command")
Set command.ActiveConnection = conn
command.Properties("Page size") = 200
groupDistinguisedName = "CN=[Group Name],OU=xxx,OU=xxx,DC=MyDomain,DC=co,DC=uk"
command.CommandText = "<LDAP://" & DomainContainer & ">;(distinguishedName=" & groupDistinguisedName & ");member;subtree"
Set rs = command.Execute
On Error Resume Next
dataVal = rs.Fields("member").Value
I've tried to run the script with a group name that does NOT exist and the script behaves in a different way - dataVal is set to Empty if the group does not exist, but is set to Null for the group I am having problems with, so it would appear that it has found the group but just somehow cannot get the members of the group.
I've tried cutting and pasting the distinguished name directly from Active Directory into the LDAP command string so I know it's not a typo on the name. This group is a large group with lots of members but I've tried other large groups too. I just can't see what could be causing the problem. Any ideas?
The "member" attribute does not include members for primary group membership.
e.g. The "Domain Users" group may have many members but its "member" attribute can be empty.
To check primary group membership, please make use of the primaryGroupToken (group) and the primaryGroupId (user) attribute.
Get the value of primaryGroupToken attribute from group
(Note that primaryGroupToken is an constructed attribute)
Search in the SAME DOMAIN for all users that has the same value in primaryGroupId
e.g. "Domain Users" group has a value of 513 in primaryGroupToken.
That means any user objects in the same domain whose primaryGroupId=513 are members of this "Domain Users" group.
Other comments:
You already know the DN and the server. Why not directly call GetObject("LDAP://[MyDomain.co.uk]/" & groupDistinguisedName) to get the group?
distinguishedName attribute is not indexed. The query can be slow in large env.
If there are >1500 (configurable) members in "member" attribute, you need to use range retrieval. Otherwise you only get 1500.

Is mailbox a PublicFolder

I have next issue: i have edb file(Exchange Server 2013), and i can get mailbox guids from it. One of mailbox is PublicFolder mailbox. It's impossible to find out if mailbox is PF, or just simple user's mailbox.
I already have functionality to get all information of mailbox by it's guid from AD.
string filter = #"(&(objectClass=user)(msExchMailboxGuid=" + ESWUtils.GetADGuidString(guid) + "))";
search.Filter = filter;
search.SearchScope = SearchScope.Subtree;
search.PropertiesToLoad.Add("mail");
search.PropertiesToLoad.Add("displayname");
search.PropertiesToLoad.Add("samaccountname");
...
Is it possible to find out, that guid belongs to PF mailbox, from AD?
In Exchange 2013, Public Folders are moved into mailboxes and out of their own database. Looks like the easiest way is to look at the msExchRecipientTypeDetails attribute.
search.Filter = "(msExchRecipientTypeDetails=68719476736)"
Combine that with your other search criteria.
Running a Get-Mailbox -PublicFolder on the mailbox will show the RecipientTypeDetails listed as PublicFolderMailbox. 68719476736 is the bitwise identifier that matches on the user attributes.

Can I create a new global security group with an existing name in Active Directory?

How can I create a global security group with a name of finance, seeing that I already have a user with that name in Active Directory. Is it possible?
You cannot have two objects of the same name in the same container - so you cannot create a group called Finance in the same container (OU) where the user Finance exists. Both user as well as group would be identified by
OU=Finance,OU=YourOU,OU=YourOtherOU,dc=YourCompany,dc=com
and that won't work - the fully distinguished bane (FQDN) of each object must be unique.
Other than that, there's a requirement that objects must have unique SAM Account Names - which by default are the same as the "display" name (Finance) - but can be set to something else.
So if your user is called Finance and has a SAM account name of Finance - then you should be able to create a global group called Finance (in a different OU/Container) by settings it's SAM account name to e.g. FinanceGroup or something like that.
You're not specifying what language/programming system you're using - if you're trying to create this group in C# / .NET 3.5 or higher, you could use code something like this:
using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
GroupPrincipal finGroup = new GroupPrincipal(ctx);
finGroup.DisplayName = "Finance";
finGroup.SamAccountName = "FinanceGroup";
finGroup.Save();
}

LDAP query for all users in sub OUs within a particular OU

The active directory I have to deal with is laid out as such: the domain contains many OUs. One of these OUs is named "Primary OU". Within this OU are several OUs named with location of global offices (ie "Chicago" "Paris").
Any user account that is an actual flesh and bone person is put into the OU named for the office they work in as their primary OU. Any user account that is an alias, generic account, or otherwise not directly tied to a real person, has the "Primary OU" OU set as their primary OU.
Data-wise, this primary OU distinction is the only thing that indicates which users are real people, and which users are not. There is no group that contains only real people, no indicator in any field that they are real people or not, and making any changes to active directory or any user accounts is strictly forbidden.
My task is writing a query that will only get all actual flesh and bone people.
Unfortunately LDAP is not exactly my strong suit and the only way I've come up with is searching each of these office sub OUs individually and putting all the results together, but there are a lot of offices and it would require a change to the query if any offices were added, which I need to avoid.
Is there a way to query all users within a particular OU's "sub" OUs, but not return any users directly in the parent OU?
Yes, sure - you would need to:
1) Bind to the particular OU
DirectoryEntry myOU = new DirectoryEntry("LDAP://OU=MyOU,......,DC=MyCompany,DC=com");
2) Enumerate all its sub-OU's
DirectorySearcher subOUsearcher = new DirectorySearcher(myOU);
subOUsearcher.SearchScope = SearchScope.OneLevel; // don't recurse down
subOUsearcher.Filter = "(objectClass=organizationalUnit)";
foreach(SearchResult subOU in subOUsearcher.FindAll())
{
// stick those Sub OU's into a list and then handle them
}
3) One-by-one enumerate all the users in each of the sub-OU's and stick them into a global list of users
DirectorySearcher userSearcher = new DirectorySearcher(myCurrentSubOu);
userSearcher.SearchScope = SearchScope.OneLevel; // don't recurse down
userSearcher.Filter = "(objectClass=user)";
foreach(SearchResult user in userSearcher.FindAll())
{
// stick those users into a list being built up
}
4) Return that list
Marc
// Create a new DirectorySearcher that starts at the root.
// You can start it anywhere you want though
// by providing a value in the DirectoryEntry constructor.
DirectorySearcher searcher = new DirectorySearcher(new DirectoryEntry());
// Set the scope to Subtree in order to search all children.
searcher.SearchScope = SearchScope.Subtree;
// Set the filter to only look for Organizational Units
// that have the name you are looking for.
searcher.Filter = "(&(objectClass=organizationalUnit)(name=" + ouName + "))";
// If you are looking for only one result then do the following two things.
SearchResult result = searcher.FindOne();
DirectoryEntry newDir = result.GetDirectoryEntry();

Resources