예제 #1
0
DWORD
DefaultModeNonSchemaEnumNSSArtefacts(
    PLSA_DM_LDAP_CONNECTION pConn,
    PCSTR          pszCellDN,
    PCSTR          pszNetBIOSDomainName,
    PAD_ENUM_STATE pEnumState,
    DWORD          dwMaxNumNSSArtefacts,
    PDWORD         pdwNumNSSArtefactsFound,
    PVOID**        pppNSSArtefactInfoList
    )
{
    DWORD dwError = 0;
    DWORD dwCount = 0;
    PCSTR pszQuery = "(&(objectClass=serviceConnectionPoint)(keywords=objectClass=centerisLikewiseMapEntry))";
    PSTR pszDN = NULL;
    PSTR pszEscapedDN = NULL;
    PVOID* ppNSSArtefactInfoList = NULL;
    PVOID* ppNSSArtefactInfoList_accumulate = NULL;
    DWORD  dwTotalNumNSSArtefactsFound = 0;
    DWORD  dwNumNSSArtefactsFound = 0;
    DWORD  dwNSSArtefactInfoLevel = 0;
    PSTR szAttributeList[] =
               {
                 AD_LDAP_NAME_TAG,
                 AD_LDAP_KEYWORDS_TAG,
                 NULL
               };

    LDAPMessage *pMessagePseudo = NULL;
    LDAP *pLd = NULL;
    HANDLE hDirectory = NULL;
    DWORD dwNumNSSArtefactsWanted = dwMaxNumNSSArtefacts;

    dwNSSArtefactInfoLevel = pEnumState->dwInfoLevel;

    BAIL_ON_INVALID_STRING(pEnumState->pszMapName);

    dwError = LwAllocateStringPrintf(
                    &pszDN,
                    "CN=%s,CN=Maps,%s",
                    pEnumState->pszMapName,
                    pszCellDN);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwLdapEscapeString(
                    &pszEscapedDN,
                    pszDN);
    BAIL_ON_LSA_ERROR(dwError);

    if (pEnumState->Cookie.bSearchFinished){
            dwError = LW_ERROR_NO_MORE_NSS_ARTEFACTS;
            BAIL_ON_LSA_ERROR(dwError);
    }

    do
    {
        dwError = LsaDmLdapDirectoryOnePagedSearch(
                       pConn,
                       pszEscapedDN,
                       pszQuery,
                       szAttributeList,
                       dwNumNSSArtefactsWanted,
                       &pEnumState->Cookie,
                       LDAP_SCOPE_ONELEVEL,
                       &hDirectory,
                       &pMessagePseudo);
        BAIL_ON_LSA_ERROR(dwError);

        pLd = LwLdapGetSession(hDirectory);

        dwCount = ldap_count_entries(
                          pLd,
                          pMessagePseudo);
        if (dwCount < 0) {
           dwError = LW_ERROR_LDAP_ERROR;
        } else if (dwCount == 0) {
           dwError = LW_ERROR_NO_MORE_NSS_ARTEFACTS;
        }
        BAIL_ON_LSA_ERROR(dwError);

        dwError = ADNonSchemaMarshalNSSArtefactInfoList(
                        hDirectory,
                        pszNetBIOSDomainName,
                        pMessagePseudo,
                        pEnumState->dwMapFlags,
                        dwNSSArtefactInfoLevel,
                        &ppNSSArtefactInfoList,
                        &dwNumNSSArtefactsFound
                        );
        BAIL_ON_LSA_ERROR(dwError);

        dwNumNSSArtefactsWanted -= dwNumNSSArtefactsFound;

        dwError = LsaAppendAndFreePtrs(
                        &dwTotalNumNSSArtefactsFound,
                        &ppNSSArtefactInfoList_accumulate,
                        &dwNumNSSArtefactsFound,
                        &ppNSSArtefactInfoList);
        BAIL_ON_LSA_ERROR(dwError);

        if (pMessagePseudo) {
               ldap_msgfree(pMessagePseudo);
               pMessagePseudo = NULL;
        }
    } while (!pEnumState->Cookie.bSearchFinished && dwNumNSSArtefactsWanted);

    *pppNSSArtefactInfoList = ppNSSArtefactInfoList_accumulate;
    *pdwNumNSSArtefactsFound = dwTotalNumNSSArtefactsFound;

cleanup:

    LW_SAFE_FREE_STRING(pszDN);
    LW_SAFE_FREE_STRING(pszEscapedDN);

    return dwError;

error:

    *pppNSSArtefactInfoList = NULL;
    *pdwNumNSSArtefactsFound = 0;

    if (ppNSSArtefactInfoList) {
        LsaFreeNSSArtefactInfoList(dwNSSArtefactInfoLevel, ppNSSArtefactInfoList, dwNumNSSArtefactsFound);
    }

    if (ppNSSArtefactInfoList_accumulate) {
        LsaFreeNSSArtefactInfoList(dwNSSArtefactInfoLevel, ppNSSArtefactInfoList_accumulate, dwTotalNumNSSArtefactsFound);
    }

    if (dwError == LW_ERROR_LDAP_NO_SUCH_OBJECT)
    {
        dwError = LW_ERROR_NO_MORE_NSS_ARTEFACTS;
    }

    goto cleanup;
}
예제 #2
0
DWORD
DefaultModeNonSchemaFindNSSArtefactByKey(
    IN PLSA_DM_LDAP_CONNECTION pConn,
    PCSTR          pszCellDN,
    PCSTR          pszNetBIOSDomainName,
    PCSTR          pszKeyName,
    PCSTR          pszMapName,
    DWORD          dwInfoLevel,
    LSA_NIS_MAP_QUERY_FLAGS dwFlags,
    PVOID*         ppNSSArtefactInfo
    )
{
    DWORD  dwError = 0;
    DWORD  dwCount = 0;
    PSTR   pszQuery = NULL;
    PSTR   pszDN = NULL;
    PSTR   pszEscapedDN = NULL;
    PSTR szAttributeList[] =
        {
             AD_LDAP_NAME_TAG,
             AD_LDAP_KEYWORDS_TAG,
             NULL
        };

    LDAPMessage *pMessagePseudo = NULL;
    PVOID* ppArtefactInfos = NULL;
    DWORD dwNumInfos = 0;
    BOOLEAN bMapExists = FALSE;
    LDAP *pLd = NULL;
    HANDLE hDirectory = NULL;

    BAIL_ON_INVALID_STRING(pszMapName);
    BAIL_ON_INVALID_STRING(pszKeyName);

    dwError = LwAllocateStringPrintf(
                    &pszDN,
                    "CN=%s,CN=Maps,%s",
                    pszMapName,
                    pszCellDN);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwLdapEscapeString(
                   &pszEscapedDN,
                   pszDN);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = ADLdap_IsValidDN(
                    pConn,
                    pszEscapedDN,
                    &bMapExists);
    BAIL_ON_LSA_ERROR(dwError);

    if (!bMapExists)
    {
        dwError = LW_ERROR_NO_SUCH_NSS_MAP;
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwError = LwAllocateStringPrintf(
                    &pszQuery,
                    "(&(objectClass=serviceConnectionPoint)(keywords=objectClass=centerisLikewiseMapEntry)(name=%s))",
                    pszKeyName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaDmLdapDirectorySearch(
                   pConn,
                   pszEscapedDN,
                   LDAP_SCOPE_ONELEVEL,
                   pszQuery,
                   szAttributeList,
                   &hDirectory,
                   &pMessagePseudo);
    BAIL_ON_LSA_ERROR(dwError);

    pLd = LwLdapGetSession(hDirectory);

    dwCount = ldap_count_entries(
                      pLd,
                      pMessagePseudo);
    if (dwCount < 0) {
       dwError = LW_ERROR_LDAP_ERROR;
    } else if (dwCount == 0) {
       dwError = LW_ERROR_NO_SUCH_NSS_KEY;
    }
    BAIL_ON_LSA_ERROR(dwError);

    dwError = ADNonSchemaMarshalNSSArtefactInfoList(
                    hDirectory,
                    pszNetBIOSDomainName,
                    pMessagePseudo,
                    dwFlags,
                    dwInfoLevel,
                    &ppArtefactInfos,
                    &dwNumInfos);
    BAIL_ON_LSA_ERROR(dwError);

    *ppNSSArtefactInfo = *ppArtefactInfos;
    *ppArtefactInfos = NULL;

cleanup:

    if (pMessagePseudo) {
        ldap_msgfree(pMessagePseudo);
    }

    if (ppArtefactInfos)
    {
        LsaFreeNSSArtefactInfoList(dwInfoLevel, ppArtefactInfos, dwNumInfos);
    }

    LW_SAFE_FREE_STRING(pszDN);
    LW_SAFE_FREE_STRING(pszEscapedDN);
    LW_SAFE_FREE_STRING(pszQuery);

    return dwError;

error:

    *ppNSSArtefactInfo = NULL;

    if (dwError == LW_ERROR_LDAP_NO_SUCH_OBJECT)
    {
        dwError = LW_ERROR_NO_SUCH_NSS_KEY;
    }

    goto cleanup;
}
예제 #3
0
static
DWORD
LsaAdBatchBuilderBatchItemGetAttributeValue(
    IN PAD_PROVIDER_DATA pProviderData,
    IN PVOID pCallbackContext,
    IN PVOID pItem,
    OUT PCSTR* ppszValue,
    OUT PVOID* ppFreeValueContext
    )
{
    DWORD dwError = 0;
    PLSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT pContext = (PLSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT)pCallbackContext;
    LSA_AD_BATCH_QUERY_TYPE QueryType = pContext->QueryType;
    BOOLEAN bIsForRealObject = pContext->bIsForRealObject;
    PLSA_LIST_LINKS pLinks = (PLSA_LIST_LINKS)pItem;
    PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks);
    PSTR pszValueToEscape = NULL;
    PSTR pszValueToHex = NULL;
    PSTR pszValue = NULL;
    PVOID pFreeValueContext = NULL;
    // Free this on error only.
    PSTR pszMatchTerm = NULL;
    PSTR pszAllocatedMatchTermValue = NULL;
    BOOLEAN bHaveReal = IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_REAL);
    BOOLEAN bHavePseudo = IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_PSEUDO);

    if (IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM))
    {
        LW_SAFE_FREE_STRING(pBatchItem->pszQueryMatchTerm);
        ClearFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM);
    }

    if ((bIsForRealObject && bHaveReal) ||
        (!bIsForRealObject && bHavePseudo))
    {
        // This can only happen in the linked cells case, but even
        // that should go away in the future as we just keep an
        // unresolved batch items list.

        LSA_ASSERT(!bIsForRealObject && (pProviderData->dwDirectoryMode == CELL_MODE));
        goto cleanup;
    }

    switch (QueryType)
    {
        case LSA_AD_BATCH_QUERY_TYPE_BY_DN:
            // Must be looking for real object
            LSA_ASSERT(bIsForRealObject);
            LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type);

            pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString;
            LSA_ASSERT(pszValueToEscape);
            break;

        case LSA_AD_BATCH_QUERY_TYPE_BY_SID:
            if (pBatchItem->pszSid)
            {
                // This is case where we already got the SID by resolving
                // the pseudo object by id/alias.
                pszValue = pBatchItem->pszSid;
            }
            else if (QueryType == pBatchItem->QueryTerm.Type)
            {
                // This is the case where the original query was
                // a query by SID.
                pszValue = (PSTR)pBatchItem->QueryTerm.pszString;
                LSA_ASSERT(pszValue);
            }
            // Will be NULL if we cannot find a SID for which to query.
            // This can happen if this batch item is for an object
            // that we did not find real but are trying to look up pseudo.
            // In that case, we have NULL and will just skip it.

            // If we have a SID string, make sure it looks like a SID.
            // Note that we must do some sanity checking to make sure
            // that the string does not need escaping since we are
            // not setting pszValueToEscape.  (The SID check takes
            // care of that.)
            if (pszValue && !LsaAdBatchHasValidCharsForSid(pszValue))
            {
                LSA_ASSERT(FALSE);
                dwError = LW_ERROR_INTERNAL;
                BAIL_ON_LSA_ERROR(dwError);
            }

            if (bIsForRealObject)
            {
                // "S-"-style SID string are only handled starting with
                // Windows 2003.  So an LDAP hex-formatted SID string
                // is needed to handle Windows 2000.

                pszValueToHex = pszValue;
                pszValue = NULL;
            }
            break;

        case LSA_AD_BATCH_QUERY_TYPE_BY_NT4:
            LSA_ASSERT(bIsForRealObject);
            if (pBatchItem->pszSamAccountName)
            {
                // Unprovisioned id/alias case where id mapper returned
                // a SAM account name (and domain name) but no SID.
                pszValueToEscape = pBatchItem->pszSamAccountName;
                // However, we currently do not have this sort of id mapper
                // support, so we LSA_ASSERT(FALSE) for now.
                LSA_ASSERT(FALSE);
            }
            else if (QueryType == pBatchItem->QueryTerm.Type)
            {
                pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString;
                LSA_ASSERT(pszValueToEscape);
            }
            break;

        case LSA_AD_BATCH_QUERY_TYPE_BY_UID:
        case LSA_AD_BATCH_QUERY_TYPE_BY_GID:
            LSA_ASSERT(!bIsForRealObject);
            LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type);

            dwError = LwAllocateStringPrintf(
                            &pszAllocatedMatchTermValue,
                            "%u",
                            (unsigned int)pBatchItem->QueryTerm.dwId);
            BAIL_ON_LSA_ERROR(dwError);
            pszValue = pszAllocatedMatchTermValue;

            // Note: It is ok to set this here because it is ok for
            // this flag to be set if the match term field in the
            // batch item is still NULL (i.e., if we fail later in
            // this function).
            SetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM);

            break;

        case LSA_AD_BATCH_QUERY_TYPE_BY_USER_ALIAS:
        case LSA_AD_BATCH_QUERY_TYPE_BY_GROUP_ALIAS:
            LSA_ASSERT(!bIsForRealObject);
            LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type);

            pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString;
            LSA_ASSERT(pszValueToEscape);
            break;

        default:
            dwError = LW_ERROR_INVALID_PARAMETER;
            BAIL_ON_LSA_ERROR(dwError);
    }

    LSA_ASSERT(!pszMatchTerm);
    LSA_ASSERT(!(pszValueToEscape && pszValueToHex));

    if (pszValueToEscape)
    {
        LSA_ASSERT(!pszValue);
        dwError = LwLdapEscapeString(&pszValue, pszValueToEscape);
        BAIL_ON_LSA_ERROR(dwError);

        pszMatchTerm = pszValueToEscape;
        pFreeValueContext = pszValue;
    }
    else if (pszValueToHex)
    {
        LSA_ASSERT(!pszValue);
        dwError = LsaSidStrToLdapFormatHexStr(pszValueToHex, &pszValue);
        BAIL_ON_LSA_ERROR(dwError);

        pszMatchTerm = pszValueToHex;
        pFreeValueContext = pszValue;
    }
    else
    {
        pszMatchTerm = pszValue;
    }

