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

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

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

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

        }
    }

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

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

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

error:
    VMDIR_APPEND_ERROR_MSG(pResult->pszErrMsg, pszLocalErrorMsg);
    goto cleanup;
}
Beispiel #2
0
/*
 * NormalizeMods:
 * 1. Normalize attribute values present in the modifications list.
 * 2. Make sure no duplicate value
 */
int
VmDirNormalizeMods(
    PVDIR_SCHEMA_CTX    pSchemaCtx,
    PVDIR_MODIFICATION  pMods,
    PSTR*               ppszErrorMsg
    )
{
    int            retVal = LDAP_SUCCESS;
    PVDIR_MODIFICATION pMod = NULL;
    unsigned int            i = 0;
    PSTR           pszDupAttributeName = NULL;
    PSTR           pszLocalErrorMsg = NULL;

    for (pMod = pMods; pMod != NULL; pMod = pMod->next)
    {
        if (pMod->attr.pATDesc == NULL
             &&
             (pMod->attr.pATDesc = VmDirSchemaAttrNameToDesc(pSchemaCtx, pMod->attr.type.lberbv.bv_val)) == NULL
           )
        {
            retVal = VMDIR_ERROR_UNDEFINED_TYPE;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg),
                                            "Undefined attribute (%s)",
                                            VDIR_SAFE_STRING(pMod->attr.type.lberbv.bv_val));
        }
        for (i=0; i < pMod->attr.numVals; i++)
        {
            retVal = VmDirSchemaBervalNormalize(pSchemaCtx, pMod->attr.pATDesc, &pMod->attr.vals[i]);
            BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg),
                        "attribute value normalization failed (%s)(%.*s)",
                        VDIR_SAFE_STRING(pMod->attr.pATDesc->pszName),
                        VMDIR_MIN(pMod->attr.vals[i].lberbv.bv_len, VMDIR_MAX_LOG_OUTPUT_LEN),
                        VDIR_SAFE_STRING(pMod->attr.vals[i].lberbv.bv_val));
        }

        // Make sure we have no duplicate value in mod->attr
        retVal = VmDirAttributeDupValueCheck(&pMod->attr, &pszDupAttributeName);
        BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg),
                                        "attribute (%s) has duplicate value",
                                        VDIR_SAFE_STRING(pszDupAttributeName));
    }

cleanup:

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

    return retVal;

error:
    goto cleanup;
}
Beispiel #3
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;
}
Beispiel #4
0
static
int
_VmDirInternalPagedSearch(
    VDIR_OPERATION *    pOperation
    )
{
    int     retVal = LDAP_SUCCESS;
    PSTR    pszLocalErrMsg = NULL;

    // should never happen - there are asserts in calling function
    if (pOperation == NULL)
    {
        BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_INVALID_PARAMETER);
    }

    /*
     * New page search
     * TODO: Iterator logic and ranking algorithm will be added in next tasks
     */
    if (pOperation->showPagedResultsCtrl != NULL &&
        IsNullOrEmptyString(pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie))
    {
        retVal = BuildCandidateList(pOperation, pOperation->request.searchReq.filter, 0);
        BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, pszLocalErrMsg, "BuildCandidateList failed.");

        if (pOperation->request.searchReq.filter->computeResult == FILTER_RES_TRUE)
        {
            retVal = VMDIR_ERROR_UNWILLING_TO_PERFORM;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(
                retVal,
                pszLocalErrMsg,
                "Full scan of Entry DB is required. Refine your search.");
        }
    }

    retVal = VmDirProcessPagedSearch(pOperation);
    BAIL_ON_VMDIR_ERROR(retVal);

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);
    return retVal;

error:
    VMDIR_LOG_ERROR(
            VMDIR_LOG_MASK_ALL,
            "%s failed, error(%d)",
            __FUNCTION__,
            retVal);
    goto cleanup;
}
Beispiel #5
0
static
int
_VmDirInternalNormalSearch(
    VDIR_OPERATION *    pOperation
    )
{
    int     retVal = LDAP_SUCCESS;
    PSTR    pszLocalErrMsg = NULL;
    ENTRYID eStartingId = 0;

    // should never happen - there are asserts in calling function
    if (pOperation == NULL)
    {
        BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_INVALID_PARAMETER);
    }

    retVal = BuildCandidateList(pOperation, pOperation->request.searchReq.filter, eStartingId);
    BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, pszLocalErrMsg, "BuildCandidateList failed.");

    if (pOperation->request.searchReq.filter->computeResult == FILTER_RES_TRUE)
    {
        retVal = VMDIR_ERROR_UNWILLING_TO_PERFORM;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(
            retVal,
            pszLocalErrMsg,
            "Full scan of Entry DB is required. Refine your search.");
    }

    retVal = VmDirProcessCandidateList(pOperation);
    BAIL_ON_VMDIR_ERROR_WITH_MSG(
        retVal,
        pszLocalErrMsg,
        "VmDirProcessCandidateList failed. (%u)(%s)",
        retVal,
        VDIR_SAFE_STRING(pOperation->ldapResult.pszErrMsg));

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);
    return retVal;

error:
    VMDIR_LOG_ERROR(
            VMDIR_LOG_MASK_ALL,
            "%s failed, error(%d)",
            __FUNCTION__,
            retVal);
    goto cleanup;
}
Beispiel #6
0
VOID
VdcadminReplNow(
    VOID
    )
{

    DWORD       dwError = 0;
    char        pszServerName[SIZE_256];
    PSTR        pszLocalErrorMsg = NULL;

    VmDirReadString(
        " Enter hostname to start replication cycle: ",
        pszServerName,
        SIZE_256,
        FALSE);

    dwError = VmDirReplNow( pszServerName );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, (pszLocalErrorMsg),
                "VdcadminReplNow: VmDirReplNow() call failed with error: %d", dwError  );

    printf( "VmDirReplNow passed\n");

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    return;

error:

    printf( "%s\n", pszLocalErrorMsg ? pszLocalErrorMsg : "Hmmm ... no local error message."  );
    goto cleanup;
}
Beispiel #7
0
int
VmDirMLDelete(
    PVDIR_OPERATION    pOperation
    )
{
    DWORD       dwError = 0;
    PSTR        pszLocalErrMsg = NULL;

    pOperation->pBECtx->pBE = VmDirBackendSelect(pOperation->reqDn.lberbv.bv_val);
    assert(pOperation->pBECtx->pBE);

    // AnonymousBind Or in case of a failed bind, do not grant delete access
    if (pOperation->conn->bIsAnonymousBind || VmDirIsFailedAccessInfo(&pOperation->conn->AccessInfo))
    {
        dwError = LDAP_INSUFFICIENT_ACCESS;
        BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrMsg, "Not bind/authenticate yet" );
    }

    dwError = VmDirInternalDeleteEntry( pOperation );
    BAIL_ON_VMDIR_ERROR( dwError );

cleanup:

    VmDirSendLdapResult( pOperation );

    VMDIR_SAFE_FREE_MEMORY( pszLocalErrMsg );

    return pOperation->ldapResult.errCode;

error:

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

    goto cleanup;
}
Beispiel #8
0
static
DWORD
_VmDirSchemaCheckNameform(
    PVDIR_SCHEMA_CTX        pCtx,
    PVDIR_ENTRY             pEntry,
    PVDIR_SCHEMA_OC_DESC    pStructOCDesc
    )
{
    DWORD       dwError = 0;
    PSTR        pszLocalErrorMsg = NULL;

    if ( !pCtx || !pStructOCDesc || !pEntry || !pEntry->dn.bvnorm_val )
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

#if 0

    // should NOT enable this until we have all namform and structure rule defined
    if ( pStructOCDesc->usNumMustRDNs > 0 )
    {   // not yet support multi RDNs case.  only check the first MUST RDN for now.
        size_t  iLen = VmDirStringLenA(pStructOCDesc->ppszMustRDNs[0]);

        if ( VmDirStringNCompareA( pEntry->dn.bvnorm_val,
                                   pStructOCDesc->ppszMustRDNs[0],
                                   iLen,
                                   FALSE ) != 0
             ||
             pEntry->dn.bvnorm_val[iLen] != '='
           )
        {
            dwError = ERROR_INVALID_ENTRY;
            BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrorMsg,
                                          "_VmDirSchemaCheckNameform: rdn must be (%s). (%d)",
                                          VDIR_SAFE_STRING( pStructOCDesc->ppszMustRDNs[0] ), dwError );
        }
    }

#endif

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return dwError;

