Пример #1
0
DWORD
VmDirPrepareSwapDBInfo(
    PCSTR                   pszHostName,    // partner server object cn
    PVMDIR_SWAP_DB_INFO*    ppSwapDBInfo
    )
{
    DWORD       dwError = 0;
    PVMDIR_SWAP_DB_INFO pLocalSwapDBInfo = NULL;

    if (!ppSwapDBInfo)
    {
        BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER);
    }

    dwError = VmDirAllocateMemory(sizeof(VMDIR_SWAP_DB_INFO), (PVOID*)&pLocalSwapDBInfo);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (pszHostName)
    {
        dwError = VmDirAllocateStringA(pszHostName, &pLocalSwapDBInfo->pszPartnerServerName);
        BAIL_ON_VMDIR_ERROR(dwError);

        VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "My partner %s", pLocalSwapDBInfo->pszPartnerServerName);
    }

    dwError = VmDirInternalGetDSERootServerCN(&pLocalSwapDBInfo->pszOrgDBServerName);
    BAIL_ON_VMDIR_ERROR(dwError);

    VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "DB was from %s", pLocalSwapDBInfo->pszOrgDBServerName);

    dwError = _VmDirComposeUtdVector(pLocalSwapDBInfo);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (!pLocalSwapDBInfo->pszPartnerServerName ||      // no partner, DR case
        VmDirStringCompareA(                            // DB copied from joining partner
            pLocalSwapDBInfo->pszPartnerServerName,
            pLocalSwapDBInfo->pszOrgDBServerName,
            FALSE) == 0)
    {
        dwError = VmDirAllocateStringA(pLocalSwapDBInfo->pszOrgDBMaxUSN, &pLocalSwapDBInfo->pszMyHighWaterMark);
        BAIL_ON_VMDIR_ERROR(dwError);
    }
    else
    {   // DB from one node but join to another
        dwError = _VmDirComposeHighWaterMark(pLocalSwapDBInfo);
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "My High Water Mark %s", pLocalSwapDBInfo->pszMyHighWaterMark);

    *ppSwapDBInfo = pLocalSwapDBInfo;

cleanup:
    return dwError;

error:
    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, " error (%u)", dwError);
    VmDirFreeSwapDBInfo(pLocalSwapDBInfo);
    goto cleanup;
}
Пример #2
0
DWORD
VmDirResetVmdir(
    VOID)
{
    DWORD dwError = 0;

    dwError = VmDirStopService();
    BAIL_ON_VMDIR_ERROR(dwError);
    VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "VMWare Directory Service stopped." );

    //Test for bug#1034595. On Windows, vmdird may fail to stop. Wait 2 seconds here.
    //Remove it if it's not useful
    VmDirSleep(2000);

    dwError = VmDirCleanupData();
    BAIL_ON_VMDIR_ERROR(dwError);
    VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "VMWare Directory Service database removed." );

    dwError = VmDirStartService();
    BAIL_ON_VMDIR_ERROR(dwError);
    VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "VMWare Directory Service ready for re-promotion." );

error:
    return dwError;
}
Пример #3
0
DWORD
VmDirIndexUpdateCommit(
    PVDIR_INDEX_UPD     pIndexUpd
    )
{
    DWORD   dwError = 0;
    LW_HASHMAP_ITER iter = LW_HASHMAP_ITER_INIT;
    LW_HASHMAP_PAIR pair = {NULL, NULL};
    PSTR            pszStatus = NULL;

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

    while (LwRtlHashMapIterate(pIndexUpd->pUpdIndexCfgMap, &iter, &pair))
    {
        PVDIR_INDEX_CFG pIndexCfg = (PVDIR_INDEX_CFG)pair.pValue;

        dwError = VmDirIndexCfgRecordProgress(pIndexUpd->pBECtx, pIndexCfg);
        BAIL_ON_VMDIR_ERROR(dwError);

        VMDIR_SAFE_FREE_MEMORY(pszStatus);
        dwError = VmDirIndexCfgStatusStringfy(pIndexCfg, &pszStatus);
        BAIL_ON_VMDIR_ERROR(dwError);

        VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, pszStatus );
    }

    if (pIndexUpd->bHasBETxn)
    {
        PVDIR_BACKEND_INTERFACE pBE = pIndexUpd->pBECtx->pBE;

        dwError = pBE->pfnBETxnCommit(pIndexUpd->pBECtx);
        BAIL_ON_VMDIR_ERROR(dwError);
        pIndexUpd->bHasBETxn = FALSE;
    }

    VmDirIndexUpdFree(gVdirIndexGlobals.pIndexUpd);
    gVdirIndexGlobals.pIndexUpd = pIndexUpd;

    VmDirConditionSignal(gVdirIndexGlobals.cond);

    VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "%s succeeded", __FUNCTION__ );

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszStatus);
    return dwError;

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

    goto cleanup;
}
Пример #4
0
/*
 * After copying DB from partner, we need to derive UTDVector for new node from partner.
 * i.e. <whatever partner node current UTDVector> + <partner invoactionid:partner max commited USN>
 */
static
DWORD
_VmDirComposeUtdVector(
    PVMDIR_SWAP_DB_INFO pSwapDBInfo
    )
{
    DWORD               dwError = 0;
    PVDIR_ENTRY         pServerEntry = NULL;
    PVDIR_ATTRIBUTE     pAttrUTDVector = NULL;
    PVDIR_ATTRIBUTE     pAttrInvocationId = NULL;
    VDIR_OPERATION      searchOp = {0};

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

    dwError = VmDirInternalSearchSeverObj(pSwapDBInfo->pszOrgDBServerName, &searchOp);
    BAIL_ON_VMDIR_ERROR(dwError);

    pServerEntry = searchOp.internalSearchEntryArray.pEntry;
    pAttrUTDVector    = VmDirEntryFindAttribute(ATTR_UP_TO_DATE_VECTOR, pServerEntry);
    pAttrInvocationId = VmDirEntryFindAttribute(ATTR_INVOCATION_ID, pServerEntry);

    dwError = _VmGetHighestCommittedUSN(&pSwapDBInfo->pszOrgDBMaxUSN);
    BAIL_ON_VMDIR_ERROR(dwError);

    VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "DB maxCommittedUSN %s", pSwapDBInfo->pszOrgDBMaxUSN);

    dwError = VmDirUTDVectorCacheInit(&pSwapDBInfo->pMyUTDVector);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (pAttrUTDVector)
    {
        dwError = VmDirUTDVectorCacheReplace(pSwapDBInfo->pMyUTDVector, pAttrUTDVector->vals[0].lberbv.bv_val);
        BAIL_ON_VMDIR_ERROR(dwError);

        VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "DB UTDVector %s", pSwapDBInfo->pMyUTDVector->pszUtdVector);
    }

    dwError = VmDirUTDVectorCacheAdd(
                pSwapDBInfo->pMyUTDVector,
                pAttrInvocationId->vals[0].lberbv.bv_val,
                pSwapDBInfo->pszOrgDBMaxUSN);
    BAIL_ON_VMDIR_ERROR(dwError);

    VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "My UTDVector %s", pSwapDBInfo->pMyUTDVector->pszUtdVector);

cleanup:
    VmDirFreeOperationContent(&searchOp);

    return dwError;

error:
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "error (%u)", dwError);
    goto cleanup;
}
Пример #5
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;
}
Пример #6
0
/*
 * Commit schema modification into cache.
 *
 * 1. commit pending cache to go live
 * 2. create self reference ctx
 * 3. release old self reference ctx
 * 4. update pEntry to have new live schema ctx association
 */
VOID
VmDirSchemaCacheModifyCommit(
    PVDIR_ENTRY  pSchemaEntry
    )
{
    DWORD               dwError = 0;
    BOOLEAN             bInLock = FALSE;
    PVDIR_SCHEMA_CTX    pOldCtx = NULL;

    if ( !pSchemaEntry || !pSchemaEntry->pSchemaCtx )
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    VMDIR_LOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);

    if ( ! gVdirSchemaGlobals.bHasPendingChange )
    {
        VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Schema cache update pass through" );
        goto cleanup;   // no schema definition change, just pass through.
    }

    gVdirSchemaGlobals.bHasPendingChange = FALSE;
    gVdirSchemaGlobals.pSchema = pSchemaEntry->pSchemaCtx->pSchema;

    pOldCtx = gVdirSchemaGlobals.pCtx;
    gVdirSchemaGlobals.pCtx = NULL;

    VdirSchemaCtxAcquireInLock(TRUE, &gVdirSchemaGlobals.pCtx); // add global instance self reference
    assert(gVdirSchemaGlobals.pCtx);

    VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Enable schema instance (%p)", gVdirSchemaGlobals.pSchema);

    VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);

