//--------------------------------------------------------------------------- // DisableTarget.cpp // // Comment: This is a COM object extension for the MCS DCTAccountReplicator. // This object implements the IExtendAccountMigration interface. In // the process method this object disables the Source and the Target // accounts depending on the settings in the VarSet. // // (c) Copyright 1995-1998, Mission Critical Software, Inc., All Rights Reserved // // Proprietary and confidential to Mission Critical Software, Inc. //--------------------------------------------------------------------------- #include "stdafx.h" #include "ResStr.h" #include #include #include "AcctDis.h" #include "DisAcct.h" #include "ARExt.h" #include "ARExt_i.c" #include "ErrDCT.hpp" //#import "\bin\McsVarSetMin.tlb" no_namespace //#import "\bin\DBManager.tlb" no_namespace #import "VarSet.tlb" no_namespace rename("property", "aproperty") #import "DBMgr.tlb" no_namespace const int LEN_Path = 255; StringLoader gString; #define AR_Status_PasswordError (0x00000400) ///////////////////////////////////////////////////////////////////////////// // CDisableTarget //--------------------------------------------------------------------------- // Get and set methods for the properties. //--------------------------------------------------------------------------- STDMETHODIMP CDisableTarget::get_sName(BSTR *pVal) { *pVal = m_sName; return S_OK; } STDMETHODIMP CDisableTarget::put_sName(BSTR newVal) { m_sName = newVal; return S_OK; } STDMETHODIMP CDisableTarget::get_sDesc(BSTR *pVal) { *pVal = m_sDesc; return S_OK; } STDMETHODIMP CDisableTarget::put_sDesc(BSTR newVal) { m_sDesc = newVal; return S_OK; } //--------------------------------------------------------------------------- // ProcessObject : This method doesn't do anything. //--------------------------------------------------------------------------- STDMETHODIMP CDisableTarget::PreProcessObject( IUnknown *pSource, //in- Pointer to the source AD object IUnknown *pTarget, //in- Pointer to the target AD object IUnknown *pMainSettings, //in- Varset filled with the settings supplied by user IUnknown **ppPropsToSet, //in,out - Varset filled with Prop-Value pairs that will be set // once all extension objects are executed. EAMAccountStats* pStats ) { // Check if the object is of user type. if not then there is no point in disabling that account. IVarSetPtr pVs = pMainSettings; _bstr_t sType = pVs->get(GET_BSTR(DCTVS_CopiedAccount_Type)); if (!sType.length()) return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); if (UStrICmp((WCHAR*)sType,L"user") && UStrICmp((WCHAR*)sType,L"inetOrgPerson")) return S_OK; if ( pSource ) { // HRESULT hr = S_OK; _variant_t vtExp; _variant_t vtFlag; _bstr_t sSourceType; IIManageDBPtr pDb = pVs->get(GET_BSTR(DCTVS_DBManager)); sSourceType = pVs->get(GET_BSTR(DCTVS_CopiedAccount_Type)); if ( !_wcsicmp((WCHAR*) sSourceType, L"user") || !_wcsicmp((WCHAR*) sSourceType, L"inetOrgPerson") ) { // Get the expiration date and put it into the AR Node. _bstr_t sSam = pVs->get(GET_BSTR(DCTVS_CopiedAccount_SourceSam)); _bstr_t sComp = pVs->get(GET_BSTR(DCTVS_Options_SourceServer)); USER_INFO_3 * pInfo = NULL; DWORD rc = NetUserGetInfo((WCHAR*) sComp, (WCHAR*)sSam, 3, (LPBYTE*)&pInfo); if ( !rc ) { vtExp = (long)pInfo->usri3_acct_expires; pVs->put(GET_BSTR(DCTVS_CopiedAccount_ExpDate), vtExp); // Get the ControlFlag and store it into the AR Node. vtFlag = (long)pInfo->usri3_flags; pVs->put(GET_BSTR(DCTVS_CopiedAccount_UserFlags), vtFlag); if ( pInfo ) NetApiBufferFree(pInfo); } } pDb->raw_SaveUserProps(pMainSettings); } return S_OK; } //--------------------------------------------------------------------------- // ProcessObject : This method checks in varset if it needs to disable any // accounts. If it does then it disables those accounts. //--------------------------------------------------------------------------- STDMETHODIMP CDisableTarget::ProcessObject( IUnknown *pSource, //in- Pointer to the source AD object IUnknown *pTarget, //in- Pointer to the target AD object IUnknown *pMainSettings, //in- Varset filled with the settings supplied by user IUnknown **ppPropsToSet, //in,out - Varset filled with Prop-Value pairs that will be set // once all extension objects are executed. EAMAccountStats* pStats ) { IVarSetPtr pVarSet = pMainSettings; _variant_t var; DWORD paramErr; USER_INFO_3 * info = NULL; long rc; WCHAR strDomain[LEN_Path]; WCHAR strAcct[LEN_Path]; HRESULT hr = S_OK; TErrorDct err; WCHAR fileName[LEN_Path]; BOOL bDisableSource = FALSE; BOOL bExpireSource = FALSE; _bstr_t temp; time_t expireTime = 0; _bstr_t bstrSameForest; BOOL bSameAsSource = FALSE; BOOL bDisableTarget = FALSE; BOOL bGotSrcState = FALSE; BOOL bSrcDisabled = FALSE; bstrSameForest = pVarSet->get(GET_BSTR(DCTVS_Options_IsIntraforest)); if (! UStrICmp((WCHAR*)bstrSameForest,GET_STRING(IDS_YES)) ) { // in the intra-forest case, we are moving the user accounts, not // copying them, so these disabling/expiring options don't make any sense return S_OK; } // Get the Error log filename from the Varset var = pVarSet->get(GET_BSTR(DCTVS_Options_Logfile)); wcscpy(fileName, (WCHAR*)V_BSTR(&var)); VariantInit(&var); // Open the error log err.LogOpen(fileName, 1); // Check if the object is of user type. if not then there is no point in disabling that account. var = pVarSet->get(GET_BSTR(DCTVS_CopiedAccount_Type)); if ( UStrICmp(var.bstrVal,L"user") && UStrICmp(var.bstrVal,L"inetOrgPerson") ) { return S_OK; } //set flags based on user selections temp = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_DisableSourceAccounts)); if ( ! UStrICmp(temp,GET_STRING(IDS_YES)) ) { bDisableSource = TRUE; } // // If disable target account option is true or unable to // set password for this account then disable account. // temp = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_DisableCopiedAccounts)); long lStatus = pVarSet->get(GET_BSTR(DCTVS_CopiedAccount_Status)); if ( ! UStrICmp(temp,GET_STRING(IDS_YES)) || (lStatus & AR_Status_PasswordError) ) { bDisableTarget = TRUE; } temp = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_TgtStateSameAsSrc)); if ( ! UStrICmp(temp,GET_STRING(IDS_YES)) ) { bSameAsSource = TRUE; } /* process the source account */ //if expire source accounts was set, retrieve the expire time, now given to us in //number of days from now temp = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_ExpireSourceAccounts)); if ( temp.length() ) { long oneDay = 24 * 60 * 60; // number of seconds in 1 day //get days until expire long lExpireDays = _wtol(temp); //get the current time time_t currentTime = time(NULL); //convert current time to local time struct tm * convtm; convtm = localtime(¤tTime); //rollback to this morning convtm->tm_hour = 0; convtm->tm_min = 0; convtm->tm_sec = 0; //convert this time back to GMT expireTime = mktime(convtm); //move forward to tonight at midnight expireTime += oneDay; //now add the desired number of days expireTime += lExpireDays * oneDay; bExpireSource = TRUE; } //get source account state var = pVarSet->get(GET_BSTR(DCTVS_CopiedAccount_SourceSam)); wcscpy(strAcct, (WCHAR*)V_BSTR(&var)); var = pVarSet->get(GET_BSTR(DCTVS_Options_SourceServer)); wcscpy(strDomain, (WCHAR*)V_BSTR(&var)); // we will use the net APIs to disable the source account rc = NetUserGetInfo(strDomain, strAcct, 3, (LPBYTE *)&info); if (rc != 0) { hr = S_FALSE; if (bDisableSource || bExpireSource || bSameAsSource) { if (pStats != NULL) { pStats->errors.users++; } err.SysMsgWrite(ErrE, rc, DCT_MSG_UNABLE_RETRIEVE_SOURCE_DISABLE_STATE_S, strAcct); if (bDisableSource || bExpireSource) { err.MsgWrite(ErrE, DCT_MSG_ACCOUNT_DISABLE_OR_EXPIRE_FAILED_S, strAcct); } if (bSameAsSource) { err.MsgWrite(ErrE, DCT_MSG_CANNOT_ENABLEDISABLE_TARGET_SAMEASSOURCE_S, strAcct); } } } else { bGotSrcState = TRUE; //set current source account state if (info->usri3_flags & UF_ACCOUNTDISABLE) bSrcDisabled = TRUE; //also save the flags in the varset to be used in setpass ARExt _variant_t vtFlag = (long)info->usri3_flags; pVarSet->put(GET_BSTR(DCTVS_CopiedAccount_UserFlags), vtFlag); //disable the source account if requested if (bDisableSource) { // Set the disable flag info->usri3_flags |= UF_ACCOUNTDISABLE; } //expire the account in given timeframe, if requested if ( bExpireSource ) { if (((time_t)info->usri3_acct_expires == TIMEQ_FOREVER) || ((time_t)info->usri3_acct_expires > expireTime)) { info->usri3_acct_expires = (DWORD)expireTime; } } //if changed, set the source information into the Domain. if (bDisableSource || bExpireSource) { rc = NetUserSetInfo(strDomain,strAcct, 3, (LPBYTE)info, ¶mErr); if (rc == NERR_Success) { if (bDisableSource) { err.MsgWrite(0, DCT_MSG_SOURCE_DISABLED_S, strAcct); } if ( bExpireSource ) { if (((time_t)info->usri3_acct_expires == TIMEQ_FOREVER) || ((time_t)info->usri3_acct_expires > expireTime)) { err.MsgWrite(0, DCT_MSG_SOURCE_EXPIRED_S, strAcct); } else { err.MsgWrite(0, DCT_MSG_SOURCE_EXPIRATION_EARLY_S, strAcct); } } } else { if (pStats != NULL) pStats->errors.users++; err.SysMsgWrite(ErrE, rc, DCT_MSG_ACCOUNT_DISABLE_OR_EXPIRE_FAILED_S, strAcct); } } NetApiBufferFree((LPVOID) info); }//if got current src account state /* process the target account */ //get the target state var = pVarSet->get(GET_BSTR(DCTVS_CopiedAccount_TargetSam)); wcscpy(strAcct, (WCHAR*)V_BSTR(&var)); var = pVarSet->get(GET_BSTR(DCTVS_Options_TargetServer)); wcscpy(strDomain, (WCHAR*)V_BSTR(&var)); // we will use the net APIs to disable the target account rc = NetUserGetInfo(strDomain, strAcct, 3, (LPBYTE *)&info); if (rc != NERR_Success) { hr = S_FALSE; if (pStats != NULL) pStats->errors.users++; err.SysMsgWrite(ErrE, rc, DCT_MSG_DISABLE_TARGET_FAILED_S, strAcct); } else { //disable the target if requested if (bDisableTarget) { // Set the disable flag info->usri3_flags |= UF_ACCOUNTDISABLE; // Set the information into the Domain. rc = NetUserSetInfo(strDomain, strAcct, 3, (LPBYTE)info, ¶mErr); if (rc == NERR_Success) { err.MsgWrite(0, DCT_MSG_TARGET_DISABLED_S, strAcct); } else { if (pStats != NULL) pStats->errors.users++; err.SysMsgWrite(ErrE, rc, DCT_MSG_DISABLE_TARGET_FAILED_S, strAcct); } } //else make target same state as source was else if (bSameAsSource) { //if the source was disabled or unable to retrieve source state, disable the target if (bSrcDisabled || !bGotSrcState) { //disable the target info->usri3_flags |= UF_ACCOUNTDISABLE; // Set the information into the Domain. rc = NetUserSetInfo( strDomain, strAcct, 3, (LPBYTE)info, ¶mErr); if (rc == NERR_Success) { err.MsgWrite(0, DCT_MSG_TARGET_DISABLED_S, strAcct); } else { if (pStats != NULL) pStats->errors.users++; err.SysMsgWrite(ErrE, rc, DCT_MSG_DISABLE_TARGET_FAILED_S, strAcct); } } else //else make sure target is enabled and not set to expire { info->usri3_flags &= ~UF_ACCOUNTDISABLE; rc = NetUserSetInfo(strDomain,strAcct,3,(LPBYTE)info,¶mErr); if (rc != NERR_Success) { if (pStats != NULL) pStats->warnings.users++; err.SysMsgWrite(ErrW, rc, DCT_MSG_ENABLE_TARGET_FAILED_S, strAcct); } } } else //else make sure target is enabled and not set to expire { info->usri3_flags &= ~UF_ACCOUNTDISABLE; rc = NetUserSetInfo(strDomain,strAcct,3,(LPBYTE)info,¶mErr); if (rc != NERR_Success) { if (pStats != NULL) pStats->warnings.users++; err.SysMsgWrite(ErrW, rc, DCT_MSG_ENABLE_TARGET_FAILED_S, strAcct); } } NetApiBufferFree((LPVOID) info); } return hr; } //--------------------------------------------------------------------------- // ProcessUndo : This function Enables the accounts that were previously // disabled.. //--------------------------------------------------------------------------- STDMETHODIMP CDisableTarget::ProcessUndo( IUnknown *pSource, //in- Pointer to the source AD object IUnknown *pTarget, //in- Pointer to the target AD object IUnknown *pMainSettings, //in- Varset filled with the settings supplied by user IUnknown **ppPropsToSet, //in,out - Varset filled with Prop-Value pairs that will be set // once all extension objects are executed. EAMAccountStats* pStats ) { IVarSetPtr pVarSet = pMainSettings; IIManageDBPtr pDb = pVarSet->get(GET_BSTR(DCTVS_DBManager)); _variant_t var; DWORD paramErr; USER_INFO_3 * info; long rc; WCHAR strDomain[LEN_Path]; WCHAR strAcct[LEN_Path]; HRESULT hr = S_OK; TErrorDct err; IUnknown * pUnk = NULL; _bstr_t sSourceName, sSourceDomain, sTgtDomain; WCHAR fileName[LEN_Path]; IVarSetPtr pVs(__uuidof(VarSet)); _variant_t vtExp, vtFlag; _bstr_t sDomainName = pVarSet->get(GET_BSTR(DCTVS_Options_SourceDomain)); pVs->QueryInterface(IID_IUnknown, (void**)&pUnk); sSourceName = pVarSet->get(GET_BSTR(DCTVS_CopiedAccount_SourceSam)); sSourceDomain = pVarSet->get(GET_BSTR(DCTVS_Options_SourceDomain)); sTgtDomain = pVarSet->get(GET_BSTR(DCTVS_Options_TargetDomain)); hr = pDb->raw_GetUserProps(sSourceDomain, sSourceName, &pUnk); if ( pUnk ) pUnk->Release(); if ( hr == S_OK ) { vtExp = pVs->get(GET_BSTR(DCTVS_CopiedAccount_ExpDate)); vtFlag = pVs->get(GET_BSTR(DCTVS_CopiedAccount_UserFlags)); } // Get the Error log filename from the Varset var = pVarSet->get(GET_BSTR(DCTVS_Options_Logfile)); wcscpy(fileName, (WCHAR*)V_BSTR(&var)); VariantInit(&var); // Open the error log err.LogOpen(fileName, 1); // Check if the object is of user type. if not then there is no point in disabling that account. var = pVarSet->get(GET_BSTR(DCTVS_CopiedAccount_Type)); if ( _wcsicmp((WCHAR*)V_BSTR(&var),L"user") != 0 && _wcsicmp((WCHAR*)V_BSTR(&var),L"inetOrgPerson") != 0 ) return S_OK; _bstr_t sDis = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_DisableSourceAccounts)); _bstr_t sExp = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_ExpireSourceAccounts)); if ( !wcscmp((WCHAR*)sDis,GET_STRING(IDS_YES)) || sExp.length() ) { // Reset the flag and the expiration date for the source account. var = pVarSet->get(GET_BSTR(DCTVS_CopiedAccount_SourceSam)); wcscpy(strAcct, (WCHAR*)V_BSTR(&var)); var = pVarSet->get(GET_BSTR(DCTVS_Options_SourceServer)); wcscpy(strDomain, (WCHAR*)V_BSTR(&var)); // we will use the net APIs to disable the source account rc = NetUserGetInfo( strDomain, strAcct, 3, (LPBYTE *)&info); if (rc != NERR_Success) { hr = S_FALSE; if (pStats != NULL) pStats->warnings.users++; err.SysMsgWrite(ErrW, rc, DCT_MSG_ENABLE_SOURCE_FAILED_S, strAcct); } else { // Set the disable flag info->usri3_flags = vtFlag.lVal; info->usri3_acct_expires = vtExp.lVal; // Set the information into the Domain. rc = NetUserSetInfo(strDomain,strAcct, 3, (LPBYTE)info, ¶mErr); NetApiBufferFree((LPVOID) info); if (rc == NERR_Success) { err.MsgWrite(0, DCT_MSG_SOURCE_ENABLED_S, strAcct); } else { if (pStats != NULL) pStats->warnings.users++; err.SysMsgWrite(ErrW, rc, DCT_MSG_ENABLE_SOURCE_FAILED_S, strAcct); } } } // Process the target account if the Varset is set var = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_DisableCopiedAccounts)); if ( (var.vt == VT_BSTR) && (_wcsicmp((WCHAR*)V_BSTR(&var),GET_STRING(IDS_YES)) == 0) ) { var = pVarSet->get(GET_BSTR(DCTVS_CopiedAccount_TargetSam)); wcscpy(strAcct, (WCHAR*)V_BSTR(&var)); var = pVarSet->get(GET_BSTR(DCTVS_Options_TargetServer)); wcscpy(strDomain, (WCHAR*)V_BSTR(&var)); // we will use the net APIs to disable the target account rc = NetUserGetInfo( strDomain, strAcct, 3, (LPBYTE *)&info); if (rc != NERR_Success) { hr = S_FALSE; if (pStats != NULL) pStats->warnings.users++; err.SysMsgWrite(ErrW, rc, DCT_MSG_ENABLE_TARGET_FAILED_S, strAcct); } else { // clear the disable flag info->usri3_flags &= ~(UF_ACCOUNTDISABLE); // Set the information into the Domain. rc = NetUserSetInfo( strDomain, strAcct, 3, (LPBYTE)info, ¶mErr); NetApiBufferFree((LPVOID) info); if (rc == NERR_Success) { err.MsgWrite(0, DCT_MSG_TARGET_ENABLED_S, strAcct); } else { if (pStats != NULL) pStats->warnings.users++; err.SysMsgWrite(ErrW, rc, DCT_MSG_ENABLE_TARGET_FAILED_S, strAcct); } } } WCHAR sFilter[5000]; wsprintf(sFilter, L"SourceDomain='%s' and SourceSam='%s'", (WCHAR*)sDomainName, strAcct); _variant_t Filter = sFilter; pDb->raw_ClearTable(L"UserProps", Filter); err.LogClose(); return hr; }