Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for attempted use of capability API before it was introduced #4620

Merged
merged 1 commit into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/AppInstallerSharedLib/Public/winget/Security.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ namespace AppInstaller::Security
// and is at least equal integrity level (higher will also be allowed).
bool IsCOMCallerSameUserAndIntegrityLevel();

// Determines if the current COM caller is at least the minimum integrity level provided.
bool IsCOMCallerIntegrityLevelAtLeast(IntegrityLevel minimumLevel);

// Determines if the current integrity level is at least the minimum integrity level provided.
bool IsCurrentIntegrityLevelAtLeast(IntegrityLevel minimumLevel);

// Gets the string representation of the given SID.
std::string ToString(PSID sid);
}
19 changes: 19 additions & 0 deletions src/AppInstallerSharedLib/Security.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,25 @@ namespace AppInstaller::Security
return true;
}

bool IsCOMCallerIntegrityLevelAtLeast(IntegrityLevel minimumLevel)
{
auto impersonation = ImpersonateCOMorRPCCaller::BeginImpersonation();
return IsCurrentIntegrityLevelAtLeast(minimumLevel);
}

bool IsCurrentIntegrityLevelAtLeast(IntegrityLevel minimumLevel)
{
IntegrityLevel callingIntegrityLevel = GetEffectiveIntegrityLevel();

if (ToIntegral(callingIntegrityLevel) < ToIntegral(minimumLevel))
{
AICLI_LOG(Core, Crit, << "Attempt to access by a lower integrity process than required: " << callingIntegrityLevel << " < " << minimumLevel);
return false;
}

return true;
}

std::string ToString(PSID sid)
{
wil::unique_hlocal_ansistring result;
Expand Down
35 changes: 28 additions & 7 deletions src/Microsoft.Management.Deployment/Helpers.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
Expand All @@ -7,6 +6,7 @@
#include <winrt/Windows.Security.Authorization.AppCapabilityAccess.h>
#include <appmodel.h>
#include <Helpers.h>
#include <winget/Security.h>

using namespace std::string_literals;
using namespace std::string_view_literals;
Expand Down Expand Up @@ -71,13 +71,34 @@ namespace winrt::Microsoft::Management::Deployment::implementation

HRESULT EnsureProcessHasCapability(Capability requiredCapability, DWORD callerProcessId)
{
// Get the caller process id and use it to check if the caller has permissions to access the feature.
winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapabilityAccessStatus status = winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapabilityAccessStatus::DeniedBySystem;
bool allowed = false;

if (winrt::Windows::Foundation::Metadata::ApiInformation::IsTypePresent(winrt::name_of<winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapability>()))
{
// Get the caller process id and use it to check if the caller has permissions to access the feature.
winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapabilityAccessStatus status = winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapabilityAccessStatus::DeniedBySystem;

auto capability = winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapability::CreateWithProcessIdForUser(nullptr, GetStringForCapability(requiredCapability), callerProcessId);
status = capability.CheckAccess();

auto capability = winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapability::CreateWithProcessIdForUser(nullptr, GetStringForCapability(requiredCapability), callerProcessId);
status = capability.CheckAccess();
allowed = (status == winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapabilityAccessStatus::Allowed);
}
else
{
// If AppCapability is not present, require at least medium IL callers
auto requiredIntegrityLevel = AppInstaller::Security::IntegrityLevel::Medium;

if (callerProcessId != GetCurrentProcessId())
{
allowed = AppInstaller::Security::IsCOMCallerIntegrityLevelAtLeast(requiredIntegrityLevel);
}
else
{
allowed = AppInstaller::Security::IsCurrentIntegrityLevelAtLeast(requiredIntegrityLevel);
}
}

return (status != winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapabilityAccessStatus::Allowed ? E_ACCESSDENIED : S_OK);
return (allowed ? S_OK : E_ACCESSDENIED);
}

HRESULT EnsureComCallerHasCapability(Capability requiredCapability)
Expand Down Expand Up @@ -168,4 +189,4 @@ namespace winrt::Microsoft::Management::Deployment::implementation

return isBackgroundProcessForPolicy;
}
}
}
5 changes: 3 additions & 2 deletions src/Microsoft.Management.Deployment/pch.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include <unknwn.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Foundation.Metadata.h>
#include <winrt/Windows.Web.Http.h>

#include <ostream>
#include <string>
#include <mutex>
#include <random>
#include <random>
Loading