Exemplo n.º 1
0
int
VmDirPerformRename(
   PVDIR_OPERATION pOperation
   )
{
    ModifyReq *        modReq = &(pOperation->request.modifyReq);
    int                retVal = LDAP_SUCCESS;
    PVDIR_LDAP_RESULT  pResult = &(pOperation->ldapResult);
    ber_len_t          size = 0;
    PSTR               pszLocalErrorMsg = NULL;

    if (!_VmDirIsRenameSupported())
    {
        pResult->errCode = retVal = LDAP_UNWILLING_TO_PERFORM;
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrorMsg, "Operation is not enabled on this server or is not supported at this domain fuctional level.");
    }

    // Get entry DN. 'm' => reqDn.bv_val points to DN within (in-place) ber
    if ( ber_scanf( pOperation->ber, "{mmb", &modReq->dn, &modReq->newrdn, &modReq->bDeleteOldRdn) == LBER_ERROR )
    {
        VMDIR_LOG_ERROR( LDAP_DEBUG_ARGS, "VmDirPerformRename: ber_scanf failed" );
        pResult->errCode = LDAP_PROTOCOL_ERROR;
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                      "Decoding error while parsing the target DN");
    }

    if (ber_peek_tag(pOperation->ber, &size) == LDAP_TAG_NEWSUPERIOR)
    {
        if ( ber_scanf(pOperation->ber, "m", &modReq->newSuperior ) == LBER_ERROR ) {
        pResult->errCode = LDAP_PROTOCOL_ERROR;
        retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Decoding error while parsing newSuperior");

        }
    }

   if ( ber_scanf( pOperation->ber, "}") == LBER_ERROR )
   {
      VMDIR_LOG_ERROR( LDAP_DEBUG_ARGS, "PerformRename: ber_scanf failed" );
      pResult->errCode = LDAP_PROTOCOL_ERROR;
      retVal = LDAP_NOTICE_OF_DISCONNECT;
      BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg), "Decoding error while parsing the end of message.");
   }

   retVal = pResult->errCode = VmDirMLModify( pOperation );
   BAIL_ON_VMDIR_ERROR(retVal);

cleanup:
    if (retVal != LDAP_NOTICE_OF_DISCONNECT)
    {
        VmDirSendLdapResult( pOperation );
    }
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    return retVal;

error:
    VMDIR_APPEND_ERROR_MSG(pResult->pszErrMsg, pszLocalErrorMsg);
    goto cleanup;
}
Exemplo n.º 2
0
static
int
_ParseCondWriteControlVal(
    VDIR_OPERATION *                        pOp,
    BerValue *                              pControlBer,    // Input: control value encoded as ber
    VDIR_CONDWRITE_CONTROL_VALUE *          pCtrlVal,       // Output
    VDIR_LDAP_RESULT *                      pLdapResult     // Output
    )
{
    int                 retVal = LDAP_SUCCESS;
    BerElementBuffer    berbuf;
    BerElement *        ber = (BerElement *)&berbuf;
    PSTR                pszLocalErrorMsg = NULL;
    PSTR                pszCondFilter = NULL;

    if (!pOp)
    {
        retVal = LDAP_PROTOCOL_ERROR;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    ber_init2( ber, pControlBer, LBER_USE_DER );

    /*
     * https://confluence.eng.vmware.com/display/LIG/Conditional+LDAP+Write+Operation
     *
     * The ConditionalWriteControl is a null terminated STRING wrapping the BER-encoded version of the following SEQUENCE:
     *
     * ControlValue ::= SEQUENCE {
     *        ConditionalWriteFilter            OCTET STRING
     *  }
     */

    if (ber_scanf(ber, "{a}", &pszCondFilter) == LBER_ERROR)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: ber_scanf failed while parsing filter value", __FUNCTION__);
        pLdapResult->errCode = LDAP_PROTOCOL_ERROR;
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Error in reading conditional write control filter");
    }

    retVal = VmDirAllocateStringA(pszCondFilter, &(pCtrlVal->pszFilter));
    BAIL_ON_VMDIR_ERROR(retVal);

cleanup:
    if (pszCondFilter)
    {
        ber_memfree(pszCondFilter);
    }
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return retVal;

error:
    VMDIR_APPEND_ERROR_MSG(pLdapResult->pszErrMsg, pszLocalErrorMsg);
    goto cleanup;
}
Exemplo n.º 3
0
/*
 * Called during entry add
 *
 *  grouptype :
 *
        http://msdn.microsoft.com/en-us/library/windows/desktop/ms675935%28v=vs.85%29.aspx
        Value   Description
        1 (0x00000001)  Specifies a group that is created by the system.
        2 (0x00000002)  Specifies a group with global scope.
        4 (0x00000004)  Specifies a group with domain local scope.
        8 (0x00000008)  Specifies a group with universal scope.
        16 (0x00000010) Specifies an APP_BASIC group for Windows Server Authorization Manager.
        32 (0x00000020) Specifies an APP_QUERY group for Windows Server Authorization Manager.
        2147483648 (0x80000000) Specifies a security group. If this flag is not set, then the group is a distribution group.

    Currently, Lotus only supports global scope (2).
 */
