static VOID _VmDirPrintWriteQueueContentsInLock( PVMDIR_WRITE_QUEUE pWriteQueue ) { PVDIR_LINKED_LIST_NODE pNode = NULL; if (VmDirLogGetMask() & LDAP_DEBUG_WRITE_QUEUE) { VmDirLinkedListGetHead(pWriteQueue->pList, &pNode); while (pNode) { VMDIR_LOG_INFO( LDAP_DEBUG_WRITE_QUEUE, "%s: USNs in the write queue: %"PRId64, __FUNCTION__, ((PVMDIR_WRITE_QUEUE_ELEMENT)pNode->pElement)->usn); pNode = pNode->pNext; } } }
/* * Determine whether the supplier's attr-value-meta-data wins by checking it against local * attr-meta-data and local attr-value-meta-data. * It first compares the <version><invocation-id> of that in local attr-meta-data which was * applied either in the previous transaction or the previous modification in the current * transactions. Then if the <version><invocation-id> matches, it looks up the local server * to see if the same attr-value-meta-data exist: if supplier's attr-value-meta-data has a * newer timestamp then it wins and inScope set to TRUE. */ DWORD VmDirReplResolveValueMetaDataConflicts( PVDIR_OPERATION pModOp, PVDIR_ATTRIBUTE pAttr, PVMDIR_VALUE_ATTRIBUTE_METADATA pSupplierValueMetaData, ENTRYID entryId, PBOOLEAN pInScope ) { DWORD dwError = 0; VDIR_BERVALUE bervSupplierValueMetaData = VDIR_BERVALUE_INIT; VDIR_BERVALUE bervConsumerValueMetaData = VDIR_BERVALUE_INIT; DEQUE valueMetaDataQueue = {0}; PVMDIR_VALUE_ATTRIBUTE_METADATA pConsumerValueMetaData = NULL; if (!pModOp || !pAttr || !pSupplierValueMetaData || !pInScope) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } *pInScope = TRUE; dwError = pModOp->pBEIF->pfnBEGetAttrMetaData(pModOp->pBECtx, pAttr, entryId); BAIL_ON_VMDIR_ERROR(dwError); //Consumer <version><originating-server-id> in metaValueData //not match supplier's <version<<originating-server-id> in metaData //this value-meta-data out of scope if (pSupplierValueMetaData->version != pAttr->pMetaData->version || VmDirStringCompareA( pSupplierValueMetaData->pszOrigInvoId, pAttr->pMetaData->pszOrigInvoId, TRUE) != 0) { *pInScope = FALSE; goto cleanup; } if (VmDirLogGetMask() & LDAP_DEBUG_REPL) { //Ignore error, used only for logging VmDirValueMetaDataSerialize(pSupplierValueMetaData, &bervSupplierValueMetaData); VmDirValueMetaDataSerialize(pConsumerValueMetaData, &bervConsumerValueMetaData); } dwError = pModOp->pBEIF->pfnBEGetAttrValueMetaData( pModOp->pBECtx, entryId, pAttr->pATDesc->usAttrID, &valueMetaDataQueue); BAIL_ON_VMDIR_ERROR(dwError); while(!dequeIsEmpty(&valueMetaDataQueue)) { VMDIR_SAFE_FREE_VALUE_METADATA(pConsumerValueMetaData); dequePopLeft(&valueMetaDataQueue, (PVOID*)&pConsumerValueMetaData); if (pConsumerValueMetaData->dwValSize != pSupplierValueMetaData->dwValSize || VmDirCompareMemory( pConsumerValueMetaData->pszValue, pSupplierValueMetaData->pszValue, pConsumerValueMetaData->dwValSize) != 0) { continue; } if (VmDirStringCompareA( pConsumerValueMetaData->pszValChgOrigTime, pSupplierValueMetaData->pszValChgOrigTime, TRUE) > 0) { *pInScope = FALSE; VMDIR_LOG_DEBUG( LDAP_DEBUG_REPL, "%s: supplier attr-value-meta lose: %s consumer: %s", __FUNCTION__, VDIR_SAFE_STRING(bervSupplierValueMetaData.lberbv_val), VDIR_SAFE_STRING(bervConsumerValueMetaData.lberbv_val)); } } if (*pInScope) { VMDIR_LOG_DEBUG( LDAP_DEBUG_REPL, "%s: supplier attr-value-meta won: %s", __FUNCTION__, VDIR_SAFE_STRING(bervSupplierValueMetaData.lberbv_val)); } cleanup: VmDirFreeBervalContent(&bervSupplierValueMetaData); VmDirFreeBervalContent(&bervConsumerValueMetaData); VMDIR_SAFE_FREE_VALUE_METADATA(pConsumerValueMetaData); VmDirFreeAttrValueMetaDataDequeueContent(&valueMetaDataQueue); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
static DWORD vmdirConnAccept( Sockbuf_IO* pSockbuf_IO, DWORD dwPort, BOOLEAN bIsLdaps ) { ber_socket_t newsockfd = -1; int retVal = LDAP_SUCCESS; ber_socket_t ip4_fd = -1; ber_socket_t ip6_fd = -1; ber_socket_t max_fd = -1; VMDIR_THREAD threadId; BOOLEAN bInLock = FALSE; int iLocalLogMask = 0; PVDIR_CONNECTION_CTX pConnCtx = NULL; fd_set event_fd_set; fd_set poll_fd_set; struct timeval timeout = {0}; // Wait for ***1st*** replication cycle to be over. if (gVmdirServerGlobals.serverId == 0) // instance has not been initialized { VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "Connection accept thread: Have NOT yet started listening on LDAP port (%u)," " waiting for the 1st replication cycle to be over.", dwPort); VMDIR_LOCK_MUTEX(bInLock, gVmdirGlobals.replCycleDoneMutex); // wait till 1st replication cycle is over if (VmDirConditionWait( gVmdirGlobals.replCycleDoneCondition, gVmdirGlobals.replCycleDoneMutex ) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "Connection accept thread: VmDirConditionWait failed." ); retVal = LDAP_OPERATIONS_ERROR; goto cleanup; } // also wake up the other (normal LDAP port/SSL LDAP port listner) LDAP connection accept thread, // waiting on 1st replication cycle to be over // BUGBUG Does not handle spurious wake up VmDirConditionSignal(gVmdirGlobals.replCycleDoneCondition); VMDIR_UNLOCK_MUTEX(bInLock, gVmdirGlobals.replCycleDoneMutex); if (VmDirdState() == VMDIRD_STATE_SHUTDOWN) // Asked to shutdown before we started accepting { goto cleanup; } VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Connection accept thread: listening on LDAP port (%u).", dwPort); } iLocalLogMask = VmDirLogGetMask(); ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &iLocalLogMask); SetupLdapPort(dwPort, &ip4_fd, &ip6_fd); if (ip4_fd < 0 && ip6_fd < 0) { VmDirSleep(1000); goto cleanup; } FD_ZERO(&event_fd_set); if (ip4_fd >= 0) { FD_SET (ip4_fd, &event_fd_set); if (ip4_fd > max_fd) { max_fd = ip4_fd; } } if (ip6_fd >= 0) { FD_SET (ip6_fd, &event_fd_set); if (ip6_fd > max_fd) { max_fd = ip6_fd; } } retVal = VmDirSyncCounterIncrement(gVmdirGlobals.pPortListenSyncCounter); if (retVal != 0 ) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "%s: VmDirSyncCounterIncrement(gVmdirGlobals.pPortListenSyncCounter) returned error", __func__); BAIL_ON_VMDIR_ERROR(retVal); } while (TRUE) { if (VmDirdState() == VMDIRD_STATE_SHUTDOWN) { goto cleanup; } poll_fd_set = event_fd_set; timeout.tv_sec = 3; timeout.tv_usec = 0; retVal = select ((int)max_fd+1, &poll_fd_set, NULL, NULL, &timeout); if (retVal < 0 ) { #ifdef _WIN32 errno = WSAGetLastError(); #endif VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: select() (port %d) call failed: %d.", __func__, dwPort, errno); VmDirSleep( 1000 ); continue; } else if (retVal == 0) { //VMDIR_LOG_INFO( LDAP_DEBUG_CONNS, "%s: select() timeout (port %d)", __func__, dwPort); continue; } if (ip4_fd >= 0 && FD_ISSET(ip4_fd, &poll_fd_set)) { newsockfd = accept(ip4_fd, (struct sockaddr *) NULL, NULL); } else if (ip6_fd >= 0 && FD_ISSET(ip6_fd, &poll_fd_set)) { newsockfd = accept(ip6_fd, (struct sockaddr *) NULL, NULL); } else { VMDIR_LOG_INFO( LDAP_DEBUG_CONNS, "%s: select() returned with no data (port %d), return: %d", __func__, dwPort, retVal); continue; } if (newsockfd < 0) { #ifdef _WIN32 errno = WSAGetLastError(); #endif if (errno != EAGAIN && errno != EWOULDBLOCK ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: accept() (port %d) failed with errno: %d.", __func__, dwPort, errno ); } continue; } if ( _VmDirFlowCtrlThrEnter() == TRUE ) { tcp_close(newsockfd); newsockfd = -1; VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "Maxmimum number of concurrent LDAP threads reached. Blocking new connection" ); continue; } retVal = VmDirAllocateMemory( sizeof(VDIR_CONNECTION_CTX), (PVOID*)&pConnCtx); BAIL_ON_VMDIR_ERROR(retVal); pConnCtx->sockFd = newsockfd; newsockfd = -1; pConnCtx->pSockbuf_IO = pSockbuf_IO; retVal = VmDirCreateThread(&threadId, TRUE, ProcessAConnection, (PVOID)pConnCtx); if (retVal != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: VmDirCreateThread() (port) failed with errno: %d", __func__, dwPort, errno ); tcp_close(pConnCtx->sockFd); _VmDirFlowCtrlThrExit(); VMDIR_SAFE_FREE_MEMORY(pConnCtx); continue; } else { pConnCtx = NULL; //thread take ownership on pConnCtx VmDirFreeVmDirThread(&threadId); } } cleanup: VMDIR_UNLOCK_MUTEX(bInLock, gVmdirGlobals.replCycleDoneMutex); if (ip4_fd >= 0) { tcp_close(ip4_fd); } if (ip6_fd >= 0) { tcp_close(ip6_fd); } if (newsockfd >= 0) { tcp_close(newsockfd); } #ifndef _WIN32 raise(SIGTERM); #endif VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "%s: Connection accept thread: stop (port %d)", __func__, dwPort); return retVal; error: goto cleanup; }
DWORD VmDirIsAttrValueInScope( PVDIR_OPERATION pOperation, PDEQUE pAllValueMetaDataQueue, PDEQUE pValueMetaDataToSendQueue ) { DWORD dwError = 0; VDIR_BERVALUE bervValueMetaData = VDIR_BERVALUE_INIT; PVMDIR_VALUE_ATTRIBUTE_METADATA pValueMetaData = NULL; if (!pOperation || !pAllValueMetaDataQueue || !pValueMetaDataToSendQueue) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } while (!dequeIsEmpty(pAllValueMetaDataQueue)) { BOOLEAN bUsnInScope = FALSE; VMDIR_SAFE_FREE_VALUE_METADATA(pValueMetaData); dequePopLeft(pAllValueMetaDataQueue, (PVOID*)&pValueMetaData); dwError = VmDirIsUsnInScope( pOperation, NULL, pValueMetaData->pszValChgOrigInvoId, pValueMetaData->valChgOrigUsn, pValueMetaData->localUsn, 0, &bUsnInScope); BAIL_ON_VMDIR_ERROR(dwError); if (!bUsnInScope) { continue; } if (VmDirLogGetMask() & LDAP_DEBUG_REPL) { //ignore error VmDirValueMetaDataSerialize(pValueMetaData, &bervValueMetaData); VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "%s: valueMetaData: %s, usnInScope true", __FUNCTION__, VDIR_SAFE_STRING(bervValueMetaData.lberbv_val)); VmDirFreeBervalContent(&bervValueMetaData); } dwError = dequePush(pValueMetaDataToSendQueue, pValueMetaData); BAIL_ON_VMDIR_ERROR(dwError); pValueMetaData = NULL; } cleanup: VMDIR_SAFE_FREE_VALUE_METADATA(pValueMetaData); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
int ParseRequestControls( VDIR_OPERATION * op, VDIR_LDAP_RESULT * lr ) { int retVal = LDAP_SUCCESS; ber_tag_t tag = LBER_ERROR; ber_len_t len = 0; char * endOfCtrlsMarker = NULL; VDIR_LDAP_CONTROL ** control = &(op->reqControls); BerValue lberBervType = {0}; BerValue lberBervCtlValue = {0}; PSTR pszLocalErrorMsg = NULL; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseRequestControls: Begin." ); *control = NULL; #ifndef _WIN32 if (ber_pvt_ber_remaining(op->ber) != 0) #else if (LBER_DEFAULT != ber_peek_tag (op->ber, &len)) #endif { if (ber_peek_tag( op->ber, &len ) != LDAP_TAG_CONTROLS ) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: Request controls expected, but something else is there in the PDU."); } // Get controls. ber_first_element => skip the sequence header, set the cursor at the 1st control in the SEQ of SEQ for( tag = ber_first_element( op->ber, &len, &endOfCtrlsMarker ); tag != LBER_ERROR; tag = ber_next_element( op->ber, &len, endOfCtrlsMarker ) ) { // m => in-place if (ber_scanf( op->ber, "{m", &lberBervType ) == LBER_ERROR) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls Error in reading control type from the PDU."); } if ( VmDirLogGetMask() & LDAP_DEBUG_ARGS) { VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, " Request Control: %s", lberBervType.bv_val ); } if (VmDirAllocateMemory( sizeof( VDIR_LDAP_CONTROL), (PVOID *)control ) != 0) { retVal = lr->errCode = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: VmDirAllocateMemory failed"); } // type points into in-place ber and does NOT own its content (*control)->type = lberBervType.bv_val; (*control)->criticality = FALSE; tag = ber_peek_tag( op->ber, &len ); if (tag == LBER_BOOLEAN) { ber_int_t criticality; if (ber_scanf( op->ber, "b", &criticality) == LBER_ERROR) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: Error in reading control criticality from the PDU."); } if (criticality) { (*control)->criticality = TRUE; } tag = ber_peek_tag( op->ber, &len ); } if (tag == LBER_OCTETSTRING) { if (ber_scanf( op->ber, "m", &lberBervCtlValue) == LBER_ERROR) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: ber_scanf failed while parsing the control value."); } } // SJ-TBD: Make sure that the control appears only once in the request, and it is present only in a search // request if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_SYNC, TRUE ) == 0) { if (VmDirdGetRunMode() != VMDIR_RUNMODE_NORMAL) { // Why block out-bound replication when catching up during restore mode? // // Reason: Partners have high-water-mark (lastLocalUsn) corresponding to this replica that is being // restored. If out-bound replication is not blocked while restore/catching-up is going on, originating // or replicated updates (if this replica is the only partner) made between the current-local-usn and // high-water-marks, that partners remember, will not get replicated out (even if the invocationId // has been fixed/changed). retVal = lr->errCode = LDAP_UNWILLING_TO_PERFORM; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: Server not in normal mode, not allowing outward replication."); } if ((retVal = ParseSyncRequestControlVal( op, &lberBervCtlValue, &((*control)->value.syncReqCtrlVal), lr)) != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: ParseSyncRequestControlVal failed."); } op->syncReqCtrl = *control; } if (VmDirStringCompareA( (*control)->type, VDIR_LDAP_CONTROL_SHOW_DELETED_OBJECTS, TRUE ) == 0) { op->showDeletedObjectsCtrl = *control; } if (VmDirStringCompareA( (*control)->type, VDIR_LDAP_CONTROL_SHOW_MASTER_KEY, TRUE ) == 0) { op->showMasterKeyCtrl = *control; } if (VmDirStringCompareA((*control)->type, LDAP_CONTROL_CONSISTENT_WRITE, TRUE ) == 0) { op->strongConsistencyWriteCtrl = *control; } if (VmDirStringCompareA((*control)->type, VDIR_LDAP_CONTROL_MANAGEDDSAIT, TRUE ) == 0) { op->manageDsaITCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_PAGEDRESULTS, TRUE ) == 0) { retVal = _ParsePagedResultControlVal( op, &lberBervCtlValue, &((*control)->value.pagedResultCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParsePagedResultControlVal failed."); } op->showPagedResultsCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_CONDITIONAL_WRITE, TRUE ) == 0) { retVal = _ParseCondWriteControlVal( op, &lberBervCtlValue, &((*control)->value.condWriteCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParseConditionalWriteControlVal failed."); } op->pCondWriteCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_APPEND_ENTRIES_CONTROL, TRUE ) == 0) { retVal = _ParseAppendEntriesControlVal( op, &lberBervCtlValue, &((*control)->value.appendEntriesCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParseAppendEntriesControlVal failed."); } op->appendEntriesCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_REQUEST_VOTE_CONTROL, TRUE ) == 0) { retVal = _ParseRequestVoteControlVal( op, &lberBervCtlValue, &((*control)->value.requestVoteCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParseRequestVoteControlVal failed."); } op->requestVoteCtrl = *control; } if (VmDirStringCompareA( (*control)->type, VMDIR_LDAP_CONTROL_TXN_SPEC, TRUE ) == 0) { retVal = VmDirAllocateMemory(lberBervCtlValue.bv_len+1, (PVOID*)&((*control)->value.txnSpecCtrlVal).pszTxnId); BAIL_ON_VMDIR_ERROR(retVal); VmDirStringNCpyA(((*control)->value.txnSpecCtrlVal).pszTxnId, lberBervCtlValue.bv_len+1, lberBervCtlValue.bv_val, lberBervCtlValue.bv_len); op->txnSpecCtrl = *control; op->pBECtx->pszTxnId = (op->txnSpecCtrl->value.txnSpecCtrlVal).pszTxnId; } if ( ber_scanf( op->ber, "}") == LBER_ERROR ) // end of control { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: ber_scanf failed while parsing the end of control"); } control = &((*control)->next); } retVal = LDAP_SUCCESS; } cleanup: VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseRequestControls: End." ); VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: DeleteControls(&(op->reqControls)); if (pszLocalErrorMsg) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, pszLocalErrorMsg); VMDIR_APPEND_ERROR_MSG(lr->pszErrMsg, pszLocalErrorMsg); } goto cleanup; }
int VmDirPerformSearch( PVDIR_OPERATION pOperation ) { ber_len_t size = 0; SearchReq * sr = &(pOperation->request.searchReq); int retVal = LDAP_SUCCESS; BerValue* pLberBerv = NULL; PSTR pszLocalErrorMsg = NULL; BOOLEAN bResultAlreadySent = FALSE; PVDIR_LDAP_RESULT pResult = &(pOperation->ldapResult); // Parse base object, scope, deref alias, sizeLimit, timeLimit and typesOnly search parameters. if ( ber_scanf( pOperation->ber, "{miiiib", &(pOperation->reqDn.lberbv), &sr->scope, &sr->derefAlias, &sr->sizeLimit, &sr->timeLimit, &sr->attrsOnly ) == LBER_ERROR ) { VMDIR_LOG_ERROR( LDAP_DEBUG_ARGS, "PerformSearch: Decoding baseDN, ... attrsOnly error." ); pResult->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Decoding error while parsing baseDN, ... attrsOnly."); } VMDIR_LOG_VERBOSE( LDAP_DEBUG_ARGS, "Search Request: base: \"%s\", scope: %d, deref: %d, sizeLimit: %d, timeLimit: %d," "attrsOnly: %d", pOperation->reqDn.lberbv.bv_val, sr->scope, sr->derefAlias, sr->sizeLimit, sr->timeLimit, sr->attrsOnly); if (sr->scope != LDAP_SCOPE_BASE && sr->scope != LDAP_SCOPE_ONELEVEL && sr->scope != LDAP_SCOPE_SUBTREE) { pResult->errCode = retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Invalid scope" ); } if (sr->sizeLimit < 0 || sr->sizeLimit > LDAP_MAXINT) { pResult->errCode = retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Invalid size limit: %d", sr->sizeLimit ); } if (sr->timeLimit < 0 || sr->timeLimit > LDAP_MAXINT) { pResult->errCode = retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Invalid time limit: %d", sr->timeLimit ); } if (sr->derefAlias != LDAP_DEREF_NEVER && sr->derefAlias != LDAP_DEREF_SEARCHING && sr->derefAlias != LDAP_DEREF_FINDING && sr->derefAlias != LDAP_DEREF_ALWAYS) { pResult->errCode = retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Invalid dereference alias parameter"); } // Parse filter retVal = ParseFilter( pOperation, &sr->filter, pResult ); BAIL_ON_VMDIR_ERROR(retVal); // Log String filter, if desired. if (VmDirLogGetLevel() >= VMDIR_LOG_VERBOSE && VmDirLogGetMask() & LDAP_DEBUG_ARGS) { VDIR_BERVALUE strFilter = VDIR_BERVALUE_INIT; FilterToStrFilter( sr->filter, &strFilter ); VMDIR_LOG_VERBOSE( LDAP_DEBUG_ARGS, " Filter: %s", strFilter.lberbv.bv_val ); VmDirFreeBervalContent(&strFilter); } // Parse attributes. 'M' => attribute names point within (in-place) the ber. size = sizeof( BerValue ); // Size of the structure is passed-in, and number of attributes are returned back in // the same parameter. if ( ber_scanf( pOperation->ber, "{M}}", &pLberBerv, &size, 0 ) == LBER_ERROR ) { pResult->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Decoding error while parsing required attributes."); } // copy pLberBerv content into sr->attrs if (pLberBerv && size > 0) { int iCnt = 0; if (VmDirAllocateMemory(sizeof(VDIR_BERVALUE) * (size+1), (PVOID*)&sr->attrs) != 0) { pResult->errCode = retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "no memory"); } for (iCnt = 0; iCnt < size; iCnt++) { sr->attrs[iCnt].lberbv.bv_val = pLberBerv[iCnt].bv_val; sr->attrs[iCnt].lberbv.bv_len = pLberBerv[iCnt].bv_len; } } // Log list of the required attributes, if desired. if (( VmDirLogGetMask() & LDAP_DEBUG_ARGS) && size > 0) { if (VmDirLogSearchRequest(sr, size) != 0) { pResult->errCode = retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "Error while logging search request"); } } // Parse LDAP controls present (if any) in the request. retVal = ParseRequestControls(pOperation, pResult); // ldapResult.errCode set inside BAIL_ON_VMDIR_ERROR( retVal ); retVal = pResult->errCode = VmDirMLSearch( pOperation ); bResultAlreadySent = TRUE; BAIL_ON_VMDIR_ERROR(retVal); cleanup: VMDIR_SAFE_FREE_MEMORY(pLberBerv); VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: VMDIR_APPEND_ERROR_MSG(pResult->pszErrMsg, pszLocalErrorMsg); if (retVal != LDAP_NOTICE_OF_DISCONNECT && bResultAlreadySent == FALSE) { VmDirSendLdapResult( pOperation ); } goto cleanup; }
static DWORD _VmDirLogSearchParameters( PVDIR_OPERATION pOperation ) { DWORD dwError = 0; PVDIR_CONNECTION pConn = pOperation->conn; SearchReq sr = pOperation->request.searchReq; VDIR_BERVALUE strFilter = VDIR_BERVALUE_INIT; static PCSTR pcszScopeStr[] = { "BASE", "ONE", "SUB" }; dwError = FilterToStrFilter(sr.filter, &strFilter); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringA( VDIR_SAFE_STRING(strFilter.lberbv.bv_val), &pConn->SuperLogRec.pszOperationParameters); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringA( VDIR_SAFE_STRING(pOperation->reqDn.lberbv.bv_val), &pConn->SuperLogRec.opInfo.searchInfo.pszBaseDN); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringA( VDIR_SAFE_STRING(pOperation->pszFilters), &pConn->SuperLogRec.opInfo.searchInfo.pszIndexResults); BAIL_ON_VMDIR_ERROR(dwError); if (sr.scope < 0 || sr.scope > 2) { VMDIR_LOG_ERROR( LDAP_DEBUG_ARGS, "_VmDirLogSearchParameters: Unknown search scope (%d)", sr.scope ); dwError = ERROR_INVALID_PARAMETER; } else { dwError = VmDirAllocateStringA( pcszScopeStr[sr.scope], &pConn->SuperLogRec.opInfo.searchInfo.pszScope); } BAIL_ON_VMDIR_ERROR(dwError); pConn->SuperLogRec.opInfo.searchInfo.dwReturned = pOperation->dwSentEntries; if (pOperation->request.searchReq.filter->candidates) { pConn->SuperLogRec.opInfo.searchInfo.dwScanned = sr.filter->candidates->size; } if (VmDirLogGetLevel() >= VMDIR_LOG_VERBOSE && VmDirLogGetMask() & LDAP_DEBUG_ARGS) { VMDIR_LOG_VERBOSE(LDAP_DEBUG_ARGS, " Filter: %s", pConn->SuperLogRec.pszOperationParameters); } cleanup: VmDirFreeBervalContent(&strFilter); return dwError; error: goto cleanup; }
static DWORD _VmDirLogSearchAttributes( PVDIR_OPERATION pOperation, ber_len_t iNumAttr ) { DWORD dwError = 0; PSTR pszAttributes = NULL; size_t currLen = 0; size_t msgSize = 0; int iCnt = 0; SearchReq *pSReq = &(pOperation->request.searchReq); if (iNumAttr > 0) { for (iCnt = 0, msgSize = 0; iCnt<iNumAttr; iCnt++) { msgSize += pSReq->attrs[iCnt].lberbv.bv_len + 2 /* for a ',' and ' ' */; } dwError = VmDirAllocateMemory(msgSize + 1, (PVOID *)&pszAttributes); BAIL_ON_VMDIR_ERROR(dwError); for (iCnt = 0, currLen = 0; iCnt<iNumAttr; iCnt++) { VmDirStringNPrintFA( pszAttributes + currLen, msgSize + 1 - currLen, msgSize - currLen, "%s, ", pSReq->attrs[iCnt].lberbv.bv_val); BAIL_ON_VMDIR_ERROR(dwError); currLen += pSReq->attrs[iCnt].lberbv.bv_len + 2; } pszAttributes[currLen - 2] = '\0'; dwError = VmDirAllocateStringA( VDIR_SAFE_STRING(pszAttributes), &pOperation->conn->SuperLogRec.opInfo.searchInfo.pszAttributes); BAIL_ON_VMDIR_ERROR(dwError); if (VmDirLogGetMask() & LDAP_DEBUG_ARGS) { VMDIR_LOG_VERBOSE(LDAP_DEBUG_ARGS, " Required attributes: %s", pszAttributes); } } cleanup: VMDIR_SAFE_FREE_MEMORY(pszAttributes); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "_VmDirLogSearchAttributes: dwError: %lu, msgSize: %lu, iNumAttr: %lu", dwError, msgSize, iNumAttr); for (iCnt = 0; iCnt<iNumAttr; iCnt++) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, " attr[%d] len: %lu, val: \"%.*s\"", iCnt, pSReq->attrs[iCnt].lberbv.bv_len, 256, VDIR_SAFE_STRING(pSReq->attrs[iCnt].lberbv.bv_val)); } goto cleanup; }