blob: 190b7296ea0202ca0c64bcd07758e4138c83e5b5 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sandbox/win/src/sandbox_policy_diagnostic.h"
#include <stddef.h>
#include <cinttypes>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/json/json_string_value_serializer.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "sandbox/win/src/sandbox_constants.h"
#include "sandbox/win/src/sandbox_policy_base.h"
#include "sandbox/win/src/target_process.h"
#include "sandbox/win/src/win_utils.h"
namespace sandbox {
namespace {
base::Value ProcessIdList(std::vector<uint32_t> process_ids) {
base::Value results(base::Value::Type::LIST);
for (const auto pid : process_ids) {
results.GetList().push_back(base::Value(base::strict_cast<double>(pid)));
}
return results;
}
std::string GetTokenLevelInEnglish(TokenLevel token) {
switch (token) {
case USER_LOCKDOWN:
return "Lockdown";
case USER_RESTRICTED:
return "Restricted";
case USER_LIMITED:
return "Limited";
case USER_INTERACTIVE:
return "Interactive";
case USER_NON_ADMIN:
return "Non Admin";
case USER_RESTRICTED_SAME_ACCESS:
return "Restricted Same Access";
case USER_UNPROTECTED:
return "Unprotected";
case USER_RESTRICTED_NON_ADMIN:
return "Restricted Non Admin";
case USER_LAST:
default:
DCHECK(false) << "Unknown TokenType";
return "Unknown";
}
}
std::string GetJobLevelInEnglish(JobLevel job) {
switch (job) {
case JOB_LOCKDOWN:
return "Lockdown";
case JOB_RESTRICTED:
return "Restricted";
case JOB_LIMITED_USER:
return "Limited User";
case JOB_INTERACTIVE:
return "Interactive";
case JOB_UNPROTECTED:
return "Unprotected";
case JOB_NONE:
return "None";
default:
DCHECK(false) << "Unknown JobLevel";
return "Unknown";
}
}
std::string GetIntegrityLevelInEnglish(IntegrityLevel integrity) {
switch (integrity) {
case INTEGRITY_LEVEL_SYSTEM:
return "S-1-16-16384 System";
case INTEGRITY_LEVEL_HIGH:
return "S-1-16-12288 High";
case INTEGRITY_LEVEL_MEDIUM:
return "S-1-16-8192 Medium";
case INTEGRITY_LEVEL_MEDIUM_LOW:
return "S-1-16-6144 Medium Low";
case INTEGRITY_LEVEL_LOW:
return "S-1-16-4096 Low";
case INTEGRITY_LEVEL_BELOW_LOW:
return "S-1-16-2048 Below Low";
case INTEGRITY_LEVEL_UNTRUSTED:
return "S-1-16-0 Untrusted";
case INTEGRITY_LEVEL_LAST:
return "Default";
default:
DCHECK(false) << "Unknown IntegrityLevel";
return "Unknown";
}
}
base::string16 GetSidAsString(const Sid* sid) {
base::string16 result;
if (!sid->ToSddlString(&result))
DCHECK(false) << "Failed to make sddl string";
return result;
}
std::string GetMitigationsAsHex(MitigationFlags mitigations) {
return base::StringPrintf("%016" PRIx64,
base::checked_cast<uint64_t>(mitigations));
}
std::string GetPlatformMitigationsAsHex(MitigationFlags mitigations) {
DWORD64 platform_flags[2] = {0};
size_t flags_size = 0;
sandbox::ConvertProcessMitigationsToPolicy(mitigations, &(platform_flags[0]),
&flags_size);
DCHECK(flags_size / sizeof(DWORD64) <= 2)
<< "Unexpected mitigation flags size";
if (flags_size == 2 * sizeof(DWORD64))
return base::StringPrintf("%016" PRIx64 "%016" PRIx64, platform_flags[0],
platform_flags[1]);
return base::StringPrintf("%016" PRIx64, platform_flags[0]);
}
} // namespace
// We are a friend of PolicyBase so that we can steal its private members
// quickly in the BrokerServices tracker thread.
PolicyDiagnostic::PolicyDiagnostic(PolicyBase* policy) {
DCHECK(policy);
// TODO(crbug/997273) Add more fields once webui plumbing is complete.
{
AutoLock lock(&policy->lock_);
for (auto&& target_process : policy->targets_) {
process_ids_.push_back(
base::strict_cast<uint32_t>(target_process->ProcessId()));
}
}
lockdown_level_ = policy->lockdown_level_;
job_level_ = policy->job_level_;
// Select the final integrity level.
if (policy->delayed_integrity_level_ == INTEGRITY_LEVEL_LAST)
desired_integrity_level_ = policy->integrity_level_;
else
desired_integrity_level_ = policy->delayed_integrity_level_;
desired_mitigations_ = policy->mitigations_ | policy->delayed_mitigations_;
if (policy->app_container_profile_)
app_container_sid_ =
std::make_unique<Sid>(policy->app_container_profile_->GetPackageSid());
if (policy->lowbox_sid_)
lowbox_sid_ = std::make_unique<Sid>(policy->lowbox_sid_);
}
PolicyDiagnostic::~PolicyDiagnostic() = default;
const char* PolicyDiagnostic::JsonString() {
// Lazily constructs json_string_.
if (json_string_)
return json_string_->c_str();
base::Value value(base::Value::Type::DICTIONARY);
value.SetKey(kProcessIds, ProcessIdList(process_ids_));
value.SetKey(kLockdownLevel,
base::Value(GetTokenLevelInEnglish(lockdown_level_)));
value.SetKey(kJobLevel, base::Value(GetJobLevelInEnglish(job_level_)));
value.SetKey(
kDesiredIntegrityLevel,
base::Value(GetIntegrityLevelInEnglish(desired_integrity_level_)));
value.SetKey(kDesiredMitigations,
base::Value(GetMitigationsAsHex(desired_mitigations_)));
value.SetKey(kPlatformMitigations,
base::Value(GetPlatformMitigationsAsHex(desired_mitigations_)));
if (app_container_sid_)
value.SetKey(kAppContainerSid,
base::Value(GetSidAsString(app_container_sid_.get())));
if (lowbox_sid_)
value.SetKey(kLowboxSid, base::Value(GetSidAsString(lowbox_sid_.get())));
auto json_string = std::make_unique<std::string>();
JSONStringValueSerializer to_json(json_string.get());
CHECK(to_json.Serialize(value));
json_string_ = std::move(json_string);
return json_string_->c_str();
}
} // namespace sandbox