DWORD
VmDirPluginGroupTypePreAdd(
    PVDIR_OPERATION  pOperation,
    PVDIR_ENTRY      pEntry,
    DWORD            dwPriorResult
    )
{
    DWORD               dwError = 0;
    PSTR                pszLocalErrorMsg = NULL;

    if ( pOperation->opType != VDIR_OPERATION_TYPE_REPL
         &&
         TRUE == VmDirIsEntryWithObjectclass(pEntry, OC_GROUP)
       )
    {
        PVDIR_ATTRIBUTE pAttrGroupType = VmDirFindAttrByName(pEntry, ATTR_GROUPTYPE);

        if (pAttrGroupType == NULL)
        {
            dwError = VmDirEntryAddSingleValueStrAttribute(pEntry, ATTR_GROUPTYPE, GROUPTYPE_GLOBAL_SCOPE);
            BAIL_ON_VMDIR_ERROR(dwError);
        }
        else
        {
            if ( pAttrGroupType->numVals != 1       // grouptype is a single value attribute
                 ||
                 VmDirStringCompareA( VDIR_SAFE_STRING( pAttrGroupType->vals[0].lberbv.bv_val),
                                       GROUPTYPE_GLOBAL_SCOPE, FALSE) != 0
               )
            {
                dwError = ERROR_INVALID_ENTRY;
                BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrorMsg, "invalid or unsupported grouptype (%s)",
                                              VDIR_SAFE_STRING( pAttrGroupType->vals[0].lberbv.bv_val));
            }
        }
    }

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return dwError;

