Beispiel #1
0
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;
        }
    }
}
Beispiel #2
0
/*
 * 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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}