WHATSNEW: Update changed parameters.
[Samba/gebeck_regimport.git] / libcli / security / access_check.c
blobc5f89af32a6ecd7dd8a4ccc7b06d47ea950aef54
1 /*
2 Unix SMB/CIFS implementation.
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
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.
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.
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/>.
24 #include "includes.h"
25 #include "libcli/security/security.h"
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. */
32 void se_map_generic(uint32_t *access_mask, const struct generic_mapping *mapping)
34 uint32_t old_mask = *access_mask;
36 if (*access_mask & GENERIC_READ_ACCESS) {
37 *access_mask &= ~GENERIC_READ_ACCESS;
38 *access_mask |= mapping->generic_read;
41 if (*access_mask & GENERIC_WRITE_ACCESS) {
42 *access_mask &= ~GENERIC_WRITE_ACCESS;
43 *access_mask |= mapping->generic_write;
46 if (*access_mask & GENERIC_EXECUTE_ACCESS) {
47 *access_mask &= ~GENERIC_EXECUTE_ACCESS;
48 *access_mask |= mapping->generic_execute;
51 if (*access_mask & GENERIC_ALL_ACCESS) {
52 *access_mask &= ~GENERIC_ALL_ACCESS;
53 *access_mask |= mapping->generic_all;
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));
62 /* Map generic access rights to object specific rights for all the ACE's
63 * in a security_acl.
66 void security_acl_map_generic(struct security_acl *sa,
67 const struct generic_mapping *mapping)
69 unsigned int i;
71 if (!sa) {
72 return;
75 for (i = 0; i < sa->num_aces; i++) {
76 se_map_generic(&sa->aces[i].access_mask, mapping);
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. */
85 void se_map_standard(uint32_t *access_mask, const struct standard_mapping *mapping)
87 uint32_t old_mask = *access_mask;
89 if (*access_mask & SEC_STD_READ_CONTROL) {
90 *access_mask &= ~SEC_STD_READ_CONTROL;
91 *access_mask |= mapping->std_read;
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;
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));
106 perform a SEC_FLAG_MAXIMUM_ALLOWED access check
108 static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
109 const struct security_token *token)
111 uint32_t denied = 0, granted = 0;
112 unsigned i;
114 if (security_token_has_sid(token, sd->owner_sid)) {
115 granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL | SEC_STD_DELETE;
116 } else if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
117 granted |= SEC_STD_DELETE;
120 if (sd->dacl == NULL) {
121 return granted & ~denied;
124 for (i = 0;i<sd->dacl->num_aces; i++) {
125 struct security_ace *ace = &sd->dacl->aces[i];
127 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
128 continue;
131 if (!security_token_has_sid(token, &ace->trustee)) {
132 continue;
135 switch (ace->type) {
136 case SEC_ACE_TYPE_ACCESS_ALLOWED:
137 granted |= ace->access_mask;
138 break;
139 case SEC_ACE_TYPE_ACCESS_DENIED:
140 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
141 denied |= ace->access_mask;
142 break;
143 default: /* Other ACE types not handled/supported */
144 break;
148 return granted & ~denied;
152 The main entry point for access checking. If returning ACCESS_DENIED
153 this function returns the denied bits in the uint32_t pointed
154 to by the access_granted pointer.
156 NTSTATUS se_access_check(const struct security_descriptor *sd,
157 const struct security_token *token,
158 uint32_t access_desired,
159 uint32_t *access_granted)
161 uint32_t i;
162 uint32_t bits_remaining;
164 *access_granted = access_desired;
165 bits_remaining = access_desired;
167 /* handle the maximum allowed flag */
168 if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
169 uint32_t orig_access_desired = access_desired;
171 access_desired |= access_check_max_allowed(sd, token);
172 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
173 *access_granted = access_desired;
174 bits_remaining = access_desired & ~SEC_STD_DELETE;
176 DEBUG(10,("se_access_check: MAX desired = 0x%x, granted = 0x%x, remaining = 0x%x\n",
177 orig_access_desired,
178 *access_granted,
179 bits_remaining));
182 /* s3 had this with #if 0 previously. To be sure the merge
183 doesn't change any behaviour, we have the above #if check
184 on _SAMBA_BUILD_. */
185 if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
186 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
187 bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
188 } else {
189 return NT_STATUS_PRIVILEGE_NOT_HELD;
193 /* a NULL dacl allows access */
194 if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
195 *access_granted = access_desired;
196 return NT_STATUS_OK;
199 /* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */
200 if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) &&
201 security_token_has_sid(token, sd->owner_sid)) {
202 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE);
204 if ((bits_remaining & SEC_STD_DELETE) &&
205 (security_token_has_privilege(token, SEC_PRIV_RESTORE))) {
206 bits_remaining &= ~SEC_STD_DELETE;
208 if ((bits_remaining & SEC_RIGHTS_PRIV_RESTORE) &&
209 security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
210 bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE);
212 if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) &&
213 security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
214 bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP);
217 if (sd->dacl == NULL) {
218 goto done;
221 /* check each ace in turn. */
222 for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
223 struct security_ace *ace = &sd->dacl->aces[i];
225 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
226 continue;
229 if (!security_token_has_sid(token, &ace->trustee)) {
230 continue;
233 switch (ace->type) {
234 case SEC_ACE_TYPE_ACCESS_ALLOWED:
235 bits_remaining &= ~ace->access_mask;
236 break;
237 case SEC_ACE_TYPE_ACCESS_DENIED:
238 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
239 if (bits_remaining & ace->access_mask) {
240 return NT_STATUS_ACCESS_DENIED;
242 break;
243 default: /* Other ACE types not handled/supported */
244 break;
248 done:
249 if (bits_remaining != 0) {
250 *access_granted = bits_remaining;
251 return NT_STATUS_ACCESS_DENIED;
254 return NT_STATUS_OK;
258 static const struct GUID *get_ace_object_type(struct security_ace *ace)
260 struct GUID *type;
262 if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT)
263 type = &ace->object.object.type.type;
264 else if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)
265 type = &ace->object.object.inherited_type.inherited_type; /* This doesn't look right. Is something wrong with the IDL? */
266 else
267 type = NULL;
269 return type;
273 /* modified access check for the purposes of DS security
274 * Lots of code duplication, it will ve united in just one
275 * function eventually */
277 NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
278 const struct security_token *token,
279 uint32_t access_desired,
280 uint32_t *access_granted,
281 struct object_tree *tree,
282 struct dom_sid *replace_sid)
284 uint32_t i;
285 uint32_t bits_remaining;
286 struct object_tree *node;
287 const struct GUID *type;
288 struct dom_sid *ps_sid = dom_sid_parse_talloc(NULL, SID_NT_SELF);
290 *access_granted = access_desired;
291 bits_remaining = access_desired;
293 /* handle the maximum allowed flag */
294 if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
295 access_desired |= access_check_max_allowed(sd, token);
296 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
297 *access_granted = access_desired;
298 bits_remaining = access_desired & ~SEC_STD_DELETE;
301 if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
302 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
303 bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
304 } else {
305 talloc_free(ps_sid);
306 return NT_STATUS_PRIVILEGE_NOT_HELD;
310 /* a NULL dacl allows access */
311 if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
312 *access_granted = access_desired;
313 talloc_free(ps_sid);
314 return NT_STATUS_OK;
317 /* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */
318 if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) &&
319 security_token_has_sid(token, sd->owner_sid)) {
320 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE);
322 if ((bits_remaining & SEC_STD_DELETE) &&
323 security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
324 bits_remaining &= ~SEC_STD_DELETE;
327 if (sd->dacl == NULL) {
328 goto done;
331 /* check each ace in turn. */
332 for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
333 struct dom_sid *trustee;
334 struct security_ace *ace = &sd->dacl->aces[i];
336 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
337 continue;
339 if (dom_sid_equal(&ace->trustee, ps_sid) && replace_sid) {
340 trustee = replace_sid;
342 else
344 trustee = &ace->trustee;
346 if (!security_token_has_sid(token, trustee)) {
347 continue;
350 switch (ace->type) {
351 case SEC_ACE_TYPE_ACCESS_ALLOWED:
352 if (tree)
353 object_tree_modify_access(tree, ace->access_mask);
355 bits_remaining &= ~ace->access_mask;
356 break;
357 case SEC_ACE_TYPE_ACCESS_DENIED:
358 if (bits_remaining & ace->access_mask) {
359 talloc_free(ps_sid);
360 return NT_STATUS_ACCESS_DENIED;
362 break;
363 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
364 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
365 /* check only in case we have provided a tree,
366 * the ACE has an object type and that type
367 * is in the tree */
368 type = get_ace_object_type(ace);
370 if (!tree)
371 continue;
373 if (!type)
374 node = tree;
375 else
376 if (!(node = get_object_tree_by_GUID(tree, type)))
377 continue;
379 if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) {
380 object_tree_modify_access(node, ace->access_mask);
381 if (node->remaining_access == 0) {
382 talloc_free(ps_sid);
383 return NT_STATUS_OK;
385 } else {
386 if (node->remaining_access & ace->access_mask){
387 talloc_free(ps_sid);
388 return NT_STATUS_ACCESS_DENIED;
391 break;
392 default: /* Other ACE types not handled/supported */
393 break;
397 done:
398 talloc_free(ps_sid);
399 if (bits_remaining != 0) {
400 return NT_STATUS_ACCESS_DENIED;
403 return NT_STATUS_OK;