cleanup:

    VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);

    if (pOldCtx)
    {
        VmDirSchemaCtxRelease(pOldCtx);
    }

    return;

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "VmDirSchemaCacheModifyCommit failed (%d)", dwError);

    goto cleanup;
}
Пример #7
0
//The log is to detect bursting traffic that
// caused write transaction avg. latency to spike.
VOID
VmDirWtxnOutstandingInc()
{
   BOOLEAN bLock = FALSE;
   double stats_peroid_ms = 0.0;
   double offered_rate = 0.0;

   VMDIR_LOCK_MUTEX(bLock, g_w_txns_mutex);
   if (g_w_txns_outstanding == 0)
   {
      g_start_ts_ms = VmDirGetTimeInMilliSec();
      g_stats_cnt = 0;
   }
   g_w_txns_outstanding++;
   g_stats_cnt++;

   if (g_w_txns_outstanding >= g_w_txns_outstanding_thresh && g_stats_cnt >= g_w_txns_outstanding_thresh)
   {
       stats_peroid_ms = (double)(VmDirGetTimeInMilliSec() - g_start_ts_ms);
       if (stats_peroid_ms > 1) //avoid float point division overflow
       {
           offered_rate = (double)g_stats_cnt * 1000.0 / stats_peroid_ms;
           VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "%s: write transactions outstanding %d for peroid %.2g ms with offered rate %.3g on %d write requests",
                       __func__,  g_w_txns_outstanding, stats_peroid_ms, offered_rate, g_stats_cnt);
       }
       g_stats_cnt = 0;
       g_start_ts_ms = VmDirGetTimeInMilliSec();
   }
   VMDIR_UNLOCK_MUTEX(bLock, g_w_txns_mutex);
}
Пример #8
0
static
DWORD
_VmDirWtxnStatsInit()
{
    DWORD dwWtxnOutstandingThresh = W_TXNS_OUTSTANDING_THRESH_D;
    DWORD dwError = 0;

    if (g_w_txns_mutex == NULL)
    {
        dwError = VmDirAllocateMutex(&g_w_txns_mutex);
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirGetRegKeyValueDword(
        VMDIR_CONFIG_PARAMETER_V1_KEY_PATH,
        VMDIR_REG_KEY_WTXN_OUTSTANDING_THRESH,
        &dwWtxnOutstandingThresh, 0);

    if (dwError == 0)
    {
       g_w_txns_outstanding_thresh = dwWtxnOutstandingThresh;
    } else
    {
       //Use the default value.
       dwError = 0;
    }

    VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "%s: W_TXNS_OUTSTANDING_THRESH = %d", __func__, g_w_txns_outstanding_thresh);

done:
    return dwError;

error:
    goto done;
}
Пример #9
0
/*
 last_pgno and max_pgs are logged. If last_pgno + pages for adding
 new data > max_pgs, mdb_put will fail with error MDB_MAP_FULL.
 Mdb first tries to reuse released pages before trying to get
 new pages from the free list. Thus even if an operation request
 new pages failed (last_pgno + pages > max_pgs),
 adding smaller data may still succeeded if the there are
 enough pages in the released pages. Max memory can be
 calculated from max_pgs * page size which is the same as the OS
 page size.
*/
void
VmDirLogDBStats(
    PVDIR_MDB_DB pDB
    )
{
    MDB_envinfo env_stats = {0};
    MDB_stat db_stats = {0};

    assert(pDB);

    if (mdb_env_info(pDB->mdbEnv, &env_stats) != MDB_SUCCESS ||
        mdb_env_stat(pDB->mdbEnv, &db_stats)!= MDB_SUCCESS)
    {
        goto error;
    }
    VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "mdb stats: last_pgno %llu, max_pgs %lld",
                   env_stats.me_last_pgno, env_stats.me_mapsize/db_stats.ms_psize);

cleanup:
    return;

error:
    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "Error retrieving MDB statistics");
    goto cleanup;
}
Пример #10
0
DWORD
VmDirIndexUpdateAbort(
    PVDIR_INDEX_UPD     pIndexUpd
    )
{
    DWORD   dwError = 0;

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

    if (pIndexUpd->bHasBETxn)
    {
        PVDIR_BACKEND_INTERFACE pBE = pIndexUpd->pBECtx->pBE;

        dwError = pBE->pfnBETxnAbort(pIndexUpd->pBECtx);
        BAIL_ON_VMDIR_ERROR(dwError);
        pIndexUpd->bHasBETxn = FALSE;
    }

    VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "%s succeeded", __FUNCTION__ );

cleanup:
    VmDirIndexUpdFree(pIndexUpd);
    return dwError;

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

    goto cleanup;
}
Пример #11
0
static
DWORD
_VmDirDeadlockDetectionVectorPairToStr(
    LW_HASHMAP_PAIR    pair,
    BOOLEAN            bStart,
    PSTR*              ppOutStr
    )
{
    PSTR    pszTempStr = NULL;
    DWORD   dwError = 0;

    VMDIR_LOG_INFO(LDAP_DEBUG_REPL, "%s: key: %s value: %d", (PSTR)pair.pKey, *(PDWORD)pair.pValue);

    if (bStart)
    {
        dwError = VmDirAllocateStringPrintf(&pszTempStr, "vector:%s:%d", pair.pKey, *(PDWORD)pair.pValue);
        BAIL_ON_VMDIR_ERROR(dwError);
    }
    else
    {
        dwError = VmDirAllocateStringPrintf(&pszTempStr, ",%s:%d", pair.pKey, *(PDWORD)pair.pValue);
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    *ppOutStr = pszTempStr;
    pszTempStr = NULL;

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszTempStr);
    return dwError;

error:
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError);
    goto cleanup;
}
Пример #12
0
/*
    4.2.2. Bind Response
    The Bind response is defined as follows.
    BindResponse ::= [APPLICATION 1] SEQUENCE {
    COMPONENTS OF LDAPResult,
    serverSaslCreds [7] OCTET STRING OPTIONAL }
 */
VOID
VmDirSendSASLBindResponse(
    PVDIR_OPERATION     pOperation
    )
{
    DWORD               dwError = 0;
    BerElementBuffer    berbuf;
    BerElement *        ber = (BerElement *) &berbuf;
    PVDIR_LDAP_RESULT   pResult = &(pOperation->ldapResult);
    ber_tag_t           respType = GetResultTag(pOperation->reqCode);

    (void) memset( (char *)&berbuf, '\0', sizeof( BerElementBuffer ));

    ber_init2( ber, NULL, LBER_USE_DER );

    VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, "VmDirSendLdapResponse: code (%d), Error (%d)(%s)",
                    respType, pResult->errCode, VDIR_SAFE_STRING(pResult->pszErrMsg));

    dwError = ber_printf( ber, "{it{ess" /*"}}"*/,
                        pOperation->msgId,                  // message sequence id
                        GetResultTag(pOperation->reqCode),  // ldap response type
                        pResult->errCode,                   // ldap return code e.g. LDAP_SASL_CONNTINUE
                        pResult->matchedDn.lberbv.bv_len > 0 ? pResult->matchedDn.lberbv.bv_val : "",
                        VDIR_SAFE_STRING(pResult->pszErrMsg));   // error text detail
    BAIL_ON_LBER_ERROR(dwError);

    // Send back TAG and SASL reply blob
    // NOTE, not exactly sure if we ever need to send Tag but WITHOUT blob reply if blob is empty.
    //       but this should NOT happen in GSSAPI scenario.
    if ( pResult->replyInfo.type == REP_SASL
         &&
         pResult->replyInfo.replyData.bvSaslReply.lberbv.bv_len > 0
       )
    {
        dwError = ber_printf( ber, "tO",
                              LDAP_TAG_SASL_RES_CREDS,
                              &pResult->replyInfo.replyData.bvSaslReply.lberbv );
        BAIL_ON_LBER_ERROR(dwError);
    }

    dwError = ber_printf( ber, "N}N}" );
    BAIL_ON_LBER_ERROR(dwError);

    dwError = WriteBerOnSocket( pOperation->conn, ber );
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:

    ber_free_buf( ber );

    return;

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "lber error (%d)", dwError);
    goto cleanup;
}
Пример #13
0
DWORD
VmDirWriteQueuePush(
    PVDIR_BACKEND_CTX           pBECtx,
    PVMDIR_WRITE_QUEUE          pWriteQueue,
    PVMDIR_WRITE_QUEUE_ELEMENT  pWriteQueueEle
    )
{
    int       dbRetVal = 0;
    USN       localUsn = 0;
    DWORD     dwError = 0;
    BOOLEAN   bInLock = FALSE;

    if (!pBECtx || !pWriteQueue || !pWriteQueueEle)
    {
        BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER);
    }

    if (pBECtx->wTxnUSN != 0)
    {
        VMDIR_LOG_ERROR(
            VMDIR_LOG_MASK_ALL,
            "%s: acquiring multiple usn in same operation context, USN: %" PRId64,
            __FUNCTION__,
            pBECtx->wTxnUSN);
        BAIL_WITH_VMDIR_ERROR(dwError, LDAP_OPERATIONS_ERROR);
    }

    VMDIR_LOCK_MUTEX(bInLock, gVmDirServerOpsGlobals.pMutex);

    if ((dbRetVal = pBECtx->pBE->pfnBEGetNextUSN(pBECtx, &localUsn)) != 0)
    {
        VMDIR_LOG_ERROR(
            VMDIR_LOG_MASK_ALL,
            "%s: pfnBEGetNextUSN failed with error code: %d",
            __FUNCTION__,
            dbRetVal);
        BAIL_WITH_VMDIR_ERROR(dwError, LDAP_OPERATIONS_ERROR);
    }

    pWriteQueueEle->usn = localUsn;

    dwError = VmDirLinkedListInsertTail(
            pWriteQueue->pList,
            (PVOID) pWriteQueueEle,
            NULL);
    BAIL_ON_VMDIR_ERROR(dwError);

    VMDIR_LOG_INFO(LDAP_DEBUG_WRITE_QUEUE, "%s: usn: %"PRId64, __FUNCTION__, localUsn);

cleanup:
    VMDIR_UNLOCK_MUTEX(bInLock, gVmDirServerOpsGlobals.pMutex);
    return dwError;

