Esempio n. 1
0
static
DWORD
_VmGetHighestCommittedUSN(
    PSTR*   ppszHighestCommittedUSN
    )
{
    DWORD               dwError = 0;
    USN                 usn = 0;
    USN                 nextUSN = 0;
    VDIR_ENTRY_ARRAY    entryArray = {0};
    PSTR                pszUSN = NULL;
    VDIR_BACKEND_CTX    beCtx = {0};

    beCtx.pBE = VmDirBackendSelect(NULL);
    assert(beCtx.pBE);

    dwError = beCtx.pBE->pfnBEGetNextUSN(&beCtx, &nextUSN);
    BAIL_ON_VMDIR_ERROR(dwError);

    for (usn=nextUSN; usn > 1LL; usn--)
    {
        VMDIR_SAFE_FREE_MEMORY(pszUSN);
        VmDirFreeEntryArrayContent(&entryArray);

        dwError = VmDirAllocateStringPrintf(&pszUSN, "%" PRId64, usn);
        BAIL_ON_VMDIR_ERROR(dwError);

        dwError = VmDirSimpleEqualFilterInternalSearch(
                    "", LDAP_SCOPE_SUBTREE, ATTR_USN_CHANGED, pszUSN, &entryArray);
        BAIL_ON_VMDIR_ERROR(dwError);

        if (entryArray.iSize == 1 )
        {
            break;
        }
    }

    if (usn == 0)
    {
        BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_STATE);
    }

    *ppszHighestCommittedUSN = pszUSN;
    pszUSN = NULL;

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszUSN);
    VmDirFreeEntryArrayContent(&entryArray);
    VmDirBackendCtxContentFree(&beCtx);

    return dwError;

error:
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "error (%u), start USN %" PRId64, dwError, nextUSN);
    goto cleanup;
}
Esempio n. 2
0
static
int
_VmGetHighestCommittedUSN(
    USN startUsn,
    USN *hcUsn)
{
    DWORD             dwError = 0;
    USN               usn = 0;
    VDIR_ENTRY_ARRAY  entryArray = {0};
    PSTR              usnStr = NULL;


    for (usn=startUsn; usn > 1LL; usn--)
    {
        VMDIR_SAFE_FREE_MEMORY(usnStr);
        VmDirFreeEntryArrayContent(&entryArray);

        dwError = VmDirAllocateStringPrintf(&usnStr, "%" PRId64, usn);
        BAIL_ON_VMDIR_ERROR(dwError);

        dwError = VmDirSimpleEqualFilterInternalSearch(
                    "", LDAP_SCOPE_SUBTREE, ATTR_USN_CHANGED, usnStr, &entryArray);
        BAIL_ON_VMDIR_ERROR(dwError);

        if (entryArray.iSize == 1 )
        {
            *hcUsn = usn;
            goto cleanup;
        }
    }
    dwError = LDAP_OPERATIONS_ERROR;
    goto error;

cleanup:
    VMDIR_SAFE_FREE_MEMORY(usnStr);
    VmDirFreeEntryArrayContent(&entryArray);
    return dwError;

error:
    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_VmGetHighestCommittedUSN: fail to find an entry with USN <= %" PRId64, startUsn);
    goto cleanup;
}
Esempio n. 3
0
void
VmDirFreeEntryArray(
    PVDIR_ENTRY_ARRAY   pEntryAry
    )
{
    if (pEntryAry)
    {
        VmDirFreeEntryArrayContent(pEntryAry);
        VMDIR_SAFE_FREE_MEMORY(pEntryAry);
    }
}
Esempio n. 4
0
void
VmDirFreeOperationContent(
    PVDIR_OPERATION op
    )
{
    DWORD dwError = ERROR_SUCCESS;

    if (op)
    {
        if (op->pSchemaCtx)
        {
            VmDirSchemaCtxRelease(op->pSchemaCtx);
        }

        if (op->syncDoneCtrl)
        {
            PLW_HASHTABLE_NODE      pNode = NULL;
            LW_HASHTABLE_ITER       iter = LW_HASHTABLE_ITER_INIT;
            UptoDateVectorEntry *   pUtdVectorEntry = NULL;
            SyncDoneControlValue *  syncDoneCtrlVal = &op->syncDoneCtrl->value.syncDoneCtrlVal;

            while ((pNode = LwRtlHashTableIterate(syncDoneCtrlVal->htUtdVector, &iter)))
            {
                dwError = LwRtlHashTableRemove(syncDoneCtrlVal->htUtdVector, pNode);
                assert( dwError == 0 );
                pUtdVectorEntry = LW_STRUCT_FROM_FIELD(pNode, UptoDateVectorEntry, Node);
                VmDirFreeBervalContent( &pUtdVectorEntry->invocationId );
                VMDIR_SAFE_FREE_MEMORY( pUtdVectorEntry );
            }
            LwRtlFreeHashTable(&syncDoneCtrlVal->htUtdVector);
            assert( syncDoneCtrlVal->htUtdVector == NULL );

            VMDIR_SAFE_FREE_MEMORY( op->syncDoneCtrl );
        }

        if (op->pCondWriteCtrl)
        {
            VMDIR_SAFE_FREE_MEMORY(op->pCondWriteCtrl->value.condWriteCtrlVal.pszFilter);
        }

        if (op->reqControls)
        {
            DeleteControls(&(op->reqControls));
        }

        switch (op->reqCode)
        {
            case LDAP_REQ_BIND:
                 VmDirFreeBindRequest(&op->request.bindReq, FALSE);
                 if (op->ldapResult.replyInfo.type == REP_SASL)
                 {
                     VmDirFreeBervalContent( &(op->ldapResult.replyInfo.replyData.bvSaslReply) );
                 }
                 break;

            case LDAP_REQ_ADD:
                 VmDirFreeAddRequest(&op->request.addReq, FALSE);
                 break;

            case LDAP_REQ_SEARCH:
                 VmDirFreeSearchRequest(&op->request.searchReq, FALSE);
                 break;

            case LDAP_REQ_MODIFY:
            case LDAP_REQ_MODDN:
                 VmDirFreeModifyRequest(&op->request.modifyReq, FALSE);
                 break;

            case LDAP_REQ_DELETE:
                 VmDirFreeDeleteRequest(&op->request.deleteReq, FALSE);
                 if (op->request.modifyReq.numMods > 0)
                 {
                     //A raft follower needs to create a modifyReq for Delete OP
                     VmDirFreeModifyRequest(&op->request.modifyReq, FALSE);
                 }
                 break;

            default:
                 break;
        }

        VmDirFreeEntryArrayContent(&(op->internalSearchEntryArray));
        VmDirFreeBervalContent( &(op->reqDn) );
        VMDIR_SAFE_FREE_MEMORY(op->ldapResult.pszErrMsg);
        VmDirBackendCtxFree(op->pBECtx);
        VMDIR_SAFE_FREE_MEMORY(op->pszFilters);

        if ( op->opType == VDIR_OPERATION_TYPE_INTERNAL )
        {   // internal op owns dummy conn for ACL check
            VmDirDeleteConnection( &(op->conn)); // passing &conn to be freed seems a bit strange
        }
   }
}
Esempio n. 5
0
/*
 * Set vmwPasswordNeverExpires (if it doesn't have a value) to TRUE
 * on the domain administrator's account.
 */