error:

    if ( !pCtx->pszErrorMsg )
    {
        pCtx->pszErrorMsg = pszLocalErrorMsg;
        pszLocalErrorMsg = NULL;

        pCtx->dwErrorCode = dwError;
    }

    goto cleanup;
}
Beispiel #9
0
static
int
_ParseCondWriteControlVal(
    VDIR_OPERATION *                        pOp,
    BerValue *                              pControlBer,    // Input: control value encoded as ber
    VDIR_CONDWRITE_CONTROL_VALUE *          pCtrlVal,       // Output
    VDIR_LDAP_RESULT *                      pLdapResult     // Output
    )
{
    int                 retVal = LDAP_SUCCESS;
    BerElementBuffer    berbuf;
    BerElement *        ber = (BerElement *)&berbuf;
    PSTR                pszLocalErrorMsg = NULL;
    PSTR                pszCondFilter = NULL;

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

    ber_init2( ber, pControlBer, LBER_USE_DER );

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

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

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

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

    return retVal;

error:
    VMDIR_APPEND_ERROR_MSG(pLdapResult->pszErrMsg, pszLocalErrorMsg);
    goto cleanup;
}
Beispiel #10
0
int
VmDirMLModify(
    PVDIR_OPERATION pOperation
    )
{
    DWORD   dwError = 0;
    PSTR    pszLocalErrMsg = NULL;

    pOperation->pBECtx->pBE = VmDirBackendSelect(pOperation->request.modifyReq.dn.lberbv.bv_val);
    assert(pOperation->pBECtx->pBE);

    // AnonymousBind Or in case of a failed bind, do not grant modify access
    if (pOperation->conn->bIsAnonymousBind || VmDirIsFailedAccessInfo(&pOperation->conn->AccessInfo))
    {
        dwError = LDAP_INSUFFICIENT_ACCESS;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(
                dwError, pszLocalErrMsg,
                "Not bind/authenticate yet");
    }

    if (!VmDirValidTxnState(pOperation->pBECtx, pOperation->reqCode))
    {
       dwError = LDAP_UNWILLING_TO_PERFORM;
       BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg,
                "%s: invaid request for transaction state", __func__);
    }

    // Mod request sanity check
    dwError = _VmDirExternalModsSanityCheck(pOperation, pOperation->request.modifyReq.mods);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirInternalModifyEntry(pOperation);
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);
    return pOperation->ldapResult.errCode;

error:
    VMDIR_SET_LDAP_RESULT_ERROR(&(pOperation->ldapResult), dwError, pszLocalErrMsg);
    goto cleanup;
}
Beispiel #11
0
VOID
VdcadminSetVmdirState(
    VOID
    )
{
    DWORD       dwError = 0;
    char        pszState[SIZE_256] = {0};
    PSTR        pszLocalErrorMsg = NULL;
    PVMDIR_SERVER_CONTEXT hServer = NULL;
    VDIR_SERVER_STATE vmdirState = VMDIRD_STATE_NORMAL;

    VmDirReadString(
        "Enter state (NORMAL|READ_ONLY): ",
        pszState,
        SIZE_256,
        FALSE);

    if ( VmDirStringCompareA( pszState, "NORMAL", FALSE) == 0 )
    {
        vmdirState = VMDIRD_STATE_NORMAL;
    }
    else if ( VmDirStringCompareA( pszState, "READ_ONLY", FALSE) == 0 )
    {
        vmdirState = VMDIRD_STATE_READ_ONLY;
    }
    else
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    if (g_hServer)
    {
        hServer = g_hServer;
    }

    dwError = VmDirSetState(hServer, vmdirState );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, (pszLocalErrorMsg),
                                  "VmDirSetState() failed. error(%u)", dwError );

    printf("\n\n State of Vmdir set to %s\n\n", pszState);

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return;

error:

    printf("\n SetVmDirState failed: %s\n", VDIR_SAFE_STRING(pszLocalErrorMsg));

    goto cleanup;
}
Beispiel #12
0
// Protects key from being created more than once
static
VOID
_VmDirInitThreadContextOnce(VOID)
{
    DWORD dwError = 0;
    PSTR pszLocalErrorMsg = NULL;

    dwError = pthread_key_create(&pThreadContext->threadLogContext, NULL);
    BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, (pszLocalErrorMsg), "pthread_key_create failed on threadLogContext");

    dwError = pthread_key_create(&pThreadContext->threadTxnContext, NULL);
    BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, (pszLocalErrorMsg), "pthread_key_create failed on threadTxnContext");

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    return;

error:
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "%s: %s errcode %d", __func__, VDIR_SAFE_STRING(pszLocalErrorMsg), dwError);
    VMDIR_SAFE_FREE_MEMORY(pThreadContext);
    goto cleanup;
}
Beispiel #13
0
/*
 * Called during entry add
 *
 *  grouptype :
 *
        http://msdn.microsoft.com/en-us/library/windows/desktop/ms675935%28v=vs.85%29.aspx
        Value   Description
        1 (0x00000001)  Specifies a group that is created by the system.
        2 (0x00000002)  Specifies a group with global scope.
        4 (0x00000004)  Specifies a group with domain local scope.
        8 (0x00000008)  Specifies a group with universal scope.
        16 (0x00000010) Specifies an APP_BASIC group for Windows Server Authorization Manager.
        32 (0x00000020) Specifies an APP_QUERY group for Windows Server Authorization Manager.
        2147483648 (0x80000000) Specifies a security group. If this flag is not set, then the group is a distribution group.

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

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

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

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return dwError;

error:

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

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

    goto cleanup;
}
Beispiel #14
0
static
DWORD
AddAttrValsToEntryStruct(
   VDIR_ENTRY *     e,
   VDIR_ATTRIBUTE * eAttr,    // Entry attribute to be updated with new attribute values
   VDIR_ATTRIBUTE * modAttr,  // Modify attribute containing new attribute values
   PSTR*            ppszErrMsg
   )
{
    unsigned int     i = 0;
    unsigned int     j = 0;
    DWORD   dwError = ERROR_SUCCESS;
    PSTR    pszErrMsg = NULL;

    assert(e->allocType == ENTRY_STORAGE_FORMAT_NORMAL);

    if ((size_t)eAttr->numVals + (size_t)modAttr->numVals > UINT16_MAX)
    {
        dwError = VMDIR_ERROR_DATA_CONSTRAINT_VIOLATION;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, (pszErrMsg),
                                      "Too many %s attribute values, max %u allowed.",
                                      VDIR_SAFE_STRING(eAttr->type.lberbv_val), UINT16_MAX);
    }

    dwError = VmDirReallocateMemoryWithInit(eAttr->vals, (PVOID*)(&(eAttr->vals)),
                                             (eAttr->numVals + modAttr->numVals + 1) * sizeof(VDIR_BERVALUE),
                                             (eAttr->numVals + 1) * sizeof(VDIR_BERVALUE));
    BAIL_ON_VMDIR_ERROR(dwError);

    for (i = 0, j = eAttr->numVals; i < modAttr->numVals; i++, j++)
    {
        dwError = VmDirBervalContentDup(&modAttr->vals[i], &eAttr->vals[j]);
        BAIL_ON_VMDIR_ERROR(dwError);
    }
    memset(&(eAttr->vals[j]), 0, sizeof(VDIR_BERVALUE)); // set last BerValue.lberbv.bv_val to NULL;
    eAttr->numVals += modAttr->numVals;

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszErrMsg);
    return dwError;

error:
    if (ppszErrMsg)
    {
        *ppszErrMsg = pszErrMsg;
        pszErrMsg = NULL;
    }

    goto cleanup;
}
Beispiel #15
0
VOID
VdcadminGetVmdirState(
    VOID
    )
{
    DWORD       dwError = 0;
    PCSTR       pszState = NULL;
    PSTR        pszLocalErrorMsg = NULL;
    PVMDIR_SERVER_CONTEXT hServer = NULL;
    UINT32      vmdirState = 0;


    if (g_hServer)
    {
        hServer = g_hServer;
    }

    dwError = VmDirGetState(hServer, &vmdirState );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, (pszLocalErrorMsg),
                                  "VmDirGetState() failed. error(%u)", dwError );

    switch (vmdirState)
    {
        case VMDIRD_STATE_UNDEFINED: pszState = "Undefined"; break;
        case VMDIRD_STATE_STARTUP:   pszState = "Startup"; break;
        case VMDIRD_STATE_READ_ONLY: pszState = "Read only"; break;
        case VMDIRD_STATE_NORMAL:    pszState = "Normal" ; break;
        case VMDIRD_STATE_SHUTDOWN:  pszState = "Shutdown"; break;
    }
    printf("\n\n VmDir State is - %s\n\n", pszState);

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return;

error:

    printf("\n GetVmDirState failed: %s\n", VDIR_SAFE_STRING(pszLocalErrorMsg));

    goto cleanup;
}
Beispiel #16
0
int
VmDirMLDelete(
    PVDIR_OPERATION    pOperation
    )
{
    DWORD   dwError = 0;
    PSTR    pszLocalErrMsg = NULL;

    pOperation->pBECtx->pBE = VmDirBackendSelect(pOperation->reqDn.lberbv.bv_val);
    assert(pOperation->pBECtx->pBE);

    // AnonymousBind Or in case of a failed bind, do not grant delete access
    if (pOperation->conn->bIsAnonymousBind || VmDirIsFailedAccessInfo(&pOperation->conn->AccessInfo))
    {
        dwError = LDAP_INSUFFICIENT_ACCESS;
        BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrMsg, "Not bind/authenticate yet" );
    }

    if (VmDirRaftDisallowUpdates("Delete"))
    {
        dwError = VMDIR_ERROR_UNWILLING_TO_PERFORM;
        BAIL_ON_VMDIR_ERROR( dwError );
    }

    dwError = VmDirInternalDeleteEntry( pOperation );
    BAIL_ON_VMDIR_ERROR( dwError );

    if (pOperation->opType == VDIR_OPERATION_TYPE_EXTERNAL)
    {
        pOperation->pBEIF->pfnBESetMaxOriginatingUSN(pOperation->pBECtx,
                                                     pOperation->pBECtx->wTxnUSN);
    }

cleanup:
    VMDIR_SAFE_FREE_MEMORY( pszLocalErrMsg );
    return pOperation->ldapResult.errCode;

error:
    VMDIR_SET_LDAP_RESULT_ERROR( &(pOperation->ldapResult), dwError, pszLocalErrMsg);
    goto cleanup;
}
Beispiel #17
0
int
VmDirMLSearch(
    PVDIR_OPERATION pOperation
    )
{
    int     retVal = 0;
    PSTR    pszLocalErrMsg = NULL;

    pOperation->pBEIF = VmDirBackendSelect(pOperation->reqDn.lberbv.bv_val);
    assert(pOperation->pBEIF);

    if (pOperation->conn->bIsAnonymousBind && !VmDirIsSearchForDseRootEntry( pOperation ))
    {
        retVal = LDAP_INSUFFICIENT_ACCESS;
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "Not bind/authenticate yet" );
    }

    // AnonymousBind is handled when retrieving search candidate result
    // DSE_ROOT_DN and PERSISTED_DSE_ROOT_DN, SCHEMA_NAMING_CONTEXT_DN
    // SUB_SCHEMA_SUB_ENTRY_DN should allow anonymous bind READ
    retVal = VmDirInternalSearch( pOperation);
    BAIL_ON_VMDIR_ERROR(retVal);

cleanup:

    VmDirSendLdapResult( pOperation );

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);

    return pOperation->ldapResult.errCode;

error:

    VMDIR_SET_LDAP_RESULT_ERROR( &(pOperation->ldapResult), retVal, pszLocalErrMsg);
    goto cleanup;
}
Beispiel #18
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;
}
Beispiel #19
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;
}
Beispiel #20
0
/* InternalSearch: Interface that can be used "internally" by the server code. One of the main differences between
 * this function and MLSearch is that this function does not send back an LDAP result to the client.
 *
 * Return: VmDir level error code.  Also, pOperation->ldapResult content is set.
 */