error:
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d) localUsn %"PRId64, dwError, localUsn);
    goto cleanup;
}
Пример #14
0
int
VmDirFirstReplicationCycle(
    PCSTR                           pszHostname,
    VMDIR_REPLICATION_AGREEMENT *   pReplAgr)
{
    int                     retVal = LDAP_SUCCESS;
    PSTR                    pszLocalErrorMsg = NULL;
    BOOLEAN                 bWriteInvocationId = FALSE;
    BOOLEAN                 bHasXlog = FALSE;
#ifndef _WIN32
    const char  *dbHomeDir = VMDIR_DB_DIR;
#else
    _TCHAR      dbHomeDir[MAX_PATH];
    size_t last_char_pos = 0;
    const char   fileSeperator = '\\';

    retVal = VmDirMDBGetHomeDir(dbHomeDir);
    BAIL_ON_VMDIR_ERROR ( retVal );
    last_char_pos = strlen(dbHomeDir) - 1;
    if (dbHomeDir[last_char_pos] == fileSeperator)
    {
        dbHomeDir[last_char_pos] = '\0';
    }
#endif

    assert( gFirstReplCycleMode == FIRST_REPL_CYCLE_MODE_COPY_DB );

    retVal = _VmDirGetRemoteDBUsingRPC(pszHostname, dbHomeDir, &bHasXlog);
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                "VmDirFirstReplicationCycle: _VmDirGetRemoteDBUsingRPC() call failed with error: %d", retVal );

    retVal = _VmDirSwapDB(dbHomeDir, bHasXlog);
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
                "VmDirFirstReplicationCycle: _VmDirSwapDB() call failed, error: %d.", retVal );

    VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "Remote DB copied from %s, and swapped successfully", pszHostname);

    // Wrap up the 1st replication cycle by updating replication cookies.
    retVal = _VmDirWrapUpFirstReplicationCycle( pszHostname, pReplAgr );

    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
            "VmDirFirstReplicationCycle: _VmDirWrapUpFirstReplicationCycle() call failed, error: %d.", retVal );

    retVal = LoadServerGlobals(&bWriteInvocationId);

    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg),
            "VmDirFirstReplicationCycle: LoadServerGlobals call failed, error: %d.", retVal );
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;
}
Пример #15
0
static
int
VmDirSASL2PATH(
    PSTR *ppszPath
    )
{
    DWORD   dwError = 0;
    PSTR    pszLocalPath = NULL;

#ifdef _WIN32
    char    sasl2SearchPathBuf[MAX_PATH] = {0};
    char    vmdirInstallPathBuf[MAX_PATH] = {0};

    // base sasl lib path
    dwError = VmDirGetRegKeyValue( VDMIR_CONFIG_SASL2_KEY_PATH,
                                   "SearchPath",
                                   sasl2SearchPathBuf,
                                   MAX_PATH );
    BAIL_ON_VMDIR_ERROR(dwError);

    // vmdir specific sasl lib path
    dwError = VmDirGetRegKeyValue(  VMDIR_CONFIG_SOFTWARE_KEY_PATH,
                                    "InstallPath",
                                    vmdirInstallPathBuf,
                                    MAX_PATH );
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirAllocateStringAVsnprintf( &pszLocalPath, "%s;%s\\sasl2",
                                             sasl2SearchPathBuf,
                                             vmdirInstallPathBuf);
#else
    dwError = VmDirAllocateStringAVsnprintf( &pszLocalPath, "%s:%s/sasl2",
                                             VMDIR_CONFIG_SASL2_LIB_PATH,
                                             VMDIR_LIB_DIR);
#endif
    BAIL_ON_VMDIR_ERROR(dwError);

    *ppszPath = pszLocalPath;

    VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "SASL2PATH=%s", pszLocalPath);

cleanup:

    return dwError;

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "VmDirSASL2PATH failed (%d)", dwError);
    VMDIR_SAFE_FREE_MEMORY( pszLocalPath );

    goto cleanup;
}
Пример #16
0
/*
 * If you want this update to be a part of bigger transaction,
 * provide pBECtx. Or leave it NULL otherwise.
 */
DWORD
VmDirIndexUpdateBegin(
    PVDIR_BACKEND_CTX   pBECtx,
    PVDIR_INDEX_UPD*    ppIndexUpd
    )
{
    DWORD   dwError = 0;
    PVDIR_INDEX_UPD pIndexUpd = NULL;

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

    dwError = VmDirIndexUpdInit(pBECtx, &pIndexUpd);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirIndexUpdCopy(gVdirIndexGlobals.pIndexUpd, pIndexUpd);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (pIndexUpd->bOwnBECtx)
    {
        PVDIR_BACKEND_INTERFACE pBE = VmDirBackendSelect(NULL);
        pIndexUpd->pBECtx->pBE = pBE;

        dwError = pBE->pfnBETxnBegin(pIndexUpd->pBECtx, VDIR_BACKEND_TXN_WRITE);
        BAIL_ON_VMDIR_ERROR(dwError);
        pIndexUpd->bHasBETxn = TRUE;
    }

    *ppIndexUpd = pIndexUpd;

    VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "%s succeeded", __FUNCTION__ );

cleanup:
    return dwError;

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

    VmDirIndexUpdFree(pIndexUpd);
    goto cleanup;
}
Пример #17
0
DWORD
VmDirSrvSetupTenantInstance(
    PCSTR pszFQDomainName,
    PCSTR pszUsername,
    PCSTR pszPassword
    )
{
    DWORD dwError = 0;
    PSTR  pszDomainDN = NULL;
    PVDIR_SCHEMA_CTX pSchemaCtx = NULL;

    VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "Setting up a tenant instance (%s).",
			               VDIR_SAFE_STRING(pszFQDomainName));

    dwError = VmDirSrvCreateDomainDN(pszFQDomainName, &pszDomainDN);
    BAIL_ON_VMDIR_ERROR(dwError);

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

    dwError = VmDirSrvSetupDomainInstance(
                    pSchemaCtx,
                    FALSE,
                    FALSE,
                    pszFQDomainName,
                    pszDomainDN,
                    pszUsername,
                    pszPassword);
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszDomainDN);

    if (pSchemaCtx)
    {
        VmDirSchemaCtxRelease(pSchemaCtx);
    }

    return dwError;

error:
    VmDirLog(LDAP_DEBUG_ANY, "VmDirSrvSetupTenantInstance failed. Error(%u)", dwError);
    goto cleanup;
}
Пример #18
0
DWORD
VmKdcRpcAuthCallback(
    PVOID         Context
    )
{
    rpc_authz_handle_t hPrivs = NULL;
    DWORD dwAuthnLevel = 0;
    DWORD dwAuthnSvc = 0;
    DWORD dwAuthzSvc = 0;
    DWORD dwError = ERROR_SUCCESS;

    dwError = VmKdcRpcBindingInqAuthClient(
            Context,
            &hPrivs, // The data referenced by this parameter is read-only,
                     // and therefore should not be modified/freed.
            NULL,    // ServerPrincipalName - we don't need it
            &dwAuthnLevel,
            &dwAuthnSvc,
            &dwAuthzSvc);
    BAIL_ON_VMKDC_ERROR(dwError);

    VMDIR_LOG_INFO(
            VMDIR_LOG_MASK_ALL,
            "Authentication Level = %d, Authentication Service = %d,"
            "Authorization Service = %d.",
            dwAuthnLevel,
            dwAuthnSvc,
            dwAuthzSvc);

    // Now check the authentication level. We require at least packet-level
    // authentication.
    if (dwAuthnLevel < rpc_c_authn_level_pkt)
    {
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL,
            "Attempt by client to use weak authentication.");

        dwError = ERROR_ACCESS_DENIED;
        BAIL_ON_VMKDC_ERROR(dwError);
    }

error:

    return dwError;
}
Пример #19
0
/*
 * Initialize vmkdcd components
 */
DWORD
VmKdcInit()
{
    DWORD dwError = 0;
    extern VMKDC_GLOBALS gVmkdcGlobals;

    InitializeGlobals(&gVmkdcGlobals);

#ifndef _WIN32
    dwError = InitializeResourceLimit();
    BAIL_ON_VMKDC_ERROR(dwError);
#endif
    dwError = VmKdcInitKrb5(&gVmkdcGlobals.pKrb5Ctx);
    BAIL_ON_VMKDC_ERROR(dwError);

    dwError = VmKdcSrvOpenServicePort(&gVmkdcGlobals, TRUE, VMKDC_SERVICE_PORT_TCP);
    BAIL_ON_VMKDC_ERROR(dwError);

    dwError = VmKdcSrvOpenServicePort(&gVmkdcGlobals, FALSE, VMKDC_SERVICE_PORT_TCP);
    BAIL_ON_VMKDC_ERROR(dwError);

    dwError = VmKdcSrvOpenServicePort(&gVmkdcGlobals, TRUE, VMKDC_SERVICE_PORT_UDP);
    BAIL_ON_VMKDC_ERROR(dwError);

    dwError = VmKdcSrvOpenServicePort(&gVmkdcGlobals, FALSE, VMKDC_SERVICE_PORT_UDP);
    BAIL_ON_VMKDC_ERROR(dwError);

    dwError = VmKdcSrvServicePortListen(&gVmkdcGlobals);
    BAIL_ON_VMKDC_ERROR(dwError);

#if 0
    dwError = VmKdcRpcServerInit();
    BAIL_ON_VMKDC_ERROR(dwError);
#endif

    dwError = VmKdcInitConnAcceptThread(&gVmkdcGlobals);
    BAIL_ON_VMKDC_ERROR(dwError);

    VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "VmKdcInit: done!");

