Пример #1
0
int
ParseSyncStateControlVal(
    BerValue *  controlValue,   // Input: control value encoded as ber,
    int *       entryState)     // Output
{
    int                 retVal = LDAP_SUCCESS;
    BerElementBuffer    berbuf;
    BerElement *        ber = (BerElement *)&berbuf;

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

    ber_init2( ber, controlValue, LBER_USE_DER );

    if (ber_scanf( ber, "{i}", entryState ) == -1 )
    {
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ParseSyncStateControlVal: ber_scanf to read entryState failed" );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

cleanup:
    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncStateControlVal: Begin." );
    return retVal;

error:
    goto cleanup;
}
Пример #2
0
static
DWORD
_VmDirSchemaAttrReplaceValue(
    PVDIR_ATTRIBUTE pAttr,
    PCSTR           pszMatchSubstr,
    PCSTR           pszValue
    )
{
#define MAX_BUF_SIZE_256    256

    DWORD       dwError = 0;
    unsigned    iCnt = 0;
    CHAR        pszBuf[MAX_BUF_SIZE_256] = {0};

    dwError = VmDirStringPrintFA( pszBuf, MAX_BUF_SIZE_256 -1 , "NAME '%s' ", pszMatchSubstr );
    BAIL_ON_VMDIR_ERROR(dwError);

    for (iCnt = 0; iCnt < pAttr->numVals; iCnt++)
    {
        if ( VmDirCaselessStrStrA( pAttr->vals[iCnt].lberbv_val, pszBuf ) != NULL )
        {
            if ( VmDirStringCompareA( VDIR_SAFE_STRING(pAttr->vals[iCnt].lberbv_val),
                                      pszValue,
                                      FALSE ) != 0
                                      )
            {
                VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Merge schema, replace old - %s",
                                VDIR_SAFE_STRING(pAttr->vals[iCnt].lberbv_val));
                VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Merge schema, replace new - %s", pszValue );
            }

            VMDIR_LOG_DEBUG( VMDIR_LOG_MASK_ALL, "Merge schema, replace old - %s",
                             VDIR_SAFE_STRING(pAttr->vals[iCnt].lberbv_val));
            VmDirFreeBervalContent( &(pAttr->vals[iCnt]) );

            dwError = VmDirAllocateStringA( pszValue, &(pAttr->vals[iCnt].lberbv_val) );
            BAIL_ON_VMDIR_ERROR(dwError);
            pAttr->vals[iCnt].lberbv_len = VmDirStringLenA( pszValue );
            pAttr->vals[iCnt].bOwnBvVal = TRUE;

            VMDIR_LOG_DEBUG( VMDIR_LOG_MASK_ALL, "Merge schema, replace new - %s",
                             VDIR_SAFE_STRING(pAttr->vals[iCnt].lberbv_val));

            break;
        }
    }

cleanup:

    return dwError;

error:

    goto cleanup;
}
Пример #3
0
static
ber_tag_t
GetResultTag(
   ber_tag_t tag )
{
   VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "GetResultTag: Begin" );

   switch( tag )
   {
      case LDAP_REQ_ADD:
         tag = LDAP_RES_ADD;
         break;
      case LDAP_REQ_BIND:
         tag = LDAP_RES_BIND;
         break;
      case LDAP_REQ_COMPARE:
         tag = LDAP_RES_COMPARE;
         break;
      case LDAP_REQ_EXTENDED:
         tag = LDAP_RES_EXTENDED;
         break;
      case LDAP_REQ_MODIFY:
         tag = LDAP_RES_MODIFY;
         break;
      case LDAP_REQ_MODRDN:
         tag = LDAP_RES_MODRDN;
         break;
      case LDAP_REQ_DELETE:
         tag = LDAP_RES_DELETE;
         break;
      case LDAP_REQ_SEARCH:
         tag = LDAP_RES_SEARCH_RESULT;
         break;
      case LDAP_REQ_ABANDON:
      case LDAP_REQ_UNBIND:
      default:
         tag = LBER_SEQUENCE;
         break;
   }

   VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "GetResultTag: End" );
   return tag;
}
Пример #4
0
int
WritePagedSearchDoneControl(
    VDIR_OPERATION *     op,
    BerElement *    ber
    )
{
    int                 retVal = LDAP_OPERATIONS_ERROR;
    BerElementBuffer    ctrlValBerbuf;
    BerElement *        ctrlValBer = (BerElement *) &ctrlValBerbuf;
    VDIR_BERVALUE       bvCtrlVal = VDIR_BERVALUE_INIT;

    if (!op || !op->showPagedResultsCtrl)
    {
        retVal = LDAP_PROTOCOL_ERROR;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    if ( op->showPagedResultsCtrl)
    {
        VDIR_PAGED_RESULT_CONTROL_VALUE*    prCtrlVal = &op->showPagedResultsCtrl->value.pagedResultCtrlVal;
        VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE,
                "WritePagedSearchDoneControl: Paged Search Done Control Value: pageSize[%d] cookie[%s]",
                prCtrlVal->pageSize,
                prCtrlVal->cookie );

        (void) memset( (char *)&ctrlValBerbuf, '\0', sizeof( BerElementBuffer ));
        ber_init2( ctrlValBer, NULL, LBER_USE_DER );

        if (ber_printf( ctrlValBer, "{is}", 0, prCtrlVal->cookie) == -1 )
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Paged Search Done Control ...) failed" );
            retVal = LDAP_OPERATIONS_ERROR;
            BAIL_ON_VMDIR_ERROR( retVal );
        }

        bvCtrlVal.lberbv.bv_val = ctrlValBer->ber_buf;
        bvCtrlVal.lberbv.bv_len = ctrlValBer->ber_ptr - ctrlValBer->ber_buf;

        if (ber_printf(ber, "t{{sO}}", LDAP_TAG_CONTROLS, LDAP_CONTROL_PAGEDRESULTS, &bvCtrlVal.lberbv ) == -1)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WritePagedSearchDoneControl: ber_printf (to print Search Done Control ...) failed" );
            retVal = LDAP_OPERATIONS_ERROR;
            BAIL_ON_VMDIR_ERROR( retVal );
        }
    }

    retVal = LDAP_SUCCESS;