int
VmDirInternalSearch(
    PVDIR_OPERATION pOperation
    )
{
    int     retVal = LDAP_SUCCESS;
    DWORD   dwEntryCount = 0;
    BOOLEAN bHasTxn = FALSE;
    PSTR    pszLocalErrMsg = NULL;
    ENTRYID     eId = 0;
    ENTRYID*    pValidatedEntries = NULL;
    PVDIR_LDAP_RESULT   pResult = &(pOperation->ldapResult);
    PVDIR_OPERATION_ML_METRIC  pMLMetrics = NULL;

    assert(pOperation && pOperation->pBEIF);

    pMLMetrics = &pOperation->MLMetrics;
    VMDIR_COLLECT_TIME(pMLMetrics->iMLStartTime);

    // compute required access for this search
    ComputeRequiredAccess(&pOperation->request.searchReq);

    // Normalize (base) DN
    retVal = VmDirNormalizeDN( &(pOperation->reqDn), pOperation->pSchemaCtx );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "DN normalization failed - (%u)(%s)",
                                  retVal, VDIR_SAFE_STRING(VmDirSchemaCtxGetErrorMsg(pOperation->pSchemaCtx)) );

    if (VmDirHandleSpecialSearch( pOperation, pResult )) // TODO, add &pszLocalErrMsg
    {
        retVal = pResult->errCode ? pResult->errCode : pResult->vmdirErrCode;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, pszLocalErrMsg, "Special search failed - (%u)", retVal);

        goto cleanup;  // done special search
    }

    if (pOperation->dbCopyCtrl) {
        retVal = VmDirExecDbCopyCtrl(pOperation);
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    if (pOperation->syncReqCtrl != NULL) // Replication
    {
        pOperation->opType = VDIR_OPERATION_TYPE_REPL;
    }

    if (pOperation->pReplAgrDisableCtrl)
    {
        retVal = VmDirExecReplAgrEnableDisableCtrl(BERVAL_NORM_VAL(pOperation->reqDn), FALSE);
        BAIL_ON_VMDIR_ERROR(retVal);
    }
    else if (pOperation->pReplAgrEnableCtrl)
    {
        retVal = VmDirExecReplAgrEnableDisableCtrl(BERVAL_NORM_VAL(pOperation->reqDn), TRUE);
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    // If base is not ROOT, read lock the base object (DnToEntryId index entry) to make sure it exists, and it does
    // not get deleted during this search processing.
    if (pOperation->reqDn.lberbv.bv_len != 0)
    {
        VMDIR_COLLECT_TIME(pMLMetrics->iBETxnBeginStartTime);

        retVal = pOperation->pBEIF->pfnBETxnBegin( pOperation->pBECtx, VDIR_BACKEND_TXN_READ );
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "txn begin (%u)(%s)",
                retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));
        bHasTxn = TRUE;

        VMDIR_COLLECT_TIME(pMLMetrics->iBETxnBeginEndTime);

        // Lookup in the DN index.
        retVal = pOperation->pBEIF->pfnBEDNToEntryId( pOperation->pBECtx, &(pOperation->reqDn), &eId );
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "DNToEID (%u)(%s)",
                retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));
    }

    // start txn if not has one already.
    if (! pOperation->pBECtx->pBEPrivate)
    {
        retVal = pOperation->pBEIF->pfnBETxnBegin( pOperation->pBECtx, VDIR_BACKEND_TXN_READ );
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "txn begin (%u)(%s)",
                                      retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));
        bHasTxn = TRUE;
    }

    retVal = AppendDNFilter( pOperation );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "Appending DN filter failed.");

    /*
     * TODO cleanup During background thread implementation of page search
     */
    if (gVmdirGlobals.bPagedSearchReadAhead)
    {
        if (pOperation->showPagedResultsCtrl != NULL &&
            !IsNullOrEmptyString(pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie))
        {
            retVal = VmDirPagedSearchCacheRead(
                        pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie,
                        &pValidatedEntries,
                        &dwEntryCount);
            BAIL_ON_VMDIR_ERROR(retVal);
        }
    }

    if (pOperation->showPagedResultsCtrl == NULL)
    {
        retVal = _VmDirInternalNormalSearch(pOperation);
        BAIL_ON_VMDIR_ERROR(retVal);
    }
    else
    {
        retVal = _VmDirInternalPagedSearch(pOperation);
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    /*
     * TODO cleanup During background thread implementation of page search
     */
    if (pValidatedEntries != NULL)
    {
        retVal = ProcessPreValidatedEntries(
                    pOperation,
                    dwEntryCount,
                    pValidatedEntries);
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    VMDIR_COLLECT_TIME(pMLMetrics->iBETxnCommitStartTime);

    retVal = pOperation->pBEIF->pfnBETxnCommit( pOperation->pBECtx);
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "txn commit (%u)(%s)",
                                  retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));
    bHasTxn = FALSE;

    VMDIR_COLLECT_TIME(pMLMetrics->iBETxnCommitEndTime);

cleanup:

    // collect metrics
    VMDIR_COLLECT_TIME(pMLMetrics->iMLEndTime);
    VmDirInternalMetricsUpdate(pOperation);
    VmDirInternalMetricsLogInefficientOp(pOperation);

    VMDIR_SAFE_FREE_MEMORY(pValidatedEntries);
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);
    return retVal;

error:

    if (bHasTxn)
    {
        pOperation->pBEIF->pfnBETxnAbort(pOperation->pBECtx);
    }

    VMDIR_SET_LDAP_RESULT_ERROR(&pOperation->ldapResult, retVal, pszLocalErrMsg);
    goto cleanup;
}
Beispiel #21
0
/*
 * Test whether the origUsn is in scope so that attribute, attr-meta-data or
 * attr-value-meta-data be sent back to the replicaiton consumer based on whether
 * the origUsn for that invocationId has been processed already by the consumer
 * TODO: Needed Refractoring
 */
