int ParseSyncStateControlVal( BerValue * controlValue, // Input: control value encoded as ber, int * entryState) // Output { int retVal = LDAP_SUCCESS; BerElementBuffer berbuf; BerElement * ber = (BerElement *)&berbuf; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncStateControlVal: Begin." ); ber_init2( ber, controlValue, LBER_USE_DER ); if (ber_scanf( ber, "{i}", entryState ) == -1 ) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ParseSyncStateControlVal: ber_scanf to read entryState failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } cleanup: VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncStateControlVal: Begin." ); return retVal; error: goto cleanup; }
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; }
static ber_tag_t GetResultTag( ber_tag_t tag ) { VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "GetResultTag: Begin" ); switch( tag ) { case LDAP_REQ_ADD: tag = LDAP_RES_ADD; break; case LDAP_REQ_BIND: tag = LDAP_RES_BIND; break; case LDAP_REQ_COMPARE: tag = LDAP_RES_COMPARE; break; case LDAP_REQ_EXTENDED: tag = LDAP_RES_EXTENDED; break; case LDAP_REQ_MODIFY: tag = LDAP_RES_MODIFY; break; case LDAP_REQ_MODRDN: tag = LDAP_RES_MODRDN; break; case LDAP_REQ_DELETE: tag = LDAP_RES_DELETE; break; case LDAP_REQ_SEARCH: tag = LDAP_RES_SEARCH_RESULT; break; case LDAP_REQ_ABANDON: case LDAP_REQ_UNBIND: default: tag = LBER_SEQUENCE; break; } VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "GetResultTag: End" ); return tag; }
int WritePagedSearchDoneControl( VDIR_OPERATION * op, BerElement * ber ) { int retVal = LDAP_OPERATIONS_ERROR; BerElementBuffer ctrlValBerbuf; BerElement * ctrlValBer = (BerElement *) &ctrlValBerbuf; VDIR_BERVALUE bvCtrlVal = VDIR_BERVALUE_INIT; if (!op || !op->showPagedResultsCtrl) { retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } if ( op->showPagedResultsCtrl) { VDIR_PAGED_RESULT_CONTROL_VALUE* prCtrlVal = &op->showPagedResultsCtrl->value.pagedResultCtrlVal; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WritePagedSearchDoneControl: Paged Search Done Control Value: pageSize[%d] cookie[%s]", prCtrlVal->pageSize, prCtrlVal->cookie ); (void) memset( (char *)&ctrlValBerbuf, '\0', sizeof( BerElementBuffer )); ber_init2( ctrlValBer, NULL, LBER_USE_DER ); if (ber_printf( ctrlValBer, "{is}", 0, prCtrlVal->cookie) == -1 ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Paged Search Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } bvCtrlVal.lberbv.bv_val = ctrlValBer->ber_buf; bvCtrlVal.lberbv.bv_len = ctrlValBer->ber_ptr - ctrlValBer->ber_buf; if (ber_printf(ber, "t{{sO}}", LDAP_TAG_CONTROLS, LDAP_CONTROL_PAGEDRESULTS, &bvCtrlVal.lberbv ) == -1) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WritePagedSearchDoneControl: ber_printf (to print Search Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } } retVal = LDAP_SUCCESS; cleanup: ber_free_buf( ctrlValBer ); return retVal; error: goto cleanup; }
void DeleteControls( VDIR_LDAP_CONTROL ** controls ) { VDIR_LDAP_CONTROL * curr = NULL; VDIR_LDAP_CONTROL * next = NULL; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "DeleteControls: Begin." ); if (controls != NULL) { for (curr = *controls; curr != NULL; curr = next) { next = curr->next; VMDIR_SAFE_FREE_MEMORY( curr ); } *controls = NULL; } VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "DeleteControls: End." ); }
static DWORD _VmDirNormaliseNameField( PSTR pszSource , size_t dwLen ) { DWORD i = 0; DWORD j = 0; DWORD dwError = 0; DWORD dwState = 0; for (i=0 ; i<dwLen ;i++ ) { if (pszSource[i] == ' ') { if (dwState == 0 ) { pszSource[j++] = pszSource[i]; dwState = 1; } else { // Do Nothing , Ignore Extra Spaces .. } } else { pszSource[j++] = pszSource[i]; dwState = 0; } } pszSource[j++] = '\0' ; VMDIR_LOG_DEBUG( VMDIR_LOG_MASK_ALL, "Formatted NAME string is - %s", VDIR_SAFE_STRING(pszSource) ); return dwError ; }
/* * 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; }
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; }
static int _VmDirSwapDB( PCSTR dbHomeDir, BOOLEAN bHasXlog) { int retVal = LDAP_SUCCESS; char dbExistingName[VMDIR_MAX_FILE_NAME_LEN] = {0}; char dbNewName[VMDIR_MAX_FILE_NAME_LEN] = {0}; PSTR pszLocalErrorMsg = NULL; int errorCode = 0; BOOLEAN bLegacyDataLoaded = FALSE; PVDIR_BACKEND_INTERFACE pBE = NULL; #ifndef _WIN32 const char fileSeperator = '/'; #else const char fileSeperator = '\\'; #endif // Shutdown backend pBE = VmDirBackendSelect(NULL); assert(pBE); VmDirdStateSet(VMDIRD_STATE_SHUTDOWN); VmDirIndexLibShutdown(); VmDirSchemaLibShutdown(); pBE->pfnBEShutdown(); VmDirBackendContentFree(pBE); // move .mdb files retVal = VmDirStringPrintFA( dbExistingName, VMDIR_MAX_FILE_NAME_LEN, "%s%c%s%c%s", dbHomeDir, fileSeperator, LOCAL_PARTNER_DIR, fileSeperator, VMDIR_MDB_DATA_FILE_NAME); BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "_VmDirSwapDB: VmDirStringPrintFA() call failed with error: %d", retVal ); retVal = VmDirStringPrintFA( dbNewName, VMDIR_MAX_FILE_NAME_LEN, "%s%c%s", dbHomeDir, fileSeperator, VMDIR_MDB_DATA_FILE_NAME ); BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "_VmDirSwapDB: VmDirStringPrintFA() call failed with error: %d", retVal ); #ifdef WIN32 if (MoveFileEx(dbExistingName, dbNewName, MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING) == 0) { retVal = LDAP_OPERATIONS_ERROR; errorCode = GetLastError(); #else if (rename(dbExistingName, dbNewName) != 0) { retVal = LDAP_OPERATIONS_ERROR; errorCode = errno; #endif BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "_VmDirSwapDB: rename file from %s to %s failed, errno %d", dbExistingName, dbNewName, errorCode ); } retVal = VmDirStringPrintFA(dbNewName, VMDIR_MAX_FILE_NAME_LEN, "%s%c%s%c%s", dbHomeDir, fileSeperator, VMDIR_MDB_XLOGS_DIR_NAME); BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "_VmDirSwapDB: VmDirStringPrintFA() call failed with error: %d", retVal ); if (bHasXlog) { //move xlog directory retVal = VmDirStringPrintFA(dbExistingName, VMDIR_MAX_FILE_NAME_LEN, "%s%c%s%c%s", dbHomeDir, fileSeperator, LOCAL_PARTNER_DIR, fileSeperator, VMDIR_MDB_XLOGS_DIR_NAME); BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "_VmDirSwapDB: VmDirStringPrintFA() call failed with error: %d", retVal ); #ifdef WIN32 if (MoveFileEx(dbExistingName, dbNewName, MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING) == 0) { retVal = LDAP_OPERATIONS_ERROR; errorCode = GetLastError(); #else if (rmdir(dbNewName) != 0) { retVal = LDAP_OPERATIONS_ERROR; errorCode = errno; BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "_VmDirSwapDB cannot remove directory %s, errno %d", dbNewName, errorCode); } if (rename(dbExistingName, dbNewName) != 0) { retVal = LDAP_OPERATIONS_ERROR; errorCode = errno; #endif BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "_VmDirSwapDB cannot move directory from %s to %s, errno %d", dbNewName, dbExistingName, errorCode); } } retVal = VmDirStringPrintFA(dbExistingName, VMDIR_MAX_FILE_NAME_LEN, "%s%c%s", dbHomeDir, fileSeperator, LOCAL_PARTNER_DIR); BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "_VmDirSwapDB: VmDirStringPrintFA() call failed with error: %d", retVal ); #ifdef WIN32 if (RemoveDirectory(dbExistingName)==0) { errorCode = GetLastError(); #else if (rmdir(dbExistingName)) { errorCode = errno; #endif VMDIR_LOG_WARNING(VMDIR_LOG_MASK_ALL, "cannot remove directory %s errno %d", dbExistingName, errorCode); } VmDirdStateSet(VMDIRD_STATE_STARTUP); retVal = VmDirInitBackend(&bLegacyDataLoaded); BAIL_ON_VMDIR_ERROR(retVal); if (bLegacyDataLoaded) { retVal = VmDirPatchLocalSubSchemaSubEntry(); BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrorMsg, "_VmDirSwapDB: failed to patch subschema subentry: %d", retVal ); retVal = VmDirWriteSchemaObjects(); BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrorMsg, "_VmDirSwapDB: failed to create schema tree: %d", retVal ); } VmDirdStateSet(VMDIRD_STATE_NORMAL); cleanup: VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: retVal = LDAP_OPERATIONS_ERROR; VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s", VDIR_SAFE_STRING(pszLocalErrorMsg) ); goto cleanup; } static int _VmDirWrapUpFirstReplicationCycle( PCSTR pszHostname, VMDIR_REPLICATION_AGREEMENT * pReplAgr) { int retVal = LDAP_SUCCESS; PVDIR_ENTRY pPartnerServerEntry = NULL; PVDIR_ATTRIBUTE pAttrUpToDateVector = NULL; PVDIR_ATTRIBUTE pAttrInvocationId = NULL; USN localUsn = 0; USN partnerLocalUsn = 0; char partnerlocalUsnStr[VMDIR_MAX_USN_STR_LEN]; VDIR_BACKEND_CTX beCtx = {0}; struct berval syncDoneCtrlVal = {0}; PVDIR_SCHEMA_CTX pSchemaCtx = NULL; VDIR_OPERATION searchOp = {0}; PVDIR_FILTER pSearchFilter = NULL; PSTR pszSeparator = NULL; retVal = VmDirSchemaCtxAcquire(&pSchemaCtx); BAIL_ON_VMDIR_ERROR( retVal ); retVal = VmDirInitStackOperation( &searchOp, VDIR_OPERATION_TYPE_INTERNAL, LDAP_REQ_SEARCH, pSchemaCtx ); BAIL_ON_VMDIR_ERROR(retVal); searchOp.pBEIF = VmDirBackendSelect(NULL); assert(searchOp.pBEIF); searchOp.reqDn.lberbv.bv_val = ""; searchOp.reqDn.lberbv.bv_len = 0; searchOp.request.searchReq.scope = LDAP_SCOPE_SUBTREE; retVal = VmDirConcatTwoFilters(searchOp.pSchemaCtx, ATTR_CN, (PSTR) pszHostname, ATTR_OBJECT_CLASS, OC_DIR_SERVER, &pSearchFilter); BAIL_ON_VMDIR_ERROR(retVal); searchOp.request.searchReq.filter = pSearchFilter; retVal = VmDirInternalSearch(&searchOp); BAIL_ON_VMDIR_ERROR(retVal); if (searchOp.internalSearchEntryArray.iSize != 1) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_VmDirWrapUpFirstReplicationCycle: Unexpected (not 1) number of partner server entries found (%d)", searchOp.internalSearchEntryArray.iSize ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR(retVal); } pPartnerServerEntry = searchOp.internalSearchEntryArray.pEntry; pAttrUpToDateVector = VmDirEntryFindAttribute( ATTR_UP_TO_DATE_VECTOR, pPartnerServerEntry ); pAttrInvocationId = VmDirEntryFindAttribute( ATTR_INVOCATION_ID, pPartnerServerEntry ); assert( pAttrInvocationId != NULL ); beCtx.pBE = VmDirBackendSelect(NULL); assert(beCtx.pBE); if ((retVal = beCtx.pBE->pfnBEGetNextUSN( &beCtx, &localUsn )) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_VmDirWrapUpFirstReplicationCycle: pfnBEGetNextUSN failed with error code: %d, " "error message: %s", retVal, VDIR_SAFE_STRING(beCtx.pszBEErrorMsg) ); BAIL_ON_VMDIR_ERROR( retVal ); } retVal = _VmGetHighestCommittedUSN(localUsn, &partnerLocalUsn); BAIL_ON_VMDIR_ERROR( retVal ); VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "_VmDirWrapUpFirstReplicationCycle: partnerLocalUsn %llu locaUsn %llu", partnerLocalUsn, localUsn); if ((retVal = VmDirStringNPrintFA( partnerlocalUsnStr, sizeof(partnerlocalUsnStr), sizeof(partnerlocalUsnStr) - 1, "%" PRId64, partnerLocalUsn)) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_VmDirWrapUpFirstReplicationCycle: VmDirStringNPrintFA failed with error code: %d", retVal ); BAIL_ON_VMDIR_ERROR( retVal ); } if (pAttrUpToDateVector) { if (VmDirStringEndsWith( pAttrUpToDateVector->vals[0].lberbv.bv_val, ",", FALSE)) { pszSeparator = ""; } else { pszSeparator = ","; } // <partnerLocalUSN>,<partner up-to-date vector>,<partner server GUID>:<partnerLocalUSN>, retVal = VmDirAllocateStringPrintf( &(syncDoneCtrlVal.bv_val), "%s,%s%s%s:%s,", partnerlocalUsnStr, pAttrUpToDateVector->vals[0].lberbv.bv_val, pszSeparator, pAttrInvocationId->vals[0].lberbv.bv_val, partnerlocalUsnStr); BAIL_ON_VMDIR_ERROR(retVal); } else { // <partnerLocalUSN>,<partner server GUID>:<partnerLocalUSN>, retVal = VmDirAllocateStringPrintf( &(syncDoneCtrlVal.bv_val), "%s,%s:%s,", partnerlocalUsnStr, pAttrInvocationId->vals[0].lberbv.bv_val, partnerlocalUsnStr); BAIL_ON_VMDIR_ERROR(retVal); } VmDirSetACLMode(); syncDoneCtrlVal.bv_len = VmDirStringLenA(syncDoneCtrlVal.bv_val); if ((retVal = VmDirReplUpdateCookies( pSchemaCtx, &(syncDoneCtrlVal), pReplAgr )) != LDAP_SUCCESS) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "vdirReplicationThrFun: UpdateCookies failed. Error: %d", retVal ); BAIL_ON_VMDIR_ERROR( retVal ); } if ((retVal = _VmDirPatchDSERoot(pSchemaCtx)) != LDAP_SUCCESS) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "vdirReplicationThrFun: _VmDirPatchDSERoot failed. Error: %d", retVal ); BAIL_ON_VMDIR_ERROR( retVal ); } cleanup: VmDirFreeOperationContent(&searchOp); VmDirBackendCtxContentFree(&beCtx); VMDIR_SAFE_FREE_MEMORY(syncDoneCtrlVal.bv_val); VmDirSchemaCtxRelease(pSchemaCtx); return retVal; error: retVal = LDAP_OPERATIONS_ERROR; goto cleanup; } #ifndef VDIR_PSC_VERSION #define VDIR_PSC_VERSION "6.7.0" #endif static int _VmDirPatchDSERoot( PVDIR_SCHEMA_CTX pSchemaCtx) { int retVal = LDAP_SUCCESS; VDIR_OPERATION op = {0}; VDIR_BERVALUE bvDSERootDN = VDIR_BERVALUE_INIT; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "_VmDirPatchDSERoot: Begin" ); bvDSERootDN.lberbv.bv_val = PERSISTED_DSE_ROOT_DN; bvDSERootDN.lberbv.bv_len = VmDirStringLenA( bvDSERootDN.lberbv.bv_val ); retVal = VmDirInitStackOperation( &op, VDIR_OPERATION_TYPE_INTERNAL, LDAP_REQ_MODIFY, pSchemaCtx ); BAIL_ON_VMDIR_ERROR(retVal); retVal = VmDirNormalizeDN( &bvDSERootDN, pSchemaCtx); BAIL_ON_VMDIR_ERROR(retVal); retVal = VmDirBervalContentDup( &bvDSERootDN, &op.reqDn ); BAIL_ON_VMDIR_ERROR(retVal); op.pBEIF = VmDirBackendSelect(op.reqDn.lberbv.bv_val); assert(op.pBEIF); if (VmDirBervalContentDup( &op.reqDn, &op.request.modifyReq.dn ) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_VmDirPatchDSERoot: BervalContentDup failed." ); BAIL_ON_VMDIR_ERROR( retVal ); } retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_DC_ACCOUNT_UPN, ATTR_DC_ACCOUNT_UPN_LEN, gVmdirServerGlobals.dcAccountUPN.lberbv.bv_val, gVmdirServerGlobals.dcAccountUPN.lberbv.bv_len ); BAIL_ON_VMDIR_ERROR( retVal ); retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_DC_ACCOUNT_DN, ATTR_DC_ACCOUNT_DN_LEN, gVmdirServerGlobals.dcAccountDN.lberbv.bv_val, gVmdirServerGlobals.dcAccountDN.lberbv.bv_len ); BAIL_ON_VMDIR_ERROR( retVal ); retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_SERVER_NAME, ATTR_SERVER_NAME_LEN, gVmdirServerGlobals.serverObjDN.lberbv.bv_val, gVmdirServerGlobals.serverObjDN.lberbv.bv_len ); BAIL_ON_VMDIR_ERROR( retVal ); retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_SITE_NAME, ATTR_SITE_NAME_LEN, gVmdirServerGlobals.pszSiteName, VmDirStringLenA(gVmdirServerGlobals.pszSiteName) ); BAIL_ON_VMDIR_ERROR( retVal ); retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_PSC_VERSION, ATTR_PSC_VERSION_LEN, VDIR_PSC_VERSION, VmDirStringLenA(VDIR_PSC_VERSION) ); BAIL_ON_VMDIR_ERROR( retVal ); retVal = VmDirAppendAMod( &op, MOD_OP_REPLACE, ATTR_MAX_DOMAIN_FUNCTIONAL_LEVEL, ATTR_MAX_DOMAIN_FUNCTIONAL_LEVEL_LEN, VMDIR_MAX_DFL_STRING, VmDirStringLenA(VMDIR_MAX_DFL_STRING) ); BAIL_ON_VMDIR_ERROR( retVal ); if ((retVal = VmDirInternalModifyEntry( &op )) != 0) { // If VmDirInternall call failed, reset retVal to LDAP level error space (for B/C) retVal = op.ldapResult.errCode; VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_VmDirPatchDSERoot: InternalModifyEntry failed. " "Error code: %d, Error string: %s", retVal, VDIR_SAFE_STRING( op.ldapResult.pszErrMsg ) ); BAIL_ON_VMDIR_ERROR( retVal ); } cleanup: VmDirFreeOperationContent(&op); VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "_VmDirPatchDSERoot: End" ); return retVal; error: retVal = LDAP_OPERATIONS_ERROR; goto cleanup; }
static int _ParsePagedResultControlVal( VDIR_OPERATION * op, BerValue * controlValue, // Input: control value encoded as ber VDIR_PAGED_RESULT_CONTROL_VALUE * pageResultCtrlVal, // Output VDIR_LDAP_RESULT * lr // Output ) { int retVal = LDAP_SUCCESS; BerElementBuffer berbuf; BerElement * ber = (BerElement *)&berbuf; PSTR pszLocalErrorMsg = NULL; PSTR pszCookie = NULL; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "_ParsePagedResultControlVal: Start." ); if (!op) { retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } ber_init2( ber, controlValue, LBER_USE_DER ); /* http://www.ietf.org/rfc/rfc2696.txt * * The searchControlValue is an OCTET STRING wrapping the BER-encoded version of the following SEQUENCE: * * realSearchControlValue ::= SEQUENCE { * size INTEGER (0..maxInt), * -- requested page size from client * -- result set size estimate from server * cookie OCTET STRING } */ if (ber_scanf(ber, "{ia}", &pageResultCtrlVal->pageSize, &pszCookie) == LBER_ERROR) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_ParsePagedResultControlVal: ber_scanf failed while parsing " "pageSize and cookie in the page result control value" ); lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Error in reading pageSize and cookie in the page result control value"); } if (pageResultCtrlVal->pageSize == 0) { retVal = LDAP_CANCELLED; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "Search query was cancelled."); BAIL_ON_VMDIR_ERROR(retVal); } VmDirStringNCpyA( pageResultCtrlVal->cookie, VMDIR_ARRAY_SIZE(pageResultCtrlVal->cookie), pszCookie, VMDIR_ARRAY_SIZE(pageResultCtrlVal->cookie) - 1); VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "pageSize:%d", pageResultCtrlVal->pageSize ); VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "cookie:%s", pageResultCtrlVal->cookie ); cleanup: if (pszCookie) { ber_memfree(pszCookie); } // Even in the error case, syncDoneCtrl should be freed during operation delete. VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "_ParsePagedResultControlVal: End." ); VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: VMDIR_APPEND_ERROR_MSG(lr->pszErrMsg, pszLocalErrorMsg); goto cleanup; }
int ParseRequestControls( VDIR_OPERATION * op, VDIR_LDAP_RESULT * lr ) { int retVal = LDAP_SUCCESS; ber_tag_t tag = LBER_ERROR; ber_len_t len = 0; char * endOfCtrlsMarker = NULL; VDIR_LDAP_CONTROL ** control = &(op->reqControls); BerValue lberBervType = {0}; BerValue lberBervCtlValue = {0}; PSTR pszLocalErrorMsg = NULL; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseRequestControls: Begin." ); *control = NULL; #ifndef _WIN32 if (ber_pvt_ber_remaining(op->ber) != 0) #else if (LBER_DEFAULT != ber_peek_tag (op->ber, &len)) #endif { if (ber_peek_tag( op->ber, &len ) != LDAP_TAG_CONTROLS ) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: Request controls expected, but something else is there in the PDU."); } // Get controls. ber_first_element => skip the sequence header, set the cursor at the 1st control in the SEQ of SEQ for( tag = ber_first_element( op->ber, &len, &endOfCtrlsMarker ); tag != LBER_ERROR; tag = ber_next_element( op->ber, &len, endOfCtrlsMarker ) ) { // m => in-place if (ber_scanf( op->ber, "{m", &lberBervType ) == LBER_ERROR) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls Error in reading control type from the PDU."); } if ( VmDirLogGetMask() & LDAP_DEBUG_ARGS) { VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, " Request Control: %s", lberBervType.bv_val ); } if (VmDirAllocateMemory( sizeof( VDIR_LDAP_CONTROL), (PVOID *)control ) != 0) { retVal = lr->errCode = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: VmDirAllocateMemory failed"); } // type points into in-place ber and does NOT own its content (*control)->type = lberBervType.bv_val; (*control)->criticality = FALSE; tag = ber_peek_tag( op->ber, &len ); if (tag == LBER_BOOLEAN) { ber_int_t criticality; if (ber_scanf( op->ber, "b", &criticality) == LBER_ERROR) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: Error in reading control criticality from the PDU."); } if (criticality) { (*control)->criticality = TRUE; } tag = ber_peek_tag( op->ber, &len ); } if (tag == LBER_OCTETSTRING) { if (ber_scanf( op->ber, "m", &lberBervCtlValue) == LBER_ERROR) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: ber_scanf failed while parsing the control value."); } } // SJ-TBD: Make sure that the control appears only once in the request, and it is present only in a search // request if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_SYNC, TRUE ) == 0) { if (VmDirdGetRunMode() != VMDIR_RUNMODE_NORMAL) { // Why block out-bound replication when catching up during restore mode? // // Reason: Partners have high-water-mark (lastLocalUsn) corresponding to this replica that is being // restored. If out-bound replication is not blocked while restore/catching-up is going on, originating // or replicated updates (if this replica is the only partner) made between the current-local-usn and // high-water-marks, that partners remember, will not get replicated out (even if the invocationId // has been fixed/changed). retVal = lr->errCode = LDAP_UNWILLING_TO_PERFORM; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: Server not in normal mode, not allowing outward replication."); } if ((retVal = ParseSyncRequestControlVal( op, &lberBervCtlValue, &((*control)->value.syncReqCtrlVal), lr)) != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: ParseSyncRequestControlVal failed."); } op->syncReqCtrl = *control; } if (VmDirStringCompareA( (*control)->type, VDIR_LDAP_CONTROL_SHOW_DELETED_OBJECTS, TRUE ) == 0) { op->showDeletedObjectsCtrl = *control; } if (VmDirStringCompareA( (*control)->type, VDIR_LDAP_CONTROL_SHOW_MASTER_KEY, TRUE ) == 0) { op->showMasterKeyCtrl = *control; } if (VmDirStringCompareA((*control)->type, LDAP_CONTROL_CONSISTENT_WRITE, TRUE ) == 0) { op->strongConsistencyWriteCtrl = *control; } if (VmDirStringCompareA((*control)->type, VDIR_LDAP_CONTROL_MANAGEDDSAIT, TRUE ) == 0) { op->manageDsaITCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_PAGEDRESULTS, TRUE ) == 0) { retVal = _ParsePagedResultControlVal( op, &lberBervCtlValue, &((*control)->value.pagedResultCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParsePagedResultControlVal failed."); } op->showPagedResultsCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_CONDITIONAL_WRITE, TRUE ) == 0) { retVal = _ParseCondWriteControlVal( op, &lberBervCtlValue, &((*control)->value.condWriteCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParseConditionalWriteControlVal failed."); } op->pCondWriteCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_APPEND_ENTRIES_CONTROL, TRUE ) == 0) { retVal = _ParseAppendEntriesControlVal( op, &lberBervCtlValue, &((*control)->value.appendEntriesCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParseAppendEntriesControlVal failed."); } op->appendEntriesCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_REQUEST_VOTE_CONTROL, TRUE ) == 0) { retVal = _ParseRequestVoteControlVal( op, &lberBervCtlValue, &((*control)->value.requestVoteCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParseRequestVoteControlVal failed."); } op->requestVoteCtrl = *control; } if (VmDirStringCompareA( (*control)->type, VMDIR_LDAP_CONTROL_TXN_SPEC, TRUE ) == 0) { retVal = VmDirAllocateMemory(lberBervCtlValue.bv_len+1, (PVOID*)&((*control)->value.txnSpecCtrlVal).pszTxnId); BAIL_ON_VMDIR_ERROR(retVal); VmDirStringNCpyA(((*control)->value.txnSpecCtrlVal).pszTxnId, lberBervCtlValue.bv_len+1, lberBervCtlValue.bv_val, lberBervCtlValue.bv_len); op->txnSpecCtrl = *control; op->pBECtx->pszTxnId = (op->txnSpecCtrl->value.txnSpecCtrlVal).pszTxnId; } if ( ber_scanf( op->ber, "}") == LBER_ERROR ) // end of control { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: ber_scanf failed while parsing the end of control"); } control = &((*control)->next); } retVal = LDAP_SUCCESS; } cleanup: VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseRequestControls: End." ); VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: DeleteControls(&(op->reqControls)); if (pszLocalErrorMsg) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, pszLocalErrorMsg); VMDIR_APPEND_ERROR_MSG(lr->pszErrMsg, pszLocalErrorMsg); } goto cleanup; }
static int ParseSyncRequestControlVal( VDIR_OPERATION * op, BerValue * controlValue, // Input: control value encoded as ber SyncRequestControlValue * syncReqCtrlVal, // Output VDIR_LDAP_RESULT * lr // Output ) { int retVal = LDAP_SUCCESS; ber_tag_t tag = LBER_ERROR; ber_len_t len = 0; UptoDateVectorEntry * utdVectorEntry = NULL; BerElementBuffer berbuf; BerElement * ber = (BerElement *)&berbuf; PSTR pszLocalErrorMsg = NULL; VDIR_BACKEND_CTX backendCtx = {0}; USN maxPartnerVisibleUSN = 0; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncRequestControlVal: Begin." ); ber_init2( ber, controlValue, LBER_USE_DER ); /* http://www.rfc-editor.org/rfc/rfc4533.txt * * syncCookie ::= OCTET STRING * * syncRequestValue ::= SEQUENCE { * mode ENUMERATED { * -- 0 unused * refreshOnly (1), * -- 2 reserved * refreshAndPersist (3) * }, * cookie syncCookie OPTIONAL, * reloadHint BOOLEAN DEFAULT FALSE * } */ if (ber_scanf( ber, "{i", &(syncReqCtrlVal->mode) ) == LBER_ERROR) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ber_scanf failed while parsing the sync request " "control mode" ); lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Error in reading sync request control mode from PDU."); } syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv.bv_val = ""; syncReqCtrlVal->intLastLocalUsnProcessed = 0; if (VmDirAllocateMemory( sizeof( VDIR_LDAP_CONTROL ), (PVOID *)&op->syncDoneCtrl) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: VmDirAllocateMemory failed " ); lr->errCode = retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseSyncRequestControlVal: VmDirAllocateMemory failed."); } op->syncDoneCtrl->type = LDAP_CONTROL_SYNC_DONE; if (LwRtlCreateHashTable( &op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, UtdVectorEntryGetKey, LwRtlHashDigestPstr, LwRtlHashEqualPstr, NULL, VMDIR_UTD_VECTOR_HASH_TABLE_SIZE ) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "UpdateSyncDoneUtdVectorEntry: LwRtlCreateHashTable failed" ); lr->errCode = retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "UpdateSyncDoneUtdVectorEntry: LwRtlCreateHashTable failed"); } tag = ber_peek_tag( ber, &len ); if (tag == LBER_SEQUENCE) { // syncCookie /* syncCookie ::= SEQUENCE { * reqServerId LDAPString, * lastLocalUsnProcessed INTEGER (0 .. maxInt), * utdVector UptoDateVectorEntryList } * * UptoDateVectorEntryList ::= SEQUENCE OF uptoDateVectorEntry UptoDateVectorEntry * * UptoDateVectorEntry ::= SEQUENCE { * serverId LDAPString, * lastOrigUsnProcessed INTEGER (0 .. maxInt) } */ // {lastLocalUsnProcessed{{<serverid1><lastOrigUsnProcessed1>}{<serverid2><lastOrigUsnProcessed2>}...}} if (ber_scanf( ber, "{mmm}", &syncReqCtrlVal->reqInvocationId.lberbv, &syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv, &syncReqCtrlVal->bvUtdVector.lberbv ) == LBER_ERROR ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ber_scanf failed while parsing " "lastLocalUsnProcessed in the sync request control value" ); lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Error in reading lastLocalUsnProcessed in the sync request control value"); } VMDIR_LOG_DEBUG( LDAP_DEBUG_REPL, "ParseSyncRequestControlVal: ServerId: %s, lastLocalUsnProcessed: %s, utdVector: %s", syncReqCtrlVal->reqInvocationId.lberbv.bv_val, syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv.bv_val, syncReqCtrlVal->bvUtdVector.lberbv.bv_val ); syncReqCtrlVal->intLastLocalUsnProcessed = op->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed = VmDirStringToLA( syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv.bv_val, NULL, 10 ); { char * nextServerIdStr = NULL; char * nextOrigUsnStr = NULL; nextServerIdStr = syncReqCtrlVal->bvUtdVector.lberbv.bv_val; while( nextServerIdStr != NULL && nextServerIdStr[0] != '\0') { PLW_HASHTABLE_NODE pNode = NULL; if (VmDirAllocateMemory( sizeof(UptoDateVectorEntry), (PVOID *)&utdVectorEntry ) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: VmDirAllocateMemory failed " ); lr->errCode = retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseSyncRequestControlVal: VmDirAllocateMemory failed"); } nextOrigUsnStr = VmDirStringChrA( nextServerIdStr, ':'); *nextOrigUsnStr = '\0'; nextOrigUsnStr++; utdVectorEntry->invocationId.lberbv.bv_val = nextServerIdStr; utdVectorEntry->invocationId.lberbv.bv_len = VmDirStringLenA( nextServerIdStr ); nextServerIdStr = VmDirStringChrA( nextOrigUsnStr, ','); *nextServerIdStr = '\0'; nextServerIdStr++; utdVectorEntry->currMaxOrigUsnProcessed = utdVectorEntry->reqLastOrigUsnProcessed = atol( nextOrigUsnStr ); LwRtlHashTableResizeAndInsert( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &utdVectorEntry->Node, &pNode); assert( pNode == NULL ); // assert the key of added node is unique. } } tag = ber_peek_tag( ber, &len ); } if (tag == LBER_BOOLEAN) { ber_int_t reloadHint; if (ber_scanf( ber, "b", &reloadHint) == LBER_ERROR) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: Error in reading reloadHint from the PDU" ); lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Error in reading reloadHint from the PDU."); } if (reloadHint) { syncReqCtrlVal->reloadHint = TRUE; } } if ( ber_scanf( ber, "}") == LBER_ERROR ) // End of control value { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ber_scanf failed while parsing the end of " "sync request control value." ); lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Decoding error while parsing the end of sync request control value."); } backendCtx.pBE = VmDirBackendSelect(""); maxPartnerVisibleUSN = backendCtx.pBE->pfnBEGetLeastOutstandingUSN( &backendCtx, FALSE ) - 1; if (syncReqCtrlVal->intLastLocalUsnProcessed > maxPartnerVisibleUSN) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ServerId %s has processed my USN (%u), my max USN is (%u).", syncReqCtrlVal->reqInvocationId.lberbv.bv_val, syncReqCtrlVal->intLastLocalUsnProcessed, maxPartnerVisibleUSN ); lr->errCode = LDAP_UNWILLING_TO_PERFORM; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Partner is ahead of my changes."); } cleanup: // Even in the error case, syncDoneCtrl should be freed during operation delete. VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncRequestControlVal: End." ); VmDirBackendCtxContentFree( &backendCtx ); VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: VMDIR_APPEND_ERROR_MSG(lr->pszErrMsg, pszLocalErrorMsg); goto cleanup; }
int WriteSyncStateControl( VDIR_OPERATION * op, VDIR_ATTRIBUTE * pAttr, BerElement * ber, PSTR* ppszErrorMsg ) { int retVal = LDAP_SUCCESS; VDIR_BERVALUE syncStateCtrlType = { {VmDirStringLenA( LDAP_CONTROL_SYNC_STATE ), LDAP_CONTROL_SYNC_STATE}, 0, 0, NULL }; int entryState = LDAP_SYNC_MODIFY; BerElementBuffer ctrlValBerbuf; BerElement * ctrlValBer = (BerElement *) &ctrlValBerbuf; VDIR_BERVALUE bvCtrlVal = VDIR_BERVALUE_INIT; PSTR pszLocalErrorMsg = NULL; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WriteSyncStateControl: Begin" ); /* Logic to determine the entry state is: * Default entry state is LDAP_SYNC_MODIFY * * If ATTR_USN_CREATED value is greater than the last local USN that the consumer has seen so far, * entry state is LDAP_SYNC_ADD. * Otherwise, if isDeleted=TRUE is in the replication scope, entry state is LDAP_SYNC_DELETE. * * NOTE: The logic is based on the things (entry state + what has the consumer seen so far) seen by the supplier * at this point in time. Things/state could be different at the time when consumer tries to apply this change. * => may lead to various conflict resolution scenarios. */ for ( ; pAttr != NULL; pAttr = pAttr->next) { if (pAttr->metaData[0] != '\0') // We are sending back this attribute's meta data. => Attribute is in // replication scope. SJ-TBD: we are overloading pAttr->metaData // field. Should we have another field (e.g. inReplScope) in Attribute { if ( VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_IS_DELETED, FALSE ) == 0 && VmDirStringCompareA( pAttr->vals[0].lberbv.bv_val, VMDIR_IS_DELETED_TRUE_STR, FALSE ) == 0) { entryState = LDAP_SYNC_DELETE; continue; // Look if it is LDAP_SYNC_ADD case } if (VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_USN_CREATED, FALSE ) == 0) { entryState = LDAP_SYNC_ADD; break; } } } if (ber_printf( ber, "t{{O", LDAP_TAG_CONTROLS, &(syncStateCtrlType.lberbv) ) == -1 ) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteSyncStateControl: ber_printf (to print attribute name ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding sync state control failed."); } ////////// Build ber for the control value (void) memset( (char *)&ctrlValBerbuf, '\0', sizeof( BerElementBuffer )); ber_init2( ctrlValBer, NULL, LBER_USE_DER ); if (ber_printf( ctrlValBer, "{i}", entryState ) == -1 ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding sync state control failed."); } ////////////// Building ber for the control value done bvCtrlVal.lberbv.bv_val = ctrlValBer->ber_buf; bvCtrlVal.lberbv.bv_len = ctrlValBer->ber_ptr - ctrlValBer->ber_buf; if (ber_printf( ber, "O", &bvCtrlVal.lberbv ) == -1 ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding sync state control failed."); } if (ber_printf( ber, "}}" ) == -1 ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "Encoding sync state control failed."); } cleanup: ber_free_buf( ctrlValBer ); if (ppszErrorMsg) { *ppszErrorMsg = pszLocalErrorMsg; } else { VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); } VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WriteSyncStateControl: End" ); return( retVal ); error: goto cleanup; }
int WriteSyncDoneControl( VDIR_OPERATION * op, BerElement * ber ) { int retVal = LDAP_OPERATIONS_ERROR; PLW_HASHTABLE_NODE pNode = NULL; LW_HASHTABLE_ITER iter = LW_HASHTABLE_ITER_INIT; UptoDateVectorEntry * pUtdVectorEntry = NULL; VDIR_BERVALUE bvCtrlVal = VDIR_BERVALUE_INIT; VDIR_BERVALUE syncDoneCtrlType = { {VmDirStringLenA( LDAP_CONTROL_SYNC_DONE ), LDAP_CONTROL_SYNC_DONE}, 0, 0, NULL }; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WriteSyncDoneControl: Begin." ); if ( op->syncDoneCtrl != NULL) { if (ber_printf( ber, "t{{O", LDAP_TAG_CONTROLS, &(syncDoneCtrlType.lberbv) ) == -1 ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WriteSyncDoneControl: ber_printf (to print Sync Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } { // Construct string format of utdVector int numEntries = LwRtlHashTableGetCount( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector ); char * writer = NULL; size_t tmpLen = 0; size_t bufferSize = (numEntries + 1 /* for lastLocalUsn */) * (VMDIR_GUID_STR_LEN + 1 + VMDIR_MAX_USN_STR_LEN + 1); // Sync Done control value looks like: <lastLocalUsnChanged>,<serverId1>:<server 1 last originating USN>, // <serverId2>,<server 2 originating USN>,... if (VmDirAllocateMemory( bufferSize, (PVOID *)&bvCtrlVal.lberbv.bv_val) != 0) { retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } writer = bvCtrlVal.lberbv.bv_val; bvCtrlVal.lberbv.bv_len = 0; VmDirStringPrintFA( writer, bufferSize, "%ld,", op->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed ); tmpLen = VmDirStringLenA( writer ); writer += tmpLen; bufferSize -= tmpLen; bvCtrlVal.lberbv.bv_len += tmpLen; while ((pNode = LwRtlHashTableIterate(op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &iter))) { pUtdVectorEntry = LW_STRUCT_FROM_FIELD(pNode, UptoDateVectorEntry, Node); VmDirStringPrintFA( writer, bufferSize, "%s:%ld,", pUtdVectorEntry->invocationId.lberbv.bv_val, pUtdVectorEntry->currMaxOrigUsnProcessed ); tmpLen = VmDirStringLenA( writer ); writer += tmpLen; bufferSize -= tmpLen; bvCtrlVal.lberbv.bv_len += tmpLen; } } if (ber_printf( ber, "O}}", &bvCtrlVal.lberbv) == -1 ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WriteSyncDoneControl: ber_printf (to print Sync Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } VMDIR_LOG_DEBUG( LDAP_DEBUG_REPL, "WriteSyncDoneControl: Sync Done Control Value: %s", bvCtrlVal.lberbv.bv_val ); } retVal = LDAP_SUCCESS; cleanup: VMDIR_SAFE_FREE_MEMORY( bvCtrlVal.lberbv.bv_val ); VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WriteSyncDoneControl: Begin." ); return retVal; error: goto cleanup; }
/* * refresh account password * returns: * if force is not specified and password is not aged * {"refreshed":"false"} * if force was specified or password aged * {"refreshed":"true","password":"******"} */ DWORD VmDirRESTRefreshPassword( void* pIn, void** ppOut ) { DWORD dwError = 0; PVDIR_REST_OPERATION pRestOp = NULL; BOOLEAN bRefreshPassword = FALSE; PSTR pszNewPassword = NULL; BOOLEAN bRefreshed = FALSE; if (!pIn) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } pRestOp = (PVDIR_REST_OPERATION)pIn; dwError = VmDirRESTGetBoolParam( pRestOp, "force", &bRefreshPassword, TRUE); BAIL_ON_VMDIR_ERROR(dwError) dwError = VmDirRefreshPassword( pRestOp->pConn, bRefreshPassword, &pszNewPassword); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_LOG_DEBUG( VMDIR_LOG_MASK_ALL, "%s: force: %d, %s", __FUNCTION__, bRefreshPassword, pRestOp->pConn->AccessInfo.pszNormBindedDn); if (!IsNullOrEmptyString(pszNewPassword)) { bRefreshed = TRUE; dwError = VmDirRESTResultSetStrData( pRestOp->pResult, "password", pszNewPassword); BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirRESTResultSetBooleanData( pRestOp->pResult, "refreshed", bRefreshed); BAIL_ON_VMDIR_ERROR(dwError); cleanup: VMDIR_SET_REST_RESULT(pRestOp, NULL, dwError, NULL); VMDIR_SAFE_FREE_MEMORY(pszNewPassword); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s failed, error (%d)", __FUNCTION__, dwError); goto cleanup; }
static int ProcessCandidateList( VDIR_OPERATION * pOperation ) { int retVal = LDAP_SUCCESS; int i = 0; VDIR_CANDIDATES * cl = pOperation->request.searchReq.filter->candidates; VDIR_ENTRY srEntry = {0}; VDIR_ENTRY * pSrEntry = NULL; int numSentEntries = 0; BOOLEAN bInternalSearch = FALSE; BOOLEAN bPageResultsCtrl = FALSE; DWORD dwPageSize = 0; ENTRYID lastEID = 0; /* * If the page size is greater than or equal to the sizeLimit value, * the server should ignore the control as the request can be satisfied in a single page. */ if (pOperation->showPagedResultsCtrl && (pOperation->request.searchReq.sizeLimit == 0 || pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.pageSize < (DWORD)pOperation->request.searchReq.sizeLimit)) { VmDirLog( LDAP_DEBUG_TRACE, "showPagedResultsCtrl applies to this query." ); bPageResultsCtrl = TRUE; dwPageSize = pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.pageSize; lastEID = atoi(pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie); pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie[0] = '\0'; } if (cl && cl->size > 0) { if (pOperation->opType == VDIR_OPERATION_TYPE_INTERNAL) { //TODO, we should have a hard limit on the cl->size we handle bInternalSearch = TRUE; VmDirFreeEntryArrayContent(&pOperation->internalSearchEntryArray); retVal = VmDirAllocateMemory( sizeof(VDIR_ENTRY) * cl->size, (PVOID*)&pOperation->internalSearchEntryArray.pEntry); BAIL_ON_VMDIR_ERROR(retVal); } for (i = 0, numSentEntries = 0; (i < cl->size) && VmDirdState() != VMDIRD_STATE_SHUTDOWN && (pOperation->request.searchReq.sizeLimit == 0 /* unlimited */ || numSentEntries < pOperation->request.searchReq.sizeLimit); i++) { //skip entries we sent before if (bPageResultsCtrl && lastEID > 0) { if (cl->eIds[i] == lastEID) { lastEID = 0; } continue; } VMDIR_LOG_DEBUG( LDAP_DEBUG_FILTER, "ProcessCandidateList EID(%u)", cl->eIds[i]); pSrEntry = bInternalSearch ? (pOperation->internalSearchEntryArray.pEntry + pOperation->internalSearchEntryArray.iSize) : &srEntry; retVal = pOperation->pBEIF->pfnBEIdToEntry( pOperation->pBECtx, pOperation->pSchemaCtx, cl->eIds[i], pSrEntry, VDIR_BACKEND_ENTRY_LOCK_READ); if (retVal == 0) { if (CheckIfEntryPassesFilter( pOperation, pSrEntry, pOperation->request.searchReq.filter) == FILTER_RES_TRUE) { retVal = VmDirBuildComputedAttribute( pOperation, pSrEntry ); BAIL_ON_VMDIR_ERROR( retVal ); if (bInternalSearch) { pOperation->internalSearchEntryArray.iSize++; pSrEntry = NULL; // EntryArray takes over *pSrEntry content } else { retVal = VmDirSendSearchEntry( pOperation, pSrEntry ); if (retVal == VMDIR_ERROR_INSUFFICIENT_ACCESS) { VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "Access deny on search entry result [%s,%d] (bindedDN-%s) (targetDn-%s)\n", __FILE__, __LINE__, pOperation->conn->AccessInfo.pszBindedDn, pSrEntry->dn.lberbv.bv_val); // make sure search continues retVal = 0; } BAIL_ON_VMDIR_ERROR( retVal ); if (pSrEntry->bSearchEntrySent) { numSentEntries++; } } } //We have sent one page size of entries, so we can break here if (bPageResultsCtrl && numSentEntries == dwPageSize){ retVal = VmDirStringPrintFA( pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie, VMDIR_MAX_I64_ASCII_STR_LEN, "%u", pSrEntry->eId); BAIL_ON_VMDIR_ERROR( retVal ); break; } VmDirFreeEntryContent( pSrEntry ); pSrEntry = NULL; // Reset to NULL so that DeleteEntry is no-op. } else { // Ignore BdbEIdToEntry errors. VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "ProcessCandiateList BEIdToEntry EID(%u), error (%u)", cl->eIds[i], retVal); retVal = 0; } } VMDIR_LOG_VERBOSE( LDAP_DEBUG_FILTER, "(%d) candiates processed and (%d) entries sent", cl->size, numSentEntries); } if ( pOperation->request.searchReq.sizeLimit && numSentEntries < pOperation->request.searchReq.sizeLimit && pOperation->pBECtx->iPartialCandidates) { retVal = LDAP_UNWILLING_TO_PERFORM; VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ProcessCandiateList may return none or paritial requested entries with sizelimit %d", pOperation->request.searchReq.sizeLimit); } cleanup: pOperation->dwSentEntries = numSentEntries; VmDirFreeEntryContent( pSrEntry ); return retVal; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessCandiateList failed. (%u)", retVal); goto cleanup; }