// Expectations for Enumerations
    void CfgTest::ExpectDatabaseInEnum(CFG_ENUMERATION_HANDLE cehHandle, LPCWSTR wzExpectedFriendlyName, BOOL fExpectedSyncByDefault, LPCWSTR wzExpectedPath)
    {
        HRESULT hr = S_OK;
        DWORD dwCount = 0;
        LPCWSTR wzFriendlyName = NULL;
        BOOL fSyncByDefault = FALSE;
        LPCWSTR wzPath = NULL;

        hr = CfgEnumReadDword(cehHandle, 0, ENUM_DATA_COUNT, &dwCount);
        ExitOnFailure(hr, "Failed to get count of items in database list enumeration");

        for (DWORD i = 0; i < dwCount; ++i)
        {
            hr = CfgEnumReadString(cehHandle, i, ENUM_DATA_FRIENDLY_NAME, &wzFriendlyName);
            ExitOnFailure1(hr, "Failed to read friendly name from database list enum at index %u", i);

            hr = CfgEnumReadBool(cehHandle, i, ENUM_DATA_SYNC_BY_DEFAULT, &fSyncByDefault);
            ExitOnFailure1(hr, "Failed to read path from database list enum at index %u", i);

            hr = CfgEnumReadString(cehHandle, i, ENUM_DATA_PATH, &wzPath);
            ExitOnFailure1(hr, "Failed to read path from database list enum at index %u", i);

            // If it isn't the right friendly name, skip to the next database in the enumeration
            if (0 != lstrcmpW(wzExpectedFriendlyName, wzFriendlyName))
            {
                continue;
            }

            if (0 != lstrcmpW(wzExpectedPath, wzPath))
            {
                hr = E_FAIL;
                ExitOnFailure3(hr, "Database list friendly name '%ls' has incorrect path (expected '%ls', found '%ls')", wzExpectedFriendlyName, wzExpectedPath, wzPath);
            }

            if (fSyncByDefault != fExpectedSyncByDefault)
            {
                hr = E_FAIL;
                ExitOnFailure3(hr, "Database list friendly name '%ls' has incorrect 'sync by default' flag (expected %u, found %u)", wzExpectedFriendlyName, fExpectedSyncByDefault, fSyncByDefault);
            }

            // We found the right one, so return successfully now
            return;
        }

        hr = E_FAIL;
        ExitOnFailure2(hr, "Expected to find database in list, but didn't find it: %ls, %ls", wzFriendlyName, wzPath);

    LExit:
        return;
    }
    void CfgTest::CheckCfgAndFile(CFGDB_HANDLE cdhDb, LPCWSTR wzFileName, LPCWSTR wzFilePath, BYTE *pbBuffer, SIZE_T cbBuffer)
    {
        HRESULT hr = S_OK;
        BYTE *pbDataReadFromFile = NULL;
        DWORD cbDataReadFromFile = 0;

        ExpectFile(cdhDb, wzFileName, pbBuffer, cbBuffer);

        hr = FileRead(&pbDataReadFromFile, &cbDataReadFromFile, wzFilePath);
        ExitOnFailure1(hr, "Failed to read file: %ls", wzFilePath);

        if (cbBuffer != cbDataReadFromFile)
        {
            hr = E_FAIL;
            ExitOnFailure3(hr, "File %ls should be size %u, but was size %u instead", wzFilePath, cbBuffer, cbDataReadFromFile);
        }

        if (0 != memcmp(pbBuffer, pbDataReadFromFile, cbBuffer))
        {
            hr = E_FAIL;
            ExitOnFailure1(hr, "File contents don't match for file of name: %ls", wzFilePath);
        }
    LExit:
        ReleaseMem(pbDataReadFromFile);
    }
    void CfgTest::ExpectIniValue(INI_HANDLE iniHandle, LPCWSTR wzValueName, LPCWSTR wzExpectedValue)
    {
        HRESULT hr = S_OK;
        INI_VALUE* rgivValues = NULL;
        DWORD civValues = 0;

        hr = IniGetValueList(iniHandle, &rgivValues, &civValues);
        ExitOnFailure(hr, "Failed to get value list from INI handle");

        for (DWORD i = 0; i < civValues; ++i)
        {
            if (0 == wcscmp(rgivValues[i].wzName, wzValueName))
            {
                if (0 == wcscmp(rgivValues[i].wzValue, wzExpectedValue))
                {
                    return;
                }
                else
                {
                    hr = E_FAIL;
                    ExitOnFailure3(hr, "Found ini value %ls, but we expected to find value %ls, and found value %ls instead", wzValueName, wzExpectedValue, rgivValues[i].wzValue);
                }
            }
        }

        hr = E_NOTFOUND;
        ExitOnFailure1(hr, "Failed to find value %ls in INI", wzValueName);

    LExit:
        return;
    }
    void CfgTest::ExpectAdminProductUnregistered(CFGDB_HANDLE cdhAdminDb, LPCWSTR wzProductName, LPCWSTR wzVersion, LPCWSTR wzPublicKey)
    {
        HRESULT hr = S_OK;
        BOOL fRegistered = FALSE;

        hr = CfgAdminIsProductRegistered(cdhAdminDb, wzProductName, wzVersion, wzPublicKey, &fRegistered);
        ExitOnFailure3(hr, "Failed to check if product is registered (per-machine): %ls, %ls, %ls", wzProductName, wzVersion, wzPublicKey);

        if (fRegistered)
        {
            hr = E_FAIL;
            ExitOnFailure3(hr, "Product shouldn't be registered (per-machine), but it is!: %ls, %ls, %ls", wzProductName, wzVersion, wzPublicKey);
        }

    LExit:
        return;
    }
    void CfgTest::ExpectProductRegistered(CFGDB_HANDLE cdhUserDb, LPCWSTR wzProductName, LPCWSTR wzVersion, LPCWSTR wzPublicKey)
    {
        HRESULT hr = S_OK;
        BOOL fRegistered = FALSE;

        hr = CfgIsProductRegistered(cdhUserDb, wzProductName, wzVersion, wzPublicKey, &fRegistered);
        ExitOnFailure3(hr, "Failed to check if product is registered (per-user): %ls, %ls, %ls", wzProductName, wzVersion, wzPublicKey);

        if (!fRegistered)
        {
            hr = E_FAIL;
            ExitOnFailure3(hr, "Product should be registered (per-user), but it isn't!: %ls, %ls, %ls", wzProductName, wzVersion, wzPublicKey);
        }

    LExit:
        return;
    }
    void CfgTest::CheckCfgAndRegValueFlag(CFGDB_HANDLE cdhDb, HKEY hk, LPCWSTR wzCfgName, LPCWSTR wzName, BOOL fExpectedValue, DWORD dwOffset)
    {
        HRESULT hr = S_OK;
        BYTE *pbBytes;
        DWORD cbBytes;
        BOOL fRegFoundValue = FALSE;
        BOOL fCfgFoundValue = FALSE;

        hr = RegReadBinary(hk, wzName, &pbBytes, &cbBytes);
        ExitOnFailure1(hr, "Failed to read binary value from registry named %ls", wzName);

        if (dwOffset >= cbBytes * 8)
        {
            hr = E_INVALIDARG;
            ExitOnFailure2(hr, "Not enough bytes found in registry value %ls to check offset %u", wzName, dwOffset);
        }

        fRegFoundValue = (pbBytes[dwOffset / 8] & (0x1 << (dwOffset % 8))) == 0 ? FALSE : TRUE;

        if (fRegFoundValue != fExpectedValue)
        {
            hr = E_FAIL;
            ExitOnFailure3(hr, "Boolean flag value in registry didn't match expected! RegName: %ls, Offset: %ls, Expected: %ls", wzName, dwOffset, fExpectedValue ? L"TRUE" : L"FALSE");
        }

        hr = CfgGetBool(cdhDb, wzCfgName, &fCfgFoundValue);
        ExitOnFailure1(hr, "Failed to read boolean from cfg db named %ls", wzCfgName);

        if (fCfgFoundValue != fExpectedValue)
        {
            hr = E_FAIL;
            ExitOnFailure2(hr, "Boolean flag value in cfg db didn't match expected! CfgName: %ls, Expected: %ls", wzCfgName, fExpectedValue ? L"TRUE" : L"FALSE");
        }
    LExit:
        ReleaseMem(pbBytes);
    }