DWORD
VmDirIsUsnInScope(
    PVDIR_OPERATION     pOperation,
    PCSTR               pAttrName,
    PCSTR               pszOrigInvocationId,
    USN                 origUsn,
    USN                 localUSN,
    USN                 priorSentUSNCreated,
    PBOOLEAN            pbIsUsnInScope
    )
{
    DWORD                   dwError = 0;
    PLW_HASHTABLE_NODE      pNode = NULL;
    PSTR                    pszLocalErrorMsg = NULL;
    UptoDateVectorEntry     *pUtdVectorEntry = NULL;
    UptoDateVectorEntry     *pNewUtdVectorEntry = NULL;
    int                     retVal = 0;

    if (!pOperation ||
        !pszOrigInvocationId ||
        !pbIsUsnInScope ||
        !pOperation->syncReqCtrl ||
        !pOperation->syncDoneCtrl)
    {
        BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER);
    }

    *pbIsUsnInScope = FALSE;

    //Originating server for the current state is same as the requesting server
    if (VmDirStringCompareA(
                pszOrigInvocationId,
                pOperation->syncReqCtrl->value.syncReqCtrlVal.reqInvocationId.lberbv.bv_val,
                TRUE) == 0)
    {
        *pbIsUsnInScope = FALSE;
        goto cleanup;
    }

    retVal = LwRtlHashTableFindKey(
            pOperation->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &pNode, pszOrigInvocationId);

    retVal = LwNtStatusToWin32Error(retVal);

    if (retVal != 0 && retVal != ERROR_NOT_FOUND)
    {
        VMDIR_LOG_VERBOSE(
                VMDIR_LOG_MASK_ALL,
                "%s: LwRtlHashTableFindKey failed for origInvocationId: %s",
                __FUNCTION__,
                pszOrigInvocationId);
        dwError = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, (pszLocalErrorMsg), "LwRtlHashTableFindKey failed.");
    }

    if (pNode == NULL)
    {
        VDIR_BERVALUE    bvServerId = VDIR_BERVALUE_INIT;

        dwError = VmDirAllocateMemory(sizeof(UptoDateVectorEntry), (PVOID *)&pNewUtdVectorEntry);
        BAIL_ON_VMDIR_ERROR(dwError);

        bvServerId.lberbv.bv_val = (PSTR)pszOrigInvocationId;
        bvServerId.lberbv.bv_len = VmDirStringLenA(pszOrigInvocationId);

        dwError = VmDirBervalContentDup(&bvServerId, &pNewUtdVectorEntry->invocationId);
        BAIL_ON_VMDIR_ERROR(dwError);

        pNewUtdVectorEntry->currMaxOrigUsnProcessed = origUsn;

        LwRtlHashTableResizeAndInsert(
                pOperation->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector,
                &pNewUtdVectorEntry->Node,
                &pNode);

        // assert the key of added node is unique
        assert(pNode == NULL);

        pNewUtdVectorEntry = NULL;
        *pbIsUsnInScope = TRUE;

        goto cleanup;
    }

    pUtdVectorEntry = (UptoDateVectorEntry *)LW_STRUCT_FROM_FIELD(pNode, UptoDateVectorEntry, Node);

    if (origUsn > pUtdVectorEntry->reqLastOrigUsnProcessed )
    {
        // attribute or the valueMetaData item in scope if origUsn valueMetaData is > the current highest
        if (origUsn > pUtdVectorEntry->currMaxOrigUsnProcessed )
        {
            pUtdVectorEntry->currMaxOrigUsnProcessed = origUsn;
        }

        // Note, this handles ADD->MODIFY case but not multiple MODIFYs scenario.
        // However, it is fine as consumer should be able to handle redundant feed from supplier.
        // The key point here is to NOT send ATTR_USN_CREATED, so we can derive correct sync_state in WriteSyncStateControl.
        if (localUSN > priorSentUSNCreated)
        {
            *pbIsUsnInScope = TRUE;

            if (priorSentUSNCreated > 0)
            {
                VMDIR_LOG_INFO(
                        LDAP_DEBUG_REPL,
                        "%s new usn %llu after prior usncreated %llu attr %s",
                        __FUNCTION__,
                        origUsn,
                        priorSentUSNCreated,
                        VDIR_SAFE_STRING(pAttrName));
            }
        }
        else
        {
            VMDIR_LOG_INFO(
                    LDAP_DEBUG_REPL,
                    "%s (add->modify) race condition avoided. skip prior usncreated %llu attr %s",
                    __FUNCTION__,
                    priorSentUSNCreated,
                    VDIR_SAFE_STRING(pAttrName));
        }

        goto cleanup;
    }

    VMDIR_LOG_INFO(
            LDAP_DEBUG_REPL,
            "%s: (not in scope) attr name: %s orig invo: %s utdUsn: %"PRId64" usn: %"PRId64,
            __FUNCTION__,
            VDIR_SAFE_STRING(pAttrName),
            VDIR_SAFE_STRING(pszOrigInvocationId),
            pUtdVectorEntry->reqLastOrigUsnProcessed,
            origUsn);

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    return dwError;

error:
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError);
    if (pNewUtdVectorEntry)
    {
        VmDirFreeBervalContent(&pNewUtdVectorEntry->invocationId);
    }
    VMDIR_SAFE_FREE_MEMORY(pNewUtdVectorEntry);
    goto cleanup;
}
Beispiel #22
0
static
int
BindListenOnPort(
#ifndef _WIN32
   sa_family_t   addr_type,
   size_t        addr_size,
#else
   short         addr_type,
   int           addr_size,
#endif
    void         *pServ_addr,
    ber_socket_t *pSockfd
)
{
#define LDAP_PORT_LISTEN_BACKLOG 128
   int  optname = 0;
   int  retVal = LDAP_SUCCESS;
   int  retValBind = 0;
   PSTR pszLocalErrMsg = NULL;
   int  on = 1;
#ifdef _WIN32
   DWORD sTimeout = 0;
   int  reTries = 0;
#else
   struct timeval sTimeout = {0};
#endif

   *pSockfd = -1;
   *pSockfd = socket(addr_type, SOCK_STREAM, 0);
   if (*pSockfd < 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: socket() call failed with errno: %d", __func__, errno );
   }

#ifdef _WIN32
    optname = SO_EXCLUSIVEADDRUSE;
#else
    optname = SO_REUSEADDR;
#endif

   if (setsockopt(*pSockfd, SOL_SOCKET, optname, (const char *)(&on), sizeof(on)) < 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() call failed with errno: %d", __func__, errno );
   }

   on = 1;  // turn on TCP_NODELAY below

   if (setsockopt(*pSockfd,  IPPROTO_TCP, TCP_NODELAY, (const char *)(&on), sizeof(on) ) < 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() TCP_NODELAY call failed with errno: %d", __func__, errno );
   }

   if (addr_type == AF_INET6)
   {
#ifdef _WIN32
       if (setsockopt(*pSockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)(&on), sizeof(on) ) < 0)
       {
           errno = WSAGetLastError();
#else
       if (setsockopt(*pSockfd, SOL_IPV6, IPV6_V6ONLY, (const char *)(&on), sizeof(on) ) < 0)
       {
#endif
           retVal = LDAP_OPERATIONS_ERROR;
           BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() IPV6_V6ONLY call failed with errno: %d", __func__, errno );
       }
   }

   if (gVmdirGlobals.dwLdapRecvTimeoutSec > 0)
   {
#ifdef _WIN32
       sTimeout = gVmdirGlobals.dwLdapRecvTimeoutSec*1000;
#else
       sTimeout.tv_sec = gVmdirGlobals.dwLdapRecvTimeoutSec;
       sTimeout.tv_usec = 0;
#endif
       if (setsockopt(*pSockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &sTimeout, sizeof(sTimeout)) < 0)
       {
#ifdef _WIN32
           errno = WSAGetLastError();
#endif
           retVal = LDAP_OPERATIONS_ERROR;
           BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() SO_RCVTIMEO failed, errno: %d", __func__, errno );
       }
   }

   retValBind = bind(*pSockfd, (struct sockaddr *) pServ_addr, addr_size);

#ifdef _WIN32
   // Add retry logic per PR 1347783
   reTries = 0;
   while (retValBind != 0 && reTries < MAX_NUM_OF_BIND_PORT_RETRIES)
   {
      errno = WSAGetLastError();
      if (errno != WSAEADDRINUSE)
      {
         break;
      }
      reTries++;
      VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "%s: bind() call failed with errno: %d, re-trying (%d)",
                                   __func__, errno, reTries);
      VmDirSleep(1000);
      retValBind = bind(*pSockfd, (struct sockaddr *) pServ_addr, addr_size);
   }
#endif

   if (retValBind != 0)
   {
      retVal = LDAP_OPERATIONS_ERROR;
      //need to free socket ...
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: bind() call failed with errno: %d", __func__, errno );
   }

   if (listen(*pSockfd, LDAP_PORT_LISTEN_BACKLOG) != 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: listen() call failed with errno: %d", __func__, errno );
   }

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);
    return retVal;

error:

    if (*pSockfd >= 0)
    {
        tcp_close(*pSockfd);
        *pSockfd = -1;
    }
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, VDIR_SAFE_STRING(pszLocalErrMsg));
    goto cleanup;
}

/*
 *  We own pConnection and delete it when done.
 */