cleanup:
    ber_free_buf( ctrlValBer );
    return retVal;

error:
    goto cleanup;
}
Пример #5
0
void
DeleteControls(
   VDIR_LDAP_CONTROL ** controls
   )
{
   VDIR_LDAP_CONTROL * curr = NULL;
   VDIR_LDAP_CONTROL * next = NULL;

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

   if (controls != NULL)
   {
      for (curr = *controls; curr != NULL; curr = next)
      {
         next = curr->next;
         VMDIR_SAFE_FREE_MEMORY( curr );
      }
      *controls = NULL;
   }

   VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "DeleteControls: End." );
}
Пример #6
0
static
DWORD
_VmDirNormaliseNameField(
    PSTR    pszSource ,
    size_t      dwLen
    )
{

    DWORD    i        = 0;
    DWORD    j        = 0;
    DWORD    dwError  = 0;
    DWORD    dwState  = 0;

    for (i=0 ; i<dwLen ;i++ )
    {
        if (pszSource[i] == ' ')
        {
            if (dwState == 0 )
            {
                pszSource[j++] = pszSource[i];
                dwState = 1;
            }
            else
            {
               // Do Nothing , Ignore Extra Spaces ..
            }
        }
        else
        {
            pszSource[j++] = pszSource[i];
            dwState = 0;
        }
    }

    pszSource[j++] = '\0' ;
    VMDIR_LOG_DEBUG( VMDIR_LOG_MASK_ALL, "Formatted NAME string is  - %s",
            VDIR_SAFE_STRING(pszSource) );

    return dwError ;

}
Пример #7
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;
}
Пример #8
0
static
int
NewConnection(
    ber_socket_t    sfd,
    VDIR_CONNECTION **ppConnection,
    Sockbuf_IO      *pSockbuf_IO
    )
{
    int       retVal = LDAP_SUCCESS;
    ber_len_t max = SOCK_BUF_MAX_INCOMING;
    PVDIR_CONNECTION pConn;
    PSTR      pszLocalErrMsg = NULL;

    if (VmDirAllocateMemory(sizeof(VDIR_CONNECTION), (PVOID *)&pConn) != 0)
    {
       retVal = LDAP_OPERATIONS_ERROR;
       BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, pszLocalErrMsg, "NewConnection: VmDirAllocateMemory call failed");
    }

    pConn->bIsAnonymousBind = TRUE;  // default to anonymous bind
    pConn->sd = sfd;

    retVal = VmDirGetNetworkInfoFromSocket(pConn->sd, pConn->szClientIP, sizeof(pConn->szClientIP), &pConn->dwClientPort, true);
    BAIL_ON_VMDIR_ERROR(retVal);

    retVal = VmDirGetNetworkInfoFromSocket(pConn->sd, pConn->szServerIP, sizeof(pConn->szServerIP), &pConn->dwServerPort, false);
    BAIL_ON_VMDIR_ERROR(retVal);

    VMDIR_LOG_DEBUG(VMDIR_LOG_MASK_ALL, "New connection (%s)", pConn->szClientIP);

    if ((pConn->sb = ber_sockbuf_alloc()) == NULL)
    {
       retVal = LDAP_OPERATIONS_ERROR;
       BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, pszLocalErrMsg, "New Connection (%s): ber_sockbuf_alloc() call failed with errno: %d", pConn->szClientIP, errno);
    }

    if (ber_sockbuf_ctrl(pConn->sb, LBER_SB_OPT_SET_MAX_INCOMING, &max) < 0)
    {
       retVal = LDAP_OPERATIONS_ERROR;
       BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, pszLocalErrMsg, "NewConnection (%s): ber_sockbuf_ctrl() failed while setting MAX_INCOMING", pConn->szClientIP);
    }

    if (ber_sockbuf_add_io(pConn->sb, pSockbuf_IO, LBER_SBIOD_LEVEL_PROVIDER, (void *)&sfd) != 0)
    {
       retVal = LDAP_OPERATIONS_ERROR;
       BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, pszLocalErrMsg, "NewConnection (%s): ber_sockbuf_addd_io() failed while setting LEVEL_PROVIDER", pConn->szClientIP);
    }

    //This is to disable NONBLOCK mode (when NULL passed in)
    if (ber_sockbuf_ctrl(pConn->sb, LBER_SB_OPT_SET_NONBLOCK, NULL) < 0)
    {
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, pszLocalErrMsg, "NewConnection (%s): ber_sockbuf_ctrl failed while setting NONBLOCK", pConn->szClientIP);
    }

    *ppConnection = pConn;
cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);

    return retVal;

error:

    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "NewConnection failing with error %d", retVal);

    goto cleanup;
}
Пример #9
0
static
int
_VmDirSwapDB(
    PCSTR dbHomeDir,
    BOOLEAN bHasXlog)
{
    int                     retVal = LDAP_SUCCESS;
    char                    dbExistingName[VMDIR_MAX_FILE_NAME_LEN] = {0};
    char                    dbNewName[VMDIR_MAX_FILE_NAME_LEN] = {0};
    PSTR                    pszLocalErrorMsg = NULL;
    int                     errorCode = 0;
    BOOLEAN                 bLegacyDataLoaded = FALSE;
    PVDIR_BACKEND_INTERFACE pBE = NULL;

#ifndef _WIN32
    const char   fileSeperator = '/';
#else
    const char   fileSeperator = '\\';
#endif

    // Shutdown backend
    pBE = VmDirBackendSelect(NULL);
    assert(pBE);

    VmDirdStateSet(VMDIRD_STATE_SHUTDOWN);

    VmDirIndexLibShutdown();

    VmDirSchemaLibShutdown();

    pBE->pfnBEShutdown();
    VmDirBackendContentFree(pBE);

    // move .mdb files
    retVal = VmDirStringPrintFA( dbExistingName, VMDIR_MAX_FILE_NAME_LEN, "%s%c%s%c%s", dbHomeDir, fileSeperator,
                                 LOCAL_PARTNER_DIR, fileSeperator, VMDIR_MDB_DATA_FILE_NAME);
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
            "_VmDirSwapDB: VmDirStringPrintFA() call failed with error: %d", retVal );

    retVal = VmDirStringPrintFA( dbNewName, VMDIR_MAX_FILE_NAME_LEN, "%s%c%s", dbHomeDir, fileSeperator,
                                 VMDIR_MDB_DATA_FILE_NAME );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
            "_VmDirSwapDB: VmDirStringPrintFA() call failed with error: %d", retVal );

#ifdef WIN32
    if (MoveFileEx(dbExistingName, dbNewName, MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING) == 0)
    {
        retVal = LDAP_OPERATIONS_ERROR;
        errorCode = GetLastError();
#else
    if (rename(dbExistingName, dbNewName) != 0)
    {
        retVal = LDAP_OPERATIONS_ERROR;
        errorCode = errno;
#endif
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
            "_VmDirSwapDB: rename file from %s to %s failed, errno %d", dbExistingName, dbNewName, errorCode );
    }

    retVal = VmDirStringPrintFA(dbNewName, VMDIR_MAX_FILE_NAME_LEN, "%s%c%s%c%s", dbHomeDir, fileSeperator, VMDIR_MDB_XLOGS_DIR_NAME);
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
            "_VmDirSwapDB: VmDirStringPrintFA() call failed with error: %d", retVal );

    if (bHasXlog)
    {
        //move xlog directory
        retVal = VmDirStringPrintFA(dbExistingName, VMDIR_MAX_FILE_NAME_LEN, "%s%c%s%c%s", dbHomeDir, fileSeperator,
                                    LOCAL_PARTNER_DIR, fileSeperator, VMDIR_MDB_XLOGS_DIR_NAME);
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                "_VmDirSwapDB: VmDirStringPrintFA() call failed with error: %d", retVal );

#ifdef     WIN32
        if (MoveFileEx(dbExistingName, dbNewName, MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING) == 0)
        {
            retVal = LDAP_OPERATIONS_ERROR;
            errorCode = GetLastError();
#else
        if (rmdir(dbNewName) != 0)
        {
            retVal = LDAP_OPERATIONS_ERROR;
            errorCode = errno;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "_VmDirSwapDB cannot remove directory %s, errno %d",
                                         dbNewName, errorCode);
        }

        if (rename(dbExistingName, dbNewName) != 0)
        {
            retVal = LDAP_OPERATIONS_ERROR;
            errorCode = errno;
#endif
            BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "_VmDirSwapDB cannot move directory from %s to %s, errno %d",
                                         dbNewName, dbExistingName, errorCode);
        }
    }

    retVal = VmDirStringPrintFA(dbExistingName, VMDIR_MAX_FILE_NAME_LEN, "%s%c%s", dbHomeDir, fileSeperator, LOCAL_PARTNER_DIR);
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
            "_VmDirSwapDB: VmDirStringPrintFA() call failed with error: %d", retVal );

#ifdef WIN32
    if (RemoveDirectory(dbExistingName)==0)
    {
        errorCode = GetLastError();
#else
    if (rmdir(dbExistingName))
    {
        errorCode = errno;
#endif

        VMDIR_LOG_WARNING(VMDIR_LOG_MASK_ALL, "cannot remove directory %s errno %d", dbExistingName, errorCode);
    }

    VmDirdStateSet(VMDIRD_STATE_STARTUP);

    retVal = VmDirInitBackend(&bLegacyDataLoaded);
    BAIL_ON_VMDIR_ERROR(retVal);

    if (bLegacyDataLoaded)
    {
        retVal = VmDirPatchLocalSubSchemaSubEntry();
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrorMsg,
                "_VmDirSwapDB: failed to patch subschema subentry: %d", retVal );

        retVal = VmDirWriteSchemaObjects();
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrorMsg,
                "_VmDirSwapDB: failed to create schema tree: %d", retVal );
    }

    VmDirdStateSet(VMDIRD_STATE_NORMAL);

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    return retVal;

