michael@0: // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef SANDBOX_SRC_POLICY_LOW_LEVEL_H__ michael@0: #define SANDBOX_SRC_POLICY_LOW_LEVEL_H__ michael@0: michael@0: #include michael@0: michael@0: #include "base/basictypes.h" michael@0: #include "sandbox/win/src/ipc_tags.h" michael@0: #include "sandbox/win/src/policy_engine_params.h" michael@0: #include "sandbox/win/src/policy_engine_opcodes.h" michael@0: michael@0: // Low level policy classes. michael@0: // Built on top of the PolicyOpcode and OpcodeFatory, the low level policy michael@0: // provides a way to define rules on strings and numbers but it is unaware michael@0: // of Windows specific details or how the Interceptions must be set up. michael@0: // To use these classes you construct one or more rules and add them to the michael@0: // LowLevelPolicy object like this: michael@0: // michael@0: // PolicyRule rule1(ASK_BROKER); michael@0: // rule1.AddStringMatch(IF, 0, L"\\\\/?/?\\c:\\*Microsoft*\\*.exe", true); michael@0: // rule1.AddNumberMatch(IF_NOT, 1, CREATE_ALWAYS, EQUAL); michael@0: // rule1.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_NORMAL, EQUAL); michael@0: // michael@0: // PolicyRule rule2(FAKE_SUCCESS); michael@0: // rule2.AddStringMatch(IF, 0, L"\\\\/?/?\\Pipe\\Chrome.*", false)); michael@0: // rule2.AddNumberMatch(IF, 1, OPEN_EXISTING, EQUAL)); michael@0: // michael@0: // LowLevelPolicy policyGen(*policy_memory); michael@0: // policyGen.AddRule(kNtCreateFileSvc, &rule1); michael@0: // policyGen.AddRule(kNtCreateFileSvc, &rule2); michael@0: // policyGen.Done(); michael@0: // michael@0: // At this point (error checking omitted) the policy_memory can be copied michael@0: // to the target process where it can be evaluated. michael@0: michael@0: namespace sandbox { michael@0: michael@0: // TODO(cpu): Move this constant to crosscall_client.h. michael@0: const size_t kMaxServiceCount = 32; michael@0: COMPILE_ASSERT(IPC_LAST_TAG <= kMaxServiceCount, kMaxServiceCount_is_too_low); michael@0: michael@0: // Defines the memory layout of the policy. This memory is filled by michael@0: // LowLevelPolicy object. michael@0: // For example: michael@0: // michael@0: // [Service 0] --points to---\ michael@0: // [Service 1] --------------|-----\ michael@0: // ...... | | michael@0: // [Service N] | | michael@0: // [data_size] | | michael@0: // [Policy Buffer 0] <-------/ | michael@0: // [opcodes of] | michael@0: // ....... | michael@0: // [Policy Buffer 1] <-------------/ michael@0: // [opcodes] michael@0: // ....... michael@0: // ....... michael@0: // [Policy Buffer N] michael@0: // [opcodes] michael@0: // ....... michael@0: // michael@0: // ....... michael@0: // [opcode string ] michael@0: // [opcode string ] michael@0: // ....... michael@0: // [opcode string ] michael@0: struct PolicyGlobal { michael@0: PolicyBuffer* entry[kMaxServiceCount]; michael@0: size_t data_size; michael@0: PolicyBuffer data[1]; michael@0: }; michael@0: michael@0: class PolicyRule; michael@0: michael@0: // Provides the means to collect rules into a policy store (memory) michael@0: class LowLevelPolicy { michael@0: public: michael@0: // policy_store: must contain allocated memory and the internal michael@0: // size fields set to correct values. michael@0: explicit LowLevelPolicy(PolicyGlobal* policy_store) michael@0: : policy_store_(policy_store) { michael@0: } michael@0: michael@0: // Destroys all the policy rules. michael@0: ~LowLevelPolicy(); michael@0: michael@0: // Adds a rule to be generated when Done() is called. michael@0: // service: The id of the service that this rule is associated with, michael@0: // for example the 'Open Thread' service or the "Create File" service. michael@0: // returns false on error. michael@0: bool AddRule(int service, PolicyRule* rule); michael@0: michael@0: // Generates all the rules added with AddRule() into the memory area michael@0: // passed on the constructor. Returns false on error. michael@0: bool Done(); michael@0: michael@0: private: michael@0: struct RuleNode { michael@0: const PolicyRule* rule; michael@0: int service; michael@0: }; michael@0: std::list rules_; michael@0: PolicyGlobal* policy_store_; michael@0: DISALLOW_IMPLICIT_CONSTRUCTORS(LowLevelPolicy); michael@0: }; michael@0: michael@0: // There are 'if' rules and 'if not' comparisons michael@0: enum RuleType { michael@0: IF = 0, michael@0: IF_NOT = 1, michael@0: }; michael@0: michael@0: // Possible comparisons for numbers michael@0: enum RuleOp { michael@0: EQUAL, michael@0: AND, michael@0: RANGE // TODO(cpu): Implement this option. michael@0: }; michael@0: michael@0: // Provides the means to collect a set of comparisons into a single michael@0: // rule and its associated action. michael@0: class PolicyRule { michael@0: friend class LowLevelPolicy; michael@0: michael@0: public: michael@0: explicit PolicyRule(EvalResult action); michael@0: PolicyRule(const PolicyRule& other); michael@0: ~PolicyRule(); michael@0: michael@0: // Adds a string comparison to the rule. michael@0: // rule_type: possible values are IF and IF_NOT. michael@0: // parameter: the expected index of the argument for this rule. For example michael@0: // in a 'create file' service the file name argument can be at index 0. michael@0: // string: is the desired matching pattern. michael@0: // match_opts: if the pattern matching is case sensitive or not. michael@0: bool AddStringMatch(RuleType rule_type, int16 parameter, michael@0: const wchar_t* string, StringMatchOptions match_opts); michael@0: michael@0: // Adds a number match comparison to the rule. michael@0: // rule_type: possible values are IF and IF_NOT. michael@0: // parameter: the expected index of the argument for this rule. michael@0: // number: the value to compare the input to. michael@0: // comparison_op: the comparison kind (equal, logical and, etc). michael@0: bool AddNumberMatch(RuleType rule_type, int16 parameter, michael@0: unsigned long number, RuleOp comparison_op); michael@0: michael@0: // Returns the number of opcodes generated so far. michael@0: size_t GetOpcodeCount() const { michael@0: return buffer_->opcode_count; michael@0: } michael@0: michael@0: // Called when there is no more comparisons to add. Internally it generates michael@0: // the last opcode (the action opcode). Returns false if this operation fails. michael@0: bool Done(); michael@0: michael@0: private: michael@0: void operator=(const PolicyRule&); michael@0: // Called in a loop from AddStringMatch to generate the required string michael@0: // match opcodes. rule_type, match_opts and parameter are the same as michael@0: // in AddStringMatch. michael@0: bool GenStringOpcode(RuleType rule_type, StringMatchOptions match_opts, michael@0: uint16 parameter, int state, bool last_call, michael@0: int* skip_count, std::wstring* fragment); michael@0: michael@0: // Loop over all generated opcodes and copy them to increasing memory michael@0: // addresses from opcode_start and copy the extra data (strings usually) into michael@0: // decreasing addresses from data_start. Extra data is only present in the michael@0: // string evaluation opcodes. michael@0: bool RebindCopy(PolicyOpcode* opcode_start, size_t opcode_size, michael@0: char* data_start, size_t* data_size) const; michael@0: PolicyBuffer* buffer_; michael@0: OpcodeFactory* opcode_factory_; michael@0: EvalResult action_; michael@0: bool done_; michael@0: }; michael@0: michael@0: } // namespace sandbox michael@0: michael@0: #endif // SANDBOX_SRC_POLICY_LOW_LEVEL_H__