static
DWORD
ProcessAConnection(
   PVOID pArg
   )
{
   VDIR_CONNECTION *pConn = NULL;
   int            retVal = LDAP_SUCCESS;
   ber_tag_t      tag = LBER_ERROR;
   ber_len_t      len = 0;
   BerElement *   ber = NULL;
   ber_int_t      msgid = -1;
   PVDIR_OPERATION pOperation = NULL;
   int            reTries = 0;
   BOOLEAN                      bDownOpThrCount = FALSE;
   PVDIR_CONNECTION_CTX pConnCtx = NULL;

   // increment operation thread counter
   retVal = VmDirSyncCounterIncrement(gVmdirGlobals.pOperationThrSyncCounter);
   BAIL_ON_VMDIR_ERROR(retVal);
   bDownOpThrCount = TRUE;

   pConnCtx = (PVDIR_CONNECTION_CTX)pArg;
   assert(pConnCtx);

   retVal = NewConnection(pConnCtx->sockFd, &pConn, pConnCtx->pSockbuf_IO);
   if (retVal != LDAP_SUCCESS)
   {
       VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: NewConnection [%d] failed with error: %d",
                        __func__, pConnCtx->sockFd, retVal);
       goto error;
   }

   while (TRUE)
   {
       if (VmDirdState() == VMDIRD_STATE_SHUTDOWN)
       {
           goto cleanup;
       }

      ber = ber_alloc();
      assert( ber != NULL);

      /* An LDAP request message looks like:
       * LDAPMessage ::= SEQUENCE {
       *                    messageID       MessageID,
       *                    protocolOp      CHOICE {
       *                       bindRequest     BindRequest,
       *                       unbindRequest   UnbindRequest,
       *                       searchRequest   SearchRequest,
       *                       ... },
       *                       controls       [0] Controls OPTIONAL }
       */


      // reset retry count
      reTries = 0;
      // Read complete LDAP request message (tag, length, and real message).
      while( reTries < MAX_NUM_OF_SOCK_READ_RETRIES )
      {
         if ((tag = ber_get_next( pConn->sb, &len, ber )) == LDAP_TAG_MESSAGE )
         {
            break;
         }

#ifdef _WIN32
         // in ber_get_next (liblber) call, sock_errset() call WSASetLastError()
         errno = WSAGetLastError();
         if ( errno == EWOULDBLOCK || errno == EAGAIN || errno == WSAETIMEDOUT)
#else
         if ( errno == EWOULDBLOCK || errno == EAGAIN)
#endif
         {
            if (gVmdirGlobals.dwLdapRecvTimeoutSec > 0 && ber->ber_len == 0)
            {
                VMDIR_LOG_INFO( LDAP_DEBUG_CONNS,
                    "%s: disconnecting peer (%s), idle > %d seconds",
                    __func__, pConn->szClientIP, gVmdirGlobals.dwLdapRecvTimeoutSec);
                retVal = LDAP_NOTICE_OF_DISCONNECT;
                BAIL_ON_VMDIR_ERROR( retVal );
            }

            //This may occur when not all data have recieved - set to EAGAIN/EWOULDBLOCK by ber_get_next,
            // and in such case ber->ber_len > 0;
            if (reTries > 0 && reTries % 5 == 0)
            {
                VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "%s: ber_get_next() failed with errno = %d, peer (%s), re-trying (%d)",
                                   __func__, errno , pConn->szClientIP, reTries);
            }
            VmDirSleep(200);
            reTries++;
            continue;
         }
         // Unexpected error case.
         if (errno == 0)
         {
             VMDIR_LOG_INFO( LDAP_DEBUG_CONNS, "%s: ber_get_next() peer (%s) disconnected",
                 __func__, pConn->szClientIP);
         } else
         {
             VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: ber_get_next() call failed with errno = %d peer (%s)",
                  __func__, errno, pConn->szClientIP);
         }
         retVal = LDAP_NOTICE_OF_DISCONNECT;
         BAIL_ON_VMDIR_ERROR( retVal );
      }

      // Read LDAP request messageID (tag, length (not returned since it is implicit/integer), and messageID value)
      if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID )
      {
         VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessAConnection: ber_get_int() call failed." );
         retVal = LDAP_NOTICE_OF_DISCONNECT;
         BAIL_ON_VMDIR_ERROR( retVal );
      }

      // Read protocolOp (tag) and length of the LDAP operation message, and leave the pointer at the beginning
      // of the LDAP operation message (to be parsed by PerformXYZ methods).
      if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR )
      {
         VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessAConnection: ber_peek_tag() call failed." );
         retVal = LDAP_NOTICE_OF_DISCONNECT;
         BAIL_ON_VMDIR_ERROR( retVal );
      }

      retVal = VmDirNewOperation(ber, msgid, tag, pConn, &pOperation);
      if (retVal)
      {
          VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessAConnection: NewOperation() call failed." );
          retVal = LDAP_OPERATIONS_ERROR;
      }
      BAIL_ON_VMDIR_ERROR( retVal );

      //
      // If this is a multi-stage operation don't overwrite the start time if it's already set.
      //
      pConn->SuperLogRec.iStartTime = pConn->SuperLogRec.iStartTime ? pConn->SuperLogRec.iStartTime : VmDirGetTimeInMilliSec();

      switch (tag)
      {
         case LDAP_REQ_BIND:
            retVal = VmDirPerformBind(pOperation);
            if (retVal != LDAP_SASL_BIND_IN_PROGRESS)
            {
                _VmDirCollectBindSuperLog(pConn, pOperation); // ignore error
            }

            break;

         case LDAP_REQ_ADD:
            retVal = VmDirPerformAdd(pOperation);
            break;

         case LDAP_REQ_SEARCH:
            retVal = VmDirPerformSearch(pOperation);
            break;

         case LDAP_REQ_UNBIND:
            retVal = VmDirPerformUnbind(pOperation);
            break;

         case LDAP_REQ_MODIFY:
             retVal = VmDirPerformModify(pOperation);
             break;

         case LDAP_REQ_DELETE:
             retVal = VmDirPerformDelete(pOperation);
             break;

         case LDAP_REQ_MODDN:
         case LDAP_REQ_COMPARE:
         case LDAP_REQ_ABANDON:
         case LDAP_REQ_EXTENDED:
            VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "ProcessAConnection: Operation is not yet implemented.." );
            pOperation->ldapResult.errCode = retVal = LDAP_UNWILLING_TO_PERFORM;
            // ignore following VmDirAllocateStringA error.
            VmDirAllocateStringA( "Operation is not yet implemented.", &pOperation->ldapResult.pszErrMsg);
            VmDirSendLdapResult( pOperation );
            break;

         default:
            pOperation->ldapResult.errCode = LDAP_PROTOCOL_ERROR;
            retVal = LDAP_NOTICE_OF_DISCONNECT;
            break;
      }

      pConn->SuperLogRec.iEndTime = VmDirGetTimeInMilliSec();
      VmDirOPStatisticUpdate(tag, pConn->SuperLogRec.iEndTime - pConn->SuperLogRec.iStartTime);

      if (tag != LDAP_REQ_BIND)
      {
         VmDirLogOperation(gVmdirGlobals.pLogger, tag, pConn, pOperation->ldapResult.errCode);

         _VmDirScrubSuperLogContent(tag, &pConn->SuperLogRec);
      }

      VmDirFreeOperation(pOperation);
      pOperation = NULL;

      ber_free( ber, 1);
      ber = NULL;

      if (retVal == LDAP_NOTICE_OF_DISCONNECT) // returned as a result of protocol parsing error.
      {
         // RFC 4511, section 4.1.1: If the server receives an LDAPMessage from the client in which the LDAPMessage
         // SEQUENCE tag cannot be recognized, the messageID cannot be parsed, the tag of the protocolOp is not
         // recognized as a request, or the encoding structures or lengths of data fields are found to be incorrect,
         // then the server **SHOULD** return the Notice of Disconnection, with the resultCode
         // set to protocolError, and **MUST** immediately terminate the LDAP session as described in Section 5.3.

         goto cleanup;
      }
   }

cleanup:
   if (retVal == LDAP_NOTICE_OF_DISCONNECT)
   {
      // Optionally send Notice of Disconnection with rs->err.
   }
   if (ber != NULL)
   {
      ber_free( ber, 1 );
   }
    VmDirDeleteConnection(&pConn);
    VMDIR_SAFE_FREE_MEMORY(pConnCtx);
    VmDirFreeOperation(pOperation);

    if (bDownOpThrCount)
    {
        VmDirSyncCounterDecrement(gVmdirGlobals.pOperationThrSyncCounter);
    }

    _VmDirFlowCtrlThrExit();

    // TODO: should we return dwError ?
    return 0;

