// Copyright (c) 2012 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_base.h"

#include <sddl.h>

#include "base/basictypes.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/app_container.h"
#include "sandbox/win/src/filesystem_dispatcher.h"
#include "sandbox/win/src/filesystem_policy.h"
#include "sandbox/win/src/handle_dispatcher.h"
#include "sandbox/win/src/handle_policy.h"
#include "sandbox/win/src/job.h"
#include "sandbox/win/src/interception.h"
#include "sandbox/win/src/process_mitigations.h"
#include "sandbox/win/src/named_pipe_dispatcher.h"
#include "sandbox/win/src/named_pipe_policy.h"
#include "sandbox/win/src/policy_broker.h"
#include "sandbox/win/src/policy_engine_processor.h"
#include "sandbox/win/src/policy_low_level.h"
#include "sandbox/win/src/process_mitigations_win32k_dispatcher.h"
#include "sandbox/win/src/process_mitigations_win32k_policy.h"
#include "sandbox/win/src/process_thread_dispatcher.h"
#include "sandbox/win/src/process_thread_policy.h"
#include "sandbox/win/src/registry_dispatcher.h"
#include "sandbox/win/src/registry_policy.h"
#include "sandbox/win/src/restricted_token_utils.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_utils.h"
#include "sandbox/win/src/sync_dispatcher.h"
#include "sandbox/win/src/sync_policy.h"
#include "sandbox/win/src/target_process.h"
#include "sandbox/win/src/window.h"

namespace {

// The standard windows size for one memory page.
const size_t kOneMemPage = 4096;
// The IPC and Policy shared memory sizes.
const size_t kIPCMemSize = kOneMemPage * 2;
const size_t kPolMemSize = kOneMemPage * 14;

// Helper function to allocate space (on the heap) for policy.
sandbox::PolicyGlobal* MakeBrokerPolicyMemory() {
  const size_t kTotalPolicySz = kPolMemSize;
  sandbox::PolicyGlobal* policy = static_cast<sandbox::PolicyGlobal*>
      (::operator new(kTotalPolicySz));
  DCHECK(policy);
  memset(policy, 0, kTotalPolicySz);
  policy->data_size = kTotalPolicySz - sizeof(sandbox::PolicyGlobal);
  return policy;
}

bool IsInheritableHandle(HANDLE handle) {
  if (!handle)
    return false;
  if (handle == INVALID_HANDLE_VALUE)
    return false;
  // File handles (FILE_TYPE_DISK) and pipe handles are known to be
  // inheritable.  Console handles (FILE_TYPE_CHAR) are not
  // inheritable via PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
  DWORD handle_type = GetFileType(handle);
  return handle_type == FILE_TYPE_DISK || handle_type == FILE_TYPE_PIPE;
}

HANDLE CreateLowBoxObjectDirectory(PSID lowbox_sid) {
  DWORD session_id = 0;
  if (!::ProcessIdToSessionId(::GetCurrentProcessId(), &session_id))
    return NULL;

  LPWSTR sid_string = NULL;
  if (!::ConvertSidToStringSid(lowbox_sid, &sid_string))
    return NULL;

  base::string16 directory_path = base::StringPrintf(
                   L"\\Sessions\\%d\\AppContainerNamedObjects\\%ls",
                   session_id, sid_string).c_str();
  ::LocalFree(sid_string);

  NtCreateDirectoryObjectFunction CreateObjectDirectory = NULL;
  ResolveNTFunctionPtr("NtCreateDirectoryObject", &CreateObjectDirectory);

  OBJECT_ATTRIBUTES obj_attr;
  UNICODE_STRING obj_name;
  sandbox::InitObjectAttribs(directory_path,
                             OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
                             NULL,
                             &obj_attr,
                             &obj_name,
                             NULL);

  HANDLE handle = NULL;
  NTSTATUS status = CreateObjectDirectory(&handle,
                                          DIRECTORY_ALL_ACCESS,
                                          &obj_attr);

  if (!NT_SUCCESS(status))
    return NULL;

  return handle;
}

}