error:
    retVal = LDAP_OPERATIONS_ERROR;
    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s", VDIR_SAFE_STRING(pszLocalErrorMsg) );
    goto cleanup;
}

static
int
_VmDirWrapUpFirstReplicationCycle(
    PCSTR                           pszHostname,
    VMDIR_REPLICATION_AGREEMENT *   pReplAgr)
{
    int                 retVal = LDAP_SUCCESS;
    PVDIR_ENTRY         pPartnerServerEntry = NULL;
    PVDIR_ATTRIBUTE     pAttrUpToDateVector = NULL;
    PVDIR_ATTRIBUTE     pAttrInvocationId = NULL;
    USN                 localUsn = 0;
    USN                 partnerLocalUsn = 0;
    char                partnerlocalUsnStr[VMDIR_MAX_USN_STR_LEN];
    VDIR_BACKEND_CTX    beCtx = {0};
    struct berval       syncDoneCtrlVal = {0};
    PVDIR_SCHEMA_CTX    pSchemaCtx = NULL;
    VDIR_OPERATION      searchOp = {0};
    PVDIR_FILTER        pSearchFilter = NULL;
    PSTR                pszSeparator = NULL;

    retVal = VmDirSchemaCtxAcquire(&pSchemaCtx);
    BAIL_ON_VMDIR_ERROR( retVal );

    retVal = VmDirInitStackOperation( &searchOp, VDIR_OPERATION_TYPE_INTERNAL, LDAP_REQ_SEARCH, pSchemaCtx );
    BAIL_ON_VMDIR_ERROR(retVal);

    searchOp.pBEIF = VmDirBackendSelect(NULL);
    assert(searchOp.pBEIF);

    searchOp.reqDn.lberbv.bv_val = "";
    searchOp.reqDn.lberbv.bv_len = 0;
    searchOp.request.searchReq.scope = LDAP_SCOPE_SUBTREE;

    retVal = VmDirConcatTwoFilters(searchOp.pSchemaCtx, ATTR_CN, (PSTR) pszHostname, ATTR_OBJECT_CLASS, OC_DIR_SERVER,
                                    &pSearchFilter);
    BAIL_ON_VMDIR_ERROR(retVal);

    searchOp.request.searchReq.filter = pSearchFilter;

    retVal = VmDirInternalSearch(&searchOp);
    BAIL_ON_VMDIR_ERROR(retVal);

    if (searchOp.internalSearchEntryArray.iSize != 1)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                    "_VmDirWrapUpFirstReplicationCycle: Unexpected (not 1) number of partner server entries found (%d)",
                    searchOp.internalSearchEntryArray.iSize );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    pPartnerServerEntry = searchOp.internalSearchEntryArray.pEntry;

    pAttrUpToDateVector = VmDirEntryFindAttribute( ATTR_UP_TO_DATE_VECTOR, pPartnerServerEntry );

    pAttrInvocationId = VmDirEntryFindAttribute( ATTR_INVOCATION_ID, pPartnerServerEntry );
    assert( pAttrInvocationId != NULL );

    beCtx.pBE = VmDirBackendSelect(NULL);
    assert(beCtx.pBE);

    if ((retVal = beCtx.pBE->pfnBEGetNextUSN( &beCtx, &localUsn )) != 0)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_VmDirWrapUpFirstReplicationCycle: pfnBEGetNextUSN failed with error code: %d, "
                  "error message: %s", retVal, VDIR_SAFE_STRING(beCtx.pszBEErrorMsg) );
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    retVal = _VmGetHighestCommittedUSN(localUsn, &partnerLocalUsn);
    BAIL_ON_VMDIR_ERROR( retVal );

    VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "_VmDirWrapUpFirstReplicationCycle: partnerLocalUsn %llu locaUsn %llu", partnerLocalUsn, localUsn);

    if ((retVal = VmDirStringNPrintFA( partnerlocalUsnStr, sizeof(partnerlocalUsnStr), sizeof(partnerlocalUsnStr) - 1,
                                       "%" PRId64, partnerLocalUsn)) != 0)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_VmDirWrapUpFirstReplicationCycle: VmDirStringNPrintFA failed with error code: %d",
                  retVal );
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    if (pAttrUpToDateVector)
    {
        if (VmDirStringEndsWith( pAttrUpToDateVector->vals[0].lberbv.bv_val, ",", FALSE))
        {
            pszSeparator = "";
        }
        else
        {
            pszSeparator = ",";
        }

        // <partnerLocalUSN>,<partner up-to-date vector>,<partner server GUID>:<partnerLocalUSN>,
        retVal = VmDirAllocateStringPrintf( &(syncDoneCtrlVal.bv_val), "%s,%s%s%s:%s,",
                                                partnerlocalUsnStr,
                                                pAttrUpToDateVector->vals[0].lberbv.bv_val,
                                                pszSeparator,
                                                pAttrInvocationId->vals[0].lberbv.bv_val,
                                                partnerlocalUsnStr);
        BAIL_ON_VMDIR_ERROR(retVal);
    }
    else
    {
        // <partnerLocalUSN>,<partner server GUID>:<partnerLocalUSN>,
        retVal = VmDirAllocateStringPrintf( &(syncDoneCtrlVal.bv_val), "%s,%s:%s,",
                                                partnerlocalUsnStr,
                                                pAttrInvocationId->vals[0].lberbv.bv_val,
                                                partnerlocalUsnStr);
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    VmDirSetACLMode();

    syncDoneCtrlVal.bv_len = VmDirStringLenA(syncDoneCtrlVal.bv_val);

    if ((retVal = VmDirReplUpdateCookies( pSchemaCtx, &(syncDoneCtrlVal), pReplAgr )) != LDAP_SUCCESS)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "vdirReplicationThrFun: UpdateCookies failed. Error: %d", retVal );
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    if ((retVal = _VmDirPatchDSERoot(pSchemaCtx)) != LDAP_SUCCESS)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "vdirReplicationThrFun: _VmDirPatchDSERoot failed. Error: %d", retVal );
        BAIL_ON_VMDIR_ERROR( retVal );
    }