error:
    goto cleanup;
}
Beispiel #23
0
static
DWORD
VmDirSrvModifyPersistedDSERoot(
    PVDIR_SCHEMA_CTX pSchemaCtx,
    PSTR             pszRootNamingContextDN,
    PSTR             pszConfigNamingContextDN,
    PSTR             pszSchemaNamingContextDN,
    PSTR             pszSubSchemaSubEntryDN,
    PSTR             pszServerDN,
    PSTR             pszDefaultAdminDN,
    PSTR             pszDCAccountDN,
    PSTR             pszDCAccountUPN,
    PSTR             pszDelObjsContainerDN,
    PSTR             pszSiteName
    )
{
    DWORD dwError = 0;
    PSTR ppszPersistedDSERootAttrs[] =
    {
            ATTR_ROOT_DOMAIN_NAMING_CONTEXT,    pszRootNamingContextDN,
            ATTR_DEFAULT_NAMING_CONTEXT,        pszRootNamingContextDN,
            ATTR_CONFIG_NAMING_CONTEXT,         pszConfigNamingContextDN,
            ATTR_SCHEMA_NAMING_CONTEXT,         pszSchemaNamingContextDN,
            ATTR_SUB_SCHEMA_SUB_ENTRY,          pszSubSchemaSubEntryDN,
            ATTR_NAMING_CONTEXTS,               pszRootNamingContextDN,
            ATTR_NAMING_CONTEXTS,               pszConfigNamingContextDN,
            ATTR_NAMING_CONTEXTS,               pszSchemaNamingContextDN,
            ATTR_SERVER_NAME,                   pszServerDN,
            ATTR_DEFAULT_ADMIN_DN,              pszDefaultAdminDN,
            ATTR_DC_ACCOUNT_DN,                 pszDCAccountDN,
            ATTR_DC_ACCOUNT_UPN,                pszDCAccountUPN,
            ATTR_DEL_OBJS_CONTAINER,            pszDelObjsContainerDN,
            ATTR_SITE_NAME,                     pszSiteName,
            NULL
    };

    VDIR_OPERATION  op = {0};
    PSTR            pszLocalErrMsg = NULL;
    VDIR_BERVALUE   bvDSERootDN = VDIR_BERVALUE_INIT;
    int             i = 0;

    dwError = VmDirInitStackOperation( &op, VDIR_OPERATION_TYPE_INTERNAL, LDAP_REQ_MODIFY, NULL );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrMsg,
            "VmDirSrvModifyPersistedDSERoot: VmDirInitStackOperation failed with error code: %d.", dwError );

    // Setup target DN

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

    dwError = VmDirNormalizeDN( &bvDSERootDN, op.pSchemaCtx);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirBervalContentDup( &bvDSERootDN, &op.reqDn );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrMsg,
            "VmDirSrvModifyPersistedDSERoot: BervalContentDup failed with error code: %d.", dwError );

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

    dwError = VmDirBervalContentDup( &op.reqDn, &op.request.modifyReq.dn );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrMsg,
                "VmDirSrvModifyPersistedDSERoot: BervalContentDup failed with error code: %d.", dwError );

    // Setup mods

    for (i = 0; ppszPersistedDSERootAttrs[i] != NULL; i += 2 )
    {
        dwError = VmDirAppendAMod( &op, MOD_OP_REPLACE,
                                   ppszPersistedDSERootAttrs[i],
                                   (int) VmDirStringLenA(ppszPersistedDSERootAttrs[i]),
                                   ppszPersistedDSERootAttrs[i + 1],
                                   VmDirStringLenA(ppszPersistedDSERootAttrs[i + 1]) );
        BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrMsg,
                    "VmDirSrvModifyPersistedDSERoot: VmDirAppendAMod failed with error code: %d.", dwError );
    }

    dwError = VmDirAppendAMod( &op, MOD_OP_DELETE, ATTR_INVOCATION_ID, ATTR_INVOCATION_ID_LEN,
                               gVmdirServerGlobals.invocationId.lberbv.bv_val,
                               gVmdirServerGlobals.invocationId.lberbv.bv_len );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrMsg,
                    "VmDirSrvModifyPersistedDSERoot: VmDirAppendAMod failed with error code: %d.", dwError );

    // Modify

    dwError = VmDirInternalModifyEntry( &op );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrMsg,
                "VmDirSrvModifyPersistedDSERoot: InternalModifyEntry failed. DN: %s, Error code: %d, Error string: %s",
                op.reqDn.lberbv.bv_val, dwError, VDIR_SAFE_STRING( op.ldapResult.pszErrMsg ) );

cleanup:

    VmDirFreeBervalContent(&bvDSERootDN);
    VmDirFreeOperationContent(&op);
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);

    return dwError;

error:
    VmDirLog(LDAP_DEBUG_ANY, VDIR_SAFE_STRING(pszLocalErrMsg) );
    goto cleanup;
}
Beispiel #24
0
static
int
WriteAttributes(
   VDIR_OPERATION *   op,
   PVDIR_ENTRY        pEntry,
   uint32_t           iSearchReqSpecialChars,
   BerElement *       ber,
   PSTR*              ppszErrorMsg
   )
{
    int             retVal = LDAP_SUCCESS;
    unsigned int    i = 0;
    SearchReq *     sr = &(op->request.searchReq);
    BOOLEAN         mapFSPDN = FALSE;
    PVDIR_ATTRIBUTE pAttr = NULL;
    PVDIR_ATTRIBUTE pRetAttrs[3] = {pEntry->attrs, pEntry->pComputedAttrs, NULL};
    DWORD           dwCnt = 0;
    PSTR            pszLocalErrorMsg = NULL;

    // loop through both normal and computed attributes
    for ( dwCnt = 0, pAttr = pRetAttrs[dwCnt];
          pAttr != NULL;
          ++dwCnt, pAttr = pRetAttrs[dwCnt])
    {
        for ( ; pAttr != NULL;  pAttr = pAttr->next )
        {
            BOOLEAN bSendAttribute = FALSE;

            if (op->syncReqCtrl != NULL) // Replication,
            {
                // Filter attributes based on the input utdVector, and attribute's meta-data
                retVal = IsAttrInReplScope( op, pAttr->type.lberbv.bv_val, pAttr->metaData, &bSendAttribute, &pszLocalErrorMsg );
                BAIL_ON_VMDIR_ERROR( retVal );
            }
            else
            {
                // WEI: the correct way to handle this is to have attribute level 'ACL' check
                // For instance, the 'userPassword' attribute ACL defines:
                // Deny 'READ' access to everyone including administrator/admins/SELF
                // Possibly only allow 'backup Operators' 'READ' access
                // Allow 'administrator/admins' WRITE (set password)
                // Allow 'SELF' WRITE (reset password)

                // For now, do not send 'userPassword' attribute for everyone when implicitly/explicitly requested

                // normal ldap client search request
                // check if we need to return this attribute

                if (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_USER_PASSWORD, FALSE) == 0)
                {
                    if ((iSearchReqSpecialChars & LDAP_SEARCH_REQUEST_CHAR_PASSWD) != 0)
                    {   // vmdir specific - return password only if special char '-' is requested
                        bSendAttribute = TRUE;
                    }
                }
                else if (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_KRB_MASTER_KEY, FALSE) == 0)
                {
                    //only return master key if all of following conditions are satisfied
                    if (op->showMasterKeyCtrl && // server control must be present
                            op->conn->bIsLdaps && // must be ldaps
                            op->conn->AccessInfo.pszNormBindedDn && // can't be anonymous
                            VmDirStringCompareA(op->reqDn.bvnorm_val, gVmdirServerGlobals.systemDomainDN.bvnorm_val, FALSE) == 0 && // must query system domain object
                            op->request.searchReq.scope == LDAP_SCOPE_BASE && // scope must be base
                            op->request.searchReq.attrs != NULL && // attribute must be krbMKey only
                            VmDirStringCompareA(op->request.searchReq.attrs[0].lberbv.bv_val, ATTR_KRB_MASTER_KEY, FALSE) == 0 &&
                            op->request.searchReq.attrs[1].lberbv.bv_val == NULL)
                    {
                        retVal = VmDirSrvAccessCheckIsAdminRole( //must be administrator
                                                        op,
                                                        op->conn->AccessInfo.pszNormBindedDn,
                                                        &op->conn->AccessInfo,
                                                        &bSendAttribute);
                        BAIL_ON_VMDIR_ERROR( retVal );
                    }
                }
                else if ( (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_VMW_STS_PASSWORD, FALSE) == 0)
                           ||
                           (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_VMW_STS_TENANT_KEY, FALSE) == 0)
                        )
                {
                    //only admin users can read ATTR_VMW_STS_PASSWORD, ATTR_VMW_STS_TENANT_KEY attribute
                    {
                        retVal = VmDirSrvAccessCheckIsAdminRole( //must be administrator
                                                        op,
                                                        op->conn->AccessInfo.pszNormBindedDn,
                                                        &op->conn->AccessInfo,
                                                        &bSendAttribute);
                        BAIL_ON_VMDIR_ERROR( retVal );
                    }
                }
                else if (((iSearchReqSpecialChars & LDAP_SEARCH_REQUEST_CHAR_USER) != 0)                   &&
                         pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_USER_APPLICATIONS)
                {
                    bSendAttribute = TRUE;   // return all user attributes - "*"
                }
                else if (((iSearchReqSpecialChars & LDAP_SEARCH_REQUEST_CHAR_OP) != 0)                     &&
                         (pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_DIRECTORY_OPERATION ||
                          pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_DSA_OPERATION       ||
                          pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_DISTRIBUTED_OPERATION))
                {
                    bSendAttribute = TRUE;   // return all operational attributes - "+"
                }
                else
                {
                    for (i = 0; sr->attrs && sr->attrs[i].lberbv.bv_val != NULL; i++)
                    {
                        if (VmDirStringCompareA( sr->attrs[i].lberbv.bv_val, pAttr->type.lberbv.bv_val, FALSE) == 0)
                        {
                           bSendAttribute = TRUE;
                           break;
                        }
                    }
                }
            }

            if (bSendAttribute)
            {
                if (ber_printf( ber, "{O[", &(pAttr->type) ) == -1 )
                {
                    VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print attribute name ...) failed" );
                    retVal = LDAP_OTHER;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                    "Encoding attribute type failed.");
                }

                // Non-replication/normal search request, and the attribute is FSP enabled (SJ-TBD, for now ATTR_MEMBER)
                if (op->syncReqCtrl == NULL && VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_MEMBER, FALSE) == 0)
                {
                    mapFSPDN = TRUE;
                }
                else
                {
                    mapFSPDN = FALSE;
                }

                if ( VmDirStringCompareA( pAttr->type.lberbv_val, ATTR_OBJECT_CLASS, FALSE ) == 0 )
                {
                    if ( op->syncReqCtrl == NULL ) // Not replication
                    {
                        BerValue bvOCTop = {OC_TOP_LEN, OC_TOP};
                        // explicitly send TOP as we don't store it in Entry/DB
                        if (ber_printf( ber, "O", &bvOCTop ) == -1 )
                        {
                            VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print an attribute value ...) failed." );
                            retVal = LDAP_OTHER;
                            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                            "Encoding an attribute value failed.");
                        }
                    }

                    // ADSI wants structure objetclass at the end to display correctly.
                    for ( i = pAttr->numVals ; i > 0; i-- )
                    {
                        if (ber_printf( ber, "O", &(pAttr->vals[i-1]) ) == -1 )
                        {
                            VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print an attribute value ...) failed." );
                            retVal = LDAP_OTHER;
                            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                            "Encoding an attribute value failed.");
                        }
                    }
                }
                else
                {
                    for ( i = 0; i< pAttr->numVals; i++ )
                    {
                        // SJ-TBD: A better/bit-more-expensive way is to Normalize the value, do GetParentDN, check if the 1st
                        // RDN is FSP container RDN ...
                        if (mapFSPDN && VmDirStringStrA(pAttr->vals[i].lberbv.bv_val, FSP_CONTAINER_RDN_ATTR_VALUE) != NULL)
                        {
                            char * tmpPos = VmDirStringChrA(pAttr->vals[i].lberbv.bv_val, ',');
                            assert( tmpPos != NULL);
                            *tmpPos = '\0';
                            pAttr->vals[i].lberbv.bv_len = tmpPos - pAttr->vals[i].lberbv.bv_val;
                        }
                        if (ber_printf( ber, "O", &(pAttr->vals[i]) ) == -1 )
                        {
                            VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print an attribute value ...) failed." );
                            retVal = LDAP_OTHER;
                            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                            "Encoding an attribute value failed.");
                        }
                    }
                }

                if ( ber_printf( ber, "]N}" ) == -1 )
                {
                    VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to terminate an attribute's values ...) failed" );
                    retVal = LDAP_OTHER;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                    "Encoding terminating an attribute type failed.");
                }
            }
        }
    }