error:

    VmDirLog( LDAP_DEBUG_ANY, "Group check: (%d)(%s)", dwError, VDIR_SAFE_STRING(pszLocalErrorMsg));

    VMDIR_APPEND_ERROR_MSG(pOperation->ldapResult.pszErrMsg, pszLocalErrorMsg);

    goto cleanup;
}
Exemplo n.º 4
0
static
int
DeleteRefAttributesValue(
    VDIR_OPERATION * pOperation,
    VDIR_BERVALUE * dn
    )
{
    int               retVal = LDAP_SUCCESS;
    VDIR_FILTER *     f = NULL;
    VDIR_CANDIDATES * cl = NULL;
    VDIR_ENTRY        groupEntry = {0};
    VDIR_ENTRY *      pGroupEntry = NULL;
    int          i = 0;
    VDIR_MODIFICATION mod = {0};
    ModifyReq    mr;
    VDIR_BERVALUE     delVals[2];
    PSTR              pszLocalErrorMsg = NULL;

    assert( pOperation != NULL && pOperation->pBEIF != NULL && dn != NULL);

    retVal = VmDirNormalizeDN( dn, pOperation->pSchemaCtx );
    BAIL_ON_VMDIR_ERROR( retVal );

    // Set filter
    retVal = VmDirAllocateMemory( sizeof( VDIR_FILTER ), (PVOID *)&f);
    BAIL_ON_VMDIR_ERROR( retVal );

    f->choice = LDAP_FILTER_EQUALITY;
    f->filtComp.ava.type.lberbv.bv_val = ATTR_MEMBER;
    f->filtComp.ava.type.lberbv.bv_len = ATTR_MEMBER_LEN;
    f->filtComp.ava.value = *dn;
    if ((f->filtComp.ava.pATDesc = VmDirSchemaAttrNameToDesc( pOperation->pSchemaCtx, ATTR_MEMBER)) == NULL)
    {
        retVal = VMDIR_ERROR_NO_SUCH_ATTRIBUTE;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "undefined attribute (%s)",
                                        VDIR_SAFE_STRING(ATTR_MEMBER));
    }
    // Set ModifyReq structure
    memset(&mr, 0, sizeof(ModifyReq));
    mod.operation = MOD_OP_DELETE;
    mod.attr.type.lberbv.bv_val = ATTR_MEMBER;
    mod.attr.type.lberbv.bv_len = ATTR_MEMBER_LEN;
    mod.attr.pATDesc = f->filtComp.ava.pATDesc;

    mod.attr.next = NULL;
    delVals[0] = *dn;
    memset(&(delVals[1]), 0, sizeof(VDIR_BERVALUE));
    mod.attr.vals = delVals;
    mod.attr.numVals = 1;
    mod.next = NULL;
    mr.mods = &mod;
    mr.numMods = 1;

    retVal = pOperation->pBEIF->pfnBEGetCandidates( pOperation->pBECtx, f);
    if ( retVal != 0 )
    {
        if (retVal == VMDIR_ERROR_BACKEND_ENTRY_NOTFOUND)
        {
            retVal = LDAP_SUCCESS;  // no member refer to this DN. return ok/0
        }
        else
        {
            retVal = VMDIR_ERROR_GENERIC;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                        "DeleteRefAttributesValue: Building group list (BdbGetCandidates()) failed.");
        }
    }
    else
    {
        cl = f->candidates;

        for (i = 0; i < cl->size; i++)
        {
            pGroupEntry = &groupEntry;
            if ((retVal = VmDirModifyEntryCoreLogic( pOperation, &mr, cl->eIds[i], pGroupEntry)) != 0)
            {
                switch (retVal)
                {
                    case VMDIR_ERROR_BACKEND_PARENT_NOTFOUND:
                    case VMDIR_ERROR_BACKEND_ENTRY_NOTFOUND:
                    case VMDIR_ERROR_ENTRY_NOT_FOUND:
                        continue;

                    default: // Including LDAP_LOCK_DEADLOCK, which is handled by the caller
                        BAIL_ON_VMDIR_ERROR( retVal );
                }
            }

            VmDirFreeBervalContent( &(mr.dn) ); // VmDirModifyEntryCoreLogic fill in DN if not exists
            VmDirFreeEntryContent( pGroupEntry );
            pGroupEntry = NULL; // Reset to NULL so that DeleteEntry is no-op.
        }
    }

cleanup:
    memset(&(f->filtComp.ava.value), 0, sizeof(VDIR_BERVALUE)); // Since ava.value is NOT owned by filter.
    DeleteFilter( f );
    VmDirFreeEntryContent( pGroupEntry );
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return retVal;