DWORD
VmDirSetAdministratorPasswordNeverExpires(
    VOID
    )
{
    DWORD               dwError = 0;
    PCSTR               pszDomainDn = NULL;
    const CHAR          szAdministrator[] = "cn=Administrator,cn=Users";
    const CHAR          szTrue[] = "TRUE";
    PSTR                pszAdministratorDn = NULL;
    VDIR_OPERATION      op = {0};
    PSTR                pszLocalErrMsg = NULL;
    VDIR_ENTRY_ARRAY    entryArray = {0};
    PVDIR_ENTRY         pEntry = NULL;
    VDIR_BERVALUE       bervBlob = VDIR_BERVALUE_INIT;

    pszDomainDn = gVmdirServerGlobals.systemDomainDN.lberbv.bv_val;
    if (pszDomainDn == NULL)
    {
        dwError = ERROR_INVALID_STATE;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirAllocateStringPrintf(&pszAdministratorDn, "%s,%s", szAdministrator, pszDomainDn);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirSimpleEqualFilterInternalSearch(
                    pszDomainDn,
                    LDAP_SCOPE_SUBTREE,
                    ATTR_DN,
                    pszAdministratorDn,
                    &entryArray);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (entryArray.iSize != 1)
    {
        dwError = VMDIR_ERROR_DATA_CONSTRAINT_VIOLATION;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    pEntry = &(entryArray.pEntry[0]);

    if (pEntry->allocType == ENTRY_STORAGE_FORMAT_PACK)
    {
        dwError = VmDirEntryUnpack( pEntry );
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirInitStackOperation( &op, VDIR_OPERATION_TYPE_INTERNAL, LDAP_REQ_MODIFY, NULL);
    BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "VmDirSetAdministratorPasswordNeverExpire: VmDirInitStackOperation failed: %u", dwError);

    op.pBEIF = VmDirBackendSelect(NULL);
    assert(op.pBEIF);

    op.reqDn.lberbv.bv_val = pEntry->dn.lberbv.bv_val;
    op.reqDn.lberbv.bv_len = pEntry->dn.lberbv.bv_len;
    op.request.modifyReq.dn.lberbv = op.reqDn.lberbv;

    bervBlob.lberbv.bv_val = (PSTR) szTrue;
    bervBlob.lberbv.bv_len = strlen(szTrue);
    dwError = VmDirAppendAMod( &op,
                               MOD_OP_REPLACE,
                               ATTR_PASSWORD_NEVER_EXPIRES,
                               ATTR_PASSWORD_NEVER_EXPIRES_LEN,
                               bervBlob.lberbv_val,
                               bervBlob.lberbv_len);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirInternalModifyEntry(&op);
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:

    VmDirFreeEntryArrayContent(&entryArray);
    VmDirFreeOperationContent(&op);
    VMDIR_SAFE_FREE_STRINGA(pszAdministratorDn);
    return dwError;

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                     "VmDirSetAdministratorPasswordNeverExpires failed, (%u)", dwError);
    goto cleanup;
}
Esempio n. 6
0
/*
 * Set SRP Identifier's secret on existing entry with Password set
 */
DWORD
VmDirSRPSetIdentityData(
    PCSTR       pszUPN,
    PCSTR       pszClearTextPassword
    )
{
    DWORD               dwError = 0;
    VDIR_OPERATION      op = {0};
    PSTR                pszLocalErrMsg = NULL;
    VDIR_ENTRY_ARRAY    entryArray = {0};
    PVDIR_ENTRY         pEntry = NULL;
    PVDIR_ATTRIBUTE     pAttrSecret = NULL;
    VDIR_BERVALUE       bvUPN = VDIR_BERVALUE_INIT;
    VDIR_BERVALUE       bvClearTextPassword = VDIR_BERVALUE_INIT;
    VDIR_BERVALUE       bervSecretBlob = VDIR_BERVALUE_INIT;


    if ( IsNullOrEmptyString(pszUPN)    ||
         IsNullOrEmptyString(pszClearTextPassword)
        )
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    bvUPN.lberbv_val = (PSTR)pszUPN;
    bvUPN.lberbv_len = VmDirStringLenA(pszUPN);

    bvClearTextPassword.lberbv_val = (PSTR)pszClearTextPassword;
    bvClearTextPassword.lberbv_len = VmDirStringLenA(pszClearTextPassword);

    dwError = VmDirSimpleEqualFilterInternalSearch(
                    "",
                    LDAP_SCOPE_SUBTREE,
                    ATTR_KRB_UPN,
                    pszUPN,
                    &entryArray);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (entryArray.iSize == 1)
    {
        pAttrSecret = VmDirFindAttrByName(&(entryArray.pEntry[0]), ATTR_SRP_SECRET);
        if (pAttrSecret)
        {
            dwError = VMDIR_ERROR_ENTRY_ALREADY_EXIST;
            BAIL_ON_VMDIR_ERROR(dwError);
        }
    }
    else
    {
        dwError = VMDIR_ERROR_DATA_CONSTRAINT_VIOLATION;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    pEntry = &(entryArray.pEntry[0]);

    dwError = VdirPasswordCheck(&bvClearTextPassword, pEntry);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirSRPCreateSecret(&bvUPN, &bvClearTextPassword, &bervSecretBlob);
    BAIL_ON_VMDIR_ERROR(dwError);


    if (pEntry->allocType == ENTRY_STORAGE_FORMAT_PACK)
    {
        dwError = VmDirEntryUnpack( pEntry );
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirInitStackOperation( &op, VDIR_OPERATION_TYPE_INTERNAL, LDAP_REQ_MODIFY, NULL);
    BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "VmDirSRPSetIdentityData: VmDirInitStackOperation failed: %u", dwError);

    op.pBEIF = VmDirBackendSelect(NULL);
    assert(op.pBEIF);

    op.reqDn.lberbv.bv_val = pEntry->dn.lberbv.bv_val;
    op.reqDn.lberbv.bv_len = pEntry->dn.lberbv.bv_len;
    op.request.modifyReq.dn.lberbv = op.reqDn.lberbv;

    dwError = VmDirAppendAMod( &op,
                               MOD_OP_ADD,
                               ATTR_SRP_SECRET,
                               ATTR_SRP_SECRET_LEN,
                               bervSecretBlob.lberbv_val,
                               bervSecretBlob.lberbv_len);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirInternalModifyEntry(&op);
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:

    VmDirFreeBervalContent(&bervSecretBlob);
    VmDirFreeEntryArrayContent(&entryArray);
    VmDirFreeOperationContent(&op);
    return dwError;

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                     "VmDirSRPSetIdentityData (%s) failed, (%u)", VDIR_SAFE_STRING(pszUPN), dwError);
    goto cleanup;
}
Esempio n. 7
0
/*
 * Retrieve SRP Identifier's secret and salt
 */
DWORD
VmDirSRPGetIdentityData(
    PCSTR       pszUPN,
    PBYTE*      ppByteSecret,
    DWORD*      pdwSecretLen
    )
{
    DWORD               dwError = 0;
    PVDIR_ATTRIBUTE     pAttrSecret = NULL;
    VDIR_ENTRY_ARRAY    entryArray = {0};
    PBYTE               pLocalSecret = NULL;

    if ( IsNullOrEmptyString(pszUPN)    ||
         ppByteSecret == NULL           ||
         pdwSecretLen == NULL
        )
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirSimpleEqualFilterInternalSearch(
                    "",
                    LDAP_SCOPE_SUBTREE,
                    ATTR_KRB_UPN,
                    pszUPN,
                    &entryArray);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (entryArray.iSize == 1)
    {
        pAttrSecret = VmDirFindAttrByName(&(entryArray.pEntry[0]), ATTR_SRP_SECRET);
        if (!pAttrSecret)
        {
            dwError = VMDIR_ERROR_NO_SUCH_ATTRIBUTE;
            BAIL_ON_VMDIR_ERROR(dwError);
        }

        dwError = VmDirAllocateAndCopyMemory(   pAttrSecret->vals[0].lberbv_val,
                                                pAttrSecret->vals[0].lberbv_len,
                                                (PVOID*)&pLocalSecret);
        BAIL_ON_VMDIR_ERROR(dwError);
    }
    else if (entryArray.iSize == 0)
    {
        dwError = VMDIR_ERROR_ENTRY_NOT_FOUND;
        BAIL_ON_VMDIR_ERROR(dwError);
    }
    else
    {
        dwError = VMDIR_ERROR_DATA_CONSTRAINT_VIOLATION;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    *ppByteSecret = pLocalSecret;
    *pdwSecretLen = (DWORD) (pAttrSecret->vals[0].lberbv_len);

cleanup:

    VmDirFreeEntryArrayContent(&entryArray);

    return dwError;

error:

    VMDIR_SAFE_FREE_MEMORY( pLocalSecret );

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                     "VmDirSRPGetIdentityData (%s) failed, (%u)", VDIR_SAFE_STRING(pszUPN), dwError);
    goto cleanup;
}
Esempio n. 8
0
static
DWORD
ProcessPreValidatedEntries(
    PVDIR_OPERATION pOperation,
    DWORD dwEntryCount,
    ENTRYID *pValidatedEntries
    )
{
    DWORD   i = 0;
    DWORD   dwError = 0;
    DWORD   dwSentEntries = 0;
    BOOLEAN bInternalSearch = FALSE;
    BOOLEAN bStoreRsltInMem = FALSE;
    VDIR_ENTRY  srEntry = {0};
    PVDIR_ENTRY pSrEntry = NULL;

    if (dwEntryCount == 0)
    {
        goto cleanup;
    }

    bInternalSearch = pOperation->opType == VDIR_OPERATION_TYPE_INTERNAL;
    bStoreRsltInMem = pOperation->request.searchReq.bStoreRsltInMem;

    if (bInternalSearch || bStoreRsltInMem)
    {
        VmDirFreeEntryArrayContent(&pOperation->internalSearchEntryArray);
        dwError = VmDirAllocateMemory(
                sizeof(VDIR_ENTRY) * (dwEntryCount + 1),
                (PVOID*)&pOperation->internalSearchEntryArray.pEntry);
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    for (; i < dwEntryCount; ++i)
    {
        pSrEntry = bInternalSearch || bStoreRsltInMem ?
                (pOperation->internalSearchEntryArray.pEntry +
                 pOperation->internalSearchEntryArray.iSize) : &srEntry;

        dwError = pOperation->pBEIF->pfnBESimpleIdToEntry(
                pValidatedEntries[i], pSrEntry);
        if (dwError != 0)
        {
            // Ignore errors resolving ENTRYIDs.
            VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL,
                    "%s pfnBESimpleIdToEntry EID(%u), error (%u)",
                    __FUNCTION__, pValidatedEntries[i], dwError);
            continue;
        }

        dwError = VmDirBuildComputedAttribute(pOperation, pSrEntry);
        BAIL_ON_VMDIR_ERROR(dwError);

        dwError = VmDirSendSearchEntry(pOperation, pSrEntry);
        if (dwError == VMDIR_ERROR_INSUFFICIENT_ACCESS)
        {
            VMDIR_LOG_WARNING(
                    VMDIR_LOG_MASK_ALL,
                    "Access deny on search entry result [%s,%d] (bindedDN-%s) (targetDn-%s)",
                    __FILE__,
                    __LINE__,
                    pOperation->conn->AccessInfo.pszBindedDn,
                    pSrEntry->dn.lberbv.bv_val);

            // make sure search continues
            dwError = 0;
        }
        BAIL_ON_VMDIR_ERROR(dwError);

        if (pSrEntry->bSearchEntrySent)
        {
            dwSentEntries++;
            if (bInternalSearch || bStoreRsltInMem)
            {
                pOperation->internalSearchEntryArray.iSize++;
                pSrEntry = NULL;    // EntryArray takes over *pSrEntry content
            }
        }

        VmDirFreeEntryContent(pSrEntry);
        pSrEntry = NULL;
    }

    dwError = SetPagedSearchCookie(
                pOperation,
                pValidatedEntries[dwEntryCount - 1],
                0);
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:
    pOperation->dwSentEntries = dwSentEntries;
    VmDirFreeEntryContent(pSrEntry);
    return dwError;

error:
    goto cleanup;
}
Esempio n. 9
0
/*
 *      Searches the direct group entry to confirm membership
 *      Set pAccessRoleBitmap based on getAccessInfo to avoid redundent internal search.
 */
DWORD
VmDirIsDirectMemberOf(
    PSTR                pszBindDN,
    UINT32              getAccessInfo,
    UINT32              *pAccessRoleBitmap,
    PBOOLEAN            pbIsMemberOf
    )
{
    DWORD               dwError = 0;
    BOOLEAN             bIsMemberOf = FALSE;
    VDIR_ENTRY_ARRAY    entryResultArray = {0};
    PSTR                pszGroupDN = NULL;

    if (!pbIsMemberOf || !pAccessRoleBitmap)
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    if (getAccessInfo == VDIR_ACCESS_DCGROUP_MEMBER_INFO)
    {
         if (*pAccessRoleBitmap & VDIR_ACCESS_DCGROUP_MEMBER_VALID_INFO)
         {
             *pbIsMemberOf = (*pAccessRoleBitmap & VDIR_ACCESS_IS_DCGROUP_MEMBER) != 0;
             goto cleanup;
         }
         pszGroupDN = gVmdirServerGlobals.bvDCGroupDN.lberbv_val;
    }
    else if (getAccessInfo == VDIR_ACCESS_DCCLIENT_GROUP_MEMBER_INFO)
    {
        if (*pAccessRoleBitmap & VDIR_ACCESS_DCCLIENT_GROUP_MEMBER_VALID_INFO)
        {
            *pbIsMemberOf = (*pAccessRoleBitmap & VDIR_ACCESS_IS_DCCLIENT_GROUP_MEMBER) != 0;
            goto cleanup;
        }
        pszGroupDN = gVmdirServerGlobals.bvDCClientGroupDN.lberbv_val;
    }
    else
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    if (pszGroupDN == NULL || pszBindDN == NULL)
    {
        *pbIsMemberOf = FALSE;
        goto cleanup;
    }

    VMDIR_LOG_VERBOSE(VMDIR_LOG_MASK_ALL, "VmDirIsDirectMemberOf: internal search for dn %s op %d",
          pszBindDN, getAccessInfo);

    dwError = VmDirSimpleEqualFilterInternalSearch( pszGroupDN,
                                                    LDAP_SCOPE_BASE,
                                                    ATTR_MEMBER,
                                                    pszBindDN,
                                                    &entryResultArray);
    BAIL_ON_VMDIR_ERROR(dwError);

    if ( entryResultArray.iSize > 0)
    {
        bIsMemberOf = TRUE;
    }

    if (getAccessInfo == VDIR_ACCESS_DCGROUP_MEMBER_INFO)
    {
        *pAccessRoleBitmap |= VDIR_ACCESS_DCGROUP_MEMBER_VALID_INFO;
        if (bIsMemberOf)
        {
             *pAccessRoleBitmap |= VDIR_ACCESS_IS_DCGROUP_MEMBER;
        }
    }
    else
    {
        *pAccessRoleBitmap |= VDIR_ACCESS_DCCLIENT_GROUP_MEMBER_VALID_INFO;
        if (bIsMemberOf)
        {
            *pAccessRoleBitmap |= VDIR_ACCESS_IS_DCCLIENT_GROUP_MEMBER;
        }
    }

    *pbIsMemberOf = bIsMemberOf;

cleanup:

    VmDirFreeEntryArrayContent(&entryResultArray);

    return dwError;

error:

    *pbIsMemberOf = FALSE;

    goto cleanup;
}
Esempio n. 10
0
static
int
VmDirProcessCandidateList(
    VDIR_OPERATION * pOperation
    )
{
    int               retVal = LDAP_SUCCESS;
    int               i = 0;
    VDIR_CANDIDATES * cl = pOperation->request.searchReq.filter->candidates;
    VDIR_ENTRY        srEntry = {0};
    VDIR_ENTRY *      pSrEntry = NULL;
    int               numSentEntries = 0;
    BOOLEAN           bExternalSearch = FALSE;
    BOOLEAN           bInternalSearch = FALSE;
    BOOLEAN           bStoreRsltInMem = FALSE;
    BOOLEAN           bPageResultsCtrl = FALSE;
    DWORD             dwPageSize = 0;
    ENTRYID           lastEID = 0;

    /*
     * If the page size is greater than or equal to the sizeLimit value,
     * the server should ignore the control as the request can be satisfied in a single page.
     */
    if (pOperation->showPagedResultsCtrl && (pOperation->request.searchReq.sizeLimit == 0 ||
        pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.pageSize < (DWORD)pOperation->request.searchReq.sizeLimit))
    {
        VmDirLog( LDAP_DEBUG_TRACE, "showPagedResultsCtrl applies to this query." );

        bPageResultsCtrl = TRUE;
        dwPageSize = pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.pageSize;
        lastEID = atoll(pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie);
        pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie[0] = '\0';

        VmDirSortCandidateList(cl);  // sort candidate list if not yet sorted
    }

    bExternalSearch = pOperation->opType == VDIR_OPERATION_TYPE_EXTERNAL;
    bInternalSearch = pOperation->opType == VDIR_OPERATION_TYPE_INTERNAL;
    bStoreRsltInMem = pOperation->request.searchReq.bStoreRsltInMem;

    if (cl && cl->size > 0)
    {
        if (bInternalSearch || bStoreRsltInMem)
        {   //TODO, we should have a hard limit on the cl->size we handle
            VmDirFreeEntryArrayContent(&pOperation->internalSearchEntryArray);
            retVal = VmDirAllocateMemory(   sizeof(VDIR_ENTRY) * cl->size,
                                            (PVOID*)&pOperation->internalSearchEntryArray.pEntry);
            BAIL_ON_VMDIR_ERROR(retVal);
        }

        for (i = 0, numSentEntries = 0;
             (i < cl->size) &&
             (pOperation->request.searchReq.sizeLimit == 0 /* unlimited */ ||
              numSentEntries < pOperation->request.searchReq.sizeLimit);
             i++)
        {
            if (bExternalSearch &&
                VmDirdState() == VMDIRD_STATE_SHUTDOWN &&
                pOperation->syncReqCtrl == NULL)
            {
                retVal = LDAP_UNAVAILABLE; // stop all external search ops, except replication pull
                goto cleanup;
            }

            if (!gVmdirGlobals.bPagedSearchReadAhead)
            {
                //skip entries we sent before in sorted cl->eIds.
                if (bPageResultsCtrl && cl->eIds[i] <= lastEID)
                {
                    continue;
                }
            }

            pSrEntry = bInternalSearch || bStoreRsltInMem ?
                        (pOperation->internalSearchEntryArray.pEntry + pOperation->internalSearchEntryArray.iSize) : &srEntry;

            retVal = pOperation->pBEIF->pfnBEIdToEntry(
                        pOperation->pBECtx,
                        pOperation->pSchemaCtx,
                        cl->eIds[i],
                        pSrEntry,
                        VDIR_BACKEND_ENTRY_LOCK_READ);

            if (retVal)
            {
                // Ignore BdbEIdToEntry errors.
                VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL,
                        "ProcessCandiateList BEIdToEntry EID(%u), error (%u)",
                        cl->eIds[i], retVal);

                continue;
            }

            if (CheckIfEntryPassesFilter(pOperation, pSrEntry, pOperation->request.searchReq.filter) == FILTER_RES_TRUE)
            {
                BOOLEAN bSendEntry = TRUE;
                CHAR    sha1Digest[SHA_DIGEST_LENGTH] = {0};

                retVal = VmDirBuildComputedAttribute( pOperation, pSrEntry );
                BAIL_ON_VMDIR_ERROR( retVal );

                if (pOperation->digestCtrl)
                {
                    retVal = VmDirEntrySHA1Digest(pSrEntry, sha1Digest);
                    BAIL_ON_VMDIR_ERROR(retVal);

                    if (memcmp(sha1Digest, pOperation->digestCtrl->value.digestCtrlVal.sha1Digest, SHA_DIGEST_LENGTH) == 0)
                    {
                        bSendEntry = FALSE;
                        VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL,"%s digest match %s",
                                           __FUNCTION__, pSrEntry->dn.lberbv.bv_val);
                    }
                    else
                    {
                        VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL,"%s digest mismatch %s",
                                           __FUNCTION__, pSrEntry->dn.lberbv.bv_val);
                    }
                }

                if (bSendEntry)
                {
                    retVal = VmDirSendSearchEntry(pOperation, pSrEntry);
                    if (retVal == VMDIR_ERROR_INSUFFICIENT_ACCESS)
                    {
                        VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL,
                                "Access deny on search entry result [%s,%d] (bindedDN-%s) (targetDn-%s)\n",
                                __FILE__,
                                __LINE__,
                                pOperation->conn->AccessInfo.pszBindedDn,
                                pSrEntry->dn.lberbv.bv_val);
                        // make sure search continues
                        retVal = 0;
                    }
                    BAIL_ON_VMDIR_ERROR( retVal );

                    if (pSrEntry->bSearchEntrySent)
                    {
                        numSentEntries++;
                        if (bInternalSearch || bStoreRsltInMem)
                        {
                            pOperation->internalSearchEntryArray.iSize++;
                            pSrEntry = NULL;    // EntryArray takes over *pSrEntry content

                            if (pOperation->internalSearchEntryArray.iSize > gVmdirServerGlobals.dwMaxInternalSearchLimit)
                            {
                                BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_INTERNAL_SEARCH_LIMIT);
                            }
                        }
                    }
                }
            }

            //We have sent one page size of entries, so we can break here
            if (bPageResultsCtrl && numSentEntries == dwPageSize)
            {
                retVal = SetPagedSearchCookie(pOperation, cl->eIds[i], i);
                BAIL_ON_VMDIR_ERROR(retVal);
                break;
            }

            VmDirFreeEntryContent( pSrEntry );
            pSrEntry = NULL; // Reset to NULL so that DeleteEntry is no-op.
        }

        VMDIR_LOG_VERBOSE( LDAP_DEBUG_FILTER, "(%d) candiates processed and (%d) entries sent", cl->size, numSentEntries);
    }

    if ( pOperation->request.searchReq.sizeLimit && numSentEntries < pOperation->request.searchReq.sizeLimit &&
         pOperation->pBECtx->iPartialCandidates)
    {
        retVal = LDAP_UNWILLING_TO_PERFORM;
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ProcessCandiateList may return none or paritial requested entries with sizelimit %d",
                        pOperation->request.searchReq.sizeLimit);
    }