cleanup:

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

    return( retVal );

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WriteAttributes failed (%u)(%s)",
                     retVal, VDIR_SAFE_STRING(pszLocalErrorMsg) );

    goto cleanup;
}
Beispiel #25
0
static
int
WriteMetaDataAttribute(
   VDIR_OPERATION *             op,
   VDIR_ATTRIBUTE *             pAttr,
   int                          numAttrMetaData,
   PATTRIBUTE_META_DATA_NODE    pAttrMetaData,
   BerElement *                 ber,
   BOOLEAN *                    nonTrivialAttrsInReplScope,
   PSTR*                        ppszErrorMsg
   )
{
    int             retVal = LDAP_SUCCESS;
    VDIR_BERVALUE   attrMetaData = { {ATTR_ATTR_META_DATA_LEN, ATTR_ATTR_META_DATA}, 0, 0, NULL };
    int             i = 0;
    VDIR_BERVALUE   berVal = VDIR_BERVALUE_INIT;
    char            attrMetaDataVal[256 + VMDIR_MAX_ATTR_META_DATA_LEN];
    PSTR            pszLocalErrorMsg = NULL;

    *nonTrivialAttrsInReplScope = FALSE;

    if (ber_printf( ber, "{O[", &(attrMetaData) ) == -1 )
    {
        VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to print attribute name ...) failed" );
        retVal = LDAP_OTHER;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Encoding attribute type failed.");
    }

    for ( ; pAttr != NULL; pAttr = pAttr->next)
    {
        // By this time, we have already filtered out attributes that should be send back to replication consumer
        // in prior WriteAttributes -> IsAttrInReplScope call.  They contain proper pAttr->metaData value.
        if (pAttr->metaData[0] != '\0')
        {
            VmDirStringPrintFA( attrMetaDataVal, sizeof(attrMetaDataVal), "%.256s:%s", pAttr->type.lberbv.bv_val, pAttr->metaData);
            berVal.lberbv.bv_val = attrMetaDataVal;
            berVal.lberbv.bv_len = VmDirStringLenA( attrMetaDataVal );
            if (VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_MODIFYTIMESTAMP, FALSE ) != 0 &&
                VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_USN_CHANGED, FALSE ) != 0)
            {
                // To prevent endless replication ping pong, supplier should send result only if there are changes
                // to attribute other than ATTR_USN_CHANGED and ATTR_MODIFYTIMESTAMP.
                *nonTrivialAttrsInReplScope = TRUE;
            }
            if (ber_printf( ber, "O", &berVal ) == -1 )
            {
                VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to print an attribute value ...) failed." );
                retVal = LDAP_OTHER;
                BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                "Encoding an attribute value failed.");
            }
        }
    }
    // include attrMetaData for the deleted attributes
    for (i = 0; i<numAttrMetaData; i++)
    {
        if (pAttrMetaData[i].metaData[0] != '\0')
        {
            BOOLEAN                 bSendAttrMetaData = TRUE;
            PVDIR_SCHEMA_AT_DESC    pATDesc = NULL;

            if (op->syncReqCtrl != NULL) // Replication
            {
                retVal = IsAttrInReplScope( op, NULL, pAttrMetaData[i].metaData, &bSendAttrMetaData, &pszLocalErrorMsg );
                BAIL_ON_VMDIR_ERROR( retVal );
            }
            else
            {
                bSendAttrMetaData = TRUE;
            }
            if (bSendAttrMetaData)
            {
                if ((pATDesc = VmDirSchemaAttrIdToDesc(op->pSchemaCtx, pAttrMetaData[i].attrID)) == NULL)
                {
                    VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL,
                              "WriteMetaDataAttribute: VmDirSchemaAttrIdToDesc failed for attribute id: %d.",
                              pAttrMetaData[i].attrID  );
                    retVal = LDAP_OTHER;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                    "WriteMetaDataAttribute: VmDirSchemaAttrIdToDesc failed.");
                }
                VmDirStringPrintFA( attrMetaDataVal, sizeof(attrMetaDataVal), "%.256s:%s", pATDesc->pszName, pAttrMetaData[i].metaData);
                berVal.lberbv.bv_val = attrMetaDataVal;
                berVal.lberbv.bv_len = VmDirStringLenA( attrMetaDataVal );
                *nonTrivialAttrsInReplScope = TRUE;
                if (ber_printf( ber, "O", &berVal ) == -1 )
                {
                    VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to print an attribute value ...) failed." );
                    retVal = LDAP_OTHER;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                    "Encoding an attribute value failed.");
                }
            }
        }
    }

    if ( ber_printf( ber, "]N}" ) == -1 )
    {
        VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to terminate an attribute's values ...) failed" );
        retVal = LDAP_OTHER;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Encoding terminating an attribute type failed.");
    }

cleanup:

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

    return( retVal );

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute failed (%u)(%s)",
                     retVal, VDIR_SAFE_STRING(pszLocalErrorMsg) );
    goto cleanup;
}
Beispiel #26
0
static
int
IsAttrInReplScope(
    VDIR_OPERATION *    op,
    char *              attrType,
    char *              attrMetaData,
    BOOLEAN *           inScope,
    PSTR*               ppszErrorMsg
    )
{
    int                     retVal = LDAP_SUCCESS;
    PLW_HASHTABLE_NODE      pNode = NULL;
    char                    origInvocationId[VMDIR_GUID_STR_LEN];
    USN                     origUsn = VmDirStringToLA( VmDirStringRChrA( attrMetaData, ':' ) + 1, NULL, 10 );
    int                     rc = 0;
    PSTR                    pszLocalErrorMsg = NULL;

    *inScope = FALSE;

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

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

    assert( op->syncReqCtrl != NULL );

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

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

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

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

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

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

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

cleanup:

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

    return( retVal );

error:

    goto cleanup;
}
Beispiel #27
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;
}
Beispiel #28
0
/*
 * Add a ModifyRequest to pOperation with-
 * 1. modOp
 * 2. create attribute with values from pBerValue
 *
 * i.e. this function call is equivalent of a modify section in LDIF file
 * changetype: modify
 * add/delete/replace: attributeXYZ  <<<<<<<<<<<<<<<< modOp
 * attributeXYZ: value1 <<<<<<<<<<<<<<<<<<<<<<<<<<<<< pBervalue
 * attributeXYZ: valueN <<<<<<<<<<<<<<<<<<<<<<<<<<<<< iBerValueSize
 */
