source: vendor/3.6.0/libcli/security/access_check.c

Last change on this file was 740, checked in by Silvan Scherrer, 13 years ago

Samba Server: update vendor to 3.6.0

File size: 12.8 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Copyright (C) Andrew Tridgell 2004
5 Copyright (C) Gerald Carter 2005
6 Copyright (C) Volker Lendecke 2007
7 Copyright (C) Jeremy Allison 2008
8 Copyright (C) Andrew Bartlett 2010
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "includes.h"
25#include "libcli/security/security.h"
26
27/* Map generic access rights to object specific rights. This technique is
28 used to give meaning to assigning read, write, execute and all access to
29 objects. Each type of object has its own mapping of generic to object
30 specific access rights. */
31
32void se_map_generic(uint32_t *access_mask, const struct generic_mapping *mapping)
33{
34 uint32_t old_mask = *access_mask;
35
36 if (*access_mask & GENERIC_READ_ACCESS) {
37 *access_mask &= ~GENERIC_READ_ACCESS;
38 *access_mask |= mapping->generic_read;
39 }
40
41 if (*access_mask & GENERIC_WRITE_ACCESS) {
42 *access_mask &= ~GENERIC_WRITE_ACCESS;
43 *access_mask |= mapping->generic_write;
44 }
45
46 if (*access_mask & GENERIC_EXECUTE_ACCESS) {
47 *access_mask &= ~GENERIC_EXECUTE_ACCESS;
48 *access_mask |= mapping->generic_execute;
49 }
50
51 if (*access_mask & GENERIC_ALL_ACCESS) {
52 *access_mask &= ~GENERIC_ALL_ACCESS;
53 *access_mask |= mapping->generic_all;
54 }
55
56 if (old_mask != *access_mask) {
57 DEBUG(10, ("se_map_generic(): mapped mask 0x%08x to 0x%08x\n",
58 old_mask, *access_mask));
59 }
60}
61
62/* Map generic access rights to object specific rights for all the ACE's
63 * in a security_acl.
64 */
65
66void security_acl_map_generic(struct security_acl *sa,
67 const struct generic_mapping *mapping)
68{
69 unsigned int i;
70
71 if (!sa) {
72 return;
73 }
74
75 for (i = 0; i < sa->num_aces; i++) {
76 se_map_generic(&sa->aces[i].access_mask, mapping);
77 }
78}
79
80/* Map standard access rights to object specific rights. This technique is
81 used to give meaning to assigning read, write, execute and all access to
82 objects. Each type of object has its own mapping of standard to object
83 specific access rights. */
84
85void se_map_standard(uint32_t *access_mask, const struct standard_mapping *mapping)
86{
87 uint32_t old_mask = *access_mask;
88
89 if (*access_mask & SEC_STD_READ_CONTROL) {
90 *access_mask &= ~SEC_STD_READ_CONTROL;
91 *access_mask |= mapping->std_read;
92 }
93
94 if (*access_mask & (SEC_STD_DELETE|SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER|SEC_STD_SYNCHRONIZE)) {
95 *access_mask &= ~(SEC_STD_DELETE|SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER|SEC_STD_SYNCHRONIZE);
96 *access_mask |= mapping->std_all;
97 }
98
99 if (old_mask != *access_mask) {
100 DEBUG(10, ("se_map_standard(): mapped mask 0x%08x to 0x%08x\n",
101 old_mask, *access_mask));
102 }
103}
104
105/*
106 perform a SEC_FLAG_MAXIMUM_ALLOWED access check
107*/
108static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
109 const struct security_token *token)
110{
111 uint32_t denied = 0, granted = 0;
112 unsigned i;
113
114 if (security_token_has_sid(token, sd->owner_sid)) {
115 granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL;
116 }
117
118 if (sd->dacl == NULL) {
119 return granted & ~denied;
120 }
121
122 for (i = 0;i<sd->dacl->num_aces; i++) {
123 struct security_ace *ace = &sd->dacl->aces[i];
124
125 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
126 continue;
127 }
128
129 if (!security_token_has_sid(token, &ace->trustee)) {
130 continue;
131 }
132
133 switch (ace->type) {
134 case SEC_ACE_TYPE_ACCESS_ALLOWED:
135 granted |= ace->access_mask;
136 break;
137 case SEC_ACE_TYPE_ACCESS_DENIED:
138 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
139 denied |= ace->access_mask;
140 break;
141 default: /* Other ACE types not handled/supported */
142 break;
143 }
144 }
145
146 return granted & ~denied;
147}
148
149/*
150 The main entry point for access checking. If returning ACCESS_DENIED
151 this function returns the denied bits in the uint32_t pointed
152 to by the access_granted pointer.
153*/
154NTSTATUS se_access_check(const struct security_descriptor *sd,
155 const struct security_token *token,
156 uint32_t access_desired,
157 uint32_t *access_granted)
158{
159 uint32_t i;
160 uint32_t bits_remaining;
161
162 *access_granted = access_desired;
163 bits_remaining = access_desired;
164
165 /* handle the maximum allowed flag */
166 if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
167 uint32_t orig_access_desired = access_desired;
168
169 access_desired |= access_check_max_allowed(sd, token);
170 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
171 *access_granted = access_desired;
172 bits_remaining = access_desired;
173
174 DEBUG(10,("se_access_check: MAX desired = 0x%x, granted = 0x%x, remaining = 0x%x\n",
175 orig_access_desired,
176 *access_granted,
177 bits_remaining));
178 }
179
180 /* s3 had this with #if 0 previously. To be sure the merge
181 doesn't change any behaviour, we have the above #if check
182 on _SAMBA_BUILD_. */
183 if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
184 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
185 bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
186 } else {
187 return NT_STATUS_PRIVILEGE_NOT_HELD;
188 }
189 }
190
191 /* the owner always gets SEC_STD_WRITE_DAC and SEC_STD_READ_CONTROL */
192 if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) &&
193 security_token_has_sid(token, sd->owner_sid)) {
194 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
195 }
196
197 /* TODO: remove this, as it is file server specific */
198 if ((bits_remaining & SEC_RIGHTS_PRIV_RESTORE) &&
199 security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
200 bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE);
201 }
202 if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) &&
203 security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
204 bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP);
205 }
206
207 /* a NULL dacl allows access */
208 if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
209 *access_granted = access_desired;
210 return NT_STATUS_OK;
211 }
212
213 if (sd->dacl == NULL) {
214 goto done;
215 }
216
217 /* check each ace in turn. */
218 for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
219 struct security_ace *ace = &sd->dacl->aces[i];
220
221 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
222 continue;
223 }
224
225 if (!security_token_has_sid(token, &ace->trustee)) {
226 continue;
227 }
228
229 switch (ace->type) {
230 case SEC_ACE_TYPE_ACCESS_ALLOWED:
231 bits_remaining &= ~ace->access_mask;
232 break;
233 case SEC_ACE_TYPE_ACCESS_DENIED:
234 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
235 if (bits_remaining & ace->access_mask) {
236 return NT_STATUS_ACCESS_DENIED;
237 }
238 break;
239 default: /* Other ACE types not handled/supported */
240 break;
241 }
242 }
243
244done:
245 if (bits_remaining != 0) {
246 *access_granted = bits_remaining;
247 return NT_STATUS_ACCESS_DENIED;
248 }
249
250 return NT_STATUS_OK;
251}
252
253
254static const struct GUID *get_ace_object_type(struct security_ace *ace)
255{
256 struct GUID *type;
257
258 if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT)
259 type = &ace->object.object.type.type;
260 else if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)
261 type = &ace->object.object.inherited_type.inherited_type; /* This doesn't look right. Is something wrong with the IDL? */
262 else
263 type = NULL;
264
265 return type;
266
267}
268
269/* modified access check for the purposes of DS security
270 * Lots of code duplication, it will ve united in just one
271 * function eventually */
272
273NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
274 const struct security_token *token,
275 uint32_t access_desired,
276 uint32_t *access_granted,
277 struct object_tree *tree,
278 struct dom_sid *replace_sid)
279{
280 uint32_t i;
281 uint32_t bits_remaining;
282 struct object_tree *node;
283 const struct GUID *type;
284 struct dom_sid *ps_sid = dom_sid_parse_talloc(NULL, SID_NT_SELF);
285
286 *access_granted = access_desired;
287 bits_remaining = access_desired;
288
289 /* handle the maximum allowed flag */
290 if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
291 access_desired |= access_check_max_allowed(sd, token);
292 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
293 *access_granted = access_desired;
294 bits_remaining = access_desired;
295 }
296
297 if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
298 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
299 bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
300 } else {
301 talloc_free(ps_sid);
302 return NT_STATUS_PRIVILEGE_NOT_HELD;
303 }
304 }
305
306 /* the owner always gets SEC_STD_WRITE_DAC and SEC_STD_READ_CONTROL */
307 if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) &&
308 security_token_has_sid(token, sd->owner_sid)) {
309 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
310 }
311
312 /* TODO: remove this, as it is file server specific */
313 if ((bits_remaining & SEC_RIGHTS_PRIV_RESTORE) &&
314 security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
315 bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE);
316 }
317 if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) &&
318 security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
319 bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP);
320 }
321
322 /* a NULL dacl allows access */
323 if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
324 *access_granted = access_desired;
325 talloc_free(ps_sid);
326 return NT_STATUS_OK;
327 }
328
329 if (sd->dacl == NULL) {
330 goto done;
331 }
332
333 /* check each ace in turn. */
334 for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
335 struct dom_sid *trustee;
336 struct security_ace *ace = &sd->dacl->aces[i];
337
338 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
339 continue;
340 }
341 if (dom_sid_equal(&ace->trustee, ps_sid) && replace_sid) {
342 trustee = replace_sid;
343 }
344 else
345 {
346 trustee = &ace->trustee;
347 }
348 if (!security_token_has_sid(token, trustee)) {
349 continue;
350 }
351
352 switch (ace->type) {
353 case SEC_ACE_TYPE_ACCESS_ALLOWED:
354 if (tree)
355 object_tree_modify_access(tree, ace->access_mask);
356
357 bits_remaining &= ~ace->access_mask;
358 break;
359 case SEC_ACE_TYPE_ACCESS_DENIED:
360 if (bits_remaining & ace->access_mask) {
361 talloc_free(ps_sid);
362 return NT_STATUS_ACCESS_DENIED;
363 }
364 break;
365 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
366 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
367 /* check only in case we have provided a tree,
368 * the ACE has an object type and that type
369 * is in the tree */
370 type = get_ace_object_type(ace);
371
372 if (!tree)
373 continue;
374
375 if (!type)
376 node = tree;
377 else
378 if (!(node = get_object_tree_by_GUID(tree, type)))
379 continue;
380
381 if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) {
382 object_tree_modify_access(node, ace->access_mask);
383 if (node->remaining_access == 0) {
384 talloc_free(ps_sid);
385 return NT_STATUS_OK;
386 }
387 } else {
388 if (node->remaining_access & ace->access_mask){
389 talloc_free(ps_sid);
390 return NT_STATUS_ACCESS_DENIED;
391 }
392 }
393 break;
394 default: /* Other ACE types not handled/supported */
395 break;
396 }
397 }
398
399done:
400 talloc_free(ps_sid);
401 if (bits_remaining != 0) {
402 return NT_STATUS_ACCESS_DENIED;
403 }
404
405 return NT_STATUS_OK;
406}
Note: See TracBrowser for help on using the repository browser.