cleanup:
    VmDirFreeOperationContent(&searchOp);
    VmDirBackendCtxContentFree(&beCtx);
    VMDIR_SAFE_FREE_MEMORY(syncDoneCtrlVal.bv_val);
    VmDirSchemaCtxRelease(pSchemaCtx);
    return retVal;

error:
    retVal = LDAP_OPERATIONS_ERROR;
    goto cleanup;
}

#ifndef VDIR_PSC_VERSION
#define VDIR_PSC_VERSION "6.7.0"
#endif

static
int
_VmDirPatchDSERoot(
    PVDIR_SCHEMA_CTX    pSchemaCtx)
{
    int                      retVal = LDAP_SUCCESS;
    VDIR_OPERATION           op = {0};
    VDIR_BERVALUE            bvDSERootDN = VDIR_BERVALUE_INIT;

    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "_VmDirPatchDSERoot: Begin" );

    bvDSERootDN.lberbv.bv_val = PERSISTED_DSE_ROOT_DN;
    bvDSERootDN.lberbv.bv_len = VmDirStringLenA( bvDSERootDN.lberbv.bv_val );

    retVal = VmDirInitStackOperation( &op,
                                      VDIR_OPERATION_TYPE_INTERNAL,
                                      LDAP_REQ_MODIFY,
                                      pSchemaCtx );
    BAIL_ON_VMDIR_ERROR(retVal);

    retVal = VmDirNormalizeDN( &bvDSERootDN, pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(retVal);

    retVal = VmDirBervalContentDup( &bvDSERootDN, &op.reqDn );
    BAIL_ON_VMDIR_ERROR(retVal);

    op.pBEIF = VmDirBackendSelect(op.reqDn.lberbv.bv_val);
    assert(op.pBEIF);

    if (VmDirBervalContentDup( &op.reqDn, &op.request.modifyReq.dn ) != 0)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_VmDirPatchDSERoot: BervalContentDup failed." );
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_DC_ACCOUNT_UPN, ATTR_DC_ACCOUNT_UPN_LEN,
                              gVmdirServerGlobals.dcAccountUPN.lberbv.bv_val,
                              gVmdirServerGlobals.dcAccountUPN.lberbv.bv_len );
    BAIL_ON_VMDIR_ERROR( retVal );

    retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_DC_ACCOUNT_DN, ATTR_DC_ACCOUNT_DN_LEN,
                              gVmdirServerGlobals.dcAccountDN.lberbv.bv_val,
                              gVmdirServerGlobals.dcAccountDN.lberbv.bv_len );
    BAIL_ON_VMDIR_ERROR( retVal );

    retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_SERVER_NAME, ATTR_SERVER_NAME_LEN,
                              gVmdirServerGlobals.serverObjDN.lberbv.bv_val,
                              gVmdirServerGlobals.serverObjDN.lberbv.bv_len );
    BAIL_ON_VMDIR_ERROR( retVal );

    retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_SITE_NAME, ATTR_SITE_NAME_LEN,
                              gVmdirServerGlobals.pszSiteName,
                              VmDirStringLenA(gVmdirServerGlobals.pszSiteName) );
    BAIL_ON_VMDIR_ERROR( retVal );

    retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_PSC_VERSION, ATTR_PSC_VERSION_LEN,
                              VDIR_PSC_VERSION,
                              VmDirStringLenA(VDIR_PSC_VERSION) );
    BAIL_ON_VMDIR_ERROR( retVal );

    retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_MAX_DOMAIN_FUNCTIONAL_LEVEL,
                              ATTR_MAX_DOMAIN_FUNCTIONAL_LEVEL_LEN,
                              VMDIR_MAX_DFL_STRING,
                              VmDirStringLenA(VMDIR_MAX_DFL_STRING) );
    BAIL_ON_VMDIR_ERROR( retVal );

    if ((retVal = VmDirInternalModifyEntry( &op )) != 0)
    {
        // If VmDirInternall call failed, reset retVal to LDAP level error space (for B/C)
        retVal = op.ldapResult.errCode;

        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_VmDirPatchDSERoot: InternalModifyEntry failed. "
                  "Error code: %d, Error string: %s", retVal, VDIR_SAFE_STRING( op.ldapResult.pszErrMsg ) );
        BAIL_ON_VMDIR_ERROR( retVal );
    }