error:
    return dwError;
}
Пример #20
0
/*
 * Ldap operation thr exit
 */
static
VOID
_VmDirFlowCtrlThrExit(
    VOID
    )
{
    BOOLEAN bInLock = FALSE;
    DWORD   dwFlowCtrl = 0;

    VMDIR_LOCK_MUTEX(bInLock, gVmdirGlobals.pFlowCtrlMutex);

    gVmdirGlobals.dwMaxFlowCtrlThr++;
    dwFlowCtrl = gVmdirGlobals.dwMaxFlowCtrlThr;

    VMDIR_UNLOCK_MUTEX(bInLock, gVmdirGlobals.pFlowCtrlMutex);

    VMDIR_LOG_INFO( LDAP_DEBUG_CONNS, "FlowCtrlThr++ %d", dwFlowCtrl);

    return;
}
Пример #21
0
int
VmDirPerformDelete(
   PVDIR_OPERATION pOperation
   )
{
    int              retVal = LDAP_SUCCESS;
    DeleteReq *      dr = &(pOperation->request.deleteReq);
    BOOLEAN         bResultAlreadySent = FALSE;
    // Get entry DN. 'm' => pOperation->reqDn.lberbv.bv_val points to DN within (in-place) ber
    if ( ber_scanf( pOperation->ber, "m", &(pOperation->reqDn.lberbv) ) == LBER_ERROR )
    {
        VMDIR_LOG_ERROR( LDAP_DEBUG_ARGS, "PerformDelete: ber_scanf failed" );
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, "Delete Request: dn (%s)", pOperation->reqDn.lberbv.bv_val );

    memset( dr, 0, sizeof( DeleteReq ));

    // NOTE: pOperation->reqDn.lberbv.bv_val is NULL terminated (TODO, verify this)
    dr->dn.lberbv.bv_val = pOperation->reqDn.lberbv.bv_val;
    dr->dn.lberbv.bv_len = pOperation->reqDn.lberbv.bv_len;

    retVal = VmDirMLDelete( pOperation );
    bResultAlreadySent = TRUE;
    BAIL_ON_VMDIR_ERROR(retVal);

cleanup:

    return retVal;

error:
    if (retVal != LDAP_NOTICE_OF_DISCONNECT && bResultAlreadySent == FALSE)
    {
        VmDirSendLdapResult( pOperation );
    }

    goto cleanup;
}
Пример #22
0
static
VOID
_VmDirPrintWriteQueueContentsInLock(
    PVMDIR_WRITE_QUEUE    pWriteQueue
    )
{
    PVDIR_LINKED_LIST_NODE    pNode = NULL;

    if (VmDirLogGetMask() & LDAP_DEBUG_WRITE_QUEUE)
    {
        VmDirLinkedListGetHead(pWriteQueue->pList, &pNode);
        while (pNode)
        {
            VMDIR_LOG_INFO(
                    LDAP_DEBUG_WRITE_QUEUE,
                    "%s: USNs in the write queue: %"PRId64,
                    __FUNCTION__,
                    ((PVMDIR_WRITE_QUEUE_ELEMENT)pNode->pElement)->usn);
            pNode = pNode->pNext;
        }
    }
}
Пример #23
0
/*
 * return TRUE if we are over the limit of MaxLdapOpThrs
 */