error:

    VMDIR_APPEND_ERROR_MSG(pOperation->ldapResult.pszErrMsg, pszLocalErrorMsg);
    goto cleanup;
}
Exemplo n.º 5
0
static int
_ParsePagedResultControlVal(
    VDIR_OPERATION *                    op,
    BerValue *                          controlValue,       // Input: control value encoded as ber
    VDIR_PAGED_RESULT_CONTROL_VALUE *   pageResultCtrlVal,     // Output
    VDIR_LDAP_RESULT *                  lr                  // Output
    )
{
    int                     retVal = LDAP_SUCCESS;
    BerElementBuffer        berbuf;
    BerElement *            ber = (BerElement *)&berbuf;
    PSTR                    pszLocalErrorMsg = NULL;
    PSTR                    pszCookie = NULL;

    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "_ParsePagedResultControlVal: Start." );

    if (!op)
    {
        retVal = LDAP_PROTOCOL_ERROR;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    ber_init2( ber, controlValue, LBER_USE_DER );

    /* http://www.ietf.org/rfc/rfc2696.txt
     *
     * The searchControlValue is an OCTET STRING wrapping the BER-encoded version of the following SEQUENCE:
     *
     * realSearchControlValue ::= SEQUENCE {
     *        size            INTEGER (0..maxInt),
     *                                -- requested page size from client
     *                                -- result set size estimate from server
     *        cookie          OCTET STRING
    }
    */

    if (ber_scanf(ber, "{ia}",
                    &pageResultCtrlVal->pageSize,
                    &pszCookie) == LBER_ERROR)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_ParsePagedResultControlVal: ber_scanf failed while parsing "
                  "pageSize and cookie in the page result control value" );
        lr->errCode = LDAP_PROTOCOL_ERROR;
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Error in reading pageSize and cookie in the page result control value");
    }

    if (pageResultCtrlVal->pageSize == 0)
    {
        retVal = LDAP_CANCELLED;
        VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "Search query was cancelled.");
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    VmDirStringNCpyA(
        pageResultCtrlVal->cookie,
        VMDIR_ARRAY_SIZE(pageResultCtrlVal->cookie),
        pszCookie,
        VMDIR_ARRAY_SIZE(pageResultCtrlVal->cookie) - 1);

    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "pageSize:%d", pageResultCtrlVal->pageSize );
    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "cookie:%s", pageResultCtrlVal->cookie );

cleanup:
    if (pszCookie)
    {
        ber_memfree(pszCookie);
    }
    // Even in the error case, syncDoneCtrl should be freed during operation delete.
    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "_ParsePagedResultControlVal: End." );
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    return retVal;

error:
    VMDIR_APPEND_ERROR_MSG(lr->pszErrMsg, pszLocalErrorMsg);
    goto cleanup;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