DWORD
VmDirOperationAddModReq(
    PVDIR_OPERATION   pOperation,
    int               modOp,
    char *            pszAttrName,
    PVDIR_BERVALUE    pBerValue,
    size_t            iBerValueSize
    )
{
    DWORD               dwError = 0;
    PSTR                pszLocalErrMsg = NULL;
    VDIR_MODIFICATION * pMod = NULL;
    ModifyReq *         pModReq = &(pOperation->request.modifyReq);
    size_t              iCnt = 0;

    if ( !pOperation || !pszAttrName || !pBerValue )
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

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

    pMod->operation = modOp;
    pMod->attr.next = NULL;
    pMod->attr.pATDesc = VmDirSchemaAttrNameToDesc( pOperation->pSchemaCtx, pszAttrName);
    if ( !pMod->attr.pATDesc )
    {
        dwError = ERROR_NO_SUCH_ATTRIBUTE;
        BAIL_ON_VMDIR_ERROR_WITH_MSG( dwError, pszLocalErrMsg, "attibute (%s) not defined", pszAttrName );
    }

    // attribute.type.lberbv use (schema cache) inplace memory (we don't fee it).
    pMod->attr.type.lberbv.bv_val = pMod->attr.pATDesc->pszName;
    pMod->attr.type.lberbv.bv_len = VmDirStringLenA(pMod->attr.pATDesc->pszName);

    dwError = VmDirAllocateMemory(  sizeof( VDIR_BERVALUE ) * (iBerValueSize + 1 ),
                                    (PVOID *)&(pMod->attr.vals) );
    BAIL_ON_VMDIR_ERROR( dwError );

    for (iCnt = 0; iCnt < iBerValueSize; iCnt++)
    {
        dwError = VmDirAllocateAndCopyMemory( pBerValue[iCnt].lberbv_val,
                                              pBerValue[iCnt].lberbv_len,
                                              (PVOID *)&(pMod->attr.vals[iCnt].lberbv.bv_val));
        BAIL_ON_VMDIR_ERROR( dwError );

        pMod->attr.vals[iCnt].lberbv.bv_len = pBerValue[iCnt].lberbv_len;
        pMod->attr.vals[iCnt].bOwnBvVal = TRUE;
        pMod->attr.numVals++;
    }

    pMod->next = pModReq->mods;
    pModReq->mods = pMod;   // pOpeartion->request.modifyRequest takes over pMod
    pModReq->numMods++;

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);

    return dwError;

error:

    if (pMod)
    {
        VmDirModificationFree( pMod );
    }

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

    goto cleanup;
}
Beispiel #29
0
/*
 * Set vmwPasswordNeverExpires (if it doesn't have a value) to TRUE
 * on the domain administrator's account.
 */
DWORD
VmDirSetAdministratorPasswordNeverExpires(
    VOID
    )
{
    DWORD               dwError = 0;
    PCSTR               pszDomainDn = NULL;
    const CHAR          szAdministrator[] = "cn=Administrator,cn=Users";
    const CHAR          szTrue[] = "TRUE";
    PSTR                pszAdministratorDn = NULL;
    VDIR_OPERATION      op = {0};
    PSTR                pszLocalErrMsg = NULL;
    VDIR_ENTRY_ARRAY    entryArray = {0};
    PVDIR_ENTRY         pEntry = NULL;
    VDIR_BERVALUE       bervBlob = VDIR_BERVALUE_INIT;

    pszDomainDn = gVmdirServerGlobals.systemDomainDN.lberbv.bv_val;
    if (pszDomainDn == NULL)
    {
        dwError = ERROR_INVALID_STATE;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirAllocateStringPrintf(&pszAdministratorDn, "%s,%s", szAdministrator, pszDomainDn);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirSimpleEqualFilterInternalSearch(
                    pszDomainDn,
                    LDAP_SCOPE_SUBTREE,
                    ATTR_DN,
                    pszAdministratorDn,
                    &entryArray);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (entryArray.iSize != 1)
    {
        dwError = VMDIR_ERROR_DATA_CONSTRAINT_VIOLATION;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    pEntry = &(entryArray.pEntry[0]);

    if (pEntry->allocType == ENTRY_STORAGE_FORMAT_PACK)
    {
        dwError = VmDirEntryUnpack( pEntry );
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirInitStackOperation( &op, VDIR_OPERATION_TYPE_INTERNAL, LDAP_REQ_MODIFY, NULL);
    BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "VmDirSetAdministratorPasswordNeverExpire: VmDirInitStackOperation failed: %u", dwError);

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

    op.reqDn.lberbv.bv_val = pEntry->dn.lberbv.bv_val;
    op.reqDn.lberbv.bv_len = pEntry->dn.lberbv.bv_len;
    op.request.modifyReq.dn.lberbv = op.reqDn.lberbv;

    bervBlob.lberbv.bv_val = (PSTR) szTrue;
    bervBlob.lberbv.bv_len = strlen(szTrue);
    dwError = VmDirAppendAMod( &op,
                               MOD_OP_REPLACE,
                               ATTR_PASSWORD_NEVER_EXPIRES,
                               ATTR_PASSWORD_NEVER_EXPIRES_LEN,
                               bervBlob.lberbv_val,
                               bervBlob.lberbv_len);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirInternalModifyEntry(&op);
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:

    VmDirFreeEntryArrayContent(&entryArray);
    VmDirFreeOperationContent(&op);
    VMDIR_SAFE_FREE_STRINGA(pszAdministratorDn);
    return dwError;

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                     "VmDirSetAdministratorPasswordNeverExpires failed, (%u)", dwError);
    goto cleanup;
}
Beispiel #30
0
/*
 * Set SRP Identifier's secret on existing entry with Password set
 */
DWORD
VmDirSRPSetIdentityData(
    PCSTR       pszUPN,
    PCSTR       pszClearTextPassword
    )
{
    DWORD               dwError = 0;
    VDIR_OPERATION      op = {0};
    PSTR                pszLocalErrMsg = NULL;
    VDIR_ENTRY_ARRAY    entryArray = {0};
    PVDIR_ENTRY         pEntry = NULL;
    PVDIR_ATTRIBUTE     pAttrSecret = NULL;
    VDIR_BERVALUE       bvUPN = VDIR_BERVALUE_INIT;
    VDIR_BERVALUE       bvClearTextPassword = VDIR_BERVALUE_INIT;
    VDIR_BERVALUE       bervSecretBlob = VDIR_BERVALUE_INIT;


    if ( IsNullOrEmptyString(pszUPN)    ||
         IsNullOrEmptyString(pszClearTextPassword)
        )
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    bvUPN.lberbv_val = (PSTR)pszUPN;
    bvUPN.lberbv_len = VmDirStringLenA(pszUPN);

    bvClearTextPassword.lberbv_val = (PSTR)pszClearTextPassword;
    bvClearTextPassword.lberbv_len = VmDirStringLenA(pszClearTextPassword);

    dwError = VmDirSimpleEqualFilterInternalSearch(
                    "",
                    LDAP_SCOPE_SUBTREE,
                    ATTR_KRB_UPN,
                    pszUPN,
                    &entryArray);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (entryArray.iSize == 1)
    {
        pAttrSecret = VmDirFindAttrByName(&(entryArray.pEntry[0]), ATTR_SRP_SECRET);
        if (pAttrSecret)
        {
            dwError = VMDIR_ERROR_ENTRY_ALREADY_EXIST;
            BAIL_ON_VMDIR_ERROR(dwError);
        }
    }
    else
    {
        dwError = VMDIR_ERROR_DATA_CONSTRAINT_VIOLATION;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    pEntry = &(entryArray.pEntry[0]);

    dwError = VdirPasswordCheck(&bvClearTextPassword, pEntry);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirSRPCreateSecret(&bvUPN, &bvClearTextPassword, &bervSecretBlob);
    BAIL_ON_VMDIR_ERROR(dwError);


    if (pEntry->allocType == ENTRY_STORAGE_FORMAT_PACK)
    {
        dwError = VmDirEntryUnpack( pEntry );
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirInitStackOperation( &op, VDIR_OPERATION_TYPE_INTERNAL, LDAP_REQ_MODIFY, NULL);
    BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "VmDirSRPSetIdentityData: VmDirInitStackOperation failed: %u", dwError);

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

    op.reqDn.lberbv.bv_val = pEntry->dn.lberbv.bv_val;
    op.reqDn.lberbv.bv_len = pEntry->dn.lberbv.bv_len;
    op.request.modifyReq.dn.lberbv = op.reqDn.lberbv;

    dwError = VmDirAppendAMod( &op,
                               MOD_OP_ADD,
                               ATTR_SRP_SECRET,
                               ATTR_SRP_SECRET_LEN,
                               bervSecretBlob.lberbv_val,
                               bervSecretBlob.lberbv_len);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirInternalModifyEntry(&op);
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:

    VmDirFreeBervalContent(&bervSecretBlob);
    VmDirFreeEntryArrayContent(&entryArray);
    VmDirFreeOperationContent(&op);
    return dwError;

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                     "VmDirSRPSetIdentityData (%s) failed, (%u)", VDIR_SAFE_STRING(pszUPN), dwError);
    goto cleanup;
}