Exemplo n.º 7
0
/******************************************************************
 CaExecSecureObjects - entry point for SecureObjects Custom Action
				   called as Type 1025 CustomAction (deferred binary DLL)

 NOTE: deferred CustomAction since it modifies the machine
 NOTE: CustomActionData == wzObject\twzTable\twzDomain\twzUser\tdwPermissions\twzObject\t...
******************************************************************/
extern "C" UINT __stdcall ExecSecureObjects(
	__in MSIHANDLE hInstall
	)
{
//	AssertSz(FALSE, "debug ExecSecureObjects");
	HRESULT hr = S_OK;
	DWORD er = ERROR_SUCCESS;

	LPWSTR pwz = NULL;
	LPWSTR pwzData = NULL;
	LPWSTR pwzObject = NULL;
	LPWSTR pwzTable = NULL;
	LPWSTR pwzDomain = NULL;
	DWORD dwRevision = 0;
	LPWSTR pwzUser = NULL;
	DWORD dwPermissions = 0;
	LPWSTR pwzAccount = NULL;
	PSID psid = NULL;

	EXPLICIT_ACCESSW ea = {0};
	SE_OBJECT_TYPE objectType = SE_UNKNOWN_OBJECT_TYPE;
	PSECURITY_DESCRIPTOR psd = NULL;
	SECURITY_DESCRIPTOR_CONTROL sdc = {0};
	SECURITY_INFORMATION si = {0};
	PACL pAclExisting = NULL;   // doesn't get freed
	PACL pAclNew = NULL;

	PMSIHANDLE hActionRec = ::MsiCreateRecord(1);

	//
	// initialize
	//
	hr = WcaInitialize(hInstall, "ExecSecureObjects");
	ExitOnFailure(hr, "failed to initialize");

	hr = WcaGetProperty(L"CustomActionData", &pwzData);
	ExitOnFailure(hr, "failed to get CustomActionData");

	WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %S", pwzData);

	pwz = pwzData;

	//
	// loop through all the passed in data
	//
	while (pwz && *pwz)
	{
		hr = WcaReadStringFromCaData(&pwz, &pwzObject);
		ExitOnFailure(hr, "failed to process CustomActionData");

		hr = WcaReadStringFromCaData(&pwz, &pwzTable);
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadStringFromCaData(&pwz, &pwzDomain);
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadStringFromCaData(&pwz, &pwzUser);
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&dwPermissions));
		ExitOnFailure(hr, "failed to processCustomActionData");

		WcaLog(LOGMSG_VERBOSE, "Securing Object: %S Type: %S User: %S", pwzObject, pwzTable, pwzUser);

		//
		// create the appropriate SID
		//

		// figure out the right user to put into the access block
		if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Everyone"))
		{
			hr = AclGetWellKnownSid(WinWorldSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Administrators"))
		{
			hr = AclGetWellKnownSid(WinBuiltinAdministratorsSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"LocalSystem"))
		{
			hr = AclGetWellKnownSid(WinLocalSystemSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"LocalService"))
		{
			hr = AclGetWellKnownSid(WinLocalServiceSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"NetworkService"))
		{
			hr = AclGetWellKnownSid(WinNetworkServiceSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"AuthenticatedUser"))
		{
			hr = AclGetWellKnownSid(WinAuthenticatedUserSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Guests"))
		{
			hr = AclGetWellKnownSid(WinBuiltinGuestsSid, &psid);
		}
		else if(!*pwzDomain && 0 == lstrcmpW(pwzUser, L"CREATOR OWNER"))
		{
			hr = AclGetWellKnownSid(WinCreatorOwnerSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"INTERACTIVE"))
		{
			hr = AclGetWellKnownSid(WinInteractiveSid, &psid);
		}
		else if(!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Users"))
		{
			hr = AclGetWellKnownSid(WinBuiltinUsersSid, &psid);
		}
		else
		{
			hr = StrAllocFormatted(&pwzAccount, L"%s\\%s", *pwzDomain ? pwzDomain : L".", pwzUser);
			ExitOnFailure(hr, "failed to build domain user name");

			hr = AclGetAccountSid(NULL, pwzAccount, &psid);
		}
		ExitOnFailure3(hr, "failed to get sid for account: %S%S%S", pwzDomain, *pwzDomain ? L"\\" : L"", pwzUser);

		//
		// build up the explicit access
		//
		ea.grfAccessPermissions = dwPermissions;
		ea.grfAccessMode = SET_ACCESS;

		if (0 == lstrcmpW(L"CreateFolder", pwzTable))
		{
			ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
		}
		else
		{
			ea.grfInheritance = NO_INHERITANCE;
		}

		::BuildTrusteeWithSidW(&ea.Trustee, psid);

		if (0 == lstrcmpW(L"ServiceInstall", pwzTable))
		{
			objectType = SE_SERVICE;

			// always add these permissions for services
			// these are basic permissions that are often forgotten
			dwPermissions |= SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_INTERROGATE;
		}
		else if (0 == lstrcmpW(L"CreateFolder", pwzTable) || 0 == lstrcmpW(L"File", pwzTable))
		{
			objectType = SE_FILE_OBJECT;
		}
		else if (0 == lstrcmpW(L"Registry", pwzTable))
		{
			objectType = SE_REGISTRY_KEY;
		}

		if (SE_UNKNOWN_OBJECT_TYPE != objectType)
		{
			er = ::GetNamedSecurityInfoW(pwzObject, objectType, DACL_SECURITY_INFORMATION, NULL, NULL, &pAclExisting, NULL, &psd);
			ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "failed to get security info for object: %S", pwzObject);

			//Need to see if DACL is protected so getting Descriptor information
			if(!::GetSecurityDescriptorControl(psd, &sdc, &dwRevision))
			{
				ExitOnLastError1(hr, "failed to get security descriptor control for object: %S", pwzObject);
			}

			er = ::SetEntriesInAclW(1, &ea, pAclExisting, &pAclNew);
			ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "failed to add ACLs for object: %S", pwzObject);

			if (sdc & SE_DACL_PROTECTED)
			{
				si = DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION;
			}
			else
			{
				si = DACL_SECURITY_INFORMATION;
			}
			er = ::SetNamedSecurityInfoW(pwzObject, objectType, si, NULL, NULL, pAclNew, NULL);
			MessageExitOnFailure1(hr = HRESULT_FROM_WIN32(er), msierrSecureObjectsFailedSet, "failed to set security info for object: %S", pwzObject);
		}
		else
		{
			MessageExitOnFailure1(hr = E_UNEXPECTED, msierrSecureObjectsUnknownType, "unknown object type: %S", pwzTable);
		}

		hr = WcaProgressMessage(COST_SECUREOBJECT, FALSE);
		ExitOnFailure(hr, "failed to send progress message");

		objectType = SE_UNKNOWN_OBJECT_TYPE;
	}

LExit:
	ReleaseStr(pwzUser);
	ReleaseStr(pwzDomain);
	ReleaseStr(pwzTable);
	ReleaseStr(pwzObject);
	ReleaseStr(pwzData);
	ReleaseStr(pwzAccount);

	if (pAclNew)
		::LocalFree(pAclNew);
	if (psd)
		::LocalFree(psd);
	if (psid)
		AclFreeSid(psid);

	if (FAILED(hr))
		er = ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
Exemplo n.º 8
0
/******************************************************************
 ExecFirewallExceptions - deferred custom action entry point to 
   register and remove firewall exceptions.

********************************************************************/
extern "C" UINT __stdcall ExecFirewallExceptions(
    __in MSIHANDLE hInstall
    )
{
    HRESULT hr = S_OK;
    BOOL fSupportProfiles = FALSE;
    LPWSTR pwz = NULL;
    LPWSTR pwzCustomActionData = NULL;
    int iTodo = WCA_TODO_UNKNOWN;
    LPWSTR pwzName = NULL;
    LPWSTR pwzRemoteAddresses = NULL;
    int iAttributes = 0;
    int iTarget = fetUnknown;
    LPWSTR pwzFile = NULL;
    LPWSTR pwzPort = NULL;
    LPWSTR pwzDescription = NULL;
    int iProtocol = 0;
    int iProfile = 0;

    // initialize
    hr = WcaInitialize(hInstall, "ExecFirewallExceptions");
    ExitOnFailure(hr, "failed to initialize");

    hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");
    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);

    hr = ::CoInitialize(NULL);
    ExitOnFailure(hr, "failed to initialize COM");

    // Find out if we support profiles (only on Vista or later)
    fSupportProfiles = FSupportProfiles();

    // loop through all the passed in data
    pwz = pwzCustomActionData;
    while (pwz && *pwz)
    {
        // extract the custom action data and if rolling back, swap INSTALL and UNINSTALL
        hr = WcaReadIntegerFromCaData(&pwz, &iTodo);
        ExitOnFailure(hr, "failed to read todo from custom action data");
        if (::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK))
        {
            if (WCA_TODO_INSTALL == iTodo)
            {
                iTodo = WCA_TODO_UNINSTALL;
            }
            else if (WCA_TODO_UNINSTALL == iTodo)
            {
                iTodo = WCA_TODO_INSTALL;
            }
        }

        hr = WcaReadStringFromCaData(&pwz, &pwzName);
        ExitOnFailure(hr, "failed to read name from custom action data");

        hr = WcaReadIntegerFromCaData(&pwz, &iProfile);
        ExitOnFailure(hr, "failed to read profile from custom action data");

        hr = WcaReadStringFromCaData(&pwz, &pwzRemoteAddresses);
        ExitOnFailure(hr, "failed to read remote addresses from custom action data");

        hr = WcaReadIntegerFromCaData(&pwz, &iAttributes);
        ExitOnFailure(hr, "failed to read attributes from custom action data");
        BOOL fIgnoreFailures = feaIgnoreFailures == (iAttributes & feaIgnoreFailures);

        hr = WcaReadIntegerFromCaData(&pwz, &iTarget);
        ExitOnFailure(hr, "failed to read target from custom action data");

        if (iTarget == fetApplication)
        {
            hr = WcaReadStringFromCaData(&pwz, &pwzFile);
            ExitOnFailure(hr, "failed to read file path from custom action data");
        }

        hr = WcaReadStringFromCaData(&pwz, &pwzPort);
        ExitOnFailure(hr, "failed to read port from custom action data");
        hr = WcaReadIntegerFromCaData(&pwz, &iProtocol);
        ExitOnFailure(hr, "failed to read protocol from custom action data");
        hr = WcaReadStringFromCaData(&pwz, &pwzDescription);
        ExitOnFailure(hr, "failed to read protocol from custom action data");

        switch (iTarget)
        {
        case fetPort:
            switch (iTodo)
            {
            case WCA_TODO_INSTALL:
            case WCA_TODO_REINSTALL:
                WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
                hr = AddPortException(fSupportProfiles, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription);
                ExitOnFailure3(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
                break;

            case WCA_TODO_UNINSTALL:
                WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
                hr = RemovePortException(fSupportProfiles, pwzName, pwzPort, iProtocol, fIgnoreFailures);
                ExitOnFailure3(hr, "failed to remove port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
                break;
            }
            break;

        case fetApplication:
            switch (iTodo)
            {
            case WCA_TODO_INSTALL:
            case WCA_TODO_REINSTALL:
                WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls (%ls)", pwzName, pwzFile);
                hr = AddApplicationException(fSupportProfiles, pwzFile, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription);
                ExitOnFailure2(hr, "failed to add/update application exception for name '%ls', file '%ls'", pwzName, pwzFile);
                break;

            case WCA_TODO_UNINSTALL:
                WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls (%ls)", pwzName, pwzFile);
                hr = RemoveApplicationException(fSupportProfiles, pwzName, pwzFile, fIgnoreFailures, pwzPort, iProtocol);
                ExitOnFailure2(hr, "failed to remove application exception for name '%ls', file '%ls'", pwzName, pwzFile);
                break;
            }
            break;
        }
    }

LExit:
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzName);
    ReleaseStr(pwzRemoteAddresses);
    ReleaseStr(pwzFile);
    ReleaseStr(pwzPort);
    ReleaseStr(pwzDescription);
    ::CoUninitialize();

    return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS);
}