static int
ParseSyncRequestControlVal(
    VDIR_OPERATION *            op,
    BerValue *                  controlValue,       // Input: control value encoded as ber
    SyncRequestControlValue *   syncReqCtrlVal,     // Output
    VDIR_LDAP_RESULT *          lr                  // Output
    )
{
    int                     retVal = LDAP_SUCCESS;
    ber_tag_t               tag = LBER_ERROR;
    ber_len_t               len = 0;
    UptoDateVectorEntry *   utdVectorEntry = NULL;
    BerElementBuffer        berbuf;
    BerElement *            ber = (BerElement *)&berbuf;
    PSTR                    pszLocalErrorMsg = NULL;
    VDIR_BACKEND_CTX        backendCtx = {0};
    USN                     maxPartnerVisibleUSN = 0;

    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncRequestControlVal: Begin." );

    ber_init2( ber, controlValue, LBER_USE_DER );

    /* http://www.rfc-editor.org/rfc/rfc4533.txt
     *
     *  syncCookie ::= OCTET STRING
     *
     *  syncRequestValue ::= SEQUENCE {
     *          mode ENUMERATED {
     *              -- 0 unused
     *              refreshOnly       (1),
     *              -- 2 reserved
     *              refreshAndPersist (3)
     *          },
     *          cookie     syncCookie OPTIONAL,
     *          reloadHint BOOLEAN DEFAULT FALSE
     *  }
    */

    if (ber_scanf( ber, "{i", &(syncReqCtrlVal->mode) ) == LBER_ERROR)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ber_scanf failed while parsing the sync request "
                  "control mode" );
        lr->errCode = LDAP_PROTOCOL_ERROR;
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Error in reading sync request control mode from PDU.");
    }

    syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv.bv_val = "";
    syncReqCtrlVal->intLastLocalUsnProcessed = 0;

    if (VmDirAllocateMemory( sizeof( VDIR_LDAP_CONTROL ), (PVOID *)&op->syncDoneCtrl) != 0)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: VmDirAllocateMemory failed " );
        lr->errCode = retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "ParseSyncRequestControlVal: VmDirAllocateMemory failed.");
    }
    op->syncDoneCtrl->type = LDAP_CONTROL_SYNC_DONE;
    if (LwRtlCreateHashTable( &op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, UtdVectorEntryGetKey,
                              LwRtlHashDigestPstr, LwRtlHashEqualPstr, NULL, VMDIR_UTD_VECTOR_HASH_TABLE_SIZE ) != 0)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "UpdateSyncDoneUtdVectorEntry: LwRtlCreateHashTable failed" );
        lr->errCode = retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "UpdateSyncDoneUtdVectorEntry: LwRtlCreateHashTable failed");

    }

    tag = ber_peek_tag( ber, &len );

    if (tag == LBER_SEQUENCE)
    { // syncCookie

        /* syncCookie ::= SEQUENCE {
         *                      reqServerId             LDAPString,
         *                      lastLocalUsnProcessed   INTEGER (0 .. maxInt),
         *                      utdVector               UptoDateVectorEntryList }
         *
         *   UptoDateVectorEntryList ::= SEQUENCE OF uptoDateVectorEntry UptoDateVectorEntry
         *
         *   UptoDateVectorEntry ::= SEQUENCE {
         *                            serverId              LDAPString,
         *                            lastOrigUsnProcessed  INTEGER (0 .. maxInt) }
         */
        // {lastLocalUsnProcessed{{<serverid1><lastOrigUsnProcessed1>}{<serverid2><lastOrigUsnProcessed2>}...}}

        if (ber_scanf( ber, "{mmm}",
                        &syncReqCtrlVal->reqInvocationId.lberbv,
                        &syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv,
                        &syncReqCtrlVal->bvUtdVector.lberbv ) == LBER_ERROR )
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ber_scanf failed while parsing "
                      "lastLocalUsnProcessed in the sync request control value" );
            lr->errCode = LDAP_PROTOCOL_ERROR;
            retVal = LDAP_NOTICE_OF_DISCONNECT;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "Error in reading lastLocalUsnProcessed in the sync request control value");
        }

        VMDIR_LOG_DEBUG( LDAP_DEBUG_REPL, "ParseSyncRequestControlVal: ServerId: %s, lastLocalUsnProcessed: %s, utdVector: %s",
                  syncReqCtrlVal->reqInvocationId.lberbv.bv_val, syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv.bv_val,
                  syncReqCtrlVal->bvUtdVector.lberbv.bv_val );

        syncReqCtrlVal->intLastLocalUsnProcessed = op->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed =
                                   VmDirStringToLA( syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv.bv_val, NULL, 10 );
        {
            char *                  nextServerIdStr = NULL;
            char *                  nextOrigUsnStr = NULL;

            nextServerIdStr = syncReqCtrlVal->bvUtdVector.lberbv.bv_val;

            while( nextServerIdStr != NULL && nextServerIdStr[0] != '\0')
            {
                PLW_HASHTABLE_NODE pNode = NULL;

                if (VmDirAllocateMemory( sizeof(UptoDateVectorEntry), (PVOID *)&utdVectorEntry ) != 0)
                {
                    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: VmDirAllocateMemory failed " );
                    lr->errCode = retVal = LDAP_OPERATIONS_ERROR;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                    "ParseSyncRequestControlVal: VmDirAllocateMemory failed");
                }

                nextOrigUsnStr = VmDirStringChrA( nextServerIdStr, ':');
                *nextOrigUsnStr = '\0';
                nextOrigUsnStr++;
                utdVectorEntry->invocationId.lberbv.bv_val = nextServerIdStr;
                utdVectorEntry->invocationId.lberbv.bv_len = VmDirStringLenA( nextServerIdStr );

                nextServerIdStr = VmDirStringChrA( nextOrigUsnStr, ',');
                *nextServerIdStr = '\0';
                nextServerIdStr++;

                utdVectorEntry->currMaxOrigUsnProcessed = utdVectorEntry->reqLastOrigUsnProcessed =
                                                              atol( nextOrigUsnStr );

                LwRtlHashTableResizeAndInsert( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector,
                                               &utdVectorEntry->Node, &pNode);
                assert( pNode == NULL );    // assert the key of added node is unique.
            }
        }

        tag = ber_peek_tag( ber, &len );
    }
    if (tag == LBER_BOOLEAN)
    {
        ber_int_t reloadHint;
        if (ber_scanf( ber, "b", &reloadHint) == LBER_ERROR)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: Error in reading reloadHint from the PDU" );
            lr->errCode = LDAP_PROTOCOL_ERROR;
            retVal = LDAP_NOTICE_OF_DISCONNECT;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "Error in reading reloadHint from the PDU.");
        }
        if (reloadHint)
        {
            syncReqCtrlVal->reloadHint = TRUE;
        }
    }
    if ( ber_scanf( ber, "}") == LBER_ERROR ) // End of control value
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ber_scanf failed while parsing the end of "
                  "sync request control value." );
        lr->errCode = LDAP_PROTOCOL_ERROR;
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Decoding error while parsing the end of sync request control value.");
    }

    backendCtx.pBE = VmDirBackendSelect("");
    maxPartnerVisibleUSN = backendCtx.pBE->pfnBEGetLeastOutstandingUSN( &backendCtx, FALSE ) - 1;

    if (syncReqCtrlVal->intLastLocalUsnProcessed > maxPartnerVisibleUSN)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ServerId %s has processed my USN (%u), my max USN is (%u).",
                         syncReqCtrlVal->reqInvocationId.lberbv.bv_val, syncReqCtrlVal->intLastLocalUsnProcessed, maxPartnerVisibleUSN );
        lr->errCode = LDAP_UNWILLING_TO_PERFORM;
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg), "Partner is ahead of my changes.");
    }

