EDN Admin
Well-known member
Hi,
Ive a code block that checks if a given user exists in Active Directory DC, if yes, then it checks if it is member of Domain Admin group. Here is the codeBOOLEAN
GetUserLdapPath(
IADsContainer* pContainer,
const WCHAR *pcwszUsername,
WCHAR *pwszLdapPath,
DWORD dwcchLdapPathSize,
DWORD *pdwError
)
{
VARIANT var;
ULONG lFetch;
IADs *pADs = NULL;
HRESULT hr = E_FAIL;
HRESULT hrGC = S_OK;
IUnknown *pUnk = NULL;
IDispatch *pDisp = NULL;
IEnumVARIANT *pEnum = NULL;
IDirectorySearch *pGCSearch = NULL;
if (NULL == pContainer || NULL == pcwszUsername || NULL == pwszLdapPath || 0 == dwcchLdapPathSize || NULL == pdwError)
{
return FALSE;
}
hr = pContainer->get__NewEnum(&pUnk);
if (SUCCEEDED(hr))
{
hr = pUnk->QueryInterface(IID_IEnumVARIANT, (void**) &pEnum);
if (SUCCEEDED(hr))
{
//
// Now Enumerate--there should be only one item.
//
hr = pEnum->Next(1, &var, &lFetch);
if (SUCCEEDED(hr))
{
while (hr == S_OK)
{
if (lFetch == 1)
{
pDisp = V_DISPATCH(&var);
hr = pDisp->QueryInterface(IID_IDirectorySearch, (void**)&pGCSearch);
hrGC = hr;
}
VariantClear(&var);
hr = pEnum->Next(1, &var, &lFetch);
};
}
}
if (pEnum)
{
pEnum->Release();
}
}
if (pUnk)
{
pUnk->Release();
}
if (FAILED(hrGC))
{
if (pGCSearch)
{
pGCSearch->Release();
}
return FALSE;
}
//
// Create search filter.
//
WCHAR rgSearchFilter[1024];
wsprintfW(rgSearchFilter, L"(&(objectCategory=person)(objectClass=user)(sAMAccountName=%s))", pcwszUsername);
//Search entire subtree from root.
ADS_SEARCHPREF_INFO SearchPrefs;
SearchPrefs.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
SearchPrefs.vValue.dwType = ADSTYPE_INTEGER;
SearchPrefs.vValue.Integer = ADS_SCOPE_SUBTREE;
DWORD dwNumPrefs = 1;
// COL for iterations
ADS_SEARCH_COLUMN col;
// Handle used for searching
ADS_SEARCH_HANDLE hSearch;
// Set the search preference
hr = pGCSearch->SetSearchPreference(&SearchPrefs, dwNumPrefs);
if (FAILED(hr))
{
return FALSE;
}
// Set attributes to return
CONST DWORD dwAttrNameSize = 4;
LPOLESTR pszAttribute[dwAttrNameSize] = {L"cn", L"distinguishedName", L"sAMAccountName", L"ADsPath"};
// Execute the search
hr = pGCSearch->ExecuteSearch(rgSearchFilter, pszAttribute, dwAttrNameSize, &hSearch);
if (SUCCEEDED(hr))
{
if (pGCSearch->GetFirstRow(hSearch) == S_ADS_NOMORE_ROWS)
{
return FALSE;
}
else // The UPN was found
{
do
{
// loop through the array of passed column names, print the data for each column.
for (DWORD x = 0; x < dwAttrNameSize; x++)
{
// Get the data for this column.
hr = pGCSearch->GetColumn(hSearch, pszAttribute[x], &col);
if (SUCCEEDED(hr))
{
// Print the data for the column and free the column.
// Note the attributes we asked for are type CaseIgnoreString.
// wprintf(L"%s: %srn", pszAttribute[x], col.pADsValues->CaseIgnoreString);
if (x == dwAttrNameSize - 1)
{
wcscpy(pwszLdapPath, col.pADsValues->CaseIgnoreString);
}
pGCSearch->FreeColumn(&col);
}
else
{
//wprintf(L"<%s property is not a string>", pszAttribute[x]);
}
}
}
while (pGCSearch->GetNextRow(hSearch) != S_ADS_NOMORE_ROWS);
}
// Close the search handle to clean up.
pGCSearch->CloseSearchHandle(hSearch);
}
if (pGCSearch)
{
pGCSearch->Release();
}
return TRUE;
}
BOOLEAN __stdcall
ValidateDomainUser(
const WCHAR *pcwszDomainName,
WCHAR *pwszUserName,
WCHAR *pwszPassword,
DWORD *pdwError
)
{
HRESULT hr;
BOOLEAN bRet;
DWORD dwError;
WCHAR *pwszDomainStart;
USER_INFO_1 *pUserInfo;
WCHAR wszUser[_MAX_PATH];
IADsContainer *pContainer;
WCHAR wszDomainName[_MAX_PATH];
WCHAR wszDomainNameWithoutLDAP[MAX_CNNAME_LENGTH];
if (NULL == pcwszDomainName || NULL == pwszPassword || NULL == pwszUserName || NULL == pdwError)
{
return FALSE;
}
CoInitialize(NULL);
hr = ADsOpenObject(
pcwszDomainName,
pwszUserName,
pwszPassword,
ADS_SECURE_AUTHENTICATION, // ADS_SERVER_BIND decision pending.
IID_IADsContainer,
(LPVOID*)&pContainer
);
if (FAILED(hr))
{
CoUninitialize();
return FALSE;
}
WCHAR *pwszTemp = NULL;
WCHAR wszAdsPath[_MAX_PATH] = {0};
wcscpy(wszUser, pwszUserName);
pwszTemp = wcschr(wszUser, L@);
if (pwszTemp)
{
*pwszTemp = L;
}
// Get users complete path if the user exists in domain.
bRet = GetUserLdapPath(pContainer, wszUser, wszAdsPath, ARRAY_SIZE(wszAdsPath), pdwError);
if (FALSE == bRet)
{
pContainer->Release();
CoUninitialize();
return FALSE;
}
pContainer->Release();
IADsUser *pUser = NULL;
hr = ADsOpenObject(
wszAdsPath,
pwszUserName,
pwszPassword,
ADS_SECURE_AUTHENTICATION, // ADS_SERVER_BIND decision pending.
IID_IADsUser,
(LPVOID*)&pUser
);
if (FAILED(hr))
{
CoUninitialize();
return FALSE;
}
//
// Check if the user belongs to Doamin Admins group.
// Note: Doamin Admins group name can be renamed by administrator
// where DC is installed. In this case, IsAdminUser will returns
// FALSE. It relies on group name returned by IADsUser interface.
//
bRet = IsAdminUser(pUser);
pUser->Release();
CoUninitialize();
return bRet;
}
BOOLEAN IsAdminUser(IADsUser *pUser)
{
HRESULT hr = S_OK;
IADsMembers *pGroups;
hr = pUser->Groups(&pGroups);
if (FAILED(hr))
{
return FALSE;
}
IUnknown *pUnk;
hr = pGroups->get__NewEnum(&pUnk);
if (FAILED(hr))
{
return FALSE;
}
pGroups->Release();
IEnumVARIANT *pEnum;
hr = pUnk->QueryInterface(IID_IEnumVARIANT,(void**)&pEnum);
if (FAILED(hr))
{
return FALSE;
}
pUnk->Release();
// Enumerate.
BSTR bstr;
VARIANT var;
IADs *pADs;
ULONG lFetch;
IDispatch *pDisp;
VariantInit(&var);
hr = pEnum->Next(1, &var, &lFetch);
while(hr == S_OK)
{
if (lFetch == 1)
{
pDisp = V_DISPATCH(&var);
pDisp->QueryInterface(IID_IADs, (void**)&pADs);
pADs->get_Name(&bstr);
if (0 == wcscmp(L"CN=Domain Admins", bstr))
{
SysFreeString(bstr);
pADs->Release();
VariantClear(&var);
pDisp=NULL;
pEnum->Release();
return TRUE;
}
SysFreeString(bstr);
pADs->Release();
}
VariantClear(&var);
pDisp=NULL;
hr = pEnum->Next(1, &var, &lFetch);
};
hr = pEnum->Release();
return FALSE;
}
int main()
{
DWORD dwRet;
BOOLEAN bRet = ValidateDomainUser(
L"architectsunited.com,
L"administrator@architectsunite",
L"...",
&dwRet
);
if (FALSE == bRet)
{
printf("nValidateDomainUser failed (Err Code -> %u)", dwRet);
}
else
{
printf("nValidateDomainUser success.");
}
return 0;
}
The problem is that GetFirstRow returns S_ADS_NOMORE_ROWS whereas "administrator" user exists on the DC. Can anyone show some light on the issue. I will appreciate that.
Thank you.
-Abhay
View the full article
Ive a code block that checks if a given user exists in Active Directory DC, if yes, then it checks if it is member of Domain Admin group. Here is the codeBOOLEAN
GetUserLdapPath(
IADsContainer* pContainer,
const WCHAR *pcwszUsername,
WCHAR *pwszLdapPath,
DWORD dwcchLdapPathSize,
DWORD *pdwError
)
{
VARIANT var;
ULONG lFetch;
IADs *pADs = NULL;
HRESULT hr = E_FAIL;
HRESULT hrGC = S_OK;
IUnknown *pUnk = NULL;
IDispatch *pDisp = NULL;
IEnumVARIANT *pEnum = NULL;
IDirectorySearch *pGCSearch = NULL;
if (NULL == pContainer || NULL == pcwszUsername || NULL == pwszLdapPath || 0 == dwcchLdapPathSize || NULL == pdwError)
{
return FALSE;
}
hr = pContainer->get__NewEnum(&pUnk);
if (SUCCEEDED(hr))
{
hr = pUnk->QueryInterface(IID_IEnumVARIANT, (void**) &pEnum);
if (SUCCEEDED(hr))
{
//
// Now Enumerate--there should be only one item.
//
hr = pEnum->Next(1, &var, &lFetch);
if (SUCCEEDED(hr))
{
while (hr == S_OK)
{
if (lFetch == 1)
{
pDisp = V_DISPATCH(&var);
hr = pDisp->QueryInterface(IID_IDirectorySearch, (void**)&pGCSearch);
hrGC = hr;
}
VariantClear(&var);
hr = pEnum->Next(1, &var, &lFetch);
};
}
}
if (pEnum)
{
pEnum->Release();
}
}
if (pUnk)
{
pUnk->Release();
}
if (FAILED(hrGC))
{
if (pGCSearch)
{
pGCSearch->Release();
}
return FALSE;
}
//
// Create search filter.
//
WCHAR rgSearchFilter[1024];
wsprintfW(rgSearchFilter, L"(&(objectCategory=person)(objectClass=user)(sAMAccountName=%s))", pcwszUsername);
//Search entire subtree from root.
ADS_SEARCHPREF_INFO SearchPrefs;
SearchPrefs.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
SearchPrefs.vValue.dwType = ADSTYPE_INTEGER;
SearchPrefs.vValue.Integer = ADS_SCOPE_SUBTREE;
DWORD dwNumPrefs = 1;
// COL for iterations
ADS_SEARCH_COLUMN col;
// Handle used for searching
ADS_SEARCH_HANDLE hSearch;
// Set the search preference
hr = pGCSearch->SetSearchPreference(&SearchPrefs, dwNumPrefs);
if (FAILED(hr))
{
return FALSE;
}
// Set attributes to return
CONST DWORD dwAttrNameSize = 4;
LPOLESTR pszAttribute[dwAttrNameSize] = {L"cn", L"distinguishedName", L"sAMAccountName", L"ADsPath"};
// Execute the search
hr = pGCSearch->ExecuteSearch(rgSearchFilter, pszAttribute, dwAttrNameSize, &hSearch);
if (SUCCEEDED(hr))
{
if (pGCSearch->GetFirstRow(hSearch) == S_ADS_NOMORE_ROWS)
{
return FALSE;
}
else // The UPN was found
{
do
{
// loop through the array of passed column names, print the data for each column.
for (DWORD x = 0; x < dwAttrNameSize; x++)
{
// Get the data for this column.
hr = pGCSearch->GetColumn(hSearch, pszAttribute[x], &col);
if (SUCCEEDED(hr))
{
// Print the data for the column and free the column.
// Note the attributes we asked for are type CaseIgnoreString.
// wprintf(L"%s: %srn", pszAttribute[x], col.pADsValues->CaseIgnoreString);
if (x == dwAttrNameSize - 1)
{
wcscpy(pwszLdapPath, col.pADsValues->CaseIgnoreString);
}
pGCSearch->FreeColumn(&col);
}
else
{
//wprintf(L"<%s property is not a string>", pszAttribute[x]);
}
}
}
while (pGCSearch->GetNextRow(hSearch) != S_ADS_NOMORE_ROWS);
}
// Close the search handle to clean up.
pGCSearch->CloseSearchHandle(hSearch);
}
if (pGCSearch)
{
pGCSearch->Release();
}
return TRUE;
}
BOOLEAN __stdcall
ValidateDomainUser(
const WCHAR *pcwszDomainName,
WCHAR *pwszUserName,
WCHAR *pwszPassword,
DWORD *pdwError
)
{
HRESULT hr;
BOOLEAN bRet;
DWORD dwError;
WCHAR *pwszDomainStart;
USER_INFO_1 *pUserInfo;
WCHAR wszUser[_MAX_PATH];
IADsContainer *pContainer;
WCHAR wszDomainName[_MAX_PATH];
WCHAR wszDomainNameWithoutLDAP[MAX_CNNAME_LENGTH];
if (NULL == pcwszDomainName || NULL == pwszPassword || NULL == pwszUserName || NULL == pdwError)
{
return FALSE;
}
CoInitialize(NULL);
hr = ADsOpenObject(
pcwszDomainName,
pwszUserName,
pwszPassword,
ADS_SECURE_AUTHENTICATION, // ADS_SERVER_BIND decision pending.
IID_IADsContainer,
(LPVOID*)&pContainer
);
if (FAILED(hr))
{
CoUninitialize();
return FALSE;
}
WCHAR *pwszTemp = NULL;
WCHAR wszAdsPath[_MAX_PATH] = {0};
wcscpy(wszUser, pwszUserName);
pwszTemp = wcschr(wszUser, L@);
if (pwszTemp)
{
*pwszTemp = L;
}
// Get users complete path if the user exists in domain.
bRet = GetUserLdapPath(pContainer, wszUser, wszAdsPath, ARRAY_SIZE(wszAdsPath), pdwError);
if (FALSE == bRet)
{
pContainer->Release();
CoUninitialize();
return FALSE;
}
pContainer->Release();
IADsUser *pUser = NULL;
hr = ADsOpenObject(
wszAdsPath,
pwszUserName,
pwszPassword,
ADS_SECURE_AUTHENTICATION, // ADS_SERVER_BIND decision pending.
IID_IADsUser,
(LPVOID*)&pUser
);
if (FAILED(hr))
{
CoUninitialize();
return FALSE;
}
//
// Check if the user belongs to Doamin Admins group.
// Note: Doamin Admins group name can be renamed by administrator
// where DC is installed. In this case, IsAdminUser will returns
// FALSE. It relies on group name returned by IADsUser interface.
//
bRet = IsAdminUser(pUser);
pUser->Release();
CoUninitialize();
return bRet;
}
BOOLEAN IsAdminUser(IADsUser *pUser)
{
HRESULT hr = S_OK;
IADsMembers *pGroups;
hr = pUser->Groups(&pGroups);
if (FAILED(hr))
{
return FALSE;
}
IUnknown *pUnk;
hr = pGroups->get__NewEnum(&pUnk);
if (FAILED(hr))
{
return FALSE;
}
pGroups->Release();
IEnumVARIANT *pEnum;
hr = pUnk->QueryInterface(IID_IEnumVARIANT,(void**)&pEnum);
if (FAILED(hr))
{
return FALSE;
}
pUnk->Release();
// Enumerate.
BSTR bstr;
VARIANT var;
IADs *pADs;
ULONG lFetch;
IDispatch *pDisp;
VariantInit(&var);
hr = pEnum->Next(1, &var, &lFetch);
while(hr == S_OK)
{
if (lFetch == 1)
{
pDisp = V_DISPATCH(&var);
pDisp->QueryInterface(IID_IADs, (void**)&pADs);
pADs->get_Name(&bstr);
if (0 == wcscmp(L"CN=Domain Admins", bstr))
{
SysFreeString(bstr);
pADs->Release();
VariantClear(&var);
pDisp=NULL;
pEnum->Release();
return TRUE;
}
SysFreeString(bstr);
pADs->Release();
}
VariantClear(&var);
pDisp=NULL;
hr = pEnum->Next(1, &var, &lFetch);
};
hr = pEnum->Release();
return FALSE;
}
int main()
{
DWORD dwRet;
BOOLEAN bRet = ValidateDomainUser(
L"architectsunited.com,
L"administrator@architectsunite",
L"...",
&dwRet
);
if (FALSE == bRet)
{
printf("nValidateDomainUser failed (Err Code -> %u)", dwRet);
}
else
{
printf("nValidateDomainUser success.");
}
return 0;
}
The problem is that GetFirstRow returns S_ADS_NOMORE_ROWS whereas "administrator" user exists on the DC. Can anyone show some light on the issue. I will appreciate that.
Thank you.
-Abhay
View the full article