static
BOOLEAN
_VmDirFlowCtrlThrEnter(
    VOID
    )
{
    BOOLEAN bInLock = FALSE;
    DWORD   dwFlowCtrl = 0;

    VMDIR_LOCK_MUTEX(bInLock, gVmdirGlobals.pFlowCtrlMutex);

    if ( gVmdirGlobals.dwMaxFlowCtrlThr > 0 )
    {
        dwFlowCtrl = gVmdirGlobals.dwMaxFlowCtrlThr;
        gVmdirGlobals.dwMaxFlowCtrlThr--;
    }

    VMDIR_UNLOCK_MUTEX(bInLock, gVmdirGlobals.pFlowCtrlMutex);

    VMDIR_LOG_INFO( LDAP_DEBUG_CONNS, "FlowCtrlThr-- %d", dwFlowCtrl);

    return ( dwFlowCtrl == 0 );
}
Пример #24
0
DWORD
VmDirSrvSetupHostInstance(
    PCSTR   pszFQDomainName,
    PCSTR   pszUsername,
    PCSTR   pszPassword,
    PCSTR   pszSiteName,
    PCSTR   pszReplURI,
    UINT32  firstReplCycleMode
    )
{
    DWORD   dwError = 0;

    PCSTR   pszDelObjsContainerName =     "Deleted Objects";
    PCSTR   pszConfigContainerName =      VMDIR_CONFIGURATION_CONTAINER_NAME;
    PCSTR   pszCAContainerName =          VMDIR_CA_CONTAINER_NAME;
    PCSTR   pszSitesContainerName =       VMDIR_SITES_RDN_VAL;
    PCSTR   pszSiteContainerName =        "Default-First-Site";
    PCSTR   pszServersContainerName =     VMDIR_SERVERS_CONTAINER_NAME;
    PCSTR   pszReplAgrsContainerName =    VMDIR_REPL_AGRS_CONTAINER_NAME;
    PCSTR   pszDCsContainerName =         VMDIR_DOMAIN_CONTROLLERS_RDN_VAL;
    PCSTR   pszComputersContainerName =   VMDIR_COMPUTERS_RDN_VAL;
    PCSTR   pszMSAsContainerName =        VMDIR_MSAS_RDN_VAL;

    PSTR    pszDomainDN = NULL;
    PSTR    pszDelObjsContainerDN = NULL;     // CN=Deleted Objects,<domain DN>
    PSTR    pszConfigContainerDN = NULL;      // CN=Configuration,<domain DN>
    PSTR    pszCAContainerDN = NULL;          // CN=Certificate-Authorities,CN=Configuration,<domain DN>
    PSTR    pszSitesContainerDN = NULL;       // CN=Sites,<configuration DN>
    PSTR    pszSiteContainerDN = NULL;        // CN=<Site-Name>,<Sites container DN>
    PSTR    pszServersContainerDN = NULL;     // CN=Servers,<Site container DN>
    PSTR    pszServerDN = NULL;               // CN=<fully qualified host name>,<Servers container DN>
    PSTR    pszReplAgrsContainerDN = NULL;    // CN=Replication Agreements,<Server DN>
    PSTR    pszReplAgrDN = NULL;              // labeledURI=<ldap://192.165.226.127>,<ReplAgrsContainerDN>
    PSTR    pszDCsContainerDN = NULL;         // OU=Domain Controllers,<domain DN>
    PSTR    pszComputersContainerDN = NULL;   // OU=Computers,<domain DN>
    PSTR    pszDCAccountDN = NULL;            // CN=<fully qualified host name>,OU=Domain Controllers,<domain DN>
    PSTR    pszDCAccountUPN = NULL;            // <hostname>@<domain name>
    PSTR    pszComputerAccountDN = NULL;      // CN=<fully qualified host name>,OU=Domain Computers,<domain DN>
    PSTR    pszMSAsDN = NULL;                 // CN=<Managed Service Accounts>,<domain DN>
    PSTR    pszUpperCaseFQDomainName = NULL;
    PSTR    pszLowerCaseHostName = NULL;
    PSTR    pszDefaultAdminDN = NULL;

    PVDIR_SCHEMA_CTX     pSchemaCtx = NULL;
    char                 pszHostName[VMDIR_MAX_HOSTNAME_LEN];
    VDIR_BERVALUE        bv = VDIR_BERVALUE_INIT;

    BOOLEAN                       bInLockReplCycle = FALSE;
    PVMDIR_REPLICATION_AGREEMENT  pReplAgr = NULL;
    BOOLEAN                       bInLock = FALSE;
    PSTR                          pszUserDN = NULL;
    PCSTR                         pszUsersContainerName    = "Users";
    PSTR                          pszUsersContainerDN   = NULL; // CN=Users,<domain DN>

    VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "Setting up a host instance (%s).",
			               VDIR_SAFE_STRING(pszFQDomainName));

    if (pszSiteName)
    {
        pszSiteContainerName = pszSiteName;
    }

    // If joining another node, copy schema from the partner first.
    if (!IsNullOrEmptyString(pszReplURI))
    {
        dwError = VmDirCopyPartnerSchema(
                pszFQDomainName,
                pszUsername,
                pszPassword,
                pszReplURI);
        BAIL_ON_VMDIR_ERROR(dwError);
    }

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

    // Construct important DNs and create the persisted DSE Root entry

    // Domain DN
    dwError = VmDirSrvCreateDomainDN( pszFQDomainName, &pszDomainDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Deleted objects container DN
    dwError = VmDirSrvCreateDN( pszDelObjsContainerName, pszDomainDN, &pszDelObjsContainerDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Configuration container DN
    dwError = VmDirSrvCreateDN( pszConfigContainerName, pszDomainDN, &pszConfigContainerDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Domain Controllers container DN
    dwError = VmDirAllocateStringAVsnprintf(&pszDCsContainerDN, "%s=%s,%s", ATTR_OU, pszDCsContainerName, pszDomainDN);
    BAIL_ON_VMDIR_ERROR(dwError);

    // Domain Computers container DN
    dwError = VmDirAllocateStringAVsnprintf(&pszComputersContainerDN, "%s=%s,%s", ATTR_OU, pszComputersContainerName, pszDomainDN);
    BAIL_ON_VMDIR_ERROR(dwError);

    // Sites container DN
    dwError = VmDirSrvCreateDN( pszSitesContainerName, pszConfigContainerDN, &pszSitesContainerDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Certificate-Authorities container DN
    dwError = VmDirSrvCreateDN( pszCAContainerName, pszConfigContainerDN, &pszCAContainerDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Particular site container DN
    dwError = VmDirSrvCreateDN( pszSiteContainerName, pszSitesContainerDN, &pszSiteContainerDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Servers within the site container DN
    dwError = VmDirSrvCreateDN( pszServersContainerName, pszSiteContainerDN, &pszServersContainerDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // This server DN

    // vdcpromo sets this key.
    dwError = VmDirGetRegKeyValue( VMDIR_CONFIG_PARAMETER_KEY_PATH,
                                   VMDIR_REG_KEY_DC_ACCOUNT,
                                   pszHostName,
                                   sizeof(pszHostName)-1);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirAllocASCIIUpperToLower( pszHostName, &pszLowerCaseHostName );
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirSrvCreateDN( pszLowerCaseHostName, pszServersContainerDN, &pszServerDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Domain controller account DN
    dwError = VmDirSrvCreateDN( pszLowerCaseHostName, pszDCsContainerDN, &pszDCAccountDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Domain controller account UPN
    dwError = VmDirAllocASCIILowerToUpper( pszFQDomainName, &pszUpperCaseFQDomainName );
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirAllocateStringAVsnprintf(&pszDCAccountUPN, "%s@%s", pszLowerCaseHostName, pszUpperCaseFQDomainName );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Computer account DN
    dwError = VmDirSrvCreateDN( pszLowerCaseHostName, pszComputersContainerDN, &pszComputerAccountDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Replication agreements container DN
    dwError = VmDirSrvCreateDN( pszReplAgrsContainerName, pszServerDN, &pszReplAgrsContainerDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Managed Service Accounts container DN
    dwError = VmDirSrvCreateDN( pszMSAsContainerName, pszDomainDN, &pszMSAsDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Default administrator DN
    dwError = VmDirAllocateStringAVsnprintf( &pszDefaultAdminDN, "cn=%s,cn=%s,%s",
                                             pszUsername, pszUsersContainerName, pszDomainDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    if (firstReplCycleMode != FIRST_REPL_CYCLE_MODE_USE_COPIED_DB)
    {
        // Modify persisted DSE Root entry
        dwError = VmDirSrvModifyPersistedDSERoot( pSchemaCtx, pszDomainDN, pszConfigContainerDN, SCHEMA_NAMING_CONTEXT_DN,
                                                  SUB_SCHEMA_SUB_ENTRY_DN, pszServerDN, pszDefaultAdminDN,
                                                  pszDCAccountDN, pszDCAccountUPN, pszDelObjsContainerDN,
                                                  (PSTR) pszSiteContainerName );
    }
    BAIL_ON_VMDIR_ERROR(dwError);

    // set gVmdirServerGlobals.bvDefaultAdminDN
    dwError = VmDirAllocateBerValueAVsnprintf(
                &gVmdirServerGlobals.bvDefaultAdminDN,
                "%s",
                pszDefaultAdminDN);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirNormalizeDN( &gVmdirServerGlobals.bvDefaultAdminDN, pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    // set systemDomainDN
    dwError = VmDirAllocateBerValueAVsnprintf(
                &gVmdirServerGlobals.systemDomainDN,
                "%s",
                pszDomainDN);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirNormalizeDN( &gVmdirServerGlobals.systemDomainDN, pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    // set serverObjDN
    dwError = VmDirAllocateBerValueAVsnprintf(
                &gVmdirServerGlobals.serverObjDN,
                "%s",
                pszServerDN);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirNormalizeDN( &gVmdirServerGlobals.serverObjDN, pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    // set dcAccountDN
    dwError = VmDirAllocateBerValueAVsnprintf(
                &gVmdirServerGlobals.dcAccountDN,
                "%s",
                pszDCAccountDN);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirNormalizeDN( &gVmdirServerGlobals.dcAccountDN, pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    // set dcAccountUPN
    dwError = VmDirAllocateBerValueAVsnprintf(
                &gVmdirServerGlobals.dcAccountUPN,
                "%s",
                pszDCAccountUPN);
    BAIL_ON_VMDIR_ERROR(dwError);

    // Set replInterval and replPageSize
    gVmdirServerGlobals.replInterval = VmDirStringToIA(VMDIR_DEFAULT_REPL_INTERVAL);
    gVmdirServerGlobals.replPageSize = VmDirStringToIA(VMDIR_DEFAULT_REPL_PAGE_SIZE);

    // Set utdVector
    VmDirFreeBervalContent(&bv);
    bv.lberbv.bv_val = "";
    bv.lberbv.bv_len = 0;
    dwError = VmDirBervalContentDup( &bv, &gVmdirServerGlobals.utdVector );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Set delObjsContainerDN
    VmDirFreeBervalContent(&bv);
    bv.lberbv.bv_val = pszDelObjsContainerDN;
    bv.lberbv.bv_len = VmDirStringLenA( bv.lberbv.bv_val );
    dwError = VmDirBervalContentDup( &bv, &gVmdirServerGlobals.delObjsContainerDN );
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirNormalizeDN(&gVmdirServerGlobals.delObjsContainerDN, pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirAllocateStringA( pszSiteContainerName, &gVmdirServerGlobals.pszSiteName);
    BAIL_ON_VMDIR_ERROR(dwError);

    // Create Administrator DN
    dwError = VmDirSrvCreateDN( pszUsersContainerName, pszDomainDN, &pszUsersContainerDN);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirSrvCreateUserDN( pszUsername, pszUsersContainerDN, &pszUserDN);
    BAIL_ON_VMDIR_ERROR(dwError);

    // set DomainControllerGroupDN for first,second+ host setup
    dwError = VmDirAllocateBerValueAVsnprintf(
                &gVmdirServerGlobals.bvDCGroupDN,
                "cn=%s,cn=%s,%s",
                VMDIR_DC_GROUP_NAME,
                VMDIR_BUILTIN_CONTAINER_NAME,
                pszDomainDN);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirNormalizeDN( &(gVmdirServerGlobals.bvDCGroupDN), pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    // set DCClientGroupDN for first,second+ host setup
    dwError = VmDirAllocateBerValueAVsnprintf(
                &gVmdirServerGlobals.bvDCClientGroupDN,
                "cn=%s,cn=%s,%s",
                VMDIR_DCCLIENT_GROUP_NAME,
                VMDIR_BUILTIN_CONTAINER_NAME,
                pszDomainDN);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirNormalizeDN( &(gVmdirServerGlobals.bvDCClientGroupDN), pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    // set ServicesRootDN for first,second+ host setup
    dwError = VmDirAllocateBerValueAVsnprintf(
                &gVmdirServerGlobals.bvServicesRootDN,
                "cn=%s,%s",
                VMDIR_SERVICES_CONTAINER_NAME,
                pszDomainDN);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirNormalizeDN( &(gVmdirServerGlobals.bvServicesRootDN), pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (IsNullOrEmptyString(pszReplURI)) // 1st directory instance is being setup
    {
        // Set gVmdirServerGlobals.serverId FIRST, so that correct SID can be generated for the objects added subsequently.
        gVmdirServerGlobals.serverId = 1;

        dwError = VmDirSrvSetupDomainInstance( pSchemaCtx, TRUE, TRUE, pszFQDomainName, pszDomainDN, pszUsername,
                                               pszPassword );
        BAIL_ON_VMDIR_ERROR(dwError);

        // Create Deleted Objects container
        dwError = VmDirSrvCreateContainerWithEID( pSchemaCtx, pszDelObjsContainerDN, pszDelObjsContainerName,
                                                 DEL_ENTRY_CONTAINER_ENTRY_ID );
        BAIL_ON_VMDIR_ERROR(dwError);

        // Create Domain Controllers container
        dwError = VmDirSrvCreateOUContainer( pSchemaCtx, pszDCsContainerDN, pszDCsContainerName );
        BAIL_ON_VMDIR_ERROR(dwError);

        // Create Computers container
        dwError = VmDirSrvCreateOUContainer( pSchemaCtx, pszComputersContainerDN, pszComputersContainerName );
        BAIL_ON_VMDIR_ERROR(dwError);

        // Create Managed Service Accounts container
        dwError = VmDirSrvCreateContainer( pSchemaCtx, pszMSAsDN, pszMSAsContainerName );
        BAIL_ON_VMDIR_ERROR(dwError);

        // Create Configuration container
        dwError = VmDirSrvCreateConfigContainer( pSchemaCtx, pszConfigContainerDN, pszConfigContainerName );
        BAIL_ON_VMDIR_ERROR(dwError);

        // Create Certificate-Authorities container
        dwError = VmDirSrvCreateContainer( pSchemaCtx, pszCAContainerDN, pszCAContainerName );
        BAIL_ON_VMDIR_ERROR(dwError);

        // Create Sites container
        dwError = VmDirSrvCreateContainer( pSchemaCtx, pszSitesContainerDN, pszSitesContainerName );
        BAIL_ON_VMDIR_ERROR(dwError);

        /*
        // Create Site-Name container
        dwError = VmDirSrvCreateContainer( pSchemaCtx, pszSiteContainerDN, pszSiteContainerName );
        BAIL_ON_VMDIR_ERROR(dwError);

        // Create Servers container
        dwError = VmDirSrvCreateContainer( pSchemaCtx, pszServersContainerDN, pszServersContainerName );
        BAIL_ON_VMDIR_ERROR(dwError);
        */

        // Create Site-Name container, Servers container, and THE Server object
        dwError = VmDirSrvCreateServerObj( pSchemaCtx );
        BAIL_ON_VMDIR_ERROR(dwError);

        // Create Replication Agreements container
        dwError = VmDirSrvCreateReplAgrsContainer( pSchemaCtx );
        BAIL_ON_VMDIR_ERROR(dwError);

        // 1st replica => no replication agreements => 1st replication cycle done
        VMDIR_LOCK_MUTEX(bInLockReplCycle, gVmdirGlobals.replCycleDoneMutex);
        VmDirConditionSignal(gVmdirGlobals.replCycleDoneCondition);
        VMDIR_UNLOCK_MUTEX(bInLockReplCycle, gVmdirGlobals.replCycleDoneMutex);
    }
    else
    {
        dwError = VmDirAllocateStringAVsnprintf( &pszReplAgrDN, "labeledURI=%s,%s", pszReplURI, pszReplAgrsContainerDN );
        BAIL_ON_VMDIR_ERROR(dwError);

        dwError = VmDirConstructReplAgr( pSchemaCtx, pszReplURI,
                                         VMDIR_DEFAULT_REPL_LAST_USN_PROCESSED, pszReplAgrDN, &pReplAgr );
        BAIL_ON_VMDIR_ERROR(dwError);

        gFirstReplCycleMode = firstReplCycleMode;

        VMDIR_LOCK_MUTEX(bInLock, gVmdirGlobals.replAgrsMutex);
        pReplAgr->next = gVmdirReplAgrs;
        gVmdirReplAgrs = pReplAgr; // ownership transfer
        // wake up replication thread waiting on the existence
        // of a replication agreement.
        VmDirConditionSignal(gVmdirGlobals.replAgrsCondition);
        VMDIR_UNLOCK_MUTEX(bInLock, gVmdirGlobals.replAgrsMutex);
    }

cleanup:

    if (pSchemaCtx)
    {
        VmDirSchemaCtxRelease(pSchemaCtx);
    }

    VMDIR_SAFE_FREE_MEMORY(pszDomainDN);
    VMDIR_SAFE_FREE_MEMORY(pszDelObjsContainerDN);
    VMDIR_SAFE_FREE_MEMORY(pszConfigContainerDN);
    VMDIR_SAFE_FREE_MEMORY(pszCAContainerDN);
    VMDIR_SAFE_FREE_MEMORY(pszSitesContainerDN);
    VMDIR_SAFE_FREE_MEMORY(pszSiteContainerDN);
    VMDIR_SAFE_FREE_MEMORY(pszServersContainerDN);
    VMDIR_SAFE_FREE_MEMORY(pszServerDN);
    VMDIR_SAFE_FREE_MEMORY(pszReplAgrsContainerDN);
    VMDIR_SAFE_FREE_MEMORY(pszReplAgrDN);
    VMDIR_SAFE_FREE_MEMORY(pszDCsContainerDN);
    VMDIR_SAFE_FREE_MEMORY(pszDCAccountDN);
    VMDIR_SAFE_FREE_MEMORY(pszDCAccountUPN);
    VMDIR_SAFE_FREE_MEMORY(pszComputersContainerDN);
    VMDIR_SAFE_FREE_MEMORY(pszComputerAccountDN);
    VMDIR_SAFE_FREE_MEMORY(pszMSAsDN);
    VMDIR_SAFE_FREE_MEMORY(pszUpperCaseFQDomainName);
    VMDIR_SAFE_FREE_MEMORY(pszUsersContainerDN);
    VMDIR_SAFE_FREE_MEMORY(pszUserDN);
    VMDIR_SAFE_FREE_MEMORY(pszDefaultAdminDN);
    VMDIR_SAFE_FREE_MEMORY(pszLowerCaseHostName);

    VmDirFreeBervalContent(&bv);

    return dwError;

error:
    VmDirLog(LDAP_DEBUG_ANY, "VmDirSrvSetupHostInstance failed. Error(%u)", dwError);
    goto cleanup;
}
Пример #25
0
/*
 * Main initialization loop.
 */
DWORD
VmKdcInitLoop(
    PVMKDC_GLOBALS pGlobals)
{
    DWORD dwError = 0;
    int sts = 0;
    time_t now = 0;
    struct timespec timeout = {0};

    while (1)
    {
        switch (VmKdcdState())
        {
            case VMKDCD_STARTUP:
                /*
                 * Try to initialize the directory.
                 */
                VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "Vmkdc: initializing directory");
                dwError = VmKdcInitializeDirectory(pGlobals);
                if ( VmKdcdState() == VMKDCD_STARTUP    &&
                     dwError == 0
                   )
                {
                    VmKdcdStateSet(VMKDCD_RUNNING);
                    continue;
                }

                /*
                 * Initialization of the directory failed or stopping/shutdown noticed.
                 * Wait for a while before retrying.
                 */
                pthread_mutex_lock(&pGlobals->mutex);
                now = time(NULL);
                timeout.tv_sec = now + VMKDC_DIRECTORY_POLL_SECS;
                timeout.tv_nsec = 0;
                sts = 0;
                while (pGlobals->vmkdcdState == VMKDCD_STARTUP && sts == 0)
                {
                    sts = pthread_cond_timedwait(&pGlobals->stateCond,
                                                 &pGlobals->mutex,
                                                 &timeout);
                }
                pthread_mutex_unlock(&pGlobals->mutex);
                break;

            case VMKDCD_RUNNING:
                /*
                 * Wait until the server state changes.
                 */
                pthread_mutex_lock(&pGlobals->mutex);
                while (pGlobals->vmkdcdState == VMKDCD_RUNNING)
                {
                    pthread_cond_wait(&pGlobals->stateCond,
                                      &pGlobals->mutex);
                }
                pthread_mutex_unlock(&pGlobals->mutex);
                break;

            case VMKDC_STOPPING:
                /*
                 * Notify VmKdcShutdown() STOPPING has been received.
                 * It is now safe to tear down pGlobal mutex/condition
                 * variable resources after this point.
                 */
                VmKdcdStateSet(VMKDC_SHUTDOWN);

                /* don't break here because we can't use the global mutex any more */
                goto cleanup;

            case VMKDC_SHUTDOWN:
                goto cleanup;
        }
    }

cleanup:

    return dwError;
}
Пример #26
0
void
VmDirSendLdapResult(
   VDIR_OPERATION * op
   )
{
   BerElementBuffer berbuf;
   BerElement *     ber = (BerElement *) &berbuf;
   ber_int_t        msgId = 0;
   ber_tag_t        resCode = 0;
   size_t           iNumSearchEntrySent = 0;
   PCSTR            pszSocketInfo = NULL;

   (void) memset( (char *)&berbuf, '\0', sizeof( BerElementBuffer ));

   resCode = GetResultTag( op->reqCode );
   msgId = (resCode != LBER_SEQUENCE) ? op->msgId : 0;

   if ( resCode == LDAP_RES_SEARCH_RESULT )
   {
       iNumSearchEntrySent = op->request.searchReq.iNumEntrySent;
   }

   ber_init2( ber, NULL, LBER_USE_DER );

   if (op->conn)
   {
      pszSocketInfo = op->conn->szClientIP;
   }

   if (op->ldapResult.errCode &&
       op->ldapResult.errCode != LDAP_SASL_BIND_IN_PROGRESS)
   {
       VMDIR_LOG_ERROR(
          VMDIR_LOG_MASK_ALL,
          "VmDirSendLdapResult: Request (%d), Error (%d), Message (%s), (%u) socket (%s)",
          op->reqCode,
          op->ldapResult.errCode,
          VDIR_SAFE_STRING(op->ldapResult.pszErrMsg),
          iNumSearchEntrySent,
          VDIR_SAFE_STRING(pszSocketInfo));
   }
   else if ( op->reqCode == LDAP_REQ_SEARCH )
   {
       VMDIR_LOG_INFO(
          LDAP_DEBUG_ARGS,
          "VmDirSendLdapResult: Request (%d), Error (%d), Message (%s), (%u) socket (%s)",
          op->reqCode,
          op->ldapResult.errCode,
          VDIR_SAFE_STRING(op->ldapResult.pszErrMsg),
          iNumSearchEntrySent,
          VDIR_SAFE_STRING(pszSocketInfo));
   }

   if (ber_printf( ber, "{it{essN}", msgId, resCode, op->ldapResult.errCode, "",
                       VDIR_SAFE_STRING(op->ldapResult.pszErrMsg)) == -1)
   {
      VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print msgId ...) failed" );
      goto done;
   }

   // If Search, Replication, and one or more entries were sent back => Send back Sync Done Control
   if ( op->reqCode == LDAP_REQ_SEARCH && op->syncReqCtrl != NULL && op->syncDoneCtrl != NULL)
   {
       if (WriteSyncDoneControl( op, ber ) != LDAP_SUCCESS)
       {
           goto done;
       }
   }

   if ( op->reqCode == LDAP_REQ_SEARCH && op->showPagedResultsCtrl != NULL)
   {
       if (WritePagedSearchDoneControl( op, ber ) != LDAP_SUCCESS)
       {
           goto done;
       }
   }

   if (ber_printf( ber, "N}" ) == -1)
   {
      VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print msgId ...) failed" );
      goto done;
   }

   if (WriteBerOnSocket( op->conn, ber ) != 0)
   {
      VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: WriteBerOnSocket failed" );
      goto done;
   }

done:
   ber_free_buf( ber );

}
Пример #27
0
/*
 * Create a new schema cache via pEntry, then active this cache.
 */
DWORD
VmDirSchemaInitializeViaEntry(
    PVDIR_ENTRY    pEntry
    )
{
    BOOLEAN  bLoadOk = TRUE;
    BOOLEAN  bInLock = FALSE;
    DWORD    dwError = 0;

    PVDIR_SCHEMA_CTX pLiveCtx = NULL;
    PVDIR_SCHEMA_INSTANCE pInstance = NULL;
    PVDIR_SCHEMA_INSTANCE pLiveInstance = NULL;

    VMDIR_LOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);

    // get reference to current schema, to clean up later
    pLiveInstance = gVdirSchemaGlobals.pSchema;
    pLiveCtx      = gVdirSchemaGlobals.pCtx;

    // instantiate a schema cache - pInstance
    dwError = VdirSchemaInstanceInitViaEntry(
            pEntry,
            &pInstance);
    BAIL_ON_VMDIR_ERROR(dwError);

    gVdirSchemaGlobals.pSchema = pInstance;

    dwError = VdirSchemaCtxAcquireInLock(TRUE, &gVdirSchemaGlobals.pCtx); // add self reference
    BAIL_ON_VMDIR_ERROR(dwError);

    assert(gVdirSchemaGlobals.pCtx);

    VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Startup schema instance (%p)", gVdirSchemaGlobals.pSchema);

    VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);

cleanup:

    if (bLoadOk)
    {
        VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL,
            "Schema - AttributeTypes:(size=%d, nextid=%d) Objectclasses:(size=%d)",
            pEntry->pSchemaCtx->pSchema->ats.usNumATs,
            pEntry->pSchemaCtx->pSchema->ats.usNextId,
            pEntry->pSchemaCtx->pSchema->ocs.usNumOCs);
    }

    VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);

    if (pLiveCtx)
    {
        VmDirSchemaCtxRelease(pLiveCtx);
    }

    return dwError;

error:

    if (pInstance)
    {
        VdirSchemaInstanceFree(pInstance);
    }

    gVdirSchemaGlobals.pSchema = pLiveInstance;
    gVdirSchemaGlobals.pCtx = pLiveCtx;
    pLiveCtx = NULL;

    bLoadOk = FALSE;

    goto cleanup;
}
Пример #28
0
int
VmDirSendSearchEntry(
   PVDIR_OPERATION     pOperation,
   PVDIR_ENTRY         pSrEntry
   )
{
    int                         retVal = LDAP_SUCCESS;
    BerElementBuffer            berbuf;
    BerElement *                ber = (BerElement *) &berbuf;
    BOOLEAN                     bFreeBer = FALSE;
    ber_len_t                   iBlobSize = 0;
    BerValue                    lberBervEntryBlob = {0};
    int                         nAttrs = 0;
    int                         nVals = 0;
    BOOLEAN                     attrMetaDataReqd = FALSE;
    SearchReq *                 sr = &(pOperation->request.searchReq);
    int                         i = 0;
    BOOLEAN                     nonTrivialAttrsInReplScope = FALSE;
    uint32_t                    iSearchReqSpecialChars = 0;
    PATTRIBUTE_META_DATA_NODE   pAttrMetaData = NULL;
    int                         numAttrMetaData = 0;
    PVDIR_ATTRIBUTE             pAttr = NULL;
    USN                         usnChanged = 0;
    PSTR                        pszLocalErrorMsg = NULL;

    if ( !pOperation || !pSrEntry )
    {
        retVal = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    pSrEntry->bSearchEntrySent = FALSE;

    // see if client request has "*" and/or "+" ("-" for userpassword internal to vmdir)
    // WEI TODO: when we have attribute level ACL check, this information will be useful
    // return result will depend on ACL each on each attribute client is asking before
    // generating a final result to send back
    SetSpecialReturnChar(&pOperation->request.searchReq, &iSearchReqSpecialChars);

    if ( pSrEntry->eId == DSE_ROOT_ENTRY_ID
         &&
         pOperation->request.searchReq.attrs == NULL
       )
    {
        //  For ADSI, if no specific attributes requested of DSE ROOT search,
        //  return ALL (include operational) attributes.
        iSearchReqSpecialChars |= LDAP_SEARCH_REQUEST_CHAR_OP;
    }

    // ACL check before processing/sending the current srEntry back
    retVal = VmDirSrvAccessCheck( pOperation, &pOperation->conn->AccessInfo, pSrEntry, VMDIR_RIGHT_DS_READ_PROP );
    BAIL_ON_VMDIR_ERROR( retVal );

    if ( pOperation->opType == VDIR_OPERATION_TYPE_INTERNAL )
    {
        ; // no op in INTERNAL case
    }
    else
    {
        // If not replication, and showDeletedObjectsCtrl not present, => don't send back Deleted objects (tombstones).
        if (pOperation->syncReqCtrl == NULL && pOperation->showDeletedObjectsCtrl == NULL)
        {
            pAttr = VmDirEntryFindAttribute(ATTR_IS_DELETED, pSrEntry);
            if (pAttr)
            {
                if (VmDirStringCompareA((PSTR)pAttr->vals[0].lberbv.bv_val, VMDIR_IS_DELETED_TRUE_STR, FALSE) == 0)
                {
                    goto cleanup; // Don't send this entry
                }
            }
        }
        // In case of replication request, skip certain updates
        if (pOperation->syncReqCtrl != NULL)
        {
            PVDIR_ATTRIBUTE                 pAttrUsnCreated = NULL;
            USN                             usnCreated = 0;
            USN                             limitUsn = 0;
            VMDIR_REPLICATION_AGREEMENT *   replAgr = NULL;

            pAttr = VmDirEntryFindAttribute(ATTR_USN_CHANGED, pSrEntry);
            assert( pAttr != NULL );
            usnChanged = VmDirStringToLA( pAttr->vals[0].lberbv.bv_val, NULL, 10);

            // Check if usnChanged is beyond successful replication update state
            limitUsn = VmDirdGetLimitLocalUsnToBeSupplied();
            if (limitUsn != 0 && usnChanged >= limitUsn)
            {
                VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "SendSearchEntry: bug# 863244 RACE CONDITION encountered., "
                          "usnChanged = %ld, limitLocalUsnToBeSupplied = %ld, skipping entry: %s", usnChanged,
                          limitUsn, pSrEntry->dn.lberbv.bv_val );
                goto cleanup; // Don't send this entry
            }

            // Check if usnChanged is beyond lowestPendingUncommittedUsn recorded at the beginning of replication search

            if (pOperation->lowestPendingUncommittedUsn != 0 && usnChanged >= pOperation->lowestPendingUncommittedUsn)
            {
                VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: usnChanged = %ld, lowestPendingUncommittedUsn = %ld, "
                          "skipping entry: %s", usnChanged, pOperation->lowestPendingUncommittedUsn,
                          pSrEntry->dn.lberbv.bv_val );
                goto cleanup; // Don't send this entry
            }

            // Don't send (skip) modifications to my server object, and my RAs
            pAttrUsnCreated = VmDirEntryFindAttribute(ATTR_USN_CREATED, pSrEntry);
            assert( pAttrUsnCreated != NULL );
            usnCreated = VmDirStringToLA( pAttrUsnCreated->vals[0].lberbv.bv_val, NULL, 10);
            // Only send back creation of certain objects, and not their modifications.
            // Check if consumer has already seen the creation. If yes, we are dealing with mods, which should be skipped
            // for my server object, and my RAs
            // Note: Skipping mods for RAs and Server Objects will cause inconsistencies with replicas. But these
            // two types only have local scope regarding functional effects. But if we are looking up / processing
            // information for these two types of objects on a replica, we need to watch out for potential
            // inconsistencies against the original source.
            if (pOperation->syncReqCtrl->value.syncReqCtrlVal.intLastLocalUsnProcessed > usnCreated)
            {
                if (strcmp(pSrEntry->dn.bvnorm_val, gVmdirServerGlobals.serverObjDN.bvnorm_val) == 0)
                {
                    VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to my server object, DN: %s",
                              gVmdirServerGlobals.serverObjDN.lberbv.bv_val );
                    goto cleanup; // Don't send this entry
                }
                for (replAgr = gVmdirReplAgrs; replAgr != NULL; replAgr = replAgr->next )
                {
                    if (strcmp(pSrEntry->dn.bvnorm_val, replAgr->dn.bvnorm_val) == 0)
                    {
                        VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to my RA object, DN: %s",
                                  replAgr->dn.bvnorm_val );
                        goto cleanup; // Don't send this entry
                    }
                }
            }

            // do not replicate DSE Root entry, because it is a "local" entry.
            if (pSrEntry->eId == DSE_ROOT_ENTRY_ID)
            {
                VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to DSE Root entry, DN: %s",
                          pSrEntry->dn.bvnorm_val );
                goto cleanup; // Don't send this entry
            }

        }

        // Approximate calculation for the required ber size, because apart from lengths and strings, ber also includes
        // tags.
        if ( VmDirComputeEncodedEntrySize(pSrEntry, &nAttrs, &nVals, &iBlobSize) != 0
             ||
             VmDirAllocateMemory(iBlobSize, (PVOID*)&lberBervEntryBlob.bv_val) != 0
           )
        {
            retVal = LDAP_OPERATIONS_ERROR;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg), "no memory");
        }
        lberBervEntryBlob.bv_len = iBlobSize;

        ber_init2( ber, &lberBervEntryBlob, LBER_USE_DER );  // ber takes over lberBervEntryBlob.lberbv.bv_val ownership
        bFreeBer = TRUE;

        if ( ber_printf( ber, "{it{O{", pOperation->msgId, LDAP_RES_SEARCH_ENTRY, &pSrEntry->dn ) == -1)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: ber_printf (to print msgId ...) failed" );
            retVal = LDAP_OTHER;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "Encoding msgId, RES_SEARCH_ENTRY, DN failed");
        }
        // Determine if we need to send back the attribute metaData
        if ( pOperation->syncReqCtrl != NULL ) // Replication
        {
            attrMetaDataReqd = TRUE;
        }
        else // check if attrMetaData attribute has been requested explicitly.
        {
            if (sr->attrs != NULL)
            {
                for (i = 0; sr->attrs[i].lberbv.bv_val != NULL; i++)
                {
                    if (VmDirStringCompareA( sr->attrs[i].lberbv.bv_val, ATTR_ATTR_META_DATA, FALSE) == 0)
                    {
                        attrMetaDataReqd = TRUE;
                        break;
                    }
                }
            }
        }

        if (attrMetaDataReqd)
        {
            if ((pOperation->pBEIF->pfnBEGetAllAttrsMetaData( pOperation->pBECtx, pSrEntry->eId, &pAttrMetaData,
                                                              &numAttrMetaData )) != 0)
            {
                VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: pfnBEGetAllAttrsMetaData failed for entryId: %ld",
                                   pSrEntry->eId);
                retVal = LDAP_OPERATIONS_ERROR;
                BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                "pfnBEGetAllAttrsMetaData failed.");
            }

            // SJ-TBD: Following double for loop to be optimized
            // Copy attrMetaData to corresponding attributes
            for (i=0; i<numAttrMetaData; i++)
            {
                for ( pAttr = pSrEntry->attrs; pAttr != NULL; pAttr = pAttr->next)
                {
                    if (pAttr->pATDesc->usAttrID == pAttrMetaData[i].attrID)
                    {
                        VmDirStringCpyA( pAttr->metaData, VMDIR_MAX_ATTR_META_DATA_LEN, pAttrMetaData[i].metaData );
                        pAttrMetaData[i].metaData[0] = '\0';
                    }
                }
            }
        }

        retVal = WriteAttributes( pOperation, pSrEntry, iSearchReqSpecialChars , ber, &pszLocalErrorMsg );
        BAIL_ON_VMDIR_ERROR( retVal );

        if (attrMetaDataReqd)
        {
            retVal = WriteMetaDataAttribute( pOperation, pSrEntry->attrs, numAttrMetaData, pAttrMetaData, ber,
                                             &nonTrivialAttrsInReplScope, &pszLocalErrorMsg );
            BAIL_ON_VMDIR_ERROR( retVal );
        }

        if (ber_printf( ber, "N}N}" ) == -1)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                      "ber_printf (to terminate the entry and the complete search result entry message ...) failed" );
            retVal = LDAP_OTHER;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "Encoding terminating the entry failed.");
        }

        if ( pOperation->syncReqCtrl != NULL ) // Replication, => write Sync State Control
        {
            retVal = WriteSyncStateControl( pOperation, pSrEntry->attrs, ber, &pszLocalErrorMsg );
            BAIL_ON_VMDIR_ERROR( retVal );
        }

        if (ber_printf( ber, "N}" ) == -1)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                      "ber_printf (to terminate the entry and the complete search result entry message ...) failed" );;
            retVal = LDAP_OTHER;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "Encoding terminating the entry failed.");
        }

        if ((pOperation->syncReqCtrl == NULL) || (pOperation->syncReqCtrl != NULL && nonTrivialAttrsInReplScope ))
        {
            if (WriteBerOnSocket( pOperation->conn, ber ) != 0)
            {
                VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: WriteBerOnSocket failed." );
                retVal = LDAP_UNAVAILABLE;
                BAIL_ON_VMDIR_ERROR( retVal );
            }

            pSrEntry->bSearchEntrySent = TRUE;
            sr->iNumEntrySent++;

            VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Send entry: %s", pSrEntry->dn.lberbv.bv_val);
        }
        else
        {
            VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: NOT Sending entry: %s %p %d",
                            pSrEntry->dn.lberbv.bv_val, pOperation->syncReqCtrl, nonTrivialAttrsInReplScope);
        }

        // record max local usnChanged in syncControlDone
        if (pOperation->syncReqCtrl != NULL)
        {
            if (usnChanged  > pOperation->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed)
            {
                pOperation->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed = usnChanged;
            }
        }

        retVal = LDAP_SUCCESS;
    }