cleanup:
    VmDirFreeOperationContent(&op);

    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "_VmDirPatchDSERoot: End" );
    return retVal;

error:
    retVal = LDAP_OPERATIONS_ERROR;
    goto cleanup;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #12
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;
}
Пример #13
0
int
WriteSyncStateControl(
   VDIR_OPERATION *   op,
   VDIR_ATTRIBUTE *   pAttr,
   BerElement *       ber,
   PSTR*              ppszErrorMsg
   )
{
    int                 retVal = LDAP_SUCCESS;
    VDIR_BERVALUE       syncStateCtrlType = {
                            {VmDirStringLenA( LDAP_CONTROL_SYNC_STATE ), LDAP_CONTROL_SYNC_STATE}, 0, 0, NULL };
    int                 entryState = LDAP_SYNC_MODIFY;
    BerElementBuffer    ctrlValBerbuf;
    BerElement *        ctrlValBer = (BerElement *) &ctrlValBerbuf;
    VDIR_BERVALUE       bvCtrlVal = VDIR_BERVALUE_INIT;
    PSTR                pszLocalErrorMsg = NULL;

    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WriteSyncStateControl: Begin" );

    /* Logic to determine the entry state is:
     *  Default entry state is LDAP_SYNC_MODIFY
     *
     *  If ATTR_USN_CREATED value is greater than the last local USN that the consumer has seen so far,
     *  entry state is LDAP_SYNC_ADD.
     *  Otherwise, if isDeleted=TRUE is in the replication scope, entry state is LDAP_SYNC_DELETE.
     *
     *  NOTE: The logic is based on the things (entry state + what has the consumer seen so far) seen by the supplier
     *  at this point in time. Things/state could be different at the time when consumer tries to apply this change.
     *  => may lead to various conflict resolution scenarios.
     */

    for ( ; pAttr != NULL; pAttr = pAttr->next)
    {
        if (pAttr->metaData[0] != '\0') // We are sending back this attribute's meta data. => Attribute is in
                                        // replication scope. SJ-TBD: we are overloading pAttr->metaData
                                        // field. Should we have another field (e.g. inReplScope) in Attribute
        {
            if ( VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_IS_DELETED, FALSE ) == 0 &&
                 VmDirStringCompareA( pAttr->vals[0].lberbv.bv_val, VMDIR_IS_DELETED_TRUE_STR, FALSE ) == 0)
            {
                entryState = LDAP_SYNC_DELETE;
                continue; // Look if it is LDAP_SYNC_ADD case
            }

            if (VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_USN_CREATED, FALSE ) == 0)
            {
                entryState = LDAP_SYNC_ADD;
                break;
            }
        }
    }

    if (ber_printf( ber, "t{{O", LDAP_TAG_CONTROLS, &(syncStateCtrlType.lberbv) ) == -1 )
    {
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteSyncStateControl: ber_printf (to print attribute name ...) failed" );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Encoding sync state control failed.");
    }

    ////////// Build ber for the control value

    (void) memset( (char *)&ctrlValBerbuf, '\0', sizeof( BerElementBuffer ));
    ber_init2( ctrlValBer, NULL, LBER_USE_DER );

    if (ber_printf( ctrlValBer, "{i}", entryState ) == -1 )
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Encoding sync state control failed.");
    }

    ////////////// Building ber for the control value done

    bvCtrlVal.lberbv.bv_val = ctrlValBer->ber_buf;
    bvCtrlVal.lberbv.bv_len = ctrlValBer->ber_ptr - ctrlValBer->ber_buf;

    if (ber_printf( ber, "O", &bvCtrlVal.lberbv ) == -1 )
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Encoding sync state control failed.");
    }

    if (ber_printf( ber, "}}" ) == -1 )
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg),
                                     "Encoding sync state control failed.");
    }

cleanup:
    ber_free_buf( ctrlValBer );

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

    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WriteSyncStateControl: End" );

    return( retVal );