namespace sandbox {

SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level;
SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations;

// Initializes static members.
HWINSTA PolicyBase::alternate_winstation_handle_ = NULL;
HDESK PolicyBase::alternate_desktop_handle_ = NULL;
IntegrityLevel PolicyBase::alternate_desktop_integrity_level_label_ =
    INTEGRITY_LEVEL_SYSTEM;

PolicyBase::PolicyBase()
    : ref_count(1),
      lockdown_level_(USER_LOCKDOWN),
      initial_level_(USER_LOCKDOWN),
      job_level_(JOB_LOCKDOWN),
      ui_exceptions_(0),
      memory_limit_(0),
      use_alternate_desktop_(false),
      use_alternate_winstation_(false),
      file_system_init_(false),
      relaxed_interceptions_(true),
      stdout_handle_(INVALID_HANDLE_VALUE),
      stderr_handle_(INVALID_HANDLE_VALUE),
      integrity_level_(INTEGRITY_LEVEL_LAST),
      delayed_integrity_level_(INTEGRITY_LEVEL_LAST),
      mitigations_(0),
      delayed_mitigations_(0),
      policy_maker_(NULL),
      policy_(NULL),
      lowbox_sid_(NULL) {
  ::InitializeCriticalSection(&lock_);
  // Initialize the IPC dispatcher array.
  memset(&ipc_targets_, NULL, sizeof(ipc_targets_));
  Dispatcher* dispatcher = NULL;

  dispatcher = new FilesystemDispatcher(this);
  ipc_targets_[IPC_NTCREATEFILE_TAG] = dispatcher;
  ipc_targets_[IPC_NTOPENFILE_TAG] = dispatcher;
  ipc_targets_[IPC_NTSETINFO_RENAME_TAG] = dispatcher;
  ipc_targets_[IPC_NTQUERYATTRIBUTESFILE_TAG] = dispatcher;
  ipc_targets_[IPC_NTQUERYFULLATTRIBUTESFILE_TAG] = dispatcher;

  dispatcher = new NamedPipeDispatcher(this);
  ipc_targets_[IPC_CREATENAMEDPIPEW_TAG] = dispatcher;

  dispatcher = new ThreadProcessDispatcher(this);
  ipc_targets_[IPC_NTOPENTHREAD_TAG] = dispatcher;
  ipc_targets_[IPC_NTOPENPROCESS_TAG] = dispatcher;
  ipc_targets_[IPC_CREATEPROCESSW_TAG] = dispatcher;
  ipc_targets_[IPC_NTOPENPROCESSTOKEN_TAG] = dispatcher;
  ipc_targets_[IPC_NTOPENPROCESSTOKENEX_TAG] = dispatcher;

  dispatcher = new SyncDispatcher(this);
  ipc_targets_[IPC_CREATEEVENT_TAG] = dispatcher;
  ipc_targets_[IPC_OPENEVENT_TAG] = dispatcher;

  dispatcher = new RegistryDispatcher(this);
  ipc_targets_[IPC_NTCREATEKEY_TAG] = dispatcher;
  ipc_targets_[IPC_NTOPENKEY_TAG] = dispatcher;

  dispatcher = new HandleDispatcher(this);
  ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG] = dispatcher;

  dispatcher = new ProcessMitigationsWin32KDispatcher(this);
  ipc_targets_[IPC_GDI_GDIDLLINITIALIZE_TAG] = dispatcher;
  ipc_targets_[IPC_GDI_GETSTOCKOBJECT_TAG] = dispatcher;
  ipc_targets_[IPC_USER_REGISTERCLASSW_TAG] = dispatcher;
}