cleanup:
    if (bFreeBer)
    {
        ber_free_buf( ber );
    }
    VMDIR_SAFE_FREE_MEMORY( pAttrMetaData );
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return( retVal );

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                     "SendSearchEntry failed DN=(%s), (%u)(%s)",
                     (pSrEntry && pSrEntry->dn.lberbv.bv_val) ? pSrEntry->dn.lberbv.bv_val : "",
                     retVal, VDIR_SAFE_STRING( pszLocalErrorMsg));

    if ( !pOperation->ldapResult.pszErrMsg && pszLocalErrorMsg )
    {
        pOperation->ldapResult.pszErrMsg = pszLocalErrorMsg;
        pszLocalErrorMsg = NULL;
    }

    goto cleanup;
}
Пример #29
0
/*
 * Before modify schema cache, make sure new schema is valid.
 * 1. schema of pEntry must be live one
 * 2. create new schema instance via pEntry
 * 3. check active and new schema compatibility
 *    NOT compatible - reject this operation
 *    Compatible but NO semantic chnage - update schema entry
 *    Compatible and has semantic chnage - update schema entry and cache
 * 4. make new instance pending in gVdirSchemaGlobals
 */
DWORD
VmDirSchemaCacheModifyPrepare(
    PVDIR_OPERATION      pOperation,
    VDIR_MODIFICATION*   pMods,
    PVDIR_ENTRY          pSchemaEntry
    )
{
    DWORD dwError = 0;
    BOOLEAN                 bInLock = FALSE;
    PSTR                    pszLocalErrMsg = NULL;
    BOOLEAN                 bOwnNewInstance = FALSE;
    BOOLEAN                 bCompatible = FALSE;            // schema compatible
    BOOLEAN                 bNeedCachePatch = FALSE;        // schema semantic/cache change
    PVDIR_SCHEMA_INSTANCE   pNewInstance = NULL;            // DO NOT free, pEntry should take over it.
    PVDIR_SCHEMA_INSTANCE   pEntryOrgSchemaInstance = NULL;

    if ( !pMods || !pSchemaEntry || !pOperation )
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    {
        PVDIR_MODIFICATION  pLocalMods = NULL;
        PCSTR               immutableList[] = VDIR_IMMUTABLE_SCHEMA_ELEMENT_INITIALIZER;
        int                 iImmutableSize = sizeof(immutableList)/sizeof(immutableList[0]);

        for (pLocalMods = pMods; pLocalMods; pLocalMods = pLocalMods->next)
        {
            BOOLEAN bImmutableElement = _VmDirIsNameInCaseIgnoreList( pLocalMods->attr.pATDesc->pszName,
                                                                      immutableList,
                                                                      iImmutableSize);
            if ( bImmutableElement )
            {
                dwError = ERROR_OPERATION_NOT_PERMITTED;
                BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg,
                                             "modify (%s) not allowed", pLocalMods->attr.pATDesc->pszName);
            }
        }
    }

    // make sure pEntry uses live schema
    if (! vdirIsLiveSchema(pSchemaEntry->pSchemaCtx->pSchema))
    {
        dwError = LDAP_UNWILLING_TO_PERFORM;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "Out dated schema");
    }

    pEntryOrgSchemaInstance = pSchemaEntry->pSchemaCtx->pSchema;
    // instantiate a schema cache - pNewInstance
    // If this call succeed, do NOT free pNewInstance.  pEntry->pSchemaCtx takes it over.
    dwError = VdirSchemaInstanceInitViaEntry(   pSchemaEntry,
                                                &pNewInstance);
    if ( dwError != 0
         &&
         pSchemaEntry->pSchemaCtx->pSchema != pNewInstance )
    {
        // we still own pNewInstance and need to free it.
        bOwnNewInstance = TRUE;
    }
    BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "Entry to schema instance failed (%d)", dwError);

    // check if two instances are compatible and if schema patching is needed
    dwError = VmDirSchemaInstancePatchCheck( pEntryOrgSchemaInstance,
                                             pNewInstance,
                                             &bCompatible,
                                             &bNeedCachePatch);
    BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "VmDirSchemaInstancePatch (%d)", dwError);

    if ( !bCompatible )
    {
        dwError = LDAP_UNWILLING_TO_PERFORM;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "Schema NOT compatible (%d)", dwError);
    }

    if ( !bNeedCachePatch )
    {   // no semantic change, just update schema entry
        VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Prepare schema entry update");
    }
    else
    {   // need schema entry and cache update
        VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Prepare schema entry and instance update (%p)", pNewInstance);
    }

    VMDIR_LOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);
    if ( bNeedCachePatch )
    {
        gVdirSchemaGlobals.bHasPendingChange = TRUE;
    }
    VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);


cleanup:

    VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);

    return dwError;

error:

    if ( bOwnNewInstance )
    {
        VdirSchemaInstanceFree( pNewInstance );
    }

    VMDIR_SET_LDAP_RESULT_ERROR( &pOperation->ldapResult, dwError, pszLocalErrMsg );

    goto cleanup;
}
Пример #30
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;
}