static int GenerateNewParent( PVDIR_ENTRY pEntry, PVDIR_ATTRIBUTE pDnAttr ) { int retVal = 0; VDIR_BERVALUE NewParent = VDIR_BERVALUE_INIT; if (!pEntry->pdn.bvnorm_val) { VmDirFreeBervalContent(&pEntry->pdn); retVal = VmDirGetParentDN(&pEntry->dn, &pEntry->pdn); BAIL_ON_VMDIR_ERROR(retVal); } retVal = VmDirGetParentDN(&pDnAttr->vals[0], &NewParent); BAIL_ON_VMDIR_ERROR(retVal); if (VmDirStringCompareA(pEntry->pdn.bvnorm_val, NewParent.bvnorm_val, FALSE) != 0) { retVal = VmDirBervalContentDup(&NewParent, &pEntry->newpdn); BAIL_ON_VMDIR_ERROR(retVal); } cleanup: VmDirFreeBervalContent(&NewParent); return retVal; error: goto cleanup; }
/* * Allocate string into pDupBerval */ DWORD VmDirStringToBervalContent( PCSTR pszBerval, PVDIR_BERVALUE pDupBerval ) { DWORD dwError = 0; VmDirFreeBervalContent(pDupBerval); dwError = VmDirAllocateStringA(pszBerval, &pDupBerval->lberbv.bv_val); BAIL_ON_VMDIR_ERROR(dwError); pDupBerval->bOwnBvVal = TRUE; pDupBerval->lberbv.bv_len = VmDirStringLenA(pDupBerval->lberbv.bv_val); cleanup: return dwError; error: VmDirFreeBervalContent(pDupBerval); goto cleanup; }
/* * called by replication thread only */ VOID VmDirFreeReplicationAgreement( PVMDIR_REPLICATION_AGREEMENT pReplAgr ) { if (pReplAgr && pReplAgr->dcConn.connState != DC_CONNECTION_STATE_CONNECTING) { VmDirFreeDCConnContent(&pReplAgr->dcConn); VmDirFreeBervalContent(&pReplAgr->lastLocalUsnProcessed); VmDirFreeBervalContent(&pReplAgr->dn); VMDIR_SAFE_FREE_MEMORY(pReplAgr->pszHostname); VMDIR_SAFE_FREE_MEMORY(pReplAgr->pszInvocationID); VMDIR_SAFE_FREE_MEMORY(pReplAgr); } }
/* * Free a heap Attribute * (ATTENTION: if the pAttr is within a pEntry, only when pEntry is constructed as * ENTRY_STORAGE_FORMAT_NORMAL allocation type, its attribute can be freed using this function; * otherwise, an entry's attribute free is taken care of by 'pEntry->bvs' */ VOID VmDirFreeAttribute( PVDIR_ATTRIBUTE pAttr ) { if (!pAttr) { return; } // pAttr->type is always store in place and has NO bvnorm_val. no need to free here. if (!dequeIsEmpty(&pAttr->valueMetaDataToAdd)) { VmDirFreeAttrValueMetaDataDequeueContent(&pAttr->valueMetaDataToAdd); } if (!dequeIsEmpty(&pAttr->valueMetaDataToDelete)) { VmDirFreeAttrValueMetaDataDequeueContent(&pAttr->valueMetaDataToDelete); } VmDirFreeMetaData(pAttr->pMetaData); VmDirFreeBervalContent(&pAttr->type); VmDirFreeBervalArrayContent(pAttr->vals, pAttr->numVals); VMDIR_SAFE_FREE_MEMORY(pAttr->vals); VMDIR_SAFE_FREE_MEMORY(pAttr); }
void VmDirFreeBindRequest( BindReq* pBindReq, BOOLEAN bFreeSelf) { if (pBindReq != NULL) { VmDirFreeBervalContent( &(pBindReq->cred) ); VmDirFreeBervalContent( &(pBindReq->bvMechanism) ); if (bFreeSelf) { VMDIR_SAFE_FREE_MEMORY( pBindReq ); } } }
/* * Free SASL related resources. */ VOID VmDirSASLSessionClose( PVDIR_SASL_BIND_INFO pSaslBindInfo ) { if (pSaslBindInfo) { if (pSaslBindInfo->pSaslCtx) { if (pSaslBindInfo->saslSSF > 0) { VmDirSASLSockbufRemove(pSaslBindInfo->pSockbuf); } sasl_dispose(&pSaslBindInfo->pSaslCtx); pSaslBindInfo->pSaslCtx = NULL; } VMDIR_SAFE_FREE_MEMORY(pSaslBindInfo->pSessionCB); VMDIR_SAFE_FREE_MEMORY(pSaslBindInfo->pszBindUserName); VmDirFreeBervalContent(&pSaslBindInfo->bvMechnism); } return; }
DWORD VmDirMDBSimpleDnToEntry( PSTR pszEntryDN, PVDIR_ENTRY pEntry ) { DWORD dwError = 0; PVDIR_SCHEMA_CTX pSchemaCtx = NULL; VDIR_BERVALUE entryDn = VDIR_BERVALUE_INIT; VDIR_BACKEND_CTX mdbBECtx = {0}; BOOLEAN bHasTxn = FALSE; assert(pEntry); dwError = VmDirSchemaCtxAcquire(&pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); entryDn.lberbv.bv_val = pszEntryDN; entryDn.lberbv.bv_len = VmDirStringLenA(entryDn.lberbv.bv_val); dwError = VmDirMDBTxnBegin(&mdbBECtx, VDIR_BACKEND_TXN_READ); BAIL_ON_VMDIR_ERROR(dwError); bHasTxn = TRUE; dwError = VmDirMDBDNToEntry( &mdbBECtx, pSchemaCtx, &entryDn, pEntry, VDIR_BACKEND_ENTRY_LOCK_READ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirMDBTxnCommit(&mdbBECtx); bHasTxn = FALSE; BAIL_ON_VMDIR_ERROR(dwError); cleanup: if (pSchemaCtx) { VmDirSchemaCtxRelease(pSchemaCtx); } mdbBECtx.pBEPrivate = NULL; VmDirBackendCtxContentFree(&mdbBECtx); VmDirFreeBervalContent(&entryDn); return dwError; error: if (bHasTxn) { VmDirMDBTxnAbort(&mdbBECtx); } goto cleanup; }
/* * Free a heap BerValue */ VOID VmDirFreeBerval( VDIR_BERVALUE* pBerv ) { VmDirFreeBervalContent(pBerv); VMDIR_SAFE_FREE_MEMORY(pBerv); return; }
static DWORD _VmDirSchemaAttrReplaceValue( PVDIR_ATTRIBUTE pAttr, PCSTR pszMatchSubstr, PCSTR pszValue ) { #define MAX_BUF_SIZE_256 256 DWORD dwError = 0; unsigned iCnt = 0; CHAR pszBuf[MAX_BUF_SIZE_256] = {0}; dwError = VmDirStringPrintFA( pszBuf, MAX_BUF_SIZE_256 -1 , "NAME '%s' ", pszMatchSubstr ); BAIL_ON_VMDIR_ERROR(dwError); for (iCnt = 0; iCnt < pAttr->numVals; iCnt++) { if ( VmDirCaselessStrStrA( pAttr->vals[iCnt].lberbv_val, pszBuf ) != NULL ) { if ( VmDirStringCompareA( VDIR_SAFE_STRING(pAttr->vals[iCnt].lberbv_val), pszValue, FALSE ) != 0 ) { VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Merge schema, replace old - %s", VDIR_SAFE_STRING(pAttr->vals[iCnt].lberbv_val)); VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Merge schema, replace new - %s", pszValue ); } VMDIR_LOG_DEBUG( VMDIR_LOG_MASK_ALL, "Merge schema, replace old - %s", VDIR_SAFE_STRING(pAttr->vals[iCnt].lberbv_val)); VmDirFreeBervalContent( &(pAttr->vals[iCnt]) ); dwError = VmDirAllocateStringA( pszValue, &(pAttr->vals[iCnt].lberbv_val) ); BAIL_ON_VMDIR_ERROR(dwError); pAttr->vals[iCnt].lberbv_len = VmDirStringLenA( pszValue ); pAttr->vals[iCnt].bOwnBvVal = TRUE; VMDIR_LOG_DEBUG( VMDIR_LOG_MASK_ALL, "Merge schema, replace new - %s", VDIR_SAFE_STRING(pAttr->vals[iCnt].lberbv_val)); break; } } cleanup: return dwError; error: goto cleanup; }
/* * Free a heap Attribute * (ATTENTION: if the pAttr is within a pEntry, only when pEntry is constructed as * ENTRY_STORAGE_FORMAT_NORMAL allocation type, its attribute can be freed using this function; * otherwise, an entry's attribute free is taken care of by 'pEntry->bvs' */ VOID VmDirFreeAttribute( PVDIR_ATTRIBUTE pAttr ) { if (!pAttr) { return; } VmDirFreeBervalContent(&pAttr->type); VmDirFreeBervalArrayContent(pAttr->vals, pAttr->numVals); VMDIR_SAFE_FREE_MEMORY(pAttr->vals); VMDIR_SAFE_FREE_MEMORY(pAttr); }
void VmDirFreeDeleteRequest( DeleteReq * dr, BOOLEAN freeSelf ) { if (dr != NULL) { VmDirFreeBervalContent( &(dr->dn) ); if (freeSelf) { VMDIR_SAFE_FREE_MEMORY( dr ); } } return; }
static void RemoveAttrVals( VDIR_ATTRIBUTE * eAttr, // Entry attribute to be updated after removing certain attribute values VDIR_ATTRIBUTE * modAttr // Modify attribute containing attribute values to be deleted ) { unsigned int i = 0; unsigned int j = 0; int k = 0; for (i=0; i < eAttr->numVals; i++) { // eAttr values are already normalized. assert(eAttr->vals[i].bvnorm_val); for (j = 0; j < modAttr->numVals; j++) { // modAttr values are already normalized. assert(modAttr->vals[j].bvnorm_val); if (eAttr->vals[i].bvnorm_len == modAttr->vals[j].bvnorm_len && memcmp(eAttr->vals[i].bvnorm_val, modAttr->vals[j].bvnorm_val, modAttr->vals[j].bvnorm_len) == 0) { break; } } if (j == modAttr->numVals) // current value (i th) is NOT being deleted { eAttr->vals[k++] = eAttr->vals[i]; } else // current value (i th) is being deleted { VmDirFreeBervalContent(&eAttr->vals[i]); } } eAttr->numVals = k; memset(&(eAttr->vals[k]), 0, sizeof(VDIR_BERVALUE)); // set last BerValue.lberbv.bv_val to NULL; return; }
DWORD VmDirResetPassword( PCSTR pszUPN, PCSTR pszNewPassword ) { DWORD dwError = 0; VDIR_BERVALUE bvPassword = VDIR_BERVALUE_INIT; PSTR pszDN = NULL; if ( IsNullOrEmptyString(pszUPN) || IsNullOrEmptyString(pszNewPassword) ) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirUPNToDN( pszUPN, &pszDN ); BAIL_ON_VMDIR_ERROR(dwError); bvPassword.lberbv_val = (PSTR)pszNewPassword; bvPassword.lberbv_len = VmDirStringLenA(pszNewPassword); dwError = VmDirInternalEntryAttributeReplace( NULL, pszDN, ATTR_USER_PASSWORD, &bvPassword); BAIL_ON_VMDIR_ERROR(dwError); cleanup: VmDirFreeBervalContent(&bvPassword); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "VmDirResetPassword (%s) failed, (%u)", VDIR_SAFE_STRING(pszUPN), dwError); goto cleanup; }
static DWORD _VmDirRESTCreateCondWriteCtrl( PVDIR_OPERATION pOp, PCSTR pszTenant, PCSTR pszCondWriteFilter ) { DWORD dwError = 0; VDIR_BERVALUE bvFilter = VDIR_BERVALUE_INIT; PVDIR_FILTER pObjectFilter = NULL; PVDIR_FILTER pDNFilter = NULL; dwError = StrFilterToFilter(pszCondWriteFilter, &pObjectFilter); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirRESTFilterObjectToDN( pszTenant, pObjectFilter, &pDNFilter); BAIL_ON_VMDIR_ERROR(dwError); dwError = FilterToStrFilter(pDNFilter, &bvFilter); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAddCondWriteCtrl(pOp, bvFilter.lberbv_val); BAIL_ON_VMDIR_ERROR(dwError); cleanup: VmDirFreeBervalContent(&bvFilter); DeleteFilter(pObjectFilter); DeleteFilter(pDNFilter); return dwError; error: goto cleanup; }
DWORD VmDirSrvSetupHostInstance( PCSTR pszFQDomainName, PCSTR pszUsername, PCSTR pszPassword, PCSTR pszSiteName, PCSTR pszReplURI, UINT32 firstReplCycleMode ) { DWORD dwError = 0; PCSTR pszDelObjsContainerName = "Deleted Objects"; PCSTR pszConfigContainerName = VMDIR_CONFIGURATION_CONTAINER_NAME; PCSTR pszCAContainerName = VMDIR_CA_CONTAINER_NAME; PCSTR pszSitesContainerName = VMDIR_SITES_RDN_VAL; PCSTR pszSiteContainerName = "Default-First-Site"; PCSTR pszServersContainerName = VMDIR_SERVERS_CONTAINER_NAME; PCSTR pszReplAgrsContainerName = VMDIR_REPL_AGRS_CONTAINER_NAME; PCSTR pszDCsContainerName = VMDIR_DOMAIN_CONTROLLERS_RDN_VAL; PCSTR pszComputersContainerName = VMDIR_COMPUTERS_RDN_VAL; PCSTR pszMSAsContainerName = VMDIR_MSAS_RDN_VAL; PSTR pszDomainDN = NULL; PSTR pszDelObjsContainerDN = NULL; // CN=Deleted Objects,<domain DN> PSTR pszConfigContainerDN = NULL; // CN=Configuration,<domain DN> PSTR pszCAContainerDN = NULL; // CN=Certificate-Authorities,CN=Configuration,<domain DN> PSTR pszSitesContainerDN = NULL; // CN=Sites,<configuration DN> PSTR pszSiteContainerDN = NULL; // CN=<Site-Name>,<Sites container DN> PSTR pszServersContainerDN = NULL; // CN=Servers,<Site container DN> PSTR pszServerDN = NULL; // CN=<fully qualified host name>,<Servers container DN> PSTR pszReplAgrsContainerDN = NULL; // CN=Replication Agreements,<Server DN> PSTR pszReplAgrDN = NULL; // labeledURI=<ldap://192.165.226.127>,<ReplAgrsContainerDN> PSTR pszDCsContainerDN = NULL; // OU=Domain Controllers,<domain DN> PSTR pszComputersContainerDN = NULL; // OU=Computers,<domain DN> PSTR pszDCAccountDN = NULL; // CN=<fully qualified host name>,OU=Domain Controllers,<domain DN> PSTR pszDCAccountUPN = NULL; // <hostname>@<domain name> PSTR pszComputerAccountDN = NULL; // CN=<fully qualified host name>,OU=Domain Computers,<domain DN> PSTR pszMSAsDN = NULL; // CN=<Managed Service Accounts>,<domain DN> PSTR pszUpperCaseFQDomainName = NULL; PSTR pszLowerCaseHostName = NULL; PSTR pszDefaultAdminDN = NULL; PVDIR_SCHEMA_CTX pSchemaCtx = NULL; char pszHostName[VMDIR_MAX_HOSTNAME_LEN]; VDIR_BERVALUE bv = VDIR_BERVALUE_INIT; BOOLEAN bInLockReplCycle = FALSE; PVMDIR_REPLICATION_AGREEMENT pReplAgr = NULL; BOOLEAN bInLock = FALSE; PSTR pszUserDN = NULL; PCSTR pszUsersContainerName = "Users"; PSTR pszUsersContainerDN = NULL; // CN=Users,<domain DN> VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "Setting up a host instance (%s).", VDIR_SAFE_STRING(pszFQDomainName)); if (pszSiteName) { pszSiteContainerName = pszSiteName; } // If joining another node, copy schema from the partner first. if (!IsNullOrEmptyString(pszReplURI)) { dwError = VmDirCopyPartnerSchema( pszFQDomainName, pszUsername, pszPassword, pszReplURI); BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirSchemaCtxAcquire( &pSchemaCtx ); BAIL_ON_VMDIR_ERROR(dwError); // Construct important DNs and create the persisted DSE Root entry // Domain DN dwError = VmDirSrvCreateDomainDN( pszFQDomainName, &pszDomainDN ); BAIL_ON_VMDIR_ERROR(dwError); // Deleted objects container DN dwError = VmDirSrvCreateDN( pszDelObjsContainerName, pszDomainDN, &pszDelObjsContainerDN ); BAIL_ON_VMDIR_ERROR(dwError); // Configuration container DN dwError = VmDirSrvCreateDN( pszConfigContainerName, pszDomainDN, &pszConfigContainerDN ); BAIL_ON_VMDIR_ERROR(dwError); // Domain Controllers container DN dwError = VmDirAllocateStringAVsnprintf(&pszDCsContainerDN, "%s=%s,%s", ATTR_OU, pszDCsContainerName, pszDomainDN); BAIL_ON_VMDIR_ERROR(dwError); // Domain Computers container DN dwError = VmDirAllocateStringAVsnprintf(&pszComputersContainerDN, "%s=%s,%s", ATTR_OU, pszComputersContainerName, pszDomainDN); BAIL_ON_VMDIR_ERROR(dwError); // Sites container DN dwError = VmDirSrvCreateDN( pszSitesContainerName, pszConfigContainerDN, &pszSitesContainerDN ); BAIL_ON_VMDIR_ERROR(dwError); // Certificate-Authorities container DN dwError = VmDirSrvCreateDN( pszCAContainerName, pszConfigContainerDN, &pszCAContainerDN ); BAIL_ON_VMDIR_ERROR(dwError); // Particular site container DN dwError = VmDirSrvCreateDN( pszSiteContainerName, pszSitesContainerDN, &pszSiteContainerDN ); BAIL_ON_VMDIR_ERROR(dwError); // Servers within the site container DN dwError = VmDirSrvCreateDN( pszServersContainerName, pszSiteContainerDN, &pszServersContainerDN ); BAIL_ON_VMDIR_ERROR(dwError); // This server DN // vdcpromo sets this key. dwError = VmDirGetRegKeyValue( VMDIR_CONFIG_PARAMETER_KEY_PATH, VMDIR_REG_KEY_DC_ACCOUNT, pszHostName, sizeof(pszHostName)-1); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocASCIIUpperToLower( pszHostName, &pszLowerCaseHostName ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirSrvCreateDN( pszLowerCaseHostName, pszServersContainerDN, &pszServerDN ); BAIL_ON_VMDIR_ERROR(dwError); // Domain controller account DN dwError = VmDirSrvCreateDN( pszLowerCaseHostName, pszDCsContainerDN, &pszDCAccountDN ); BAIL_ON_VMDIR_ERROR(dwError); // Domain controller account UPN dwError = VmDirAllocASCIILowerToUpper( pszFQDomainName, &pszUpperCaseFQDomainName ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringAVsnprintf(&pszDCAccountUPN, "%s@%s", pszLowerCaseHostName, pszUpperCaseFQDomainName ); BAIL_ON_VMDIR_ERROR(dwError); // Computer account DN dwError = VmDirSrvCreateDN( pszLowerCaseHostName, pszComputersContainerDN, &pszComputerAccountDN ); BAIL_ON_VMDIR_ERROR(dwError); // Replication agreements container DN dwError = VmDirSrvCreateDN( pszReplAgrsContainerName, pszServerDN, &pszReplAgrsContainerDN ); BAIL_ON_VMDIR_ERROR(dwError); // Managed Service Accounts container DN dwError = VmDirSrvCreateDN( pszMSAsContainerName, pszDomainDN, &pszMSAsDN ); BAIL_ON_VMDIR_ERROR(dwError); // Default administrator DN dwError = VmDirAllocateStringAVsnprintf( &pszDefaultAdminDN, "cn=%s,cn=%s,%s", pszUsername, pszUsersContainerName, pszDomainDN ); BAIL_ON_VMDIR_ERROR(dwError); if (firstReplCycleMode != FIRST_REPL_CYCLE_MODE_USE_COPIED_DB) { // Modify persisted DSE Root entry dwError = VmDirSrvModifyPersistedDSERoot( pSchemaCtx, pszDomainDN, pszConfigContainerDN, SCHEMA_NAMING_CONTEXT_DN, SUB_SCHEMA_SUB_ENTRY_DN, pszServerDN, pszDefaultAdminDN, pszDCAccountDN, pszDCAccountUPN, pszDelObjsContainerDN, (PSTR) pszSiteContainerName ); } BAIL_ON_VMDIR_ERROR(dwError); // set gVmdirServerGlobals.bvDefaultAdminDN dwError = VmDirAllocateBerValueAVsnprintf( &gVmdirServerGlobals.bvDefaultAdminDN, "%s", pszDefaultAdminDN); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirNormalizeDN( &gVmdirServerGlobals.bvDefaultAdminDN, pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); // set systemDomainDN dwError = VmDirAllocateBerValueAVsnprintf( &gVmdirServerGlobals.systemDomainDN, "%s", pszDomainDN); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirNormalizeDN( &gVmdirServerGlobals.systemDomainDN, pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); // set serverObjDN dwError = VmDirAllocateBerValueAVsnprintf( &gVmdirServerGlobals.serverObjDN, "%s", pszServerDN); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirNormalizeDN( &gVmdirServerGlobals.serverObjDN, pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); // set dcAccountDN dwError = VmDirAllocateBerValueAVsnprintf( &gVmdirServerGlobals.dcAccountDN, "%s", pszDCAccountDN); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirNormalizeDN( &gVmdirServerGlobals.dcAccountDN, pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); // set dcAccountUPN dwError = VmDirAllocateBerValueAVsnprintf( &gVmdirServerGlobals.dcAccountUPN, "%s", pszDCAccountUPN); BAIL_ON_VMDIR_ERROR(dwError); // Set replInterval and replPageSize gVmdirServerGlobals.replInterval = VmDirStringToIA(VMDIR_DEFAULT_REPL_INTERVAL); gVmdirServerGlobals.replPageSize = VmDirStringToIA(VMDIR_DEFAULT_REPL_PAGE_SIZE); // Set utdVector VmDirFreeBervalContent(&bv); bv.lberbv.bv_val = ""; bv.lberbv.bv_len = 0; dwError = VmDirBervalContentDup( &bv, &gVmdirServerGlobals.utdVector ); BAIL_ON_VMDIR_ERROR(dwError); // Set delObjsContainerDN VmDirFreeBervalContent(&bv); bv.lberbv.bv_val = pszDelObjsContainerDN; bv.lberbv.bv_len = VmDirStringLenA( bv.lberbv.bv_val ); dwError = VmDirBervalContentDup( &bv, &gVmdirServerGlobals.delObjsContainerDN ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirNormalizeDN(&gVmdirServerGlobals.delObjsContainerDN, pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringA( pszSiteContainerName, &gVmdirServerGlobals.pszSiteName); BAIL_ON_VMDIR_ERROR(dwError); // Create Administrator DN dwError = VmDirSrvCreateDN( pszUsersContainerName, pszDomainDN, &pszUsersContainerDN); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirSrvCreateUserDN( pszUsername, pszUsersContainerDN, &pszUserDN); BAIL_ON_VMDIR_ERROR(dwError); // set DomainControllerGroupDN for first,second+ host setup dwError = VmDirAllocateBerValueAVsnprintf( &gVmdirServerGlobals.bvDCGroupDN, "cn=%s,cn=%s,%s", VMDIR_DC_GROUP_NAME, VMDIR_BUILTIN_CONTAINER_NAME, pszDomainDN); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirNormalizeDN( &(gVmdirServerGlobals.bvDCGroupDN), pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); // set DCClientGroupDN for first,second+ host setup dwError = VmDirAllocateBerValueAVsnprintf( &gVmdirServerGlobals.bvDCClientGroupDN, "cn=%s,cn=%s,%s", VMDIR_DCCLIENT_GROUP_NAME, VMDIR_BUILTIN_CONTAINER_NAME, pszDomainDN); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirNormalizeDN( &(gVmdirServerGlobals.bvDCClientGroupDN), pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); // set ServicesRootDN for first,second+ host setup dwError = VmDirAllocateBerValueAVsnprintf( &gVmdirServerGlobals.bvServicesRootDN, "cn=%s,%s", VMDIR_SERVICES_CONTAINER_NAME, pszDomainDN); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirNormalizeDN( &(gVmdirServerGlobals.bvServicesRootDN), pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); if (IsNullOrEmptyString(pszReplURI)) // 1st directory instance is being setup { // Set gVmdirServerGlobals.serverId FIRST, so that correct SID can be generated for the objects added subsequently. gVmdirServerGlobals.serverId = 1; dwError = VmDirSrvSetupDomainInstance( pSchemaCtx, TRUE, TRUE, pszFQDomainName, pszDomainDN, pszUsername, pszPassword ); BAIL_ON_VMDIR_ERROR(dwError); // Create Deleted Objects container dwError = VmDirSrvCreateContainerWithEID( pSchemaCtx, pszDelObjsContainerDN, pszDelObjsContainerName, DEL_ENTRY_CONTAINER_ENTRY_ID ); BAIL_ON_VMDIR_ERROR(dwError); // Create Domain Controllers container dwError = VmDirSrvCreateOUContainer( pSchemaCtx, pszDCsContainerDN, pszDCsContainerName ); BAIL_ON_VMDIR_ERROR(dwError); // Create Computers container dwError = VmDirSrvCreateOUContainer( pSchemaCtx, pszComputersContainerDN, pszComputersContainerName ); BAIL_ON_VMDIR_ERROR(dwError); // Create Managed Service Accounts container dwError = VmDirSrvCreateContainer( pSchemaCtx, pszMSAsDN, pszMSAsContainerName ); BAIL_ON_VMDIR_ERROR(dwError); // Create Configuration container dwError = VmDirSrvCreateConfigContainer( pSchemaCtx, pszConfigContainerDN, pszConfigContainerName ); BAIL_ON_VMDIR_ERROR(dwError); // Create Certificate-Authorities container dwError = VmDirSrvCreateContainer( pSchemaCtx, pszCAContainerDN, pszCAContainerName ); BAIL_ON_VMDIR_ERROR(dwError); // Create Sites container dwError = VmDirSrvCreateContainer( pSchemaCtx, pszSitesContainerDN, pszSitesContainerName ); BAIL_ON_VMDIR_ERROR(dwError); /* // Create Site-Name container dwError = VmDirSrvCreateContainer( pSchemaCtx, pszSiteContainerDN, pszSiteContainerName ); BAIL_ON_VMDIR_ERROR(dwError); // Create Servers container dwError = VmDirSrvCreateContainer( pSchemaCtx, pszServersContainerDN, pszServersContainerName ); BAIL_ON_VMDIR_ERROR(dwError); */ // Create Site-Name container, Servers container, and THE Server object dwError = VmDirSrvCreateServerObj( pSchemaCtx ); BAIL_ON_VMDIR_ERROR(dwError); // Create Replication Agreements container dwError = VmDirSrvCreateReplAgrsContainer( pSchemaCtx ); BAIL_ON_VMDIR_ERROR(dwError); // 1st replica => no replication agreements => 1st replication cycle done VMDIR_LOCK_MUTEX(bInLockReplCycle, gVmdirGlobals.replCycleDoneMutex); VmDirConditionSignal(gVmdirGlobals.replCycleDoneCondition); VMDIR_UNLOCK_MUTEX(bInLockReplCycle, gVmdirGlobals.replCycleDoneMutex); } else { dwError = VmDirAllocateStringAVsnprintf( &pszReplAgrDN, "labeledURI=%s,%s", pszReplURI, pszReplAgrsContainerDN ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirConstructReplAgr( pSchemaCtx, pszReplURI, VMDIR_DEFAULT_REPL_LAST_USN_PROCESSED, pszReplAgrDN, &pReplAgr ); BAIL_ON_VMDIR_ERROR(dwError); gFirstReplCycleMode = firstReplCycleMode; VMDIR_LOCK_MUTEX(bInLock, gVmdirGlobals.replAgrsMutex); pReplAgr->next = gVmdirReplAgrs; gVmdirReplAgrs = pReplAgr; // ownership transfer // wake up replication thread waiting on the existence // of a replication agreement. VmDirConditionSignal(gVmdirGlobals.replAgrsCondition); VMDIR_UNLOCK_MUTEX(bInLock, gVmdirGlobals.replAgrsMutex); } cleanup: if (pSchemaCtx) { VmDirSchemaCtxRelease(pSchemaCtx); } VMDIR_SAFE_FREE_MEMORY(pszDomainDN); VMDIR_SAFE_FREE_MEMORY(pszDelObjsContainerDN); VMDIR_SAFE_FREE_MEMORY(pszConfigContainerDN); VMDIR_SAFE_FREE_MEMORY(pszCAContainerDN); VMDIR_SAFE_FREE_MEMORY(pszSitesContainerDN); VMDIR_SAFE_FREE_MEMORY(pszSiteContainerDN); VMDIR_SAFE_FREE_MEMORY(pszServersContainerDN); VMDIR_SAFE_FREE_MEMORY(pszServerDN); VMDIR_SAFE_FREE_MEMORY(pszReplAgrsContainerDN); VMDIR_SAFE_FREE_MEMORY(pszReplAgrDN); VMDIR_SAFE_FREE_MEMORY(pszDCsContainerDN); VMDIR_SAFE_FREE_MEMORY(pszDCAccountDN); VMDIR_SAFE_FREE_MEMORY(pszDCAccountUPN); VMDIR_SAFE_FREE_MEMORY(pszComputersContainerDN); VMDIR_SAFE_FREE_MEMORY(pszComputerAccountDN); VMDIR_SAFE_FREE_MEMORY(pszMSAsDN); VMDIR_SAFE_FREE_MEMORY(pszUpperCaseFQDomainName); VMDIR_SAFE_FREE_MEMORY(pszUsersContainerDN); VMDIR_SAFE_FREE_MEMORY(pszUserDN); VMDIR_SAFE_FREE_MEMORY(pszDefaultAdminDN); VMDIR_SAFE_FREE_MEMORY(pszLowerCaseHostName); VmDirFreeBervalContent(&bv); return dwError; error: VmDirLog(LDAP_DEBUG_ANY, "VmDirSrvSetupHostInstance failed. Error(%u)", dwError); goto cleanup; }
void VmDirFreeOperationContent( PVDIR_OPERATION op ) { DWORD dwError = ERROR_SUCCESS; if (op) { if (op->pSchemaCtx) { VmDirSchemaCtxRelease(op->pSchemaCtx); } if (op->syncDoneCtrl) { PLW_HASHTABLE_NODE pNode = NULL; LW_HASHTABLE_ITER iter = LW_HASHTABLE_ITER_INIT; UptoDateVectorEntry * pUtdVectorEntry = NULL; SyncDoneControlValue * syncDoneCtrlVal = &op->syncDoneCtrl->value.syncDoneCtrlVal; while ((pNode = LwRtlHashTableIterate(syncDoneCtrlVal->htUtdVector, &iter))) { dwError = LwRtlHashTableRemove(syncDoneCtrlVal->htUtdVector, pNode); assert( dwError == 0 ); pUtdVectorEntry = LW_STRUCT_FROM_FIELD(pNode, UptoDateVectorEntry, Node); VmDirFreeBervalContent( &pUtdVectorEntry->invocationId ); VMDIR_SAFE_FREE_MEMORY( pUtdVectorEntry ); } LwRtlFreeHashTable(&syncDoneCtrlVal->htUtdVector); assert( syncDoneCtrlVal->htUtdVector == NULL ); VMDIR_SAFE_FREE_MEMORY( op->syncDoneCtrl ); } if (op->pCondWriteCtrl) { VMDIR_SAFE_FREE_MEMORY(op->pCondWriteCtrl->value.condWriteCtrlVal.pszFilter); } if (op->reqControls) { DeleteControls(&(op->reqControls)); } switch (op->reqCode) { case LDAP_REQ_BIND: VmDirFreeBindRequest(&op->request.bindReq, FALSE); if (op->ldapResult.replyInfo.type == REP_SASL) { VmDirFreeBervalContent( &(op->ldapResult.replyInfo.replyData.bvSaslReply) ); } break; case LDAP_REQ_ADD: VmDirFreeAddRequest(&op->request.addReq, FALSE); break; case LDAP_REQ_SEARCH: VmDirFreeSearchRequest(&op->request.searchReq, FALSE); break; case LDAP_REQ_MODIFY: case LDAP_REQ_MODDN: VmDirFreeModifyRequest(&op->request.modifyReq, FALSE); break; case LDAP_REQ_DELETE: VmDirFreeDeleteRequest(&op->request.deleteReq, FALSE); if (op->request.modifyReq.numMods > 0) { //A raft follower needs to create a modifyReq for Delete OP VmDirFreeModifyRequest(&op->request.modifyReq, FALSE); } break; default: break; } VmDirFreeEntryArrayContent(&(op->internalSearchEntryArray)); VmDirFreeBervalContent( &(op->reqDn) ); VMDIR_SAFE_FREE_MEMORY(op->ldapResult.pszErrMsg); VmDirBackendCtxFree(op->pBECtx); VMDIR_SAFE_FREE_MEMORY(op->pszFilters); if ( op->opType == VDIR_OPERATION_TYPE_INTERNAL ) { // internal op owns dummy conn for ACL check VmDirDeleteConnection( &(op->conn)); // passing &conn to be freed seems a bit strange } } }
/* * Determine whether the supplier's attr-value-meta-data wins by checking it against local * attr-meta-data and local attr-value-meta-data. * It first compares the <version><invocation-id> of that in local attr-meta-data which was * applied either in the previous transaction or the previous modification in the current * transactions. Then if the <version><invocation-id> matches, it looks up the local server * to see if the same attr-value-meta-data exist: if supplier's attr-value-meta-data has a * newer timestamp then it wins and inScope set to TRUE. */ DWORD VmDirReplResolveValueMetaDataConflicts( PVDIR_OPERATION pModOp, PVDIR_ATTRIBUTE pAttr, PVMDIR_VALUE_ATTRIBUTE_METADATA pSupplierValueMetaData, ENTRYID entryId, PBOOLEAN pInScope ) { DWORD dwError = 0; VDIR_BERVALUE bervSupplierValueMetaData = VDIR_BERVALUE_INIT; VDIR_BERVALUE bervConsumerValueMetaData = VDIR_BERVALUE_INIT; DEQUE valueMetaDataQueue = {0}; PVMDIR_VALUE_ATTRIBUTE_METADATA pConsumerValueMetaData = NULL; if (!pModOp || !pAttr || !pSupplierValueMetaData || !pInScope) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } *pInScope = TRUE; dwError = pModOp->pBEIF->pfnBEGetAttrMetaData(pModOp->pBECtx, pAttr, entryId); BAIL_ON_VMDIR_ERROR(dwError); //Consumer <version><originating-server-id> in metaValueData //not match supplier's <version<<originating-server-id> in metaData //this value-meta-data out of scope if (pSupplierValueMetaData->version != pAttr->pMetaData->version || VmDirStringCompareA( pSupplierValueMetaData->pszOrigInvoId, pAttr->pMetaData->pszOrigInvoId, TRUE) != 0) { *pInScope = FALSE; goto cleanup; } if (VmDirLogGetMask() & LDAP_DEBUG_REPL) { //Ignore error, used only for logging VmDirValueMetaDataSerialize(pSupplierValueMetaData, &bervSupplierValueMetaData); VmDirValueMetaDataSerialize(pConsumerValueMetaData, &bervConsumerValueMetaData); } dwError = pModOp->pBEIF->pfnBEGetAttrValueMetaData( pModOp->pBECtx, entryId, pAttr->pATDesc->usAttrID, &valueMetaDataQueue); BAIL_ON_VMDIR_ERROR(dwError); while(!dequeIsEmpty(&valueMetaDataQueue)) { VMDIR_SAFE_FREE_VALUE_METADATA(pConsumerValueMetaData); dequePopLeft(&valueMetaDataQueue, (PVOID*)&pConsumerValueMetaData); if (pConsumerValueMetaData->dwValSize != pSupplierValueMetaData->dwValSize || VmDirCompareMemory( pConsumerValueMetaData->pszValue, pSupplierValueMetaData->pszValue, pConsumerValueMetaData->dwValSize) != 0) { continue; } if (VmDirStringCompareA( pConsumerValueMetaData->pszValChgOrigTime, pSupplierValueMetaData->pszValChgOrigTime, TRUE) > 0) { *pInScope = FALSE; VMDIR_LOG_DEBUG( LDAP_DEBUG_REPL, "%s: supplier attr-value-meta lose: %s consumer: %s", __FUNCTION__, VDIR_SAFE_STRING(bervSupplierValueMetaData.lberbv_val), VDIR_SAFE_STRING(bervConsumerValueMetaData.lberbv_val)); } } if (*pInScope) { VMDIR_LOG_DEBUG( LDAP_DEBUG_REPL, "%s: supplier attr-value-meta won: %s", __FUNCTION__, VDIR_SAFE_STRING(bervSupplierValueMetaData.lberbv_val)); } cleanup: VmDirFreeBervalContent(&bervSupplierValueMetaData); VmDirFreeBervalContent(&bervConsumerValueMetaData); VMDIR_SAFE_FREE_VALUE_METADATA(pConsumerValueMetaData); VmDirFreeAttrValueMetaDataDequeueContent(&valueMetaDataQueue); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
/* * 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; }
/* * 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; }
DWORD VmDirIsAttrValueInScope( PVDIR_OPERATION pOperation, PDEQUE pAllValueMetaDataQueue, PDEQUE pValueMetaDataToSendQueue ) { DWORD dwError = 0; VDIR_BERVALUE bervValueMetaData = VDIR_BERVALUE_INIT; PVMDIR_VALUE_ATTRIBUTE_METADATA pValueMetaData = NULL; if (!pOperation || !pAllValueMetaDataQueue || !pValueMetaDataToSendQueue) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } while (!dequeIsEmpty(pAllValueMetaDataQueue)) { BOOLEAN bUsnInScope = FALSE; VMDIR_SAFE_FREE_VALUE_METADATA(pValueMetaData); dequePopLeft(pAllValueMetaDataQueue, (PVOID*)&pValueMetaData); dwError = VmDirIsUsnInScope( pOperation, NULL, pValueMetaData->pszValChgOrigInvoId, pValueMetaData->valChgOrigUsn, pValueMetaData->localUsn, 0, &bUsnInScope); BAIL_ON_VMDIR_ERROR(dwError); if (!bUsnInScope) { continue; } if (VmDirLogGetMask() & LDAP_DEBUG_REPL) { //ignore error VmDirValueMetaDataSerialize(pValueMetaData, &bervValueMetaData); VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "%s: valueMetaData: %s, usnInScope true", __FUNCTION__, VDIR_SAFE_STRING(bervValueMetaData.lberbv_val)); VmDirFreeBervalContent(&bervValueMetaData); } dwError = dequePush(pValueMetaDataToSendQueue, pValueMetaData); BAIL_ON_VMDIR_ERROR(dwError); pValueMetaData = NULL; } cleanup: VMDIR_SAFE_FREE_VALUE_METADATA(pValueMetaData); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
int VmDirPerformSearch( PVDIR_OPERATION pOperation ) { ber_len_t size = 0; SearchReq * sr = &(pOperation->request.searchReq); int retVal = LDAP_SUCCESS; BerValue* pLberBerv = NULL; PSTR pszLocalErrorMsg = NULL; BOOLEAN bResultAlreadySent = FALSE; PVDIR_LDAP_RESULT pResult = &(pOperation->ldapResult); // Parse base object, scope, deref alias, sizeLimit, timeLimit and typesOnly search parameters. if ( ber_scanf( pOperation->ber, "{miiiib", &(pOperation->reqDn.lberbv), &sr->scope, &sr->derefAlias, &sr->sizeLimit, &sr->timeLimit, &sr->attrsOnly ) == LBER_ERROR ) { VMDIR_LOG_ERROR( LDAP_DEBUG_ARGS, "PerformSearch: Decoding baseDN, ... attrsOnly error." ); pResult->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Decoding error while parsing baseDN, ... attrsOnly."); } VMDIR_LOG_VERBOSE( LDAP_DEBUG_ARGS, "Search Request: base: \"%s\", scope: %d, deref: %d, sizeLimit: %d, timeLimit: %d," "attrsOnly: %d", pOperation->reqDn.lberbv.bv_val, sr->scope, sr->derefAlias, sr->sizeLimit, sr->timeLimit, sr->attrsOnly); if (sr->scope != LDAP_SCOPE_BASE && sr->scope != LDAP_SCOPE_ONELEVEL && sr->scope != LDAP_SCOPE_SUBTREE) { pResult->errCode = retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Invalid scope" ); } if (sr->sizeLimit < 0 || sr->sizeLimit > LDAP_MAXINT) { pResult->errCode = retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Invalid size limit: %d", sr->sizeLimit ); } if (sr->timeLimit < 0 || sr->timeLimit > LDAP_MAXINT) { pResult->errCode = retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Invalid time limit: %d", sr->timeLimit ); } if (sr->derefAlias != LDAP_DEREF_NEVER && sr->derefAlias != LDAP_DEREF_SEARCHING && sr->derefAlias != LDAP_DEREF_FINDING && sr->derefAlias != LDAP_DEREF_ALWAYS) { pResult->errCode = retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Invalid dereference alias parameter"); } // Parse filter retVal = ParseFilter( pOperation, &sr->filter, pResult ); BAIL_ON_VMDIR_ERROR(retVal); // Log String filter, if desired. if (VmDirLogGetLevel() >= VMDIR_LOG_VERBOSE && VmDirLogGetMask() & LDAP_DEBUG_ARGS) { VDIR_BERVALUE strFilter = VDIR_BERVALUE_INIT; FilterToStrFilter( sr->filter, &strFilter ); VMDIR_LOG_VERBOSE( LDAP_DEBUG_ARGS, " Filter: %s", strFilter.lberbv.bv_val ); VmDirFreeBervalContent(&strFilter); } // Parse attributes. 'M' => attribute names point within (in-place) the ber. size = sizeof( BerValue ); // Size of the structure is passed-in, and number of attributes are returned back in // the same parameter. if ( ber_scanf( pOperation->ber, "{M}}", &pLberBerv, &size, 0 ) == LBER_ERROR ) { pResult->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Decoding error while parsing required attributes."); } // copy pLberBerv content into sr->attrs if (pLberBerv && size > 0) { int iCnt = 0; if (VmDirAllocateMemory(sizeof(VDIR_BERVALUE) * (size+1), (PVOID*)&sr->attrs) != 0) { pResult->errCode = retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "no memory"); } for (iCnt = 0; iCnt < size; iCnt++) { sr->attrs[iCnt].lberbv.bv_val = pLberBerv[iCnt].bv_val; sr->attrs[iCnt].lberbv.bv_len = pLberBerv[iCnt].bv_len; } } // Log list of the required attributes, if desired. if (( VmDirLogGetMask() & LDAP_DEBUG_ARGS) && size > 0) { if (VmDirLogSearchRequest(sr, size) != 0) { pResult->errCode = retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "Error while logging search request"); } } // Parse LDAP controls present (if any) in the request. retVal = ParseRequestControls(pOperation, pResult); // ldapResult.errCode set inside BAIL_ON_VMDIR_ERROR( retVal ); retVal = pResult->errCode = VmDirMLSearch( pOperation ); bResultAlreadySent = TRUE; BAIL_ON_VMDIR_ERROR(retVal); cleanup: VMDIR_SAFE_FREE_MEMORY(pLberBerv); VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: VMDIR_APPEND_ERROR_MSG(pResult->pszErrMsg, pszLocalErrorMsg); if (retVal != LDAP_NOTICE_OF_DISCONNECT && bResultAlreadySent == FALSE) { VmDirSendLdapResult( pOperation ); } goto cleanup; }
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; }
static DWORD constructDeletedObjDN( VDIR_BERVALUE * dn, const char * objectGuidStr, VDIR_BERVALUE * deletedObjDN ) { DWORD dwError = 0; VDIR_BERVALUE parentDN = VDIR_BERVALUE_INIT; size_t deletedObjDNLen = 0; size_t delObjsConatinerDNLength = gVmdirServerGlobals.delObjsContainerDN.lberbv.bv_len; char * delObjsConatinerDN = gVmdirServerGlobals.delObjsContainerDN.lberbv.bv_val; deletedObjDN->lberbv.bv_val = NULL; deletedObjDN->lberbv.bv_len = 0; if (!delObjsConatinerDN) { dwError = VMDIR_ERROR_ENTRY_NOT_FOUND; BAIL_ON_VMDIR_ERROR( dwError ); } dwError = VmDirGetParentDN( dn, &parentDN ); BAIL_ON_VMDIR_ERROR( dwError ); // Format of the DN of a deleted object is: // <original RDN>#objectGUID:<object GUID string>,<DN of the Deleted objects container> deletedObjDNLen = (parentDN.lberbv.bv_len ? dn->lberbv.bv_len - parentDN.lberbv.bv_len - 1 /* Count out RDN separator */ : dn->lberbv.bv_len) + 1 /* for # */ + ATTR_OBJECT_GUID_LEN + 1 /* for : */ + VmDirStringLenA( objectGuidStr ) + 1 /* for , */ + delObjsConatinerDNLength; dwError = VmDirAllocateMemory( deletedObjDNLen + 1, (PVOID *)&deletedObjDN->lberbv.bv_val ); BAIL_ON_VMDIR_ERROR( dwError ); deletedObjDN->lberbv.bv_len = parentDN.lberbv.bv_len ? dn->lberbv.bv_len - parentDN.lberbv.bv_len - 1 /* Count out RDN separator */ : dn->lberbv.bv_len; // TODO: how do we know the actual buffer size ? dwError = VmDirCopyMemory( deletedObjDN->lberbv.bv_val, deletedObjDN->lberbv.bv_len, dn->lberbv.bv_val, deletedObjDN->lberbv.bv_len ); BAIL_ON_VMDIR_ERROR( dwError ); deletedObjDN->lberbv.bv_val[deletedObjDN->lberbv.bv_len] = '#'; deletedObjDN->lberbv.bv_len++; // TODO: how do we know the actual buffer size ? dwError = VmDirCopyMemory( deletedObjDN->lberbv.bv_val + deletedObjDN->lberbv.bv_len, ATTR_OBJECT_GUID_LEN, ATTR_OBJECT_GUID, ATTR_OBJECT_GUID_LEN ); BAIL_ON_VMDIR_ERROR( dwError ); deletedObjDN->lberbv.bv_len += ATTR_OBJECT_GUID_LEN; deletedObjDN->lberbv.bv_val[deletedObjDN->lberbv.bv_len] = ':'; deletedObjDN->lberbv.bv_len++; // TODO: how do we know the actual buffer size ? dwError = VmDirCopyMemory( deletedObjDN->lberbv.bv_val + deletedObjDN->lberbv.bv_len, VmDirStringLenA( objectGuidStr ), (PVOID)objectGuidStr, VmDirStringLenA( objectGuidStr ) ); BAIL_ON_VMDIR_ERROR( dwError ); deletedObjDN->lberbv.bv_len += VmDirStringLenA( objectGuidStr ); // TODO: how do we know the actual buffer size ? VmDirStringPrintFA( deletedObjDN->lberbv.bv_val + deletedObjDN->lberbv.bv_len, delObjsConatinerDNLength + 2, ",%s", delObjsConatinerDN ); deletedObjDN->lberbv.bv_len += delObjsConatinerDNLength + 1 /* for , */; cleanup: VmDirFreeBervalContent( &parentDN ); return dwError; error: if (deletedObjDN->lberbv.bv_val != NULL) { VmDirFreeMemory( deletedObjDN->lberbv.bv_val ); deletedObjDN->lberbv.bv_val = NULL; } deletedObjDN->lberbv.bv_len = 0; goto cleanup; }
/* * 1) Find the attribute that holds attribute meta data. * 2) Attributes for usnCreated/usnChanged are updated with current local USN * 3) If we are doing a modify/delete, attribute meta data is checked to see supplier/consumer wins. * - If supplier attribute won, update its meta data with current local USN. * - If consumer wins don't write corresponding attribute. * - Special case: supplier lost for UsnChanged, replace the metaData with consumer's metaData. * 4) If no attribute metaData exists, create it. */ DWORD VmDirReplSetAttrNewMetaData( PVDIR_OPERATION pOperation, PVDIR_ENTRY pEntry, PLW_HASHMAP* ppMetaDataMap ) { DWORD dwError = LDAP_SUCCESS; PVDIR_ATTRIBUTE pCurrAttr = NULL; PVDIR_ATTRIBUTE pPrevAttr = NULL; PVDIR_ATTRIBUTE pAttrAttrMetaData = NULL; PLW_HASHMAP pMetaDataMap = NULL; if (!pOperation || !pEntry || !ppMetaDataMap) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } for (pPrevAttr = NULL, pCurrAttr = pEntry->attrs; pCurrAttr; pPrevAttr = pCurrAttr, pCurrAttr = pCurrAttr->next) { if (VmDirStringCompareA(pCurrAttr->type.lberbv.bv_val, ATTR_ATTR_META_DATA, FALSE) == 0) { if (pPrevAttr == NULL) { pEntry->attrs = pCurrAttr->next; } else { pPrevAttr->next = pCurrAttr->next; } pAttrAttrMetaData = pCurrAttr; dwError = VmDirAttributeMetaDataToHashMap(pAttrAttrMetaData, &pMetaDataMap); BAIL_ON_VMDIR_ERROR(dwError); *ppMetaDataMap = pMetaDataMap; continue; } if (VmDirStringCompareA(pCurrAttr->type.lberbv.bv_val, ATTR_USN_CREATED, FALSE) == 0 || VmDirStringCompareA(pCurrAttr->type.lberbv.bv_val, ATTR_USN_CHANGED, FALSE) == 0) { char pszLocalUsn[VMDIR_MAX_USN_STR_LEN] = {'\0'}; size_t localUsnStrlen = 0; dwError = VmDirStringNPrintFA( pszLocalUsn, sizeof(pszLocalUsn), sizeof(pszLocalUsn) - 1, "%"PRId64, pOperation->pWriteQueueEle->usn); BAIL_ON_VMDIR_ERROR(dwError); localUsnStrlen = VmDirStringLenA(pszLocalUsn); VmDirFreeBervalContent(&pCurrAttr->vals[0]); dwError = VmDirAllocateAndCopyMemory(pszLocalUsn, localUsnStrlen, (PVOID*)&pCurrAttr->vals[0].lberbv.bv_val); BAIL_ON_VMDIR_ERROR(dwError); pCurrAttr->vals[0].lberbv.bv_len = localUsnStrlen; pCurrAttr->vals[0].bOwnBvVal = TRUE; continue; } } if (pAttrAttrMetaData == NULL) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: attrMetaData attribute not present in Entry: %s", __FUNCTION__, pEntry->dn.lberbv.bv_val); BAIL_WITH_VMDIR_ERROR(dwError, LDAP_OPERATIONS_ERROR); } if (pOperation->reqCode == LDAP_REQ_MODIFY) { dwError = VmDirReplResolveConflicts( pOperation, pEntry, pMetaDataMap); BAIL_ON_VMDIR_ERROR(dwError); } dwError = _VmDirReplPopulateAttrNewMetaData( pEntry, pOperation->pWriteQueueEle->usn, pMetaDataMap); BAIL_ON_VMDIR_ERROR(dwError); cleanup: VmDirFreeAttribute(pAttrAttrMetaData); return dwError; error: goto cleanup; }
void VmDirFreeEntryContent( VDIR_ENTRY * e ) { VmDirLog( LDAP_DEBUG_TRACE, "DeleteEntry: Begin" ); if ( e ) { VmDirLog( LDAP_DEBUG_TRACE, "DeleteEntry: DN = %s", e ? (e->dn.lberbv.bv_val ? e->dn.lberbv.bv_val : "") : "" ); if (e->pParentEntry) { VmDirFreeEntryContent(e->pParentEntry); VMDIR_SAFE_FREE_MEMORY(e->pParentEntry); } VmDirFreeLDAPDNContent( &(e->ldapDN) ); VmDirFreeBervalContent( &(e->dn) ); VmDirFreeBervalContent( &(e->pdn) ); VmDirFreeBervalContent( &(e->newpdn) ); if (e->allocType == ENTRY_STORAGE_FORMAT_PACK) { PVDIR_ATTRIBUTE pCurrAttr = NULL; PVDIR_ATTRIBUTE pTempAttr = NULL; pCurrAttr = e->attrs; while(pCurrAttr != NULL) { pTempAttr = pCurrAttr->next; VmDirFreeMetaData(pCurrAttr->pMetaData); pCurrAttr = pTempAttr; } VMDIR_SAFE_FREE_MEMORY( e->encodedEntry ); VmDirFreeBervalArrayContent(e->bvs, e->usNumBVs); VMDIR_SAFE_FREE_MEMORY( e->bvs ); VMDIR_SAFE_FREE_MEMORY( e->savedAttrsPtr ); } else if (e->allocType == ENTRY_STORAGE_FORMAT_NORMAL) { VDIR_ATTRIBUTE * currAttr = NULL; VDIR_ATTRIBUTE * tmpAttr = NULL; VMDIR_SAFE_FREE_MEMORY( e->encodedEntry ); for (currAttr = e->attrs; currAttr != NULL; ) { tmpAttr = currAttr->next; VmDirFreeAttribute(currAttr); currAttr = tmpAttr; } } if (e->pComputedAttrs) { VDIR_ATTRIBUTE * currAttr = NULL; VDIR_ATTRIBUTE * tmpAttr = NULL; for (currAttr = e->pComputedAttrs; currAttr != NULL; ) { tmpAttr = currAttr->next; VmDirFreeAttribute(currAttr); currAttr = tmpAttr; } } VmDirSchemaCtxRelease(e->pSchemaCtx); VmDirAclCtxContentFree(e->pAclCtx); VMDIR_SAFE_FREE_MEMORY(e->pAclCtx); VMDIR_SAFE_FREE_MEMORY(e->pszGuid); memset(e, 0, sizeof(*e)); } VmDirLog( LDAP_DEBUG_TRACE, "DeleteEntry: End" ); }
static int DeleteRefAttributesValue( VDIR_OPERATION * pOperation, VDIR_BERVALUE * dn ) { int retVal = LDAP_SUCCESS; VDIR_FILTER * f = NULL; VDIR_CANDIDATES * cl = NULL; VDIR_ENTRY groupEntry = {0}; VDIR_ENTRY * pGroupEntry = NULL; int i = 0; VDIR_MODIFICATION mod = {0}; ModifyReq mr; VDIR_BERVALUE delVals[2]; PSTR pszLocalErrorMsg = NULL; assert( pOperation != NULL && pOperation->pBEIF != NULL && dn != NULL); retVal = VmDirNormalizeDN( dn, pOperation->pSchemaCtx ); BAIL_ON_VMDIR_ERROR( retVal ); // Set filter retVal = VmDirAllocateMemory( sizeof( VDIR_FILTER ), (PVOID *)&f); BAIL_ON_VMDIR_ERROR( retVal ); f->choice = LDAP_FILTER_EQUALITY; f->filtComp.ava.type.lberbv.bv_val = ATTR_MEMBER; f->filtComp.ava.type.lberbv.bv_len = ATTR_MEMBER_LEN; f->filtComp.ava.value = *dn; if ((f->filtComp.ava.pATDesc = VmDirSchemaAttrNameToDesc( pOperation->pSchemaCtx, ATTR_MEMBER)) == NULL) { retVal = VMDIR_ERROR_NO_SUCH_ATTRIBUTE; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "undefined attribute (%s)", VDIR_SAFE_STRING(ATTR_MEMBER)); } // Set ModifyReq structure memset(&mr, 0, sizeof(ModifyReq)); mod.operation = MOD_OP_DELETE; mod.attr.type.lberbv.bv_val = ATTR_MEMBER; mod.attr.type.lberbv.bv_len = ATTR_MEMBER_LEN; mod.attr.pATDesc = f->filtComp.ava.pATDesc; mod.attr.next = NULL; delVals[0] = *dn; memset(&(delVals[1]), 0, sizeof(VDIR_BERVALUE)); mod.attr.vals = delVals; mod.attr.numVals = 1; mod.next = NULL; mr.mods = &mod; mr.numMods = 1; retVal = pOperation->pBEIF->pfnBEGetCandidates( pOperation->pBECtx, f); if ( retVal != 0 ) { if (retVal == VMDIR_ERROR_BACKEND_ENTRY_NOTFOUND) { retVal = LDAP_SUCCESS; // no member refer to this DN. return ok/0 } else { retVal = VMDIR_ERROR_GENERIC; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "DeleteRefAttributesValue: Building group list (BdbGetCandidates()) failed."); } } else { cl = f->candidates; for (i = 0; i < cl->size; i++) { pGroupEntry = &groupEntry; if ((retVal = VmDirModifyEntryCoreLogic( pOperation, &mr, cl->eIds[i], pGroupEntry)) != 0) { switch (retVal) { case VMDIR_ERROR_BACKEND_PARENT_NOTFOUND: case VMDIR_ERROR_BACKEND_ENTRY_NOTFOUND: case VMDIR_ERROR_ENTRY_NOT_FOUND: continue; default: // Including LDAP_LOCK_DEADLOCK, which is handled by the caller BAIL_ON_VMDIR_ERROR( retVal ); } } VmDirFreeBervalContent( &(mr.dn) ); // VmDirModifyEntryCoreLogic fill in DN if not exists VmDirFreeEntryContent( pGroupEntry ); pGroupEntry = NULL; // Reset to NULL so that DeleteEntry is no-op. } } cleanup: memset(&(f->filtComp.ava.value), 0, sizeof(VDIR_BERVALUE)); // Since ava.value is NOT owned by filter. DeleteFilter( f ); VmDirFreeEntryContent( pGroupEntry ); VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: VMDIR_APPEND_ERROR_MSG(pOperation->ldapResult.pszErrMsg, pszLocalErrorMsg); goto cleanup; }
/* * TODO: Should not allow renaming computers, domain controllers, replication * agreements, server objects */ static int VmDirGenerateRenameAttrsMods( PVDIR_OPERATION pOperation ) { int retVal = 0; ModifyReq * modReq = &(pOperation->request.modifyReq); VDIR_BERVALUE parentdn = VDIR_BERVALUE_INIT; VDIR_BERVALUE NewDn = VDIR_BERVALUE_INIT; VDIR_BERVALUE OldRdn = VDIR_BERVALUE_INIT; VDIR_BERVALUE NewRdn = VDIR_BERVALUE_INIT; PSTR pszOldRdnAttrName = NULL; PSTR pszOldRdnAttrVal = NULL; PSTR pszNewRdnAttrName = NULL; PSTR pszNewRdnAttrVal = NULL; if (modReq->newrdn.lberbv.bv_len == 0) { goto cleanup; // Nothing to do } if (strchr(modReq->newrdn.lberbv.bv_val, RDN_SEPARATOR_CHAR)) // FIXME : Need to handle escape { retVal = VMDIR_ERROR_UNWILLING_TO_PERFORM; //BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, pszLocalErrMsg, "New RDN has more than one component"); BAIL_ON_VMDIR_ERROR(retVal); } if (modReq->newSuperior.lberbv.bv_len) { retVal = VmDirNormalizeDN(&(modReq->newSuperior), pOperation->pSchemaCtx); BAIL_ON_VMDIR_ERROR(retVal) retVal = VmDirCatDN(&modReq->newrdn, &modReq->newSuperior, &NewDn); BAIL_ON_VMDIR_ERROR(retVal); } else { retVal = VmDirGetParentDN(&modReq->dn, &parentdn); BAIL_ON_VMDIR_ERROR(retVal); retVal = VmDirCatDN(&modReq->newrdn, &parentdn, &NewDn); BAIL_ON_VMDIR_ERROR(retVal); } retVal = VmDirNormalizeDN(&NewDn, pOperation->pSchemaCtx); BAIL_ON_VMDIR_ERROR(retVal); retVal = VmDirGetRdn(&NewDn, &NewRdn); BAIL_ON_VMDIR_ERROR(retVal); retVal = VmDirRdnToNameValue(&NewRdn, &pszNewRdnAttrName, &pszNewRdnAttrVal); BAIL_ON_VMDIR_ERROR(retVal); retVal = VmDirGetRdn(&modReq->dn, &OldRdn); BAIL_ON_VMDIR_ERROR(retVal); retVal = VmDirRdnToNameValue(&OldRdn, &pszOldRdnAttrName, &pszOldRdnAttrVal); BAIL_ON_VMDIR_ERROR(retVal); // Change DN retVal = VmDirAppendAMod(pOperation, MOD_OP_REPLACE, ATTR_DN, ATTR_DN_LEN, NewDn.bvnorm_val, NewDn.bvnorm_len); BAIL_ON_VMDIR_ERROR(retVal); if (strcmp(pszNewRdnAttrName, pszOldRdnAttrName) == 0) { if (strcmp(pszNewRdnAttrVal, pszOldRdnAttrVal) != 0) { // Change was like CN=User1,... to CN=User2,... then may want to // modify CN if bDeleteOldRdn if (modReq->bDeleteOldRdn) { retVal = VmDirAppendAMod(pOperation, MOD_OP_DELETE, pszOldRdnAttrName, (int) VmDirStringLenA(pszOldRdnAttrName), pszOldRdnAttrVal, VmDirStringLenA(pszOldRdnAttrVal)); BAIL_ON_VMDIR_ERROR(retVal); } retVal = VmDirAppendAMod(pOperation, MOD_OP_ADD, pszNewRdnAttrName, (int)VmDirStringLenA(pszNewRdnAttrName), pszNewRdnAttrVal, VmDirStringLenA(pszNewRdnAttrVal)); BAIL_ON_VMDIR_ERROR(retVal); } } else { // If change was like CN=User1,... to OU=MyOU,... then // need to add attribute OU=MyOu and potentially delete attribute CN=User1 retVal = VmDirAppendAMod(pOperation, MOD_OP_ADD, pszNewRdnAttrName, (int)VmDirStringLenA(pszNewRdnAttrName), pszNewRdnAttrVal, VmDirStringLenA(pszNewRdnAttrVal)); BAIL_ON_VMDIR_ERROR(retVal); if (modReq->bDeleteOldRdn) { retVal = VmDirAppendAMod(pOperation, MOD_OP_DELETE, pszOldRdnAttrName,(int) VmDirStringLenA(pszOldRdnAttrName), NULL, 0); BAIL_ON_VMDIR_ERROR(retVal); } } cleanup: VmDirFreeBervalContent(&parentdn); VmDirFreeBervalContent(&NewDn); VmDirFreeBervalContent(&OldRdn); VmDirFreeBervalContent(&NewRdn); VMDIR_SAFE_FREE_STRINGA(pszOldRdnAttrName); VMDIR_SAFE_FREE_STRINGA(pszOldRdnAttrVal); VMDIR_SAFE_FREE_STRINGA(pszNewRdnAttrName); VMDIR_SAFE_FREE_STRINGA(pszNewRdnAttrVal); return retVal; error: goto cleanup; }
static DWORD _PopulateOperationModAttributes( LDAP *pLd, LDAPMessage *pEntry, PVDIR_OPERATION pLdapOp ) { DWORD dwError = 0; struct berval** ppValues = NULL; PLW_HASHMAP pHashMap = NULL; PSTR pszBuf = NULL; PSTR pszAttrName = NULL; PSTR pszAttrMetaData = NULL; PSTR pszAttrUsnlessMetaData = NULL; PSTR pszAttrNewMetaData = NULL; PSTR pszKey = NULL; PSTR pszValue = NULL; USN localUsn = 0; PVDIR_BERVALUE pBerValue = NULL; size_t iBerValueSize = 0; DWORD i = 0, j = 0; dwError = LwRtlCreateHashMap( &pHashMap, LwRtlHashDigestPstrCaseless, LwRtlHashEqualPstrCaseless, NULL ); BAIL_ON_VMDIR_ERROR(dwError); dwError = pLdapOp->pBEIF->pfnBEGetNextUSN(pLdapOp->pBECtx, &localUsn); BAIL_ON_VMDIR_ERROR(dwError); if (!(ppValues = ldap_get_values_len(pLd, pEntry, ATTR_ATTR_META_DATA))) { dwError = VMDIR_ERROR_SCHEMA_BAD_METADATA; BAIL_ON_VMDIR_ERROR(dwError); } for (i = 0; ppValues[i] != NULL; i++) { dwError = VmDirAllocateStringA(ppValues[i]->bv_val, &pszBuf); BAIL_ON_VMDIR_ERROR(dwError); pszAttrName = VmDirStringTokA(pszBuf, ":", &pszAttrMetaData); VmDirStringTokA(pszAttrMetaData, ":", &pszAttrUsnlessMetaData); dwError = VmDirAllocateStringPrintf( &pszAttrNewMetaData, "%ld:%s", localUsn, pszAttrUsnlessMetaData); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringA(pszAttrName, &pszKey); BAIL_ON_VMDIR_ERROR(dwError); dwError = LwRtlHashMapInsert(pHashMap, pszKey, pszAttrNewMetaData, NULL); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_SAFE_FREE_MEMORY(pszBuf); } ldap_value_free_len(ppValues); ppValues = NULL; for (i = 0; ppszSchemaEntryAttrs[i] != NULL; i++) { if (VmDirStringCompareA(ppszSchemaEntryAttrs[i], ATTR_ATTR_META_DATA, FALSE) != 0) { ppValues = ldap_get_values_len(pLd, pEntry, ppszSchemaEntryAttrs[i]); if (ppValues) { iBerValueSize = ldap_count_values_len(ppValues); dwError = VmDirAllocateMemory( sizeof(VDIR_BERVALUE) * iBerValueSize, (PVOID*)&pBerValue); BAIL_ON_VMDIR_ERROR(dwError); if (VmDirStringCompareA(ppszSchemaEntryAttrs[i], ATTR_USN_CHANGED, FALSE) == 0) { assert(iBerValueSize == 1); dwError = VmDirAllocateStringPrintf(&pBerValue[0].lberbv_val, "%ld", localUsn); BAIL_ON_VMDIR_ERROR(dwError); pBerValue[0].lberbv_len = VmDirStringLenA(pBerValue[0].lberbv_val); pBerValue[0].bOwnBvVal = TRUE; } else { for (j = 0; j < iBerValueSize; j++) { dwError = VmDirAllocateStringA(ppValues[j]->bv_val, &pBerValue[j].lberbv_val); BAIL_ON_VMDIR_ERROR(dwError); pBerValue[j].lberbv_len = ppValues[j]->bv_len; pBerValue[j].bOwnBvVal = TRUE; } } dwError = VmDirOperationAddModReq( pLdapOp, MOD_OP_REPLACE, ppszSchemaEntryAttrs[i], pBerValue, iBerValueSize); BAIL_ON_VMDIR_ERROR(dwError); dwError = LwRtlHashMapFindKey( pHashMap, (PVOID*)&pszValue, ppszSchemaEntryAttrs[i]); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirStringCpyA( pLdapOp->request.modifyReq.mods->attr.metaData, VMDIR_MAX_ATTR_META_DATA_LEN, pszValue); BAIL_ON_VMDIR_ERROR(dwError); ldap_value_free_len(ppValues); ppValues = NULL; for (j = 0; j < iBerValueSize; j++) { VmDirFreeBervalContent(&pBerValue[j]); } VMDIR_SAFE_FREE_MEMORY(pBerValue); } } } cleanup: LwRtlHashMapClear(pHashMap, _FreeStringPair, NULL); LwRtlFreeHashMap(&pHashMap); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s,%d failed, error(%d)", __FUNCTION__, __LINE__, dwError ); VMDIR_SAFE_FREE_MEMORY(pszBuf); VMDIR_SAFE_FREE_MEMORY(pszAttrNewMetaData); if (ppValues) { ldap_value_free_len(ppValues); } for (j = 0; j < iBerValueSize; j++) { VmDirFreeBervalContent(&pBerValue[j]); } VMDIR_SAFE_FREE_MEMORY(pBerValue); goto cleanup; }
/* * Duplicate content of pBerval into pDupBerval */ DWORD VmDirBervalContentDup( PVDIR_BERVALUE pBerval, PVDIR_BERVALUE pDupBerval ) { DWORD dwError = 0; assert(pBerval && pDupBerval); VmDirFreeBervalContent(pDupBerval); dwError = VmDirAllocateMemory(pBerval->lberbv.bv_len+1, (PVOID*)&pDupBerval->lberbv.bv_val); BAIL_ON_VMDIR_ERROR(dwError); if (pBerval->lberbv.bv_len > 0) { dwError = VmDirCopyMemory( pDupBerval->lberbv.bv_val, (pBerval->lberbv.bv_len+1), pBerval->lberbv.bv_val, pBerval->lberbv.bv_len ); BAIL_ON_VMDIR_ERROR(dwError); } pDupBerval->bOwnBvVal = TRUE; pDupBerval->lberbv.bv_len = pBerval->lberbv.bv_len; if (pBerval->lberbv.bv_val == pBerval->bvnorm_val) { pDupBerval->bvnorm_val = pDupBerval->lberbv.bv_val; pDupBerval->bvnorm_len = pDupBerval->lberbv.bv_len; } else if (pBerval->bvnorm_val == NULL) { pDupBerval->bvnorm_val = NULL; pDupBerval->bvnorm_len = 0; } else { dwError = VmDirAllocateMemory(pBerval->bvnorm_len+1, (PVOID*)&pDupBerval->bvnorm_val); BAIL_ON_VMDIR_ERROR(dwError); if (pBerval->bvnorm_len > 0) { dwError = VmDirCopyMemory( pDupBerval->bvnorm_val, pBerval->bvnorm_len+1, pBerval->bvnorm_val, pBerval->bvnorm_len ); BAIL_ON_VMDIR_ERROR(dwError); } pDupBerval->bvnorm_len = pBerval->bvnorm_len; } cleanup: return dwError; error: VmDirFreeBervalContent(pDupBerval); goto cleanup; }
/* * DelAttrValsFromEntryStruct: Deletes a complete attribute or specific attribute values from the entry. * Assumption: This function assumes/asserts that the modAttr does exist in the entry. * */ static int DelAttrValsFromEntryStruct( PVDIR_SCHEMA_CTX pSchemaCtx, VDIR_ENTRY * e, VDIR_ATTRIBUTE * modAttr, PSTR* ppszErrorMsg ) { int retVal = LDAP_SUCCESS; VDIR_ATTRIBUTE * prevAttr = NULL; VDIR_ATTRIBUTE * currAttr = NULL; VDIR_ATTRIBUTE * eAttr = NULL; unsigned int i = 0; unsigned int j = 0; PSTR pszLocalErrorMsg = NULL; assert(e->allocType == ENTRY_STORAGE_FORMAT_NORMAL); // Locate which attribute (values) we are trying to delete for (currAttr = e->attrs; currAttr != NULL; prevAttr = currAttr, currAttr = currAttr->next) { if (VmDirStringCompareA(modAttr->type.lberbv.bv_val, currAttr->type.lberbv.bv_val, FALSE) == 0) { break; } } assert(currAttr != NULL); eAttr = currAttr; // Normalize eAttr values for (i = 0; i < eAttr->numVals; i++) { retVal = VmDirSchemaBervalNormalize(pSchemaCtx, eAttr->pATDesc, &eAttr->vals[i]); BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "normalize (%s)(%.*s)", VDIR_SAFE_STRING(eAttr->pATDesc->pszName), VMDIR_MIN(eAttr->vals[i].lberbv.bv_len, VMDIR_MAX_LOG_OUTPUT_LEN), VDIR_SAFE_STRING(eAttr->vals[i].lberbv.bv_val)); } if (modAttr->numVals == 1 && eAttr->pATDesc->bSingleValue && (VmDirStringCompareA(eAttr->pATDesc->pszName, ATTR_MODIFYTIMESTAMP, FALSE) == 0 || VmDirStringCompareA(eAttr->pATDesc->pszName, ATTR_CREATETIMESTAMP, FALSE) == 0 || VmDirStringCompareA(eAttr->pATDesc->pszName, ATTR_CREATORS_NAME, FALSE) == 0 || VmDirStringCompareA(eAttr->pATDesc->pszName, ATTR_MODIFIERS_NAME, FALSE) == 0)) { /* Force deleting the attribute value whether or not the value matches. * A raft follower may alter the timestamps/creator locally, e.g. rollback vmwAttrUniquenessScope, * which may fail to remove the value if it doesn't match that value seen at the raft leader. */ VmDirFreeBervalContent(&modAttr->vals[0]); modAttr->numVals = 0; } // Complete attribute is to be deleted. if (modAttr->numVals == 0) { // Make a copy of BerValues into modAttr so that these values can be used to delete from the index, // if it is an indexed attribute. VMDIR_SAFE_FREE_MEMORY(modAttr->vals); retVal = VmDirAllocateMemory((eAttr->numVals + 1) * sizeof(VDIR_BERVALUE), (PVOID *)&modAttr->vals); BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "no memory"); for (i = 0; i < eAttr->numVals; i++) { VmDirBervalContentDup(&eAttr->vals[i], &modAttr->vals[i]); } modAttr->numVals = eAttr->numVals; // Adjust the "next" pointer of the attribute before the attribute being deleted. => Altering the attribute // chain. if (prevAttr == NULL) // if it is the first attribute { e->attrs = eAttr->next; } else { prevAttr->next = eAttr->next; } VmDirFreeAttribute(eAttr); } else // Specific attribute values need to be deleted. { // Check if all attribute values that are being deleted exist in the Attribute for (i=0; i < modAttr->numVals; i++) { // modAttr values are already normalized. assert(modAttr->vals[i].bvnorm_val); for (j = 0; j < eAttr->numVals; j++) { // eAttr values are already normalized. assert(eAttr->vals[j].bvnorm_val); if (modAttr->vals[i].bvnorm_len == eAttr->vals[j].bvnorm_len && memcmp(modAttr->vals[i].bvnorm_val, eAttr->vals[j].bvnorm_val, modAttr->vals[i].bvnorm_len) == 0) { break; } } if (j == eAttr->numVals) // did not find a match { retVal = VMDIR_ERROR_NO_SUCH_ATTRIBUTE; BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "Attribute (%s) value (%.*s) being deleted does not exist.", VDIR_SAFE_STRING(modAttr->type.lberbv.bv_val), VMDIR_MIN(modAttr->vals[i].lberbv.bv_len, VMDIR_MAX_LOG_OUTPUT_LEN), VDIR_SAFE_STRING(modAttr->vals[i].lberbv.bv_val)); } } // All values are being deleted. => Delete the whole attribute if (modAttr->numVals == eAttr->numVals) { // Adjust the "next" pointer of the attribute before the attribute being deleted. => Altering the attribute // chain. if (prevAttr == NULL) // if it is the first attribute { e->attrs = eAttr->next; } else { prevAttr->next = eAttr->next; } VmDirFreeAttribute(eAttr); } else { RemoveAttrVals(eAttr, modAttr); } } cleanup: if (ppszErrorMsg) { *ppszErrorMsg = pszLocalErrorMsg; } else { VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); } return retVal; error: goto cleanup; }