cleanup:
    // Even in the error case, syncDoneCtrl should be freed during operation delete.
    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncRequestControlVal: End." );
    VmDirBackendCtxContentFree( &backendCtx );
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return retVal;

error:

    VMDIR_APPEND_ERROR_MSG(lr->pszErrMsg, pszLocalErrorMsg);

    goto cleanup;
}
Exemplo n.º 8
0
static
int
_ParseRequestVoteControlVal(
    VDIR_OPERATION *                        pOp,
    BerValue *                              pControlBer,    // Input: control value encoded as ber
    PVDIR_REQUEST_VOTE_CONTROL_VALUE        pCtrlVal,       // Output
    VDIR_LDAP_RESULT *                      pLdapResult     // Output
    )
{
    int                 retVal = LDAP_SUCCESS;
    BerElementBuffer    berbuf = {0};
    BerElement *        ber = (BerElement *)&berbuf;
    PSTR                pszLocalErrorMsg = NULL;
    ber_int_t           term = 0;
    BerValue            candidateId = {0};
    BerValue            lastLogIndex = {0};
    ber_int_t           lastLogTerm = 0;

    if (!pOp || !pControlBer )
    {
        retVal = LDAP_PROTOCOL_ERROR;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    if (!pCtrlVal || !pLdapResult)
    {
        retVal = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    ber_init2( ber, pControlBer, LBER_USE_DER );

    /*
     * The RequestVoteControl the BER-encoded version of the following SEQUENCE:
     *
     * ControlValue ::= SEQUENCE {
     *        term                    Integer
     *        candidateId             OCTET STRING
     *        lastLogIndex            OCTET STRING
     *        lastLogTerm             Integer
     *  }
     */

    if (ber_scanf(ber, "{immi}", &term, &candidateId, &lastLogIndex, &lastLogTerm) == LBER_ERROR)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: ber_scanf failed while parsing filter value", __FUNCTION__);
        pLdapResult->errCode = LDAP_PROTOCOL_ERROR;
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Error in reading cluster state control filter");
    }

    pCtrlVal->term = term;

    retVal = VmDirAllocateStringA(candidateId.bv_val, &(pCtrlVal->candidateId));
    BAIL_ON_VMDIR_ERROR(retVal);

    pCtrlVal->lastLogIndex = VmDirStringToLA(lastLogIndex.bv_val, NULL, 10);
    BAIL_ON_VMDIR_ERROR(retVal);

    pCtrlVal->lastLogTerm = lastLogTerm;

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    return retVal;

error:
    if (pszLocalErrorMsg && pLdapResult->pszErrMsg)
    {
       VMDIR_APPEND_ERROR_MSG(pLdapResult->pszErrMsg, pszLocalErrorMsg);
    }
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "%s Error: %d", __func__, retVal);
    goto cleanup;
}
Exemplo n.º 9
0
static
int
_ParseAppendEntriesControlVal(
    VDIR_OPERATION *                        pOp,
    BerValue *                              pControlBer,    // Input: control value encoded as ber
    PVDIR_APPEND_ENTRIES_CONTROL_VALUE      pCtrlVal,       // Output
    VDIR_LDAP_RESULT *                      pLdapResult     // Output
    )
{
    int                 retVal = LDAP_SUCCESS;
    BerElementBuffer    berbuf = {0};
    BerElement *        ber = (BerElement *)&berbuf;
    PSTR                pszLocalErrorMsg = NULL;
    ber_int_t           term = 0;
    BerValue            leader = {0};
    BerValue            preLogIndex= {0};
    ber_int_t           preLogTerm = 0;
    BerValue            leaderCommit = {0};
    BerValue            entries = {0};

    if (!pOp || !pControlBer)
    {
        retVal = LDAP_PROTOCOL_ERROR;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    if (!pCtrlVal || !pLdapResult)
    {
        retVal = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    ber_init2( ber, pControlBer, LBER_USE_DER );

    /*
     * The AppendEntriesControl the BER-encoded version of the following SEQUENCE:
     *
     * ControlValue ::= SEQUENCE {
     *        term                    Integer
     *        leader                  OCTET STRING
     *        preLogIndex             OCTET STRING
     *        prevLogTerm             Integer
     *        leaderCommit            OCTET STRING
     *        entries                 OCTET STRING
     *  }
     */

    if (ber_scanf(ber, "{immimm}", &term, &leader, &preLogIndex, &preLogTerm, &leaderCommit, &entries) == LBER_ERROR)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: ber_scanf failed while parsing filter value", __FUNCTION__);
        pLdapResult->errCode = LDAP_PROTOCOL_ERROR;
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Error in reading cluster state control filter");
    }

    pCtrlVal->term = term;

    retVal = VmDirAllocateStringA(leader.bv_val, &(pCtrlVal->leader));
    BAIL_ON_VMDIR_ERROR(retVal);

    pCtrlVal->preLogIndex = VmDirStringToLA(preLogIndex.bv_val, NULL, 10);
    BAIL_ON_VMDIR_ERROR(retVal);

    pCtrlVal->preLogTerm = preLogTerm;

    pCtrlVal->leaderCommit = VmDirStringToLA(leaderCommit.bv_val, NULL, 10);
    BAIL_ON_VMDIR_ERROR(retVal);

    retVal = VmDirAllocateAndCopyMemory(entries.bv_val, entries.bv_len, (PVOID*)&(pCtrlVal->entries.lberbv_val));
    BAIL_ON_VMDIR_ERROR(retVal);
    pCtrlVal->entries.lberbv_len = entries.bv_len;

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    return retVal;

error:
    if (pszLocalErrorMsg && pLdapResult->pszErrMsg)
    {
        VMDIR_APPEND_ERROR_MSG(pLdapResult->pszErrMsg, pszLocalErrorMsg);
    }
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "%s Error: %d", __func__, retVal);
    goto cleanup;
}
Exemplo n.º 10
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;
}