#ifndef REPLICATION_V2
    retVal = VmDirUpdateSyncDoneCtl(
            pOperation,
            numSentEntries);
    BAIL_ON_VMDIR_ERROR(retVal);
#endif

cleanup:
    pOperation->dwSentEntries = numSentEntries;
    VmDirFreeEntryContent(pSrEntry);
    return retVal;

error:
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ProcessCandiateList failed. (%u)", retVal);
    goto cleanup;
}
Esempio n. 11
0
/* This function re-instantiates the current vmdir instance with a
 * foreign (MDB) database file. It is triggered by running vdcadmintool
 * with option 8.  Before this action, a foreign database files must be copied
 * onto diretory mdb_home_dir/partner/ which may include mdb WAL files under
 * xlogs/. See PR 1995325 for the functional spec and use cases.
 */
DWORD
VmDirSrvServerReset(
    PDWORD pServerResetState
    )
{
    int i = 0;
    DWORD dwError = 0;
    VDIR_ENTRY_ARRAY entryArray = {0};
    const char  *dbHomeDir = VMDIR_DB_DIR;
    PVDIR_SCHEMA_CTX pSchemaCtx = NULL;
    BOOLEAN bWriteInvocationId = FALSE;
    PSTR pszConfigurationContainerDn = NULL;
    PSTR pszDomainControllerContainerDn = NULL;
    PSTR pszManagedServiceAccountContainerDn = NULL;
    DEQUE computers = {0};
    PSTR pszComputer = NULL;
    PVDIR_ATTRIBUTE pAttrUPN = NULL;
    BOOLEAN bMdbWalEnable = FALSE;

    VmDirGetMdbWalEnable(&bMdbWalEnable);

    //swap current vmdir database file with the foriegn one under partner/
    dwError = _VmDirSwapDB(dbHomeDir, bMdbWalEnable);
    BAIL_ON_VMDIR_ERROR(dwError);

    //Delete Computers (domain controller accounts) under Domain Controller container
    dwError = VmDirAllocateStringPrintf(&pszDomainControllerContainerDn, "ou=%s,%s",
                VMDIR_DOMAIN_CONTROLLERS_RDN_VAL, gVmdirServerGlobals.systemDomainDN.lberbv_val);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirSimpleEqualFilterInternalSearch(pszDomainControllerContainerDn, LDAP_SCOPE_ONE,
                ATTR_OBJECT_CLASS, OC_COMPUTER, &entryArray);
    BAIL_ON_VMDIR_ERROR(dwError);

    if(entryArray.iSize > 0)
    {
        for (i = 0; i < entryArray.iSize; i++)
        {
            pAttrUPN = VmDirFindAttrByName(&entryArray.pEntry[i], ATTR_KRB_UPN);
            if (pAttrUPN)
            {
               PSTR pPc = NULL;
               dwError = VmDirAllocateStringA(pAttrUPN->vals[0].lberbv_val, &pPc);
               dequePush(&computers, pPc);
            }
            dwError = VmDirDeleteEntry(&entryArray.pEntry[i]);
            BAIL_ON_VMDIR_ERROR(dwError);
        }
    }
    VmDirFreeEntryArrayContent(&entryArray);

    /* Delete all entries in the subtree under Configuration container
     *  (e.g. under cn=Configuration,dc=vmware,dc=com).
     * This will remove the old replication topology
     */
    dwError = VmDirAllocateStringPrintf(&pszConfigurationContainerDn, "cn=%s,%s",
                VMDIR_CONFIGURATION_CONTAINER_NAME, gVmdirServerGlobals.systemDomainDN.lberbv_val);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirSimpleEqualFilterInternalSearch(pszConfigurationContainerDn, LDAP_SCOPE_SUBTREE,
                ATTR_OBJECT_CLASS, OC_DIR_SERVER, &entryArray);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (entryArray.iSize > 0)
    {
        for (i = 0; i < entryArray.iSize; i++)
        {
            /* Delete all replication agreement entries for a server and
             * the server it self under the configuration/site container
             */
            dwError = VmDirInternalDeleteTree(entryArray.pEntry[i].dn.lberbv_val);
            BAIL_ON_VMDIR_ERROR(dwError);
        }
    }
    VmDirFreeEntryArrayContent(&entryArray);

    //Delete ManagedServiceAccount entries that are associated with any of the domain controllers

    dwError = VmDirAllocateStringPrintf(&pszManagedServiceAccountContainerDn, "cn=%s,%s",
                VMDIR_MSAS_RDN_VAL, gVmdirServerGlobals.systemDomainDN.lberbv_val);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirSimpleEqualFilterInternalSearch(pszManagedServiceAccountContainerDn, LDAP_SCOPE_ONE,
                ATTR_OBJECT_CLASS, OC_MANAGED_SERVICE_ACCOUNT, &entryArray);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (entryArray.iSize > 0)
    {
        for (i = 0; i < entryArray.iSize; i++)
        {
            PDEQUE_NODE p = NULL;
            pAttrUPN = VmDirFindAttrByName(&entryArray.pEntry[i], ATTR_KRB_UPN);
            for(p = computers.pHead; p != NULL; p = p->pNext)
            {
                if (VmDirStringCaseStrA(pAttrUPN->vals[0].lberbv_val, p->pElement) != NULL)
                {
                    dwError = VmDirDeleteEntry(&entryArray.pEntry[i]);
                    BAIL_ON_VMDIR_ERROR(dwError);
                    break;
                }
            }
        }
    }

    dwError = VmDirSchemaCtxAcquire(&pSchemaCtx );
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirSrvCreateServerObj(pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    //Create server and replication entries for the current instance
    // on top of the (cleaned up) foreign database.
    dwError = VmDirSrvCreateReplAgrsContainer(pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = _VmDirPatchDSERoot(pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    VmDirSchemaCtxRelease(pSchemaCtx);
    pSchemaCtx = NULL;

    dwError = LoadServerGlobals(&bWriteInvocationId);
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:
    if (pSchemaCtx)
    {
        VmDirSchemaCtxRelease(pSchemaCtx);
    }

    VmDirFreeEntryArrayContent(&entryArray);

    VMDIR_SAFE_FREE_MEMORY(pszConfigurationContainerDn);
    VMDIR_SAFE_FREE_MEMORY(pszDomainControllerContainerDn);

    while(!dequeIsEmpty(&computers))
    {
        dequePopLeft(&computers, (PVOID*)&pszComputer);
        VMDIR_SAFE_FREE_MEMORY(pszComputer);
    }
    return dwError;

error:
    goto cleanup;
}
Esempio n. 12
0
static
DWORD
_VmKdcGetKrbUPNKey(
    PSTR        pszUpnName,
    PBYTE*      ppKeyBlob,
    DWORD*      pSize
    )
{
    DWORD               dwError = 0;
    PVDIR_ATTRIBUTE     pKrbUPNKey = NULL;
    PBYTE               pRetUPNKey = NULL;
    VDIR_ENTRY_ARRAY    entryArray = {0};

    if (IsNullOrEmptyString(pszUpnName)
        || !ppKeyBlob
        || !pSize
       )
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMKDC_ERROR(dwError);
    }

    dwError = VmDirSimpleEqualFilterInternalSearch(
                    "",
                    LDAP_SCOPE_SUBTREE,
                    ATTR_KRB_UPN,
                    pszUpnName,
                    &entryArray);
    BAIL_ON_VMKDC_ERROR(dwError);

    if (entryArray.iSize == 1)
    {
        pKrbUPNKey = VmDirFindAttrByName(&(entryArray.pEntry[0]), ATTR_KRB_PRINCIPAL_KEY);

        if (!pKrbUPNKey)
        {
            dwError = ERROR_NO_PRINC;
            BAIL_ON_VMKDC_ERROR(dwError);
        }

        dwError = VmDirAllocateAndCopyMemory(
                        pKrbUPNKey->vals[0].lberbv.bv_val,
                        pKrbUPNKey->vals[0].lberbv.bv_len,
                        (PVOID*)& pRetUPNKey
                        );
        BAIL_ON_VMKDC_ERROR(dwError);

        *ppKeyBlob = pRetUPNKey;
        *pSize     = (DWORD) pKrbUPNKey->vals[0].lberbv.bv_len;
        pRetUPNKey = NULL;
    }
    else
    {
        dwError = ERROR_NO_PRINC;
        BAIL_ON_VMKDC_ERROR(dwError);
    }

cleanup:

    VmDirFreeEntryArrayContent(&entryArray);

    return dwError;

error:

    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "_VmKdcGetKrbUPNKey: failed (%u)(%s)", dwError, VDIR_SAFE_STRING(pszUpnName));

    VMKDC_SAFE_FREE_MEMORY(pRetUPNKey);

    // keep error code space to KDC specific
    dwError = ERROR_NO_PRINC;

    goto cleanup;

}
Esempio n. 13
0
DWORD
VmDirGetKrbUPNKey(
    PSTR        pszUpnName,
    PBYTE*      ppKeyBlob,
    DWORD*      pSize
)
{
    DWORD               dwError = 0;
    PVDIR_ATTRIBUTE     pKrbUPNKey = NULL;
    PBYTE               pRetUPNKey = NULL;
    VDIR_ENTRY_ARRAY    entryArray = {0};

    if (IsNullOrEmptyString(pszUpnName)
        || !ppKeyBlob
        || !pSize
       )
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirSimpleEqualFilterInternalSearch(
                    "",
                    LDAP_SCOPE_SUBTREE,
                    ATTR_KRB_UPN,
                    pszUpnName,
                    &entryArray);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (entryArray.iSize == 1)
    {
        pKrbUPNKey = VmDirFindAttrByName(&(entryArray.pEntry[0]), ATTR_KRB_PRINCIPAL_KEY);

        if (!pKrbUPNKey)
        {
            dwError = VMDIR_ERROR_NO_SUCH_ATTRIBUTE;
            BAIL_ON_VMDIR_ERROR(dwError);
        }

        dwError = VmDirAllocateMemory(
                            pKrbUPNKey->vals[0].lberbv.bv_len,
                            (PVOID*)&pRetUPNKey
                            );
        BAIL_ON_VMDIR_ERROR(dwError);

        dwError = VmDirCopyMemory(
                        pRetUPNKey,
                        pKrbUPNKey->vals[0].lberbv.bv_len,
                        pKrbUPNKey->vals[0].lberbv.bv_val,
                        pKrbUPNKey->vals[0].lberbv.bv_len
                        );
        BAIL_ON_VMDIR_ERROR(dwError);

        *ppKeyBlob = pRetUPNKey;
        *pSize     = (DWORD) pKrbUPNKey->vals[0].lberbv.bv_len;
        pRetUPNKey = NULL;
    }
    else
    {
        dwError = VMDIR_ERROR_ENTRY_NOT_FOUND;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

cleanup:

    VmDirFreeEntryArrayContent(&entryArray);

    return dwError;

error:

    VMDIR_LOG_ERROR( LDAP_DEBUG_RPC, "VmDirGetKrbUPNKey failed. (%u)(%s)",
                                     dwError, VDIR_SAFE_STRING(pszUpnName));
    VMDIR_SAFE_FREE_MEMORY(pRetUPNKey);

    goto cleanup;

}
Esempio n. 14
0
DWORD
VmDirGetUPNMemberships(
    PCSTR pszUpnName,
    PSTR **pppszMemberships,
    PDWORD pdwMemberships
    )
{
    DWORD dwError = 0;
    VDIR_ENTRY_ARRAY entryArray = {0};
    VDIR_OPERATION searchOp = {0};
    BOOLEAN bHasTxn = FALSE;
    PVDIR_ATTRIBUTE pMemberOf = NULL;
    PSTR *ppszMemberships = NULL;
    DWORD dwMemberships = 0;
    DWORD i = 0;

    if (IsNullOrEmptyString(pszUpnName) ||
        pppszMemberships == NULL ||
        pdwMemberships == NULL)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirSimpleEqualFilterInternalSearch(
                "",
                LDAP_SCOPE_SUBTREE,
                ATTR_KRB_UPN,
                pszUpnName,
                &entryArray);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (entryArray.iSize == 0)
    {
        dwError = VMDIR_ERROR_ENTRY_NOT_FOUND;
        BAIL_ON_VMDIR_ERROR(dwError);
    }
    else if (entryArray.iSize > 1)
    {
        dwError = VMDIR_ERROR_DATA_CONSTRAINT_VIOLATION;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirInitStackOperation(&searchOp, VDIR_OPERATION_TYPE_INTERNAL, LDAP_REQ_SEARCH, NULL);
    BAIL_ON_VMDIR_ERROR(dwError);

    searchOp.pBEIF = VmDirBackendSelect(NULL);

    dwError = searchOp.pBEIF->pfnBETxnBegin(searchOp.pBECtx, VDIR_BACKEND_TXN_READ);
    BAIL_ON_VMDIR_ERROR(dwError);
    bHasTxn = TRUE;

    dwError = VmDirBuildMemberOfAttribute(&searchOp, entryArray.pEntry, &pMemberOf);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (pMemberOf)
    {
        dwMemberships = pMemberOf->numVals;
    }

    if (dwMemberships)
    {
        dwError = VmDirAllocateMemory(dwMemberships * sizeof(PSTR), (PVOID)&ppszMemberships);
        BAIL_ON_VMDIR_ERROR(dwError);

        for (i = 0; i < dwMemberships; i++)
        {
            PCSTR pszMemberOf = pMemberOf->vals[i].lberbv.bv_val;

            dwError = VmDirAllocateStringA(pszMemberOf, &ppszMemberships[i]);
            BAIL_ON_VMDIR_ERROR(dwError);
        }
    }

    *pppszMemberships = ppszMemberships;
    *pdwMemberships = dwMemberships;

cleanup:

    if (pMemberOf)
    {
        VmDirFreeAttribute(pMemberOf);
    }
    if (bHasTxn)
    {
        searchOp.pBEIF->pfnBETxnCommit(searchOp.pBECtx);
    }
    VmDirFreeOperationContent(&searchOp);
    VmDirFreeEntryArrayContent(&entryArray);

    return dwError;

error:
    VmDirFreeMemberships(ppszMemberships, dwMemberships);

    goto cleanup;
}
Esempio n. 15
0
static
int
ProcessCandidateList(
    VDIR_OPERATION * pOperation
    )
{
    int               retVal = LDAP_SUCCESS;
    int               i = 0;
    VDIR_CANDIDATES * cl = pOperation->request.searchReq.filter->candidates;
    VDIR_ENTRY        srEntry = {0};
    VDIR_ENTRY *      pSrEntry = NULL;
    int               numSentEntries = 0;
    BOOLEAN           bInternalSearch = FALSE;
    BOOLEAN           bPageResultsCtrl = FALSE;
    DWORD             dwPageSize = 0;
    ENTRYID           lastEID = 0;

    /*
     * If the page size is greater than or equal to the sizeLimit value,
     * the server should ignore the control as the request can be satisfied in a single page.
     */
    if (pOperation->showPagedResultsCtrl && (pOperation->request.searchReq.sizeLimit == 0 ||
            pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.pageSize < (DWORD)pOperation->request.searchReq.sizeLimit))
    {
        VmDirLog( LDAP_DEBUG_TRACE, "showPagedResultsCtrl applies to this query." );
        bPageResultsCtrl = TRUE;
        dwPageSize = pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.pageSize;
        lastEID = atoi(pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie);
        pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie[0] = '\0';
    }

    if (cl && cl->size > 0)
    {
        if (pOperation->opType == VDIR_OPERATION_TYPE_INTERNAL)
        {   //TODO, we should have a hard limit on the cl->size we handle
            bInternalSearch = TRUE;
            VmDirFreeEntryArrayContent(&pOperation->internalSearchEntryArray);
            retVal = VmDirAllocateMemory(   sizeof(VDIR_ENTRY) * cl->size,
                                            (PVOID*)&pOperation->internalSearchEntryArray.pEntry);
            BAIL_ON_VMDIR_ERROR(retVal);
        }

        for (i = 0, numSentEntries = 0;
             (i < cl->size) && VmDirdState() != VMDIRD_STATE_SHUTDOWN &&
             (pOperation->request.searchReq.sizeLimit == 0 /* unlimited */ ||
              numSentEntries < pOperation->request.searchReq.sizeLimit);
             i++)
        {
            //skip entries we sent before
            if (bPageResultsCtrl && lastEID > 0)
            {
                if (cl->eIds[i] == lastEID)
                {
                    lastEID = 0;
                }
                continue;
            }

            VMDIR_LOG_DEBUG( LDAP_DEBUG_FILTER, "ProcessCandidateList EID(%u)", cl->eIds[i]);

            pSrEntry = bInternalSearch ?
                        (pOperation->internalSearchEntryArray.pEntry + pOperation->internalSearchEntryArray.iSize) : &srEntry;

            retVal = pOperation->pBEIF->pfnBEIdToEntry(
                        pOperation->pBECtx,
                        pOperation->pSchemaCtx,
                        cl->eIds[i],
                        pSrEntry,
                        VDIR_BACKEND_ENTRY_LOCK_READ);

            if (retVal == 0)
            {
                if (CheckIfEntryPassesFilter( pOperation, pSrEntry, pOperation->request.searchReq.filter) == FILTER_RES_TRUE)
                {
                    retVal = VmDirBuildComputedAttribute( pOperation, pSrEntry );
                    BAIL_ON_VMDIR_ERROR( retVal );

                    if (bInternalSearch)
                    {
                        pOperation->internalSearchEntryArray.iSize++;
                        pSrEntry = NULL;    // EntryArray takes over *pSrEntry content
                    }
                    else
                    {
                        retVal = VmDirSendSearchEntry( pOperation, pSrEntry );
                        if (retVal == VMDIR_ERROR_INSUFFICIENT_ACCESS)
                        {
                            VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL,
                                               "Access deny on search entry result [%s,%d] (bindedDN-%s) (targetDn-%s)\n",
                                               __FILE__, __LINE__, pOperation->conn->AccessInfo.pszBindedDn, pSrEntry->dn.lberbv.bv_val);
                            // make sure search continues
                            retVal = 0;
                        }
                        BAIL_ON_VMDIR_ERROR( retVal );

                        if (pSrEntry->bSearchEntrySent)
                        {
                            numSentEntries++;
                        }
                    }
                }

                //We have sent one page size of entries, so we can break here
                if (bPageResultsCtrl && numSentEntries == dwPageSize){
                    retVal = VmDirStringPrintFA(
                            pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie,
                            VMDIR_MAX_I64_ASCII_STR_LEN,
                            "%u",
                            pSrEntry->eId);
                    BAIL_ON_VMDIR_ERROR( retVal );
                    break;
                }

                VmDirFreeEntryContent( pSrEntry );
                pSrEntry = NULL; // Reset to NULL so that DeleteEntry is no-op.
            }
            else
            {
                // Ignore BdbEIdToEntry errors.
                VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "ProcessCandiateList BEIdToEntry EID(%u), error (%u)",
                                                       cl->eIds[i], retVal);
                retVal = 0;
            }
        }

        VMDIR_LOG_VERBOSE( LDAP_DEBUG_FILTER, "(%d) candiates processed and (%d) entries sent", cl->size, numSentEntries);
    }

    if ( pOperation->request.searchReq.sizeLimit && numSentEntries < pOperation->request.searchReq.sizeLimit &&
         pOperation->pBECtx->iPartialCandidates)
    {
        retVal = LDAP_UNWILLING_TO_PERFORM;
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ProcessCandiateList may return none or paritial requested entries with sizelimit %d",
                        pOperation->request.searchReq.sizeLimit);
    }

cleanup:

    pOperation->dwSentEntries = numSentEntries;
    VmDirFreeEntryContent( pSrEntry );

    return retVal;

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessCandiateList failed. (%u)", retVal);
    goto cleanup;
}