error:

    goto cleanup;
}
Пример #14
0
int
WriteSyncDoneControl(
    VDIR_OPERATION *     op,
    BerElement *    ber
    )
{
    int                     retVal = LDAP_OPERATIONS_ERROR;
    PLW_HASHTABLE_NODE      pNode = NULL;
    LW_HASHTABLE_ITER       iter = LW_HASHTABLE_ITER_INIT;
    UptoDateVectorEntry *   pUtdVectorEntry = NULL;
    VDIR_BERVALUE           bvCtrlVal = VDIR_BERVALUE_INIT;
    VDIR_BERVALUE           syncDoneCtrlType = {
                                {VmDirStringLenA( LDAP_CONTROL_SYNC_DONE ), LDAP_CONTROL_SYNC_DONE}, 0, 0, NULL };

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

    if ( op->syncDoneCtrl != NULL)
    {
        if (ber_printf( ber, "t{{O", LDAP_TAG_CONTROLS, &(syncDoneCtrlType.lberbv) ) == -1 )
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WriteSyncDoneControl: ber_printf (to print Sync Done Control ...) failed" );
            retVal = LDAP_OPERATIONS_ERROR;
            BAIL_ON_VMDIR_ERROR( retVal );
        }
        { // Construct string format of utdVector
            int     numEntries = LwRtlHashTableGetCount( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector );
            char *  writer = NULL;
            size_t  tmpLen = 0;
            size_t bufferSize = (numEntries + 1 /* for lastLocalUsn */) *
                                (VMDIR_GUID_STR_LEN + 1 + VMDIR_MAX_USN_STR_LEN + 1);

            // Sync Done control value looks like: <lastLocalUsnChanged>,<serverId1>:<server 1 last originating USN>,
            // <serverId2>,<server 2 originating USN>,...

            if (VmDirAllocateMemory( bufferSize, (PVOID *)&bvCtrlVal.lberbv.bv_val) != 0)
            {
                retVal = LDAP_OPERATIONS_ERROR;
                BAIL_ON_VMDIR_ERROR( retVal );
            }
            writer = bvCtrlVal.lberbv.bv_val;
            bvCtrlVal.lberbv.bv_len = 0;

            VmDirStringPrintFA( writer, bufferSize, "%ld,", op->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed );
            tmpLen = VmDirStringLenA( writer );
            writer += tmpLen;
            bufferSize -= tmpLen;
            bvCtrlVal.lberbv.bv_len += tmpLen;

            while ((pNode = LwRtlHashTableIterate(op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &iter)))
            {
                pUtdVectorEntry = LW_STRUCT_FROM_FIELD(pNode, UptoDateVectorEntry, Node);
                VmDirStringPrintFA( writer, bufferSize, "%s:%ld,", pUtdVectorEntry->invocationId.lberbv.bv_val,
                                    pUtdVectorEntry->currMaxOrigUsnProcessed );
                tmpLen = VmDirStringLenA( writer );
                writer += tmpLen;
                bufferSize -= tmpLen;
                bvCtrlVal.lberbv.bv_len += tmpLen;
            }
        }

        if (ber_printf( ber, "O}}", &bvCtrlVal.lberbv) == -1 )
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WriteSyncDoneControl: ber_printf (to print Sync Done Control ...) failed" );
            retVal = LDAP_OPERATIONS_ERROR;
            BAIL_ON_VMDIR_ERROR( retVal );
        }

        VMDIR_LOG_DEBUG( LDAP_DEBUG_REPL, "WriteSyncDoneControl: Sync Done Control Value: %s", bvCtrlVal.lberbv.bv_val );
    }

    retVal = LDAP_SUCCESS;

cleanup:
    VMDIR_SAFE_FREE_MEMORY( bvCtrlVal.lberbv.bv_val );
    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WriteSyncDoneControl: Begin." );
    return retVal;

