Beispiel #1
0
DWORD
VmDirStringErrorA(
   PSTR buffer,
   size_t numberOfElements,
   int errnum
)
{
    return VmDirStringNCpyA(
        buffer, numberOfElements, strerror(errnum), numberOfElements - 1 );
}
Beispiel #2
0
VOID
_Test_VmDirStringNCpyA_NullDestinationString(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;

    dwError = VmDirStringNCpyA(NULL, 4, "test", 4);
    TestAssertEquals(dwError, ERROR_INVALID_PARAMETER);
}
Beispiel #3
0
VOID
_Test_VmDirStringNCpyA_SourceStringTooLong(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szDestination[4] = { 'a' };

    dwError = VmDirStringNCpyA(
                szDestination,
                VMDIR_ARRAY_SIZE(szDestination),
                "Hello, world!",
                7);
    TestAssertEquals(dwError, ERROR_INVALID_PARAMETER);
    TestAssertEquals(szDestination[0], 'a');
}
Beispiel #4
0
VOID
_Test_VmDirStringNCpyA_EmptySourceStringWrongCount(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szDestination[16] = { 'a' };

    dwError = VmDirStringNCpyA(
                szDestination,
                VMDIR_ARRAY_SIZE(szDestination),
                "",
                10);
    TestAssertEquals(dwError, 0);
    TestAssertEquals(szDestination[0], '\0');
}
Beispiel #5
0
VOID
_Test_VmDirStringNCpyA_NullSourceString(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szDestination[16] = { 'a' };

    dwError = VmDirStringNCpyA(
                szDestination,
                VMDIR_ARRAY_SIZE(szDestination),
                NULL,
                10);
    TestAssertEquals(dwError, ERROR_INVALID_PARAMETER);
    TestAssertEquals(szDestination[0], 'a');
}
Beispiel #6
0
VOID
_Test_VmDirStringNCpyA_CallShouldFailCountMatchesSize(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szBuffer[4] = { 'a' };

    dwError = VmDirStringNCpyA(
                szBuffer,
                VMDIR_ARRAY_SIZE(szBuffer),
                "abcd",
                4);
    TestAssertEquals(dwError, ERROR_INVALID_PARAMETER);
    TestAssertEquals(szBuffer[0], 'a');
}
Beispiel #7
0
VOID
_Test_VmDirStringNCpyA_CallShouldSucceedWithTruncation(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szDestination[6] = { 'a' };

    dwError = VmDirStringNCpyA(
                szDestination,
                VMDIR_ARRAY_SIZE(szDestination),
                "Hello, world!",
                VMDIR_ARRAY_SIZE(szDestination) - 1);
    TestAssertEquals(dwError, 0);
    TestAssertStrEquals(szDestination, "Hello");
}
Beispiel #8
0
VOID
_Test_VmDirStringNCpyA_EmptySourceStringRightCount(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szDestination[16] = { '\0' };

    //
    // This call will yield different results on windows and linux. On
    // the former we call the _s version of strncpy so the string's first byte
    // will be NULL, regardless of what it is coming into the call. However,
    // on linux the string will be untouched after the call.
    //
    dwError = VmDirStringNCpyA(
                szDestination,
                VMDIR_ARRAY_SIZE(szDestination),
                "",
                0);
    TestAssertEquals(dwError, 0);
    TestAssertEquals(szDestination[0], '\0');
}
Beispiel #9
0
static
int
IsAttrInReplScope(
    VDIR_OPERATION *    op,
    char *              attrType,
    char *              attrMetaData,
    BOOLEAN *           inScope,
    PSTR*               ppszErrorMsg
    )
{
    int                     retVal = LDAP_SUCCESS;
    PLW_HASHTABLE_NODE      pNode = NULL;
    char                    origInvocationId[VMDIR_GUID_STR_LEN];
    USN                     origUsn = VmDirStringToLA( VmDirStringRChrA( attrMetaData, ':' ) + 1, NULL, 10 );
    int                     rc = 0;
    PSTR                    pszLocalErrorMsg = NULL;

    *inScope = FALSE;

    // attrMetaData format is: <local USN>:<version no>:<originating server ID>:<originating time>:<originating USN>
    VmDirStringNCpyA( origInvocationId, VMDIR_GUID_STR_LEN,
                      VmDirStringChrA( VmDirStringChrA( attrMetaData, ':' ) + 1, ':') + 1, VMDIR_GUID_STR_LEN - 1);
    origInvocationId[VMDIR_GUID_STR_LEN - 1] = '\0';

    // Skip the attribute:
    //    - if the originating server for the current state is same as the requesting server or if it is one of those
    //      attributes that have "local" scope only. E.g. sending ATTR_LAST_LOCAL_USN_PROCESSED and
    //      ATTR_UP_TO_DATE_VECTOR, causes continuous back-forth replication of Replication Agreements and Server
    //      entries between various servers.

    assert( op->syncReqCtrl != NULL );

    if ((attrType != NULL && (VmDirStringCompareA( attrType, ATTR_LAST_LOCAL_USN_PROCESSED, FALSE) == 0 ||
                              VmDirStringCompareA( attrType, ATTR_UP_TO_DATE_VECTOR, FALSE) == 0 ||
                              VmDirStringCompareA( attrType, VDIR_ATTRIBUTE_SEQUENCE_RID, FALSE) == 0)))

    {
        // Reset metaData value so that we don't send local only attribute back.
        attrMetaData[0] = '\0';
        *inScope = FALSE;
        goto cleanup;
    }
    else if ( attrType != NULL && (VmDirStringCompareA( attrType, ATTR_USN_CHANGED, FALSE) == 0))
    {
        ; // always send uSNChanged. (PR 1573117)
    }
    else if (VmDirStringCompareA( origInvocationId,
                  op->syncReqCtrl->value.syncReqCtrlVal.reqInvocationId.lberbv.bv_val,TRUE ) == 0)
    {
        // Change is originated from the requesting server.
        // Reset metaData value so that we don't send metaData as well as this attribute back.
        attrMetaData[0] = '\0';
        *inScope = FALSE;
        goto cleanup;
    }
    else
    {
        rc = LwRtlHashTableFindKey( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &pNode, origInvocationId );
        rc = LwNtStatusToWin32Error(rc);
        if (rc != 0 && rc != ERROR_NOT_FOUND)
        {
            VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "IsAttrInReplScope: LwRtlHashTableFindKey failed for origInvocationId: %s",
                      origInvocationId );
            retVal = LDAP_OPERATIONS_ERROR;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "LwRtlHashTableFindKey failed.");
        }

        if (pNode == NULL) // Attribute is to be sent in the result entry.
        {
            UptoDateVectorEntry * utdVectorEntry = NULL;
            VDIR_BERVALUE         bvServerId = VDIR_BERVALUE_INIT;

            if (VmDirAllocateMemory( sizeof( UptoDateVectorEntry ), (PVOID *)&utdVectorEntry) != 0)
            {
                retVal = LDAP_OPERATIONS_ERROR;
                BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                "IsAttrInReplScope: BervalContentDup failed.");
            }
            bvServerId.lberbv.bv_val = origInvocationId;
            bvServerId.lberbv.bv_len = VmDirStringLenA( origInvocationId );
            if (VmDirBervalContentDup( &bvServerId, &utdVectorEntry->invocationId ) != 0)
            {
                retVal = LDAP_OPERATIONS_ERROR;
                BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                "IsAttrInReplScope: BervalContentDup failed.");
            }
            utdVectorEntry->currMaxOrigUsnProcessed = origUsn;
            LwRtlHashTableResizeAndInsert( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector,
                                           &utdVectorEntry->Node, &pNode);
            assert( pNode == NULL );    // assert the key of added node is unique
        }
        else
        {
            UptoDateVectorEntry *   utdVectorEntry = NULL;
            utdVectorEntry = (UptoDateVectorEntry *)LW_STRUCT_FROM_FIELD(pNode, UptoDateVectorEntry, Node);

            if (origUsn > utdVectorEntry->reqLastOrigUsnProcessed )
            { // Attribute is to be sent in the result entry.
                // Update if origUsn of this attribute is > the current highest
                if (origUsn > utdVectorEntry->currMaxOrigUsnProcessed )
                {
                    utdVectorEntry->currMaxOrigUsnProcessed = origUsn;
                }
            }
            else
            {
                VMDIR_LOG_VERBOSE( LDAP_DEBUG_REPL_ATTR,
                          "IsAttrInReplScope: Attribute: %s, metaData: %s, replication scope = FALSE",
                          attrType, attrMetaData );

                // Reset metaData value so that we don't send metaData for this attribute back.
                attrMetaData[0] = '\0';
                *inScope = FALSE;
                goto cleanup;
            }
        }
    }

    VMDIR_LOG_INFO( LDAP_DEBUG_REPL_ATTR, "IsAttrInReplScope: Attribute: %s, metaData: %s, replication scope = TRUE",
              attrType, attrMetaData );
    *inScope = TRUE;

