Reputation: 256751
How can i get the IADs
interface of an Active Directory user - by username?
Note: Native code
i am trying to write the function that can get the IADs
interface of a user in Active Directory.
i have the following "pseudocode" so far:
public IADs GetUserObject(string samAccountName)
{
IADs ads;
//Get the current domain's distinguished name ("dc=stackoverflow,dc=com")
AdsGetObject("LDAP://rootDSE", IADs, ref ads);
String dn = ads.Get("defaultNamingContext"); //"dc=stackoverflow,dc=com"
String path;
//Attempt #1 to bind to a user by username
path = "LDAP://sSAMAccountName="+samAccountName+",dc=stackoverflow,dc=com"
AdsGetObject(path, IADs, ref ads); //invalid syntax
return ads;
}
The trick, that i cannot figure out, is how to bind to the user by their account name. The following variantions don't work:
LDAP://sSAMAccountName=ian,dc=stackoverflow,dc=com
LDAP://dc=stackoverflow,dc=com;(&(objectCategory=user)(sAMAccountName=ian))
<LDAP://dc=stackoverflow,dc=com>;(&(objectCategory=user)(sAMAccountName=ian))
Edit:
A version that does work, but doesn't answer my question, is:
LDAP://cn=Ian Boyd,ou=Avatar Users,dc=stackoverflow,dc=com
It doesn't answer my question for two reasons:
- i don't know the user's
CN
(Common-Name) (e.g. Ian Boyd), only theirsAMAccountName
(e.g. ian)- doesn't work for users not in the Avatar Users organizational unit; and i don't know a user's OU
Which comes from the notes i had before:
Note:
tl;dr: How would you write the utility function:
public IADs GetUserObject(string samAccountName)
{
//TODO: ask stackoverflow
}
Update 2:
Note:
IADs
for a user)Update 3:
It certainly might require me to apply "filters", except i don't know where. The only ActiveDs interface that mentions Filter is IADSContainer
, but i don't know where to get one.
i tried randomly to get the IADsContainer
interface from the root IADs
interface, but "rootDSE" doesn't support IADsContainer
:
IADs ads = AdsGetObject("LDAP://rootDSE");
IADsContainer container = (IADsContainer)ads; //interface not supported exception
i could
IADsContainer
of the AD root
IADsContainer
But keeping track of all these questions is difficult.
Upvotes: 1
Views: 8603
Reputation: 221997
If you know the value of sAMAccountName
and need to get IADs
of the user you need first find the user in Active Directory by the sAMAccountName
and get distinguishedName
attribute of the user. You know already how to get IADs
by distinguishedName
.
So you should just follow the code from MSDN for example. First you get IDirectorySearch
interface of the AD container of defaultNamingContext
of "LDAP://rootDSE"
.
IADs domain;
ADsGetObject("LDAP://rootDSE", IADs, domain);
Then you use IDirectorySearch::ExecuteSearch to apply search using the filter string:
(&(objectClass=user)(objectCategory=person)(sAMAccountName=theName))
Note: The search filter syntax is described here.
IDirectorySearch directorySearch = domain as IDirectorySearch;
ADS_SEARCH_HANDLE searchHandle;
directorySearch.ExecuteSearch(
"(&(objectClass=user)(objectCategory=person)(sAMAccountName=ian))",
attributeNames, numberOfAttributes,
out searchHandle);
you use the known value of sAMAccountName
instead of theName
.
for pAttributeNames
you can use LPOLESTR
array which consist from L"distinguishedName"
only (see pszNonVerboseList
from the code example and look the code of FindUsers
in case of bIsVerbose
as FALSE
).
You should get distinguishedName
attribute of first (and the only if any exist) found item. Having distinguishedName
attribute you can use AdsGetObject
to get the IADs
of the user.
Alternatively you can get objectGUID
attribute of the user instead of distinguishedName
attribute and use binding by GUID syntax, but the usage of distinguishedName
I personally find more clear and understandable.
public IADs GetUserObject(string samAccountName)
{
IADs ads;
//Get the current domain's distinguished name (e.g. "dc=stackoverflow,dc=com")
AdsGetObject("LDAP://rootDSE", IADs, ref ads);
String dn = ads.Get("defaultNamingContext"); //"dc=stackoverflow,dc=com"
//Get the the object of the current domain (e.g. LDAP://dc=stackoverflow,dc=com)
AdsGetObject("LDAP://"+dn, IADs, ref ads);
//Now we're going to search for the "distinguishedName" of this user
//setup the search filter for the user we want
String filter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName="+samAccountName+"))";
//specify that we only need to return one attribute, distinguishedNamem,
//otherwise it returns all attributes and is a waste of resources
String[] searchAttributes = { "distinguishedName" };
//run the search
IDirectorySearch ds = ads as IDirectorySearch;
ADS_SEARCH_HANDLE searchHandle;
ds.ExecuteSearch(filter, searchAttributes, 1, out searchHandle);
ds.GetFirstRow(searchHandle);
//Now get the details of the "distinguishedName" column
ADS_SEARCH_COLUMN column;
ds.GetColumn(searchHandle, "distinguishedName", ref column);
//Get the user's distinguishedName
String dn = column.pADsValues.DNString;
//Now that we have the user's distinguishedName, we can do what we really wanted:
AdsGetObject("LDAP://"+dn, IADs, ads);
return ads;
}
This means that conceptually it can be broken down into two steps:
samAccountName
IADs
for a distinguishedNameAnd splitting the code:
public IADs GetUserObject(string samAccountName)
{
String userDistinguishedName = GetUserDistinguishedName(samAccountName);
return GetObject("LDAP://"+userDistingishedName);
}
public String GetUserDistinguishedName(string samAccountName)
{
//Get the current domain's distinguished name (e.g. "dc=stackoverflow,dc=com")
IADs ads = GetObject("LDAP://rootDSE");
String dn = ads.Get("defaultNamingContext"); //"dc=stackoverflow,dc=com"
//Get the the object of the current domain (e.g. LDAP://dc=stackoverflow,dc=com)
ads := GetObject("LDAP://"+dn);
//Now we're going to search for the "distinguishedName" of this user
//setup the search filter for the user we want
String filter = '(&(objectClass=user)(objectCategory=person)(sAMAccountName='+samAccountName+'))';
//specify that we only need to return one attribute, distinguishedNamem,
//otherwise it returns all attributes and is a waste of resources
String[] searchAttributes = { "distinguishedName" };
//run the search
IDirectorySearch ds = ads as IDirectorySearch;
ADS_SEARCH_HANDLE searchHandle;
ds.ExecuteSearch(filter, searchAttributes, 1, out searchHandle);
ds.GetFirstRow(searchHandle);
//Now get the details of the "distinguishedName" column
ADS_SEARCH_COLUMN column;
ds.GetColumn(searchHandle, "distinguishedName", ref column);
//Get the user's distinguishedName
return column.pADsValues.DNString;
}
Upvotes: 3
Reputation: 72640
Here is a sample in C++
IADs *pObject;
HRESULT hr;
// Initialize COM.
CoInitialize(NULL);
hr = ADsGetObject(L"LDAP://CN=JPB,OU=MonOU,DC=societe,DC=fr",
IID_IADs,
(void**) &pObject);
if(SUCCEEDED(hr))
{
// Use the object.
// Release the object.
pObject->Release()
}
// Uninitialize COM.
CoUninitialize();
You can find more information in Binding to Active Directory Domain Services.
Upvotes: 0