PolicyBase::~PolicyBase() {
  ClearSharedHandles();

  TargetSet::iterator it;
  for (it = targets_.begin(); it != targets_.end(); ++it) {
    TargetProcess* target = (*it);
    delete target;
  }
  delete ipc_targets_[IPC_NTCREATEFILE_TAG];
  delete ipc_targets_[IPC_CREATENAMEDPIPEW_TAG];
  delete ipc_targets_[IPC_NTOPENTHREAD_TAG];
  delete ipc_targets_[IPC_CREATEEVENT_TAG];
  delete ipc_targets_[IPC_NTCREATEKEY_TAG];
  delete ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG];
  delete policy_maker_;
  delete policy_;

  if (lowbox_sid_)
    ::LocalFree(lowbox_sid_);

  ::DeleteCriticalSection(&lock_);
}

void PolicyBase::AddRef() {
  ::InterlockedIncrement(&ref_count);
}

void PolicyBase::Release() {
  if (0 == ::InterlockedDecrement(&ref_count))
    delete this;
}

ResultCode PolicyBase::SetTokenLevel(TokenLevel initial, TokenLevel lockdown) {
  if (initial < lockdown) {
    return SBOX_ERROR_BAD_PARAMS;
  }
  initial_level_ = initial;
  lockdown_level_ = lockdown;
  return SBOX_ALL_OK;
}

TokenLevel PolicyBase::GetInitialTokenLevel() const {
  return initial_level_;
}

TokenLevel PolicyBase::GetLockdownTokenLevel() const{
  return lockdown_level_;
}