cleanup:

    if (ppszErrorMsg)
    {
        *ppszErrorMsg = pszLocalErrorMsg;
    }
    else
    {
        VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    }

    return( retVal );

error:

    goto cleanup;
}
Beispiel #10
0
/*
 * This generic search with pagination is new and isn't mature. Please be
 * careful with the * scope, base, and use an indexed filter.
 * Note that ulPageSize == 0 will ignore paging.
 */
DWORD
VmDirFilterInternalSearch(
        PCSTR               pszBaseDN,
        int                 searchScope,
        PCSTR               pszFilter,
        unsigned long       ulPageSize,
        PSTR                *ppszPageCookie,
        PVDIR_ENTRY_ARRAY   pEntryArray
    )
{
    DWORD           dwError = 0;
    VDIR_OPERATION  searchOP = {0};
    VDIR_BERVALUE   bervDN = VDIR_BERVALUE_INIT;
    PVDIR_FILTER    pFilter = NULL;
    PVDIR_LDAP_CONTROL showPagedResultsCtrl = NULL;
    PSTR pszPageCookie = NULL;

    if ( !pszBaseDN || !pszFilter || !pEntryArray ||
        (ulPageSize != 0 && ppszPageCookie == NULL))
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    if (ulPageSize != 0)
    {
        dwError = VmDirAllocateMemory( sizeof(VDIR_LDAP_CONTROL), (PVOID *)&showPagedResultsCtrl );
        BAIL_ON_VMDIR_ERROR(dwError);

        showPagedResultsCtrl->value.pagedResultCtrlVal.pageSize = ulPageSize;
        if (ppszPageCookie && *ppszPageCookie)
        {
            VmDirStringNCpyA(showPagedResultsCtrl->value.pagedResultCtrlVal.cookie,
                             VMDIR_ARRAY_SIZE(showPagedResultsCtrl->value.pagedResultCtrlVal.cookie),
                             *ppszPageCookie,
                             VMDIR_ARRAY_SIZE(showPagedResultsCtrl->value.pagedResultCtrlVal.cookie) - 1);
        }
        else
        {
            showPagedResultsCtrl->value.pagedResultCtrlVal.cookie[0] = '\0';
        }
    }

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

    bervDN.lberbv.bv_val = (PSTR)pszBaseDN;
    bervDN.lberbv.bv_len = VmDirStringLenA(pszBaseDN);

    searchOP.pBEIF = VmDirBackendSelect( pszBaseDN );
    assert(searchOP.pBEIF);

    dwError = VmDirBervalContentDup( &bervDN, &searchOP.reqDn);
    BAIL_ON_VMDIR_ERROR(dwError);

    searchOP.request.searchReq.scope = searchScope;

    dwError = StrFilterToFilter(pszFilter, &pFilter);
    BAIL_ON_VMDIR_ERROR(dwError);

    searchOP.request.searchReq.filter = pFilter;
    pFilter  = NULL; // search request takes over pFilter

    searchOP.showPagedResultsCtrl = showPagedResultsCtrl;

    dwError = VmDirInternalSearch( &searchOP );
    BAIL_ON_VMDIR_ERROR(dwError);

    // caller takes over searchOP.internalSearchEntryArray contents
    pEntryArray->iSize = searchOP.internalSearchEntryArray.iSize;
    pEntryArray->pEntry = searchOP.internalSearchEntryArray.pEntry;
    searchOP.internalSearchEntryArray.iSize = 0;
    searchOP.internalSearchEntryArray.pEntry = NULL;

    if (showPagedResultsCtrl)
    {
        dwError = VmDirAllocateStringA(showPagedResultsCtrl->value.pagedResultCtrlVal.cookie, &pszPageCookie);
        BAIL_ON_VMDIR_ERROR(dwError);

        *ppszPageCookie = pszPageCookie;
        pszPageCookie = NULL;
    }

cleanup:

    VMDIR_SAFE_FREE_MEMORY(showPagedResultsCtrl);

    VmDirFreeOperationContent(&searchOP);

    if (pFilter)
    {
        DeleteFilter(pFilter);
    }

    return dwError;

error:
    goto cleanup;
}
Beispiel #11
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;
}
Beispiel #12
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;
}