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; }
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; }
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; }