source: vendor/current/libcli/security/access_check.c@ 746

Last change on this file since 746 was 746, checked in by Silvan Scherrer, 12 years ago

Samba Server: updated vendor to 3.6.9

File size: 13.1 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 uint32_t explicitly_denied_bits = 0;
162
163 *access_granted = access_desired;
164 bits_remaining = access_desired;
165
166 /* handle the maximum allowed flag */
167 if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
168 uint32_t orig_access_desired = access_desired;
169
170 access_desired |= access_check_max_allowed(sd, token);
171 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
172 *access_granted = access_desired;
173 bits_remaining = access_desired;
174
175 DEBUG(10,("se_access_check: MAX desired = 0x%x, granted = 0x%x, remaining = 0x%x\n",
176 orig_access_desired,
177 *access_granted,
178 bits_remaining));
179 }
180
181 /* the owner always gets SEC_STD_WRITE_DAC and SEC_STD_READ_CONTROL */
182 if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) &&
183 security_token_has_sid(token, sd->owner_sid)) {
184 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
185 }
186
187 /* a NULL dacl allows access */
188 if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
189 *access_granted = access_desired;
190 return NT_STATUS_OK;
191 }
192
193 if (sd->dacl == NULL) {
194 goto done;
195 }
196
197 /* check each ace in turn. */
198 for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
199 struct security_ace *ace = &sd->dacl->aces[i];
200
201 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
202 continue;
203 }
204
205 if (!security_token_has_sid(token, &ace->trustee)) {
206 continue;
207 }
208
209 switch (ace->type) {
210 case SEC_ACE_TYPE_ACCESS_ALLOWED:
211 bits_remaining &= ~ace->access_mask;
212 break;
213 case SEC_ACE_TYPE_ACCESS_DENIED:
214 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
215 explicitly_denied_bits |= (bits_remaining & ace->access_mask);
216 break;
217 default: /* Other ACE types not handled/supported */
218 break;
219 }
220 }
221
222 bits_remaining |= explicitly_denied_bits;
223
224 /*
225 * We check privileges here because they override even DENY entries.
226 */
227
228 /* Does the user have the privilege to gain SEC_PRIV_SECURITY? */
229 if (bits_remaining & SEC_FLAG_SYSTEM_SECURITY) {
230 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
231 bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
232 } else {
233 return NT_STATUS_PRIVILEGE_NOT_HELD;
234 }
235 }
236
237 /* TODO: remove this, as it is file server specific */
238 if ((bits_remaining & SEC_RIGHTS_PRIV_RESTORE) &&
239 security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
240 bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE);
241 }
242 if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) &&
243 security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
244 bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP);
245 }
246
247 if ((bits_remaining & SEC_STD_WRITE_OWNER) &&
248 security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) {
249 bits_remaining &= ~(SEC_STD_WRITE_OWNER);
250 }
251
252done:
253 if (bits_remaining != 0) {
254 *access_granted = bits_remaining;
255 return NT_STATUS_ACCESS_DENIED;
256 }
257
258 return NT_STATUS_OK;
259}
260
261
262static const struct GUID *get_ace_object_type(struct security_ace *ace)
263{
264 struct GUID *type;
265
266 if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT)
267 type = &ace->object.object.type.type;
268 else if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)
269 type = &ace->object.object.inherited_type.inherited_type; /* This doesn't look right. Is something wrong with the IDL? */
270 else
271 type = NULL;
272
273 return type;
274
275}
276
277/* modified access check for the purposes of DS security
278 * Lots of code duplication, it will ve united in just one
279 * function eventually */
280
281NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
282 const struct security_token *token,
283 uint32_t access_desired,
284 uint32_t *access_granted,
285 struct object_tree *tree,
286 struct dom_sid *replace_sid)
287{
288 uint32_t i;
289 uint32_t bits_remaining;
290 struct object_tree *node;
291 const struct GUID *type;
292 struct dom_sid *ps_sid = dom_sid_parse_talloc(NULL, SID_NT_SELF);
293
294 *access_granted = access_desired;
295 bits_remaining = access_desired;
296
297 /* handle the maximum allowed flag */
298 if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
299 access_desired |= access_check_max_allowed(sd, token);
300 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
301 *access_granted = access_desired;
302 bits_remaining = access_desired;
303 }
304
305 if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
306 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
307 bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
308 } else {
309 talloc_free(ps_sid);
310 return NT_STATUS_PRIVILEGE_NOT_HELD;
311 }
312 }
313
314 /* the owner always gets SEC_STD_WRITE_DAC and SEC_STD_READ_CONTROL */
315 if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) &&
316 security_token_has_sid(token, sd->owner_sid)) {
317 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
318 }
319
320 /* TODO: remove this, as it is file server specific */
321 if ((bits_remaining & SEC_RIGHTS_PRIV_RESTORE) &&
322 security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
323 bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE);
324 }
325 if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) &&
326 security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
327 bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP);
328 }
329
330 /* a NULL dacl allows access */
331 if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
332 *access_granted = access_desired;
333 talloc_free(ps_sid);
334 return NT_STATUS_OK;
335 }
336
337 if (sd->dacl == NULL) {
338 goto done;
339 }
340
341 /* check each ace in turn. */
342 for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
343 struct dom_sid *trustee;
344 struct security_ace *ace = &sd->dacl->aces[i];
345
346 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
347 continue;
348 }
349 if (dom_sid_equal(&ace->trustee, ps_sid) && replace_sid) {
350 trustee = replace_sid;
351 }
352 else
353 {
354 trustee = &ace->trustee;
355 }
356 if (!security_token_has_sid(token, trustee)) {
357 continue;
358 }
359
360 switch (ace->type) {
361 case SEC_ACE_TYPE_ACCESS_ALLOWED:
362 if (tree)
363 object_tree_modify_access(tree, ace->access_mask);
364
365 bits_remaining &= ~ace->access_mask;
366 break;
367 case SEC_ACE_TYPE_ACCESS_DENIED:
368 if (bits_remaining & ace->access_mask) {
369 talloc_free(ps_sid);
370 return NT_STATUS_ACCESS_DENIED;
371 }
372 break;
373 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
374 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
375 /* check only in case we have provided a tree,
376 * the ACE has an object type and that type
377 * is in the tree */
378 type = get_ace_object_type(ace);
379
380 if (!tree)
381 continue;
382
383 if (!type)
384 node = tree;
385 else
386 if (!(node = get_object_tree_by_GUID(tree, type)))
387 continue;
388
389 if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) {
390 object_tree_modify_access(node, ace->access_mask);
391 if (node->remaining_access == 0) {
392 talloc_free(ps_sid);
393 return NT_STATUS_OK;
394 }
395 } else {
396 if (node->remaining_access & ace->access_mask){
397 talloc_free(ps_sid);
398 return NT_STATUS_ACCESS_DENIED;
399 }
400 }
401 break;
402 default: /* Other ACE types not handled/supported */
403 break;
404 }
405 }
406
407done:
408 talloc_free(ps_sid);
409 if (bits_remaining != 0) {
410 return NT_STATUS_ACCESS_DENIED;
411 }
412
413 return NT_STATUS_OK;
414}
Note: See TracBrowser for help on using the repository browser.