1// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef SANDBOX_SRC_POLICY_LOW_LEVEL_H__
6#define SANDBOX_SRC_POLICY_LOW_LEVEL_H__
7
8#include <list>
9
10#include "base/basictypes.h"
11#include "sandbox/win/src/ipc_tags.h"
12#include "sandbox/win/src/policy_engine_params.h"
13#include "sandbox/win/src/policy_engine_opcodes.h"
14
15// Low level policy classes.
16// Built on top of the PolicyOpcode and OpcodeFatory, the low level policy
17// provides a way to define rules on strings and numbers but it is unaware
18// of Windows specific details or how the Interceptions must be set up.
19// To use these classes you construct one or more rules and add them to the
20// LowLevelPolicy object like this:
21//
22//   PolicyRule rule1(ASK_BROKER);
23//   rule1.AddStringMatch(IF, 0, L"\\\\/?/?\\c:\\*Microsoft*\\*.exe", true);
24//   rule1.AddNumberMatch(IF_NOT, 1, CREATE_ALWAYS, EQUAL);
25//   rule1.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_NORMAL, EQUAL);
26//
27//   PolicyRule rule2(FAKE_SUCCESS);
28//   rule2.AddStringMatch(IF, 0, L"\\\\/?/?\\Pipe\\Chrome.*", false));
29//   rule2.AddNumberMatch(IF, 1, OPEN_EXISTING, EQUAL));
30//
31//   LowLevelPolicy policyGen(*policy_memory);
32//   policyGen.AddRule(kNtCreateFileSvc, &rule1);
33//   policyGen.AddRule(kNtCreateFileSvc, &rule2);
34//   policyGen.Done();
35//
36// At this point (error checking omitted) the policy_memory can be copied
37// to the target process where it can be evaluated.
38
39namespace sandbox {
40
41// TODO(cpu): Move this constant to crosscall_client.h.
42const size_t kMaxServiceCount = 32;
43COMPILE_ASSERT(IPC_LAST_TAG <= kMaxServiceCount, kMaxServiceCount_is_too_low);
44
45// Defines the memory layout of the policy. This memory is filled by
46// LowLevelPolicy object.
47// For example:
48//
49//  [Service 0] --points to---\
50//  [Service 1] --------------|-----\
51//   ......                   |     |
52//  [Service N]               |     |
53//  [data_size]               |     |
54//  [Policy Buffer 0] <-------/     |
55//  [opcodes of]                    |
56//  .......                         |
57//  [Policy Buffer 1] <-------------/
58//  [opcodes]
59//  .......
60//  .......
61//  [Policy Buffer N]
62//  [opcodes]
63//  .......
64//   <possibly unused space here>
65//  .......
66//  [opcode string ]
67//  [opcode string ]
68//  .......
69//  [opcode string ]
70struct PolicyGlobal {
71  PolicyBuffer* entry[kMaxServiceCount];
72  size_t data_size;
73  PolicyBuffer data[1];
74};
75
76class PolicyRule;
77
78// Provides the means to collect rules into a policy store (memory)
79class LowLevelPolicy {
80 public:
81  // policy_store: must contain allocated memory and the internal
82  // size fields set to correct values.
83  explicit LowLevelPolicy(PolicyGlobal* policy_store)
84      : policy_store_(policy_store) {
85  }
86
87  // Destroys all the policy rules.
88  ~LowLevelPolicy();
89
90  // Adds a rule to be generated when Done() is called.
91  // service: The id of the service that this rule is associated with,
92  // for example the 'Open Thread' service or the "Create File" service.
93  // returns false on error.
94  bool AddRule(int service, PolicyRule* rule);
95
96  // Generates all the rules added with AddRule() into the memory area
97  // passed on the constructor. Returns false on error.
98  bool Done();
99
100 private:
101  struct RuleNode {
102    const PolicyRule* rule;
103    int service;
104  };
105  std::list<RuleNode> rules_;
106  PolicyGlobal* policy_store_;
107  DISALLOW_IMPLICIT_CONSTRUCTORS(LowLevelPolicy);
108};
109
110// There are 'if' rules and 'if not' comparisons
111enum RuleType {
112  IF = 0,
113  IF_NOT = 1,
114};
115
116// Possible comparisons for numbers
117enum RuleOp {
118  EQUAL,
119  AND,
120  RANGE   // TODO(cpu): Implement this option.
121};
122
123// Provides the means to collect a set of comparisons into a single
124// rule and its associated action.
125class PolicyRule {
126  friend class LowLevelPolicy;
127
128 public:
129  explicit PolicyRule(EvalResult action);
130  PolicyRule(const PolicyRule& other);
131  ~PolicyRule();
132
133  // Adds a string comparison to the rule.
134  // rule_type: possible values are IF and IF_NOT.
135  // parameter: the expected index of the argument for this rule. For example
136  // in a 'create file' service the file name argument can be at index 0.
137  // string: is the desired matching pattern.
138  // match_opts: if the pattern matching is case sensitive or not.
139  bool AddStringMatch(RuleType rule_type, int16 parameter,
140                      const wchar_t* string, StringMatchOptions match_opts);
141
142  // Adds a number match comparison to the rule.
143  // rule_type: possible values are IF and IF_NOT.
144  // parameter: the expected index of the argument for this rule.
145  // number: the value to compare the input to.
146  // comparison_op: the comparison kind (equal, logical and, etc).
147  bool AddNumberMatch(RuleType rule_type, int16 parameter,
148                      unsigned long number, RuleOp comparison_op);
149
150  // Returns the number of opcodes generated so far.
151  size_t GetOpcodeCount() const {
152    return buffer_->opcode_count;
153  }
154
155  // Called when there is no more comparisons to add. Internally it generates
156  // the last opcode (the action opcode). Returns false if this operation fails.
157  bool Done();
158
159 private:
160  void operator=(const PolicyRule&);
161  // Called in a loop from AddStringMatch to generate the required string
162  // match opcodes. rule_type, match_opts and parameter are the same as
163  // in AddStringMatch.
164  bool GenStringOpcode(RuleType rule_type, StringMatchOptions match_opts,
165                       uint16 parameter, int state, bool last_call,
166                       int* skip_count, std::wstring* fragment);
167
168  // Loop over all generated opcodes and copy them to increasing memory
169  // addresses from opcode_start and copy the extra data (strings usually) into
170  // decreasing addresses from data_start. Extra data is only present in the
171  // string evaluation opcodes.
172  bool RebindCopy(PolicyOpcode* opcode_start, size_t opcode_size,
173                  char* data_start, size_t* data_size) const;
174  PolicyBuffer* buffer_;
175  OpcodeFactory* opcode_factory_;
176  EvalResult action_;
177  bool done_;
178};
179
180}  // namespace sandbox
181
182#endif  // SANDBOX_SRC_POLICY_LOW_LEVEL_H__
183