skel_ -> cap_
[Samba/gebeck_regimport.git] / source3 / lib / util_seaccess.c
blobeba8cab7fb82734911713df2c4fe1ecda31bef33
1 /*
2 Unix SMB/CIFS implementation.
3 Copyright (C) Luke Kenneth Casson Leighton 1996-2000.
4 Copyright (C) Tim Potter 2000.
5 Copyright (C) Re-written by Jeremy Allison 2000.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 extern DOM_SID global_sid_Builtin;
26 /**********************************************************************************
27 Check if this ACE has a SID in common with the token.
28 **********************************************************************************/
30 static BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace)
32 size_t i;
34 for (i = 0; i < token->num_sids; i++) {
35 if (sid_equal(&ace->trustee, &token->user_sids[i]))
36 return True;
39 return False;
42 /*********************************************************************************
43 Check an ACE against a SID. We return the remaining needed permission
44 bits not yet granted. Zero means permission allowed (no more needed bits).
45 **********************************************************************************/
47 static uint32 check_ace(SEC_ACE *ace, const NT_USER_TOKEN *token, uint32 acc_desired,
48 NTSTATUS *status)
50 uint32 mask = ace->info.mask;
53 * Inherit only is ignored.
56 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
57 return acc_desired;
61 * If this ACE has no SID in common with the token,
62 * ignore it as it cannot be used to make an access
63 * determination.
66 if (!token_sid_in_ace( token, ace))
67 return acc_desired;
69 switch (ace->type) {
70 case SEC_ACE_TYPE_ACCESS_ALLOWED:
72 * This is explicitly allowed.
73 * Remove the bits from the remaining
74 * access required. Return the remaining
75 * bits needed.
77 acc_desired &= ~mask;
78 break;
79 case SEC_ACE_TYPE_ACCESS_DENIED:
81 * This is explicitly denied.
82 * If any bits match terminate here,
83 * we are denied.
85 if (acc_desired & mask) {
86 *status = NT_STATUS_ACCESS_DENIED;
87 return 0xFFFFFFFF;
89 break;
90 case SEC_ACE_TYPE_SYSTEM_ALARM:
91 case SEC_ACE_TYPE_SYSTEM_AUDIT:
92 *status = NT_STATUS_NOT_IMPLEMENTED;
93 return 0xFFFFFFFF;
94 default:
95 *status = NT_STATUS_INVALID_PARAMETER;
96 return 0xFFFFFFFF;
99 return acc_desired;
102 /*********************************************************************************
103 Maximum access was requested. Calculate the max possible. Fail if it doesn't
104 include other bits requested.
105 **********************************************************************************/
107 static BOOL get_max_access( SEC_ACL *the_acl, const NT_USER_TOKEN *token, uint32 *granted,
108 uint32 desired,
109 NTSTATUS *status)
111 uint32 acc_denied = 0;
112 uint32 acc_granted = 0;
113 size_t i;
115 for ( i = 0 ; i < the_acl->num_aces; i++) {
116 SEC_ACE *ace = &the_acl->ace[i];
117 uint32 mask = ace->info.mask;
119 if (!token_sid_in_ace( token, ace))
120 continue;
122 switch (ace->type) {
123 case SEC_ACE_TYPE_ACCESS_ALLOWED:
124 acc_granted |= (mask & ~acc_denied);
125 break;
126 case SEC_ACE_TYPE_ACCESS_DENIED:
127 acc_denied |= (mask & ~acc_granted);
128 break;
129 case SEC_ACE_TYPE_SYSTEM_ALARM:
130 case SEC_ACE_TYPE_SYSTEM_AUDIT:
131 *status = NT_STATUS_NOT_IMPLEMENTED;
132 *granted = 0;
133 return False;
134 default:
135 *status = NT_STATUS_INVALID_PARAMETER;
136 *granted = 0;
137 return False;
142 * If we were granted no access, or we desired bits that we
143 * didn't get, then deny.
146 if ((acc_granted == 0) || ((acc_granted & desired) != desired)) {
147 *status = NT_STATUS_ACCESS_DENIED;
148 *granted = 0;
149 return False;
153 * Return the access we did get.
156 *granted = acc_granted;
157 *status = NT_STATUS_OK;
158 return True;
161 /* Map generic access rights to object specific rights. This technique is
162 used to give meaning to assigning read, write, execute and all access to
163 objects. Each type of object has its own mapping of generic to object
164 specific access rights. */
166 void se_map_generic(uint32 *access_mask, struct generic_mapping *mapping)
168 uint32 old_mask = *access_mask;
170 if (*access_mask & GENERIC_READ_ACCESS) {
171 *access_mask &= ~GENERIC_READ_ACCESS;
172 *access_mask |= mapping->generic_read;
175 if (*access_mask & GENERIC_WRITE_ACCESS) {
176 *access_mask &= ~GENERIC_WRITE_ACCESS;
177 *access_mask |= mapping->generic_write;
180 if (*access_mask & GENERIC_EXECUTE_ACCESS) {
181 *access_mask &= ~GENERIC_EXECUTE_ACCESS;
182 *access_mask |= mapping->generic_execute;
185 if (*access_mask & GENERIC_ALL_ACCESS) {
186 *access_mask &= ~GENERIC_ALL_ACCESS;
187 *access_mask |= mapping->generic_all;
190 if (old_mask != *access_mask) {
191 DEBUG(10, ("se_map_generic(): mapped mask 0x%08x to 0x%08x\n",
192 old_mask, *access_mask));
196 /* Map standard access rights to object specific rights. This technique is
197 used to give meaning to assigning read, write, execute and all access to
198 objects. Each type of object has its own mapping of standard to object
199 specific access rights. */
201 void se_map_standard(uint32 *access_mask, struct standard_mapping *mapping)
203 uint32 old_mask = *access_mask;
205 if (*access_mask & READ_CONTROL_ACCESS) {
206 *access_mask &= ~READ_CONTROL_ACCESS;
207 *access_mask |= mapping->std_read;
210 if (*access_mask & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS)) {
211 *access_mask &= ~(DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS);
212 *access_mask |= mapping->std_all;
215 if (old_mask != *access_mask) {
216 DEBUG(10, ("se_map_standard(): mapped mask 0x%08x to 0x%08x\n",
217 old_mask, *access_mask));
221 /*****************************************************************************
222 Check access rights of a user against a security descriptor. Look at
223 each ACE in the security descriptor until an access denied ACE denies
224 any of the desired rights to the user or any of the users groups, or one
225 or more ACEs explicitly grant all requested access rights. See
226 "Access-Checking" document in MSDN.
227 *****************************************************************************/
229 BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token,
230 uint32 acc_desired, uint32 *acc_granted,
231 NTSTATUS *status)
233 extern NT_USER_TOKEN anonymous_token;
234 size_t i;
235 SEC_ACL *the_acl;
236 fstring sid_str;
237 uint32 tmp_acc_desired = acc_desired;
239 if (!status || !acc_granted)
240 return False;
242 if (!token)
243 token = &anonymous_token;
245 *status = NT_STATUS_OK;
246 *acc_granted = 0;
248 DEBUG(10,("se_access_check: requested access 0x%08x, for NT token with %u entries and first sid %s.\n",
249 (unsigned int)acc_desired, (unsigned int)token->num_sids,
250 sid_to_string(sid_str, &token->user_sids[0])));
253 * No security descriptor or security descriptor with no DACL
254 * present allows all access.
257 /* ACL must have something in it */
259 if (!sd || (sd && (!(sd->type & SEC_DESC_DACL_PRESENT) || sd->dacl == NULL))) {
260 *status = NT_STATUS_OK;
261 *acc_granted = acc_desired;
262 DEBUG(5, ("se_access_check: no sd or blank DACL, access allowed\n"));
263 return True;
266 /* The user sid is the first in the token */
267 if (DEBUGLVL(3)) {
268 DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &token->user_sids[PRIMARY_USER_SID_INDEX]) ));
270 for (i = 1; i < token->num_sids; i++) {
271 DEBUGADD(3, ("se_access_check: also %s\n",
272 sid_to_string(sid_str, &token->user_sids[i])));
276 /* Is the token the owner of the SID ? */
278 if (sd->owner_sid) {
279 for (i = 0; i < token->num_sids; i++) {
280 if (sid_equal(&token->user_sids[i], sd->owner_sid)) {
282 * The owner always has SEC_RIGHTS_WRITE_DAC & READ_CONTROL.
284 if (tmp_acc_desired & WRITE_DAC_ACCESS)
285 tmp_acc_desired &= ~WRITE_DAC_ACCESS;
286 if (tmp_acc_desired & READ_CONTROL_ACCESS)
287 tmp_acc_desired &= ~READ_CONTROL_ACCESS;
292 the_acl = sd->dacl;
294 if (tmp_acc_desired & MAXIMUM_ALLOWED_ACCESS) {
295 tmp_acc_desired &= ~MAXIMUM_ALLOWED_ACCESS;
296 return get_max_access( the_acl, token, acc_granted, tmp_acc_desired,
297 status);
300 for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) {
301 SEC_ACE *ace = &the_acl->ace[i];
303 DEBUGADD(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n",
304 (unsigned int)i, ace->type, ace->flags,
305 sid_to_string(sid_str, &ace->trustee),
306 (unsigned int) ace->info.mask,
307 (unsigned int)tmp_acc_desired ));
309 tmp_acc_desired = check_ace( ace, token, tmp_acc_desired, status);
310 if (NT_STATUS_V(*status)) {
311 *acc_granted = 0;
312 DEBUG(5,("se_access_check: ACE %u denied with status %s.\n", (unsigned int)i, nt_errstr(*status)));
313 return False;
318 * If there are no more desired permissions left then
319 * access was allowed.
322 if (tmp_acc_desired == 0) {
323 *acc_granted = acc_desired;
324 *status = NT_STATUS_OK;
325 DEBUG(5,("se_access_check: access (%x) granted.\n", (unsigned int)acc_desired ));
326 return True;
329 *acc_granted = 0;
330 *status = NT_STATUS_ACCESS_DENIED;
331 DEBUG(5,("se_access_check: access (%x) denied.\n", (unsigned int)acc_desired ));
332 return False;
335 /* Create a child security descriptor using another security descriptor as
336 the parent container. This child object can either be a container or
337 non-container object. */
339 SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
340 BOOL child_container)
342 SEC_DESC_BUF *sdb;
343 SEC_DESC *sd;
344 SEC_ACL *new_dacl, *the_acl;
345 SEC_ACE *new_ace_list = NULL;
346 unsigned int new_ace_list_ndx = 0, i;
347 size_t size;
349 /* Currently we only process the dacl when creating the child. The
350 sacl should also be processed but this is left out as sacls are
351 not implemented in Samba at the moment.*/
353 the_acl = parent_ctr->dacl;
355 if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces)))
356 return NULL;
358 for (i = 0; the_acl && i < the_acl->num_aces; i++) {
359 SEC_ACE *ace = &the_acl->ace[i];
360 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
361 uint8 new_flags = 0;
362 BOOL inherit = False;
363 fstring sid_str;
365 /* The OBJECT_INHERIT_ACE flag causes the ACE to be
366 inherited by non-container children objects. Container
367 children objects will inherit it as an INHERIT_ONLY
368 ACE. */
370 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
372 if (!child_container) {
373 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
374 } else {
375 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
378 inherit = True;
381 /* The CONAINER_INHERIT_ACE flag means all child container
382 objects will inherit and use the ACE. */
384 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
385 if (!child_container) {
386 inherit = False;
387 } else {
388 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
392 /* The INHERIT_ONLY_ACE is not used by the se_access_check()
393 function for the parent container, but is inherited by
394 all child objects as a normal ACE. */
396 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
397 /* Move along, nothing to see here */
400 /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
401 is inherited by child objects but not grandchildren
402 objects. We clear the object inherit and container
403 inherit flags in the inherited ACE. */
405 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
406 new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
407 SEC_ACE_FLAG_CONTAINER_INHERIT);
410 /* Add ACE to ACE list */
412 if (!inherit)
413 continue;
415 init_sec_access(&new_ace->info, ace->info.mask);
416 init_sec_ace(new_ace, &ace->trustee, ace->type,
417 new_ace->info, new_flags);
419 sid_to_string(sid_str, &ace->trustee);
421 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
422 " inherited as %s:%d/0x%02x/0x%08x\n", sid_str,
423 ace->type, ace->flags, ace->info.mask,
424 sid_str, new_ace->type, new_ace->flags,
425 new_ace->info.mask));
427 new_ace_list_ndx++;
430 /* Create child security descriptor to return */
432 new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
434 /* Use the existing user and group sids. I don't think this is
435 correct. Perhaps the user and group should be passed in as
436 parameters by the caller? */
438 sd = make_sec_desc(ctx, SEC_DESC_REVISION,
439 parent_ctr->owner_sid,
440 parent_ctr->grp_sid,
441 parent_ctr->sacl,
442 new_dacl, &size);
444 sdb = make_sec_desc_buf(ctx, size, sd);
446 return sdb;
449 /*******************************************************************
450 samr_make_sam_obj_sd
451 ********************************************************************/
453 NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
455 extern DOM_SID global_sid_World;
456 DOM_SID adm_sid;
457 DOM_SID act_sid;
459 SEC_ACE ace[3];
460 SEC_ACCESS mask;
462 SEC_ACL *psa = NULL;
464 sid_copy(&adm_sid, &global_sid_Builtin);
465 sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
467 sid_copy(&act_sid, &global_sid_Builtin);
468 sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
470 /*basic access for every one*/
471 init_sec_access(&mask, GENERIC_RIGHTS_SAM_EXECUTE | GENERIC_RIGHTS_SAM_READ);
472 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
474 /*full access for builtin aliases Administrators and Account Operators*/
475 init_sec_access(&mask, GENERIC_RIGHTS_SAM_ALL_ACCESS);
476 init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
477 init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
479 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
480 return NT_STATUS_NO_MEMORY;
482 if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL)
483 return NT_STATUS_NO_MEMORY;
485 return NT_STATUS_OK;