cleanup:
    // Note that the match value can be different from the value,
    // which we may need to escape or hex.
    pBatchItem->pszQueryMatchTerm = pszMatchTerm;
    *ppszValue = pszValue;
    *ppFreeValueContext = pFreeValueContext;

    return dwError;

error:
    // assing output in cleanup in case of goto cleanup in function.
    pszValueToEscape = NULL;
    pszValue = NULL;
    LW_SAFE_FREE_STRING(pFreeValueContext);
    LW_SAFE_FREE_STRING(pszAllocatedMatchTermValue);
    goto cleanup;
}
예제 #4
0
static
DWORD
AD_RawFindComputerDn(
    IN HANDLE hDirectory,
    IN PCSTR pszDnsDomainName,
    IN PCSTR pszSamAccountName,
    OUT PSTR* ppszComputerDn
    )
{
    DWORD dwError = 0;
    LDAP* pLd = NULL;
    PSTR pszDirectoryRoot = NULL;
    PSTR pszEscapedSamAccountName = NULL;
    PSTR szAttributeList[] = {"*", NULL};
    PSTR pszQuery = NULL;
    LDAPMessage *pMessage = NULL;
    int count = 0;
    PSTR pszComputerDn = NULL;

    pLd = LwLdapGetSession(hDirectory);

    dwError = LwLdapConvertDomainToDN(
                    pszDnsDomainName,
                    &pszDirectoryRoot);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwLdapEscapeString(
                    &pszEscapedSamAccountName,
                    pszSamAccountName);
    BAIL_ON_LSA_ERROR(dwError);
    
    LwStrToUpper(pszEscapedSamAccountName);

    dwError = LwAllocateStringPrintf(
                    &pszQuery,
                    "(sAMAccountName=%s)",
                    pszEscapedSamAccountName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwLdapDirectorySearch(
                    hDirectory,
                    pszDirectoryRoot,
                    LDAP_SCOPE_SUBTREE,
                    pszQuery,
                    szAttributeList,
                    &pMessage);
    BAIL_ON_LSA_ERROR(dwError);

    count = ldap_count_entries(pLd, pMessage);
    if (count < 0)
    {
        dwError = LW_ERROR_LDAP_ERROR;
    }
    else if (count == 0)
    {
        dwError = LW_ERROR_NO_SUCH_DOMAIN;
    }
    else if (count > 1)
    {
        dwError = LW_ERROR_DUPLICATE_DOMAINNAME;
    }
    BAIL_ON_LSA_ERROR(dwError);   

    dwError = LwLdapGetDN(hDirectory, pMessage, &pszComputerDn);
    BAIL_ON_LSA_ERROR(dwError);

    if (LW_IS_NULL_OR_EMPTY_STR(pszComputerDn))
    {
        dwError = LW_ERROR_LDAP_FAILED_GETDN;
        BAIL_ON_LSA_ERROR(dwError);        
    }

error:
    if (dwError)
    {
        LW_SAFE_FREE_STRING(pszComputerDn);
    }

    LW_SAFE_FREE_STRING(pszDirectoryRoot);
    LW_SAFE_FREE_STRING(pszEscapedSamAccountName);
    LW_SAFE_FREE_STRING(pszQuery);

    if (pMessage)
    {
        ldap_msgfree(pMessage);
    }

    *ppszComputerDn = pszComputerDn;

    return dwError;
}
예제 #5
0
파일: adldap.c 프로젝트: borland667/pbis
DWORD
ADFindComputerDN(
    IN PLSA_DM_LDAP_CONNECTION pConn,
    PCSTR pszSamAccountName,
    PCSTR pszDomainName,
    PSTR* ppszComputerDN
    )
{
    DWORD dwError = 0;
    LDAP *pLd = NULL;
    PSTR pszDirectoryRoot = NULL;
    PSTR szAttributeList[] = {"*", NULL};
    PSTR pszQuery = NULL;
    LDAPMessage *pMessage = NULL;
    DWORD dwCount = 0;
    PSTR pszComputerDN = NULL;
    PSTR pszEscapedUpperSamAccountName = NULL;
    HANDLE hDirectory = NULL;

    dwError = LwLdapConvertDomainToDN(pszDomainName, &pszDirectoryRoot);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwLdapEscapeString(
                &pszEscapedUpperSamAccountName,
                pszSamAccountName);
    BAIL_ON_LSA_ERROR(dwError);

    LwStrToUpper(pszEscapedUpperSamAccountName);

    dwError = LwAllocateStringPrintf(&pszQuery,
                                      "(sAMAccountName=%s)",
                                      pszEscapedUpperSamAccountName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaDmLdapDirectorySearch(
                    pConn,
                    pszDirectoryRoot,
                    LDAP_SCOPE_SUBTREE,
                    pszQuery,
                    szAttributeList,
                    &hDirectory,
                    &pMessage);
    BAIL_ON_LSA_ERROR(dwError);

    pLd = LwLdapGetSession(hDirectory);

    dwCount = ldap_count_entries(
                pLd,
                pMessage
                );
    if (dwCount < 0) {
        dwError = LW_ERROR_LDAP_ERROR;
    } else if (dwCount == 0) {
        dwError = LW_ERROR_NO_SUCH_DOMAIN;
    } else if (dwCount > 1) {
        dwError = LW_ERROR_DUPLICATE_DOMAINNAME;
    }
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwLdapGetDN(
                    hDirectory,
                    pMessage,
                    &pszComputerDN);
    BAIL_ON_LSA_ERROR(dwError);

    if (LW_IS_NULL_OR_EMPTY_STR(pszComputerDN))
    {
        dwError = LW_ERROR_LDAP_FAILED_GETDN;
        BAIL_ON_LSA_ERROR(dwError);
    }

    *ppszComputerDN = pszComputerDN;

cleanup:
    LW_SAFE_FREE_STRING(pszEscapedUpperSamAccountName);
    LW_SAFE_FREE_STRING(pszDirectoryRoot);
    LW_SAFE_FREE_STRING(pszQuery);

    if (pMessage) {
        ldap_msgfree(pMessage);
    }

    return dwError;

error:

    *ppszComputerDN = NULL;
    LW_SAFE_FREE_STRING(pszComputerDN);

    goto cleanup;
}
예제 #6
0
파일: adldap.c 프로젝트: borland667/pbis
DWORD
ADLdap_AddDomainLocalGroups(
    IN PAD_PROVIDER_CONTEXT pContext,
    IN PLSA_SECURITY_OBJECT pObject,
    IN OUT PLW_HASH_TABLE pGroupHash
    )
{
    DWORD dwError =  0;
    PLSA_DM_LDAP_CONNECTION pConn = NULL;
    PSTR szAttributeList[] = {
        AD_LDAP_OBJECTSID_TAG,
        NULL
    };
    PSTR pDomainDN = NULL;
    PSTR pszEscapedDN = NULL;
    // Do not free. This is owned by pConn
    HANDLE hDirectory = NULL;
    LDAPMessage* pMessage = NULL;
    // Do not free. This is owned by pConn
    LDAP* pLd = NULL;
    PSTR pGroupSid = NULL;
    PSTR pFilter = NULL;
    // Do not free
    LDAPMessage* pCurrentMessage = NULL;

    dwError = LsaDmLdapOpenDc(
                    pContext,
                    pContext->pState->pszDomainName,
                    &pConn);
    BAIL_ON_LSA_ERROR(dwError);
    
    dwError = LwLdapConvertDomainToDN(
                    pContext->pState->pszDomainName,
                    &pDomainDN);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwLdapEscapeString(&pszEscapedDN, pObject->pszDN);
    BAIL_ON_LSA_ERROR(dwError);

    // groupType: 2147483652 = 0x80000004 = ( GROUP_TYPE_RESOURCE_GROUP |
    // GROUP_TYPE_SECURITY_ENABLED ) = domain local security group
    dwError = LwAllocateStringPrintf(
                    &pFilter,
                    "(&(|(member=%s)(member=CN=%s,CN=ForeignSecurityPrincipals,%s))(groupType=2147483652))",
                    pszEscapedDN,
                    pObject->pszObjectSid,
                    pDomainDN);
    BAIL_ON_LSA_ERROR(dwError);
 
    dwError = LsaDmLdapDirectorySearch(
                    pConn,
                    pDomainDN,
                    LDAP_SCOPE_SUBTREE,
                    pFilter,
                    szAttributeList,
                    &hDirectory,
                    &pMessage);
    BAIL_ON_LSA_ERROR(dwError);                   

    pLd = LwLdapGetSession(hDirectory);

    pCurrentMessage = ldap_first_entry(pLd, pMessage);
    while (pCurrentMessage)
    {
        LW_SAFE_FREE_STRING(pGroupSid);
        dwError = ADLdap_GetObjectSid(
                        hDirectory,
                        pCurrentMessage,
                        &pGroupSid);
        BAIL_ON_LSA_ERROR(dwError);

        if (!LwHashExists(pGroupHash, pGroupSid))
        {
            // Set the value of the hash entry so this string gets freed with
            // the hash.
            dwError = LwHashSetValue(pGroupHash, pGroupSid, pGroupSid);
            BAIL_ON_LSA_ERROR(dwError);

            pGroupSid = NULL;
        }

        pCurrentMessage = ldap_next_entry(pLd, pCurrentMessage);
    }

cleanup:
    LsaDmLdapClose(pConn);
    LW_SAFE_FREE_STRING(pszEscapedDN);
    LW_SAFE_FREE_STRING(pDomainDN);
    LW_SAFE_FREE_STRING(pFilter);
    LW_SAFE_FREE_STRING(pGroupSid);
    if (pMessage)
    {
        ldap_msgfree(pMessage);
    }
    return dwError;

error:
    goto cleanup;
}