ResultCode PolicyBase::SetJobLevel(JobLevel job_level, uint32 ui_exceptions) {
  if (memory_limit_ && job_level == JOB_NONE) {
    return SBOX_ERROR_BAD_PARAMS;
  }
  job_level_ = job_level;
  ui_exceptions_ = ui_exceptions;
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetJobMemoryLimit(size_t memory_limit) {
  if (memory_limit && job_level_ == JOB_NONE) {
    return SBOX_ERROR_BAD_PARAMS;
  }
  memory_limit_ = memory_limit;
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetAlternateDesktop(bool alternate_winstation) {
  use_alternate_desktop_ = true;
  use_alternate_winstation_ = alternate_winstation;
  return CreateAlternateDesktop(alternate_winstation);
}

base::string16 PolicyBase::GetAlternateDesktop() const {
  // No alternate desktop or winstation. Return an empty string.
  if (!use_alternate_desktop_ && !use_alternate_winstation_) {
    return base::string16();
  }

  // The desktop and winstation should have been created by now.
  // If we hit this scenario, it means that the user ignored the failure
  // during SetAlternateDesktop, so we ignore it here too.
  if (use_alternate_desktop_ && !alternate_desktop_handle_) {
    return base::string16();
  }
  if (use_alternate_winstation_ && (!alternate_desktop_handle_ ||
                                    !alternate_winstation_handle_)) {
    return base::string16();
  }

  return GetFullDesktopName(alternate_winstation_handle_,
                            alternate_desktop_handle_);
}

ResultCode PolicyBase::CreateAlternateDesktop(bool alternate_winstation) {
  if (alternate_winstation) {
    // Previously called with alternate_winstation = false?
    if (!alternate_winstation_handle_ && alternate_desktop_handle_)
      return SBOX_ERROR_UNSUPPORTED;

    // Check if it's already created.
    if (alternate_winstation_handle_ && alternate_desktop_handle_)
      return SBOX_ALL_OK;

    DCHECK(!alternate_winstation_handle_);
    // Create the window station.
    ResultCode result = CreateAltWindowStation(&alternate_winstation_handle_);
    if (SBOX_ALL_OK != result)
      return result;

    // Verify that everything is fine.
    if (!alternate_winstation_handle_ ||
        GetWindowObjectName(alternate_winstation_handle_).empty())
      return SBOX_ERROR_CANNOT_CREATE_DESKTOP;

    // Create the destkop.
    result = CreateAltDesktop(alternate_winstation_handle_,
                              &alternate_desktop_handle_);
    if (SBOX_ALL_OK != result)
      return result;

    // Verify that everything is fine.
    if (!alternate_desktop_handle_ ||
        GetWindowObjectName(alternate_desktop_handle_).empty())
      return SBOX_ERROR_CANNOT_CREATE_DESKTOP;
  } else {
    // Previously called with alternate_winstation = true?
    if (alternate_winstation_handle_)
      return SBOX_ERROR_UNSUPPORTED;

    // Check if it already exists.
    if (alternate_desktop_handle_)
      return SBOX_ALL_OK;

    // Create the destkop.
    ResultCode result = CreateAltDesktop(NULL, &alternate_desktop_handle_);
    if (SBOX_ALL_OK != result)
      return result;

    // Verify that everything is fine.
    if (!alternate_desktop_handle_ ||
        GetWindowObjectName(alternate_desktop_handle_).empty())
      return SBOX_ERROR_CANNOT_CREATE_DESKTOP;
  }

  return SBOX_ALL_OK;
}

void PolicyBase::DestroyAlternateDesktop() {
  if (alternate_desktop_handle_) {
    ::CloseDesktop(alternate_desktop_handle_);
    alternate_desktop_handle_ = NULL;
  }

  if (alternate_winstation_handle_) {
    ::CloseWindowStation(alternate_winstation_handle_);
    alternate_winstation_handle_ = NULL;
  }
}

ResultCode PolicyBase::SetIntegrityLevel(IntegrityLevel integrity_level) {
  integrity_level_ = integrity_level;
  return SBOX_ALL_OK;
}

IntegrityLevel PolicyBase::GetIntegrityLevel() const {
  return integrity_level_;
}

ResultCode PolicyBase::SetDelayedIntegrityLevel(
    IntegrityLevel integrity_level) {
  delayed_integrity_level_ = integrity_level;
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetAppContainer(const wchar_t* sid) {
  if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8)
    return SBOX_ALL_OK;

  // SetLowBox and SetAppContainer are mutually exclusive.
  if (lowbox_sid_)
    return SBOX_ERROR_UNSUPPORTED;

  // Windows refuses to work with an impersonation token for a process inside
  // an AppContainer. If the caller wants to use a more privileged initial
  // token, or if the lockdown level will prevent the process from starting,
  // we have to fail the operation.
  if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_)
    return SBOX_ERROR_CANNOT_INIT_APPCONTAINER;

  DCHECK(!appcontainer_list_.get());
  appcontainer_list_.reset(new AppContainerAttributes);
  ResultCode rv = appcontainer_list_->SetAppContainer(sid, capabilities_);
  if (rv != SBOX_ALL_OK)
    return rv;

  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetCapability(const wchar_t* sid) {
  capabilities_.push_back(sid);
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetLowBox(const wchar_t* sid) {
  if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8)
    return SBOX_ERROR_UNSUPPORTED;

  // SetLowBox and SetAppContainer are mutually exclusive.
  if (appcontainer_list_.get())
    return SBOX_ERROR_UNSUPPORTED;

  DCHECK(sid);

  if (lowbox_sid_)
    return SBOX_ERROR_BAD_PARAMS;

  if (!ConvertStringSidToSid(sid, &lowbox_sid_))
    return SBOX_ERROR_GENERIC;

  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetProcessMitigations(
    MitigationFlags flags) {
  if (!CanSetProcessMitigationsPreStartup(flags))
    return SBOX_ERROR_BAD_PARAMS;
  mitigations_ = flags;
  return SBOX_ALL_OK;
}

MitigationFlags PolicyBase::GetProcessMitigations() {
  return mitigations_;
}

ResultCode PolicyBase::SetDelayedProcessMitigations(
    MitigationFlags flags) {
  if (!CanSetProcessMitigationsPostStartup(flags))
    return SBOX_ERROR_BAD_PARAMS;
  delayed_mitigations_ = flags;
  return SBOX_ALL_OK;
}

MitigationFlags PolicyBase::GetDelayedProcessMitigations() const {
  return delayed_mitigations_;
}

void PolicyBase::SetStrictInterceptions() {
  relaxed_interceptions_ = false;
}

ResultCode PolicyBase::SetStdoutHandle(HANDLE handle) {
  if (!IsInheritableHandle(handle))
    return SBOX_ERROR_BAD_PARAMS;
  stdout_handle_ = handle;
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::SetStderrHandle(HANDLE handle) {
  if (!IsInheritableHandle(handle))
    return SBOX_ERROR_BAD_PARAMS;
  stderr_handle_ = handle;
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::AddRule(SubSystem subsystem,
                               Semantics semantics,
                               const wchar_t* pattern) {
  ResultCode result = AddRuleInternal(subsystem, semantics, pattern);
  LOG_IF(ERROR, result != SBOX_ALL_OK) << "Failed to add sandbox rule."
                                       << " error = " << result
                                       << ", subsystem = " << subsystem
                                       << ", semantics = " << semantics
                                       << ", pattern = '" << pattern << "'";
  return result;
}

ResultCode PolicyBase::AddDllToUnload(const wchar_t* dll_name) {
  blacklisted_dlls_.push_back(dll_name);
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::AddKernelObjectToClose(const base::char16* handle_type,
                                              const base::char16* handle_name) {
  return handle_closer_.AddHandle(handle_type, handle_name);
}

void* PolicyBase::AddHandleToShare(HANDLE handle) {
  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return nullptr;

  if (!handle)
    return nullptr;

  HANDLE duped_handle = nullptr;
  if (!::DuplicateHandle(::GetCurrentProcess(), handle, ::GetCurrentProcess(),
                         &duped_handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
    return nullptr;
  }
  handles_to_share_.push_back(new base::win::ScopedHandle(duped_handle));
  return duped_handle;
}

const HandleList& PolicyBase::GetHandlesBeingShared() {
  return handles_to_share_;
}

void PolicyBase::ClearSharedHandles() {
  STLDeleteElements(&handles_to_share_);
}

// When an IPC is ready in any of the targets we get called. We manage an array
// of IPC dispatchers which are keyed on the IPC tag so we normally delegate
// to the appropriate dispatcher unless we can handle the IPC call ourselves.
Dispatcher* PolicyBase::OnMessageReady(IPCParams* ipc,
                                       CallbackGeneric* callback) {
  DCHECK(callback);
  static const IPCParams ping1 = {IPC_PING1_TAG, {UINT32_TYPE}};
  static const IPCParams ping2 = {IPC_PING2_TAG, {INOUTPTR_TYPE}};

  if (ping1.Matches(ipc) || ping2.Matches(ipc)) {
    *callback = reinterpret_cast<CallbackGeneric>(
                    static_cast<Callback1>(&PolicyBase::Ping));
    return this;
  }

  Dispatcher* dispatch = GetDispatcher(ipc->ipc_tag);
  if (!dispatch) {
    NOTREACHED();
    return NULL;
  }
  return dispatch->OnMessageReady(ipc, callback);
}

// Delegate to the appropriate dispatcher.
bool PolicyBase::SetupService(InterceptionManager* manager, int service) {
  if (IPC_PING1_TAG == service || IPC_PING2_TAG == service)
    return true;

  Dispatcher* dispatch = GetDispatcher(service);
  if (!dispatch) {
    NOTREACHED();
    return false;
  }
  return dispatch->SetupService(manager, service);
}

ResultCode PolicyBase::MakeJobObject(base::win::ScopedHandle* job) {
  if (job_level_ != JOB_NONE) {
    // Create the windows job object.
    Job job_obj;
    DWORD result = job_obj.Init(job_level_, NULL, ui_exceptions_,
                                memory_limit_);
    if (ERROR_SUCCESS != result)
      return SBOX_ERROR_GENERIC;

    *job = job_obj.Take();
  } else {
    *job = base::win::ScopedHandle();
  }
  return SBOX_ALL_OK;
}

ResultCode PolicyBase::MakeTokens(base::win::ScopedHandle* initial,
                                  base::win::ScopedHandle* lockdown,
                                  base::win::ScopedHandle* lowbox) {
  if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer() &&
      lowbox_sid_) {
    return SBOX_ERROR_BAD_PARAMS;
  }

  // Create the 'naked' token. This will be the permanent token associated
  // with the process and therefore with any thread that is not impersonating.
  DWORD result = CreateRestrictedToken(lockdown_level_,  integrity_level_,
                                       PRIMARY, lockdown);
  if (ERROR_SUCCESS != result)
    return SBOX_ERROR_GENERIC;

  // If we're launching on the alternate desktop we need to make sure the
  // integrity label on the object is no higher than the sandboxed process's
  // integrity level. So, we lower the label on the desktop process if it's
  // not already low enough for our process.
  if (alternate_desktop_handle_ && use_alternate_desktop_ &&
      integrity_level_ != INTEGRITY_LEVEL_LAST &&
      alternate_desktop_integrity_level_label_ < integrity_level_ &&
      base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) {
    // Integrity label enum is reversed (higher level is a lower value).
    static_assert(INTEGRITY_LEVEL_SYSTEM < INTEGRITY_LEVEL_UNTRUSTED,
                  "Integrity level ordering reversed.");
    result = SetObjectIntegrityLabel(alternate_desktop_handle_,
                                     SE_WINDOW_OBJECT,
                                     L"",
                                     GetIntegrityLevelString(integrity_level_));
    if (ERROR_SUCCESS != result)
      return SBOX_ERROR_GENERIC;

    alternate_desktop_integrity_level_label_ = integrity_level_;
  }

  // We are maintaining two mutually exclusive approaches. One is to start an
  // AppContainer process through StartupInfoEx and other is replacing
  // existing token with LowBox token after process creation.
  if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer()) {
    // Windows refuses to work with an impersonation token. See SetAppContainer
    // implementation for more details.
    if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_)
      return SBOX_ERROR_CANNOT_INIT_APPCONTAINER;

    *initial = base::win::ScopedHandle();
    return SBOX_ALL_OK;
  }

  if (lowbox_sid_) {
    NtCreateLowBoxToken CreateLowBoxToken = NULL;
    ResolveNTFunctionPtr("NtCreateLowBoxToken", &CreateLowBoxToken);
    OBJECT_ATTRIBUTES obj_attr;
    InitializeObjectAttributes(&obj_attr, NULL, 0, NULL, NULL);
    HANDLE token_lowbox = NULL;

    if (!lowbox_directory_.IsValid())
      lowbox_directory_.Set(CreateLowBoxObjectDirectory(lowbox_sid_));
    DCHECK(lowbox_directory_.IsValid());

    // The order of handles isn't important in the CreateLowBoxToken call.
    // The kernel will maintain a reference to the object directory handle.
    HANDLE saved_handles[1] = {lowbox_directory_.Get()};
    DWORD saved_handles_count = lowbox_directory_.IsValid() ? 1 : 0;

    NTSTATUS status = CreateLowBoxToken(&token_lowbox, lockdown->Get(),
                                        TOKEN_ALL_ACCESS, &obj_attr,
                                        lowbox_sid_, 0, NULL,
                                        saved_handles_count, saved_handles);
    if (!NT_SUCCESS(status))
      return SBOX_ERROR_GENERIC;

    DCHECK(token_lowbox);
    lowbox->Set(token_lowbox);
  }

  // Create the 'better' token. We use this token as the one that the main
  // thread uses when booting up the process. It should contain most of
  // what we need (before reaching main( ))
  result = CreateRestrictedToken(initial_level_, integrity_level_,
                                 IMPERSONATION, initial);
  if (ERROR_SUCCESS != result)
    return SBOX_ERROR_GENERIC;

  return SBOX_ALL_OK;
}

const AppContainerAttributes* PolicyBase::GetAppContainer() const {
  if (!appcontainer_list_.get() || !appcontainer_list_->HasAppContainer())
    return NULL;

  return appcontainer_list_.get();
}

const PSID PolicyBase::GetLowBoxSid() const {
  return lowbox_sid_;
}

bool PolicyBase::AddTarget(TargetProcess* target) {
  if (NULL != policy_)
    policy_maker_->Done();

  if (!ApplyProcessMitigationsToSuspendedProcess(target->Process(),
                                                 mitigations_)) {
    return false;
  }

  if (!SetupAllInterceptions(target))
    return false;

  if (!SetupHandleCloser(target))
    return false;

  // Initialize the sandbox infrastructure for the target.
  if (ERROR_SUCCESS != target->Init(this, policy_, kIPCMemSize, kPolMemSize))
    return false;

  g_shared_delayed_integrity_level = delayed_integrity_level_;
  ResultCode ret = target->TransferVariable(
                       "g_shared_delayed_integrity_level",
                       &g_shared_delayed_integrity_level,
                       sizeof(g_shared_delayed_integrity_level));
  g_shared_delayed_integrity_level = INTEGRITY_LEVEL_LAST;
  if (SBOX_ALL_OK != ret)
    return false;

  // Add in delayed mitigations and pseudo-mitigations enforced at startup.
  g_shared_delayed_mitigations = delayed_mitigations_ |
      FilterPostStartupProcessMitigations(mitigations_);
  if (!CanSetProcessMitigationsPostStartup(g_shared_delayed_mitigations))
    return false;

  ret = target->TransferVariable("g_shared_delayed_mitigations",
                                 &g_shared_delayed_mitigations,
                                 sizeof(g_shared_delayed_mitigations));
  g_shared_delayed_mitigations = 0;
  if (SBOX_ALL_OK != ret)
    return false;

  AutoLock lock(&lock_);
  targets_.push_back(target);
  return true;
}

bool PolicyBase::OnJobEmpty(HANDLE job) {
  AutoLock lock(&lock_);
  TargetSet::iterator it;
  for (it = targets_.begin(); it != targets_.end(); ++it) {
    if ((*it)->Job() == job)
      break;
  }
  if (it == targets_.end()) {
    return false;
  }
  TargetProcess* target = *it;
  targets_.erase(it);
  delete target;
  return true;
}

EvalResult PolicyBase::EvalPolicy(int service,
                                  CountedParameterSetBase* params) {
  if (NULL != policy_) {
    if (NULL == policy_->entry[service]) {
      // There is no policy for this particular service. This is not a big
      // deal.
      return DENY_ACCESS;
    }
    for (int i = 0; i < params->count; i++) {
      if (!params->parameters[i].IsValid()) {
        NOTREACHED();
        return SIGNAL_ALARM;
      }
    }
    PolicyProcessor pol_evaluator(policy_->entry[service]);
    PolicyResult result =  pol_evaluator.Evaluate(kShortEval,
                                                  params->parameters,
                                                  params->count);
    if (POLICY_MATCH == result) {
      return pol_evaluator.GetAction();
    }
    DCHECK(POLICY_ERROR != result);
  }

  return DENY_ACCESS;
}

HANDLE PolicyBase::GetStdoutHandle() {
  return stdout_handle_;
}

HANDLE PolicyBase::GetStderrHandle() {
  return stderr_handle_;
}

// We service IPC_PING_TAG message which is a way to test a round trip of the
// IPC subsystem. We receive a integer cookie and we are expected to return the
// cookie times two (or three) and the current tick count.
bool PolicyBase::Ping(IPCInfo* ipc, void* arg1) {
  switch (ipc->ipc_tag) {
    case IPC_PING1_TAG: {
      IPCInt ipc_int(arg1);
      uint32 cookie = ipc_int.As32Bit();
      ipc->return_info.extended_count = 2;
      ipc->return_info.extended[0].unsigned_int = ::GetTickCount();
      ipc->return_info.extended[1].unsigned_int = 2 * cookie;
      return true;
    }
    case IPC_PING2_TAG: {
      CountedBuffer* io_buffer = reinterpret_cast<CountedBuffer*>(arg1);
      if (sizeof(uint32) != io_buffer->Size())
        return false;

      uint32* cookie = reinterpret_cast<uint32*>(io_buffer->Buffer());
      *cookie = (*cookie) * 3;
      return true;
    }
    default: return false;
  }
}

Dispatcher* PolicyBase::GetDispatcher(int ipc_tag) {
  if (ipc_tag >= IPC_LAST_TAG || ipc_tag <= IPC_UNUSED_TAG)
    return NULL;

  return ipc_targets_[ipc_tag];
}

bool PolicyBase::SetupAllInterceptions(TargetProcess* target) {
  InterceptionManager manager(target, relaxed_interceptions_);

  if (policy_) {
    for (int i = 0; i < IPC_LAST_TAG; i++) {
      if (policy_->entry[i] && !ipc_targets_[i]->SetupService(&manager, i))
          return false;
    }
  }

  if (!blacklisted_dlls_.empty()) {
    std::vector<base::string16>::iterator it = blacklisted_dlls_.begin();
    for (; it != blacklisted_dlls_.end(); ++it) {
      manager.AddToUnloadModules(it->c_str());
    }
  }

  if (!SetupBasicInterceptions(&manager))
    return false;

  if (!manager.InitializeInterceptions())
    return false;

  // Finally, setup imports on the target so the interceptions can work.
  return SetupNtdllImports(target);
}

bool PolicyBase::SetupHandleCloser(TargetProcess* target) {
  return handle_closer_.InitializeTargetHandles(target);
}

ResultCode PolicyBase::AddRuleInternal(SubSystem subsystem,
                                       Semantics semantics,
                                       const wchar_t* pattern) {
  if (NULL == policy_) {
    policy_ = MakeBrokerPolicyMemory();
    DCHECK(policy_);
    policy_maker_ = new LowLevelPolicy(policy_);
    DCHECK(policy_maker_);
  }

  switch (subsystem) {
    case SUBSYS_FILES: {
      if (!file_system_init_) {
        if (!FileSystemPolicy::SetInitialRules(policy_maker_))
          return SBOX_ERROR_BAD_PARAMS;
        file_system_init_ = true;
      }
      if (!FileSystemPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }
    case SUBSYS_SYNC: {
      if (!SyncPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }
    case SUBSYS_PROCESS: {
      if (lockdown_level_ < USER_INTERACTIVE &&
          TargetPolicy::PROCESS_ALL_EXEC == semantics) {
        // This is unsupported. This is a huge security risk to give full access
        // to a process handle.
        return SBOX_ERROR_UNSUPPORTED;
      }
      if (!ProcessPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }
    case SUBSYS_NAMED_PIPES: {
      if (!NamedPipePolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }
    case SUBSYS_REGISTRY: {
      if (!RegistryPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }
    case SUBSYS_HANDLES: {
      if (!HandlePolicy::GenerateRules(pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }

    case SUBSYS_WIN32K_LOCKDOWN: {
      if (!ProcessMitigationsWin32KLockdownPolicy::GenerateRules(
              pattern, semantics, policy_maker_)) {
        NOTREACHED();
        return SBOX_ERROR_BAD_PARAMS;
      }
      break;
    }

    default: { return SBOX_ERROR_UNSUPPORTED; }
  }

  return SBOX_ALL_OK;
}

}  // namespace sandbox
