blob: b9afc6e3e9db892cb75a4dcab9f4ab0a43bed32a [file] [log] [blame]
// Copyright (c) 2006-2011 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.
#ifndef SANDBOX_SRC_SANDBOX_POLICY_BASE_H_
#define SANDBOX_SRC_SANDBOX_POLICY_BASE_H_
#include <windows.h>
#include <list>
#include <vector>
#include "base/basictypes.h"
#include "base/string16.h"
#include "sandbox/src/crosscall_server.h"
#include "sandbox/src/handle_closer.h"
#include "sandbox/src/ipc_tags.h"
#include "sandbox/src/policy_engine_opcodes.h"
#include "sandbox/src/policy_engine_params.h"
#include "sandbox/src/sandbox_policy.h"
#include "sandbox/src/win_utils.h"
namespace sandbox {
class TargetProcess;
class PolicyRule;
class LowLevelPolicy;
struct PolicyGlobal;
// We act as a policy dispatcher, implementing the handler for the "ping" IPC,
// so we have to provide the appropriate handler on the OnMessageReady method.
// There is a static_cast for the handler, and the compiler only performs the
// cast if the first base class is Dispatcher.
class PolicyBase : public Dispatcher, public TargetPolicy {
public:
PolicyBase();
virtual void AddRef() {
::InterlockedIncrement(&ref_count);
}
virtual void Release() {
if (0 == ::InterlockedDecrement(&ref_count))
delete this;
}
virtual ResultCode SetTokenLevel(TokenLevel initial, TokenLevel lockdown) {
if (initial < lockdown) {
return SBOX_ERROR_BAD_PARAMS;
}
initial_level_ = initial;
lockdown_level_ = lockdown;
return SBOX_ALL_OK;
}
virtual ResultCode SetJobLevel(JobLevel job_level, uint32 ui_exceptions) {
job_level_ = job_level;
ui_exceptions_ = ui_exceptions;
return SBOX_ALL_OK;
}
virtual ResultCode SetAlternateDesktop(bool alternate_winstation) {
use_alternate_desktop_ = true;
use_alternate_winstation_ = alternate_winstation;
return CreateAlternateDesktop(alternate_winstation);
}
virtual std::wstring GetAlternateDesktop() const;
virtual ResultCode CreateAlternateDesktop(bool alternate_winstation);
virtual void 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;
}
}
virtual ResultCode SetIntegrityLevel(IntegrityLevel integrity_level) {
integrity_level_ = integrity_level;
return SBOX_ALL_OK;
}
virtual ResultCode SetDelayedIntegrityLevel(IntegrityLevel integrity_level) {
delayed_integrity_level_ = integrity_level;
return SBOX_ALL_OK;
}
virtual void SetStrictInterceptions() {
relaxed_interceptions_ = false;
}
virtual ResultCode AddRule(SubSystem subsystem, Semantics semantics,
const wchar_t* pattern);
virtual ResultCode AddDllToUnload(const wchar_t* dll_name) {
blacklisted_dlls_.push_back(std::wstring(dll_name));
return SBOX_ALL_OK;
}
virtual ResultCode AddKernelObjectToClose(const char16* handle_type,
const char16* handle_name) {
return handle_closer_.AddHandle(handle_type, handle_name);
}
// Creates a Job object with the level specified in a previous call to
// SetJobLevel(). Returns the standard windows of ::GetLastError().
DWORD MakeJobObject(HANDLE* job);
// Creates the two tokens with the levels specified in a previous call to
// SetTokenLevel(). Returns the standard windows of ::GetLastError().
DWORD MakeTokens(HANDLE* initial, HANDLE* lockdown);
// Adds a target process to the internal list of targets. Internally a
// call to TargetProcess::Init() is issued.
bool AddTarget(TargetProcess* target);
// Called when there are no more active processes in a Job.
// Removes a Job object associated with this policy and the target associated
// with the job.
bool OnJobEmpty(HANDLE job);
// Overrides Dispatcher::OnMessageReady.
virtual Dispatcher* OnMessageReady(IPCParams* ipc, CallbackGeneric* callback);
// Dispatcher interface.
virtual bool SetupService(InterceptionManager* manager, int service);
virtual EvalResult EvalPolicy(int service, CountedParameterSetBase* params);
private:
~PolicyBase();
// Test IPC providers.
bool Ping(IPCInfo* ipc, void* cookie);
// Returns a dispatcher from ipc_targets_.
Dispatcher* GetDispatcher(int ipc_tag);
// Sets up interceptions for a new target.
bool SetupAllInterceptions(TargetProcess* target);
// Sets up the handle closer for a new target.
bool SetupHandleCloser(TargetProcess* target);
// This lock synchronizes operations on the targets_ collection.
CRITICAL_SECTION lock_;
// Maintains the list of target process associated with this policy.
// The policy takes ownership of them.
typedef std::list<TargetProcess*> TargetSet;
TargetSet targets_;
// Standard object-lifetime reference counter.
volatile LONG ref_count;
// The user-defined global policy settings.
TokenLevel lockdown_level_;
TokenLevel initial_level_;
JobLevel job_level_;
uint32 ui_exceptions_;
bool use_alternate_desktop_;
bool use_alternate_winstation_;
IntegrityLevel integrity_level_;
IntegrityLevel delayed_integrity_level_;
// The array of objects that will answer IPC calls.
Dispatcher* ipc_targets_[IPC_LAST_TAG];
// Object in charge of generating the low level policy.
LowLevelPolicy* policy_maker_;
// Memory structure that stores the low level policy.
PolicyGlobal* policy_;
// Helps the file system policy initialization.
bool file_system_init_;
// Operation mode for the interceptions.
bool relaxed_interceptions_;
// The list of dlls to unload in the target process.
std::vector<std::wstring> blacklisted_dlls_;
// This is a map of handle-types to names that we need to close in the
// target process. A null set means we need to close all handles of the
// given type.
HandleCloser handle_closer_;
static HDESK alternate_desktop_handle_;
static HWINSTA alternate_winstation_handle_;
DISALLOW_COPY_AND_ASSIGN(PolicyBase);
};
} // namespace sandbox
#endif // SANDBOX_SRC_SANDBOX_POLICY_BASE_H_