error:
    goto cleanup;
}
Пример #15
0
/*
 * refresh account password
 * returns:
 * if force is not specified and password is not aged
 *  {"refreshed":"false"}
 * if force was specified or password aged
 *  {"refreshed":"true","password":"******"}
*/
DWORD
VmDirRESTRefreshPassword(
    void*   pIn,
    void**  ppOut
    )
{
    DWORD dwError = 0;
    PVDIR_REST_OPERATION pRestOp = NULL;
    BOOLEAN bRefreshPassword = FALSE;
    PSTR pszNewPassword = NULL;
    BOOLEAN bRefreshed = FALSE;

    if (!pIn)
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    pRestOp = (PVDIR_REST_OPERATION)pIn;

    dwError = VmDirRESTGetBoolParam(
                  pRestOp,
                  "force",
                  &bRefreshPassword,
                  TRUE);
    BAIL_ON_VMDIR_ERROR(dwError)

    dwError = VmDirRefreshPassword(
                  pRestOp->pConn,
                  bRefreshPassword,
                  &pszNewPassword);
    BAIL_ON_VMDIR_ERROR(dwError);

    VMDIR_LOG_DEBUG(
            VMDIR_LOG_MASK_ALL,
            "%s: force: %d, %s",
            __FUNCTION__, bRefreshPassword,
            pRestOp->pConn->AccessInfo.pszNormBindedDn);

    if (!IsNullOrEmptyString(pszNewPassword))
    {
        bRefreshed = TRUE;
        dwError = VmDirRESTResultSetStrData(
                      pRestOp->pResult,
                      "password",
                      pszNewPassword);
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirRESTResultSetBooleanData(
                  pRestOp->pResult,
                  "refreshed",
                  bRefreshed);
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:
    VMDIR_SET_REST_RESULT(pRestOp, NULL, dwError, NULL);
    VMDIR_SAFE_FREE_MEMORY(pszNewPassword);
    return dwError;

error:
    VMDIR_LOG_ERROR(
            VMDIR_LOG_MASK_ALL,
            "%s failed, error (%d)",
            __FUNCTION__,
            dwError);

    goto cleanup;
}
Пример #16
0
static
int
ProcessCandidateList(
    VDIR_OPERATION * pOperation
    )
{
    int               retVal = LDAP_SUCCESS;
    int               i = 0;
    VDIR_CANDIDATES * cl = pOperation->request.searchReq.filter->candidates;
    VDIR_ENTRY        srEntry = {0};
    VDIR_ENTRY *      pSrEntry = NULL;
    int               numSentEntries = 0;
    BOOLEAN           bInternalSearch = FALSE;
    BOOLEAN           bPageResultsCtrl = FALSE;
    DWORD             dwPageSize = 0;
    ENTRYID           lastEID = 0;

    /*
     * If the page size is greater than or equal to the sizeLimit value,
     * the server should ignore the control as the request can be satisfied in a single page.
     */
    if (pOperation->showPagedResultsCtrl && (pOperation->request.searchReq.sizeLimit == 0 ||
            pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.pageSize < (DWORD)pOperation->request.searchReq.sizeLimit))
    {
        VmDirLog( LDAP_DEBUG_TRACE, "showPagedResultsCtrl applies to this query." );
        bPageResultsCtrl = TRUE;
        dwPageSize = pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.pageSize;
        lastEID = atoi(pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie);
        pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie[0] = '\0';
    }

    if (cl && cl->size > 0)
    {
        if (pOperation->opType == VDIR_OPERATION_TYPE_INTERNAL)
        {   //TODO, we should have a hard limit on the cl->size we handle
            bInternalSearch = TRUE;
            VmDirFreeEntryArrayContent(&pOperation->internalSearchEntryArray);
            retVal = VmDirAllocateMemory(   sizeof(VDIR_ENTRY) * cl->size,
                                            (PVOID*)&pOperation->internalSearchEntryArray.pEntry);
            BAIL_ON_VMDIR_ERROR(retVal);
        }

        for (i = 0, numSentEntries = 0;
             (i < cl->size) && VmDirdState() != VMDIRD_STATE_SHUTDOWN &&
             (pOperation->request.searchReq.sizeLimit == 0 /* unlimited */ ||
              numSentEntries < pOperation->request.searchReq.sizeLimit);
             i++)
        {
            //skip entries we sent before
            if (bPageResultsCtrl && lastEID > 0)
            {
                if (cl->eIds[i] == lastEID)
                {
                    lastEID = 0;
                }
                continue;
            }

            VMDIR_LOG_DEBUG( LDAP_DEBUG_FILTER, "ProcessCandidateList EID(%u)", cl->eIds[i]);

            pSrEntry = bInternalSearch ?
                        (pOperation->internalSearchEntryArray.pEntry + pOperation->internalSearchEntryArray.iSize) : &srEntry;

            retVal = pOperation->pBEIF->pfnBEIdToEntry(
                        pOperation->pBECtx,
                        pOperation->pSchemaCtx,
                        cl->eIds[i],
                        pSrEntry,
                        VDIR_BACKEND_ENTRY_LOCK_READ);

            if (retVal == 0)
            {
                if (CheckIfEntryPassesFilter( pOperation, pSrEntry, pOperation->request.searchReq.filter) == FILTER_RES_TRUE)
                {
                    retVal = VmDirBuildComputedAttribute( pOperation, pSrEntry );
                    BAIL_ON_VMDIR_ERROR( retVal );

                    if (bInternalSearch)
                    {
                        pOperation->internalSearchEntryArray.iSize++;
                        pSrEntry = NULL;    // EntryArray takes over *pSrEntry content
                    }
                    else
                    {
                        retVal = VmDirSendSearchEntry( pOperation, pSrEntry );
                        if (retVal == VMDIR_ERROR_INSUFFICIENT_ACCESS)
                        {
                            VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL,
                                               "Access deny on search entry result [%s,%d] (bindedDN-%s) (targetDn-%s)\n",
                                               __FILE__, __LINE__, pOperation->conn->AccessInfo.pszBindedDn, pSrEntry->dn.lberbv.bv_val);
                            // make sure search continues
                            retVal = 0;
                        }
                        BAIL_ON_VMDIR_ERROR( retVal );

                        if (pSrEntry->bSearchEntrySent)
                        {
                            numSentEntries++;
                        }
                    }
                }

                //We have sent one page size of entries, so we can break here
                if (bPageResultsCtrl && numSentEntries == dwPageSize){
                    retVal = VmDirStringPrintFA(
                            pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie,
                            VMDIR_MAX_I64_ASCII_STR_LEN,
                            "%u",
                            pSrEntry->eId);
                    BAIL_ON_VMDIR_ERROR( retVal );
                    break;
                }

                VmDirFreeEntryContent( pSrEntry );
                pSrEntry = NULL; // Reset to NULL so that DeleteEntry is no-op.
            }
            else
            {
                // Ignore BdbEIdToEntry errors.
                VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "ProcessCandiateList BEIdToEntry EID(%u), error (%u)",
                                                       cl->eIds[i], retVal);
                retVal = 0;
            }
        }

        VMDIR_LOG_VERBOSE( LDAP_DEBUG_FILTER, "(%d) candiates processed and (%d) entries sent", cl->size, numSentEntries);
    }

    if ( pOperation->request.searchReq.sizeLimit && numSentEntries < pOperation->request.searchReq.sizeLimit &&
         pOperation->pBECtx->iPartialCandidates)
    {
        retVal = LDAP_UNWILLING_TO_PERFORM;
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ProcessCandiateList may return none or paritial requested entries with sizelimit %d",
                        pOperation->request.searchReq.sizeLimit);
    }

cleanup:

    pOperation->dwSentEntries = numSentEntries;
    VmDirFreeEntryContent( pSrEntry );

    return retVal;

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessCandiateList failed. (%u)", retVal);
    goto cleanup;
}