Example #1
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);
}
Example #2
0
/********************************************************************
 AllocateAcl - allocate an acl and populate it with this user and
                 permission information user could be user or domain\user

********************************************************************/
HRESULT AllocateAcl(SCA_SMBP* pssp, PACL* ppACL)
{
    HRESULT hr = S_OK;
    EXPLICIT_ACCESSW* pEA = NULL;
    DWORD cEA = 0;
    DWORD dwCounter = 0;

    PSID psid = NULL;
    LPCWSTR wzUser = NULL;
    DWORD nPermissions = 0;
    DWORD nErrorReturn = 0;
    ACCESS_MODE accessMode = NOT_USED_ACCESS;

    cEA = pssp->dwUserPermissionCount + 1;
    if (cEA >= MAXSIZE_T / sizeof(EXPLICIT_ACCESSW))
    {
        ExitOnFailure1(hr = E_OUTOFMEMORY, "Too many user permissions to allocate: %u", cEA);
    }

    pEA = static_cast<EXPLICIT_ACCESSW*>(MemAlloc(cEA * sizeof(EXPLICIT_ACCESSW), TRUE));
    ExitOnNull(pEA, hr, E_OUTOFMEMORY, "failed to allocate memory for explicit access structure");

    // figure out how big the psid is
    for (dwCounter = 0; dwCounter < pssp->dwUserPermissionCount; ++dwCounter)
    {
        wzUser = pssp->pUserPerms[dwCounter].wzUser;
        nPermissions = pssp->pUserPerms[dwCounter].nPermissions;
        accessMode = pssp->pUserPerms[dwCounter].accessMode;
        //
        // create the appropriate SID
        //

        // figure out the right user to put into the access block
        if (0 == lstrcmpW(wzUser, L"Everyone"))
        {
            hr = AclGetWellKnownSid(WinWorldSid, &psid);
        }
        else if (0 == lstrcmpW(wzUser, L"Administrators"))
        {
            hr = AclGetWellKnownSid(WinBuiltinAdministratorsSid, &psid);
        }
        else if (0 == lstrcmpW(wzUser, L"LocalSystem"))
        {
            hr = AclGetWellKnownSid(WinLocalSystemSid, &psid);
        }
        else if (0 == lstrcmpW(wzUser, L"LocalService"))
        {
            hr = AclGetWellKnownSid(WinLocalServiceSid, &psid);
        }
        else if (0 == lstrcmpW(wzUser, L"NetworkService"))
        {
            hr = AclGetWellKnownSid(WinNetworkServiceSid, &psid);
        }
        else if (0 == lstrcmpW(wzUser, L"AuthenticatedUser"))
        {
            hr = AclGetWellKnownSid(WinAuthenticatedUserSid, &psid);
        }
        else if (0 == lstrcmpW(wzUser, L"Guests"))
        {
            hr = AclGetWellKnownSid(WinBuiltinGuestsSid, &psid);
        }
        else if(0 == lstrcmpW(wzUser, L"CREATOR OWNER"))
        {
            hr = AclGetWellKnownSid(WinCreatorOwnerSid, &psid);
        }
        else
        {
            hr = AclGetAccountSid(NULL, wzUser, &psid);
        }
        ExitOnFailure1(hr, "failed to get sid for account: %ls", wzUser);

        // we now have a valid pSid, fill in the EXPLICIT_ACCESS

        /* Permissions options:   (see sca.sdh for defined sdl options)
        #define GENERIC_READ      (0x80000000L)    2147483648
        #define GENERIC_WRITE     (0x40000000L)    1073741824
        #define GENERIC_EXECUTE   (0x20000000L)    536870912
        #define GENERIC_ALL       (0x10000000L)    268435456
        */
        pEA[dwCounter].grfAccessPermissions = nPermissions;
        pEA[dwCounter].grfAccessMode = accessMode;
        pEA[dwCounter].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
#pragma prefast(push)
#pragma prefast(disable:25029)
        ::BuildTrusteeWithSidW(&(pEA[dwCounter].Trustee), psid);
#pragma prefast(pop)
    }

    // create a new ACL that contains the ACE
    *ppACL = NULL;
#pragma prefast(push)
#pragma prefast(disable:25029)
    nErrorReturn = ::SetEntriesInAclW(dwCounter, pEA, NULL, ppACL);
#pragma prefast(pop)
    ExitOnFailure(hr = HRESULT_FROM_WIN32(nErrorReturn), "failed to allocate ACL");

LExit:
    if (psid)
    {
        AclFreeSid(psid);
    }

    ReleaseMem(pEA);

    return hr;
}