2 Unix SMB/Netbios implementation.
4 Copyright (C) Luke Kenneth Casson Leighton 1996-2000.
5 Copyright (C) Tim Potter 2000.
6 Copyright (C) Re-written by Jeremy Allison 2000.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL;
29 /**********************************************************************************
30 Check if this ACE has a SID in common with the token.
31 **********************************************************************************/
33 static BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace)
37 for (i = 0; i < token->num_sids; i++) {
38 if (sid_equal(&ace->sid, &token->user_sids[i]))
45 /*********************************************************************************
46 Check an ACE against a SID. We return the remaining needed permission
47 bits not yet granted. Zero means permission allowed (no more needed bits).
48 **********************************************************************************/
50 static uint32 check_ace(SEC_ACE *ace, NT_USER_TOKEN *token, uint32 acc_desired,
53 uint32 mask = ace->info.mask;
56 * Inherit only is ignored.
59 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
64 * If this ACE has no SID in common with the token,
65 * ignore it as it cannot be used to make an access
69 if (!token_sid_in_ace( token, ace))
73 case SEC_ACE_TYPE_ACCESS_ALLOWED:
75 * This is explicitly allowed.
76 * Remove the bits from the remaining
77 * access required. Return the remaining
82 case SEC_ACE_TYPE_ACCESS_DENIED:
84 * This is explicitly denied.
85 * If any bits match terminate here,
88 if (acc_desired & mask) {
89 *status = NT_STATUS_ACCESS_DENIED;
93 case SEC_ACE_TYPE_SYSTEM_ALARM:
94 case SEC_ACE_TYPE_SYSTEM_AUDIT:
95 *status = NT_STATUS_NOT_IMPLEMENTED;
98 *status = NT_STATUS_INVALID_PARAMETER;
105 /*********************************************************************************
106 Maximum access was requested. Calculate the max possible. Fail if it doesn't
107 include other bits requested.
108 **********************************************************************************/
110 static BOOL get_max_access( SEC_ACL *the_acl, NT_USER_TOKEN *token, uint32 *granted,
114 uint32 acc_denied = 0;
115 uint32 acc_granted = 0;
118 for ( i = 0 ; i < the_acl->num_aces; i++) {
119 SEC_ACE *ace = &the_acl->ace[i];
120 uint32 mask = ace->info.mask;
122 if (!token_sid_in_ace( token, ace))
126 case SEC_ACE_TYPE_ACCESS_ALLOWED:
127 acc_granted |= (mask & ~acc_denied);
129 case SEC_ACE_TYPE_ACCESS_DENIED:
130 acc_denied |= (mask & ~acc_granted);
132 case SEC_ACE_TYPE_SYSTEM_ALARM:
133 case SEC_ACE_TYPE_SYSTEM_AUDIT:
134 *status = NT_STATUS_NOT_IMPLEMENTED;
138 *status = NT_STATUS_INVALID_PARAMETER;
145 * If we were granted no access, or we desired bits that we
146 * didn't get, then deny.
149 if ((acc_granted == 0) || ((acc_granted & desired) != desired)) {
150 *status = NT_STATUS_ACCESS_DENIED;
156 * Return the access we did get.
159 *granted = acc_granted;
160 *status = NT_STATUS_OK;
164 /* Map generic access rights to object specific rights. This technique is
165 used to give meaning to assigning read, write, execute and all access to
166 objects. Each type of object has its own mapping of generic to object
167 specific access rights. */
169 void se_map_generic(uint32 *access_mask, struct generic_mapping *mapping)
171 uint32 old_mask = *access_mask;
173 if (*access_mask & GENERIC_READ_ACCESS) {
174 *access_mask &= ~GENERIC_READ_ACCESS;
175 *access_mask |= mapping->generic_read;
178 if (*access_mask & GENERIC_WRITE_ACCESS) {
179 *access_mask &= ~GENERIC_WRITE_ACCESS;
180 *access_mask |= mapping->generic_write;
183 if (*access_mask & GENERIC_EXECUTE_ACCESS) {
184 *access_mask &= ~GENERIC_EXECUTE_ACCESS;
185 *access_mask |= mapping->generic_execute;
188 if (*access_mask & GENERIC_ALL_ACCESS) {
189 *access_mask &= ~GENERIC_ALL_ACCESS;
190 *access_mask |= mapping->generic_all;
193 if (old_mask != *access_mask) {
194 DEBUG(10, ("se_map_generic(): mapped mask 0x%08x to 0x%08x\n",
195 old_mask, *access_mask));
199 /*****************************************************************************
200 Check access rights of a user against a security descriptor. Look at
201 each ACE in the security descriptor until an access denied ACE denies
202 any of the desired rights to the user or any of the users groups, or one
203 or more ACEs explicitly grant all requested access rights. See
204 "Access-Checking" document in MSDN.
205 *****************************************************************************/
207 BOOL se_access_check(SEC_DESC *sd, NT_USER_TOKEN *token,
208 uint32 acc_desired, uint32 *acc_granted,
211 extern NT_USER_TOKEN anonymous_token;
215 uint32 tmp_acc_desired = acc_desired;
217 if (!status || !acc_granted)
221 token = &anonymous_token;
223 *status = NT_STATUS_OK;
226 DEBUG(10,("se_access_check: requested access %x, for NT token with %u entries and first sid %s.\n",
227 (unsigned int)acc_desired, (unsigned int)token->num_sids,
228 sid_to_string(sid_str, &token->user_sids[0])));
231 * No security descriptor or security descriptor with no DACL
232 * present allows all access.
235 /* ACL must have something in it */
237 if (!sd || (sd && (!(sd->type & SEC_DESC_DACL_PRESENT) || sd->dacl == NULL))) {
238 *status = NT_STATUS_OK;
239 *acc_granted = acc_desired;
240 DEBUG(5, ("se_access_check: no sd or blank DACL, access allowed\n"));
244 /* The user sid is the first in the token */
246 DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &token->user_sids[0]) ));
248 for (i = 1; i < token->num_sids; i++) {
249 DEBUG(3, ("se_access_check: also %s\n",
250 sid_to_string(sid_str, &token->user_sids[i])));
253 /* Is the token the owner of the SID ? */
256 for (i = 0; i < token->num_sids; i++) {
257 if (sid_equal(&token->user_sids[i], sd->owner_sid)) {
259 * The owner always has SEC_RIGHTS_WRITE_DAC & READ_CONTROL.
261 if (tmp_acc_desired & WRITE_DAC_ACCESS)
262 tmp_acc_desired &= ~WRITE_DAC_ACCESS;
263 if (tmp_acc_desired & READ_CONTROL_ACCESS)
264 tmp_acc_desired &= ~READ_CONTROL_ACCESS;
271 if (tmp_acc_desired & MAXIMUM_ALLOWED_ACCESS) {
272 tmp_acc_desired &= ~MAXIMUM_ALLOWED_ACCESS;
273 return get_max_access( the_acl, token, acc_granted, tmp_acc_desired,
277 for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) {
278 SEC_ACE *ace = &the_acl->ace[i];
280 DEBUG(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n",
281 (unsigned int)i, ace->type, ace->flags,
282 sid_to_string(sid_str, &ace->sid),
283 (unsigned int) ace->info.mask,
284 (unsigned int)tmp_acc_desired ));
286 tmp_acc_desired = check_ace( ace, token, tmp_acc_desired, status);
287 if (NT_STATUS_V(*status)) {
289 DEBUG(5,("se_access_check: ACE %u denied with status %s.\n", (unsigned int)i, get_nt_error_msg(*status)));
295 * If there are no more desired permissions left then
296 * access was allowed.
299 if (tmp_acc_desired == 0) {
300 *acc_granted = acc_desired;
301 *status = NT_STATUS_OK;
302 DEBUG(5,("se_access_check: access (%x) granted.\n", (unsigned int)acc_desired ));
307 *status = NT_STATUS_ACCESS_DENIED;
308 DEBUG(5,("se_access_check: access (%x) denied.\n", (unsigned int)acc_desired ));
312 /* Create a child security descriptor using another security descriptor as
313 the parent container. This child object can either be a container or
314 non-container object. */
316 SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
317 BOOL child_container)
321 SEC_ACL *new_dacl, *the_acl;
322 SEC_ACE *new_ace_list = NULL;
323 int new_ace_list_ndx = 0, i;
326 /* Currently we only process the dacl when creating the child. The
327 sacl should also be processed but this is left out as sacls are
328 not implemented in Samba at the moment.*/
330 the_acl = parent_ctr->dacl;
332 if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces)))
335 for (i = 0; the_acl && i < the_acl->num_aces; i++) {
336 SEC_ACE *ace = &the_acl->ace[i];
337 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
339 BOOL inherit = False;
342 /* The OBJECT_INHERIT_ACE flag causes the ACE to be
343 inherited by non-container children objects. Container
344 children objects will inherit it as an INHERIT_ONLY
347 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
349 if (!child_container) {
350 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
352 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
358 /* The CONAINER_INHERIT_ACE flag means all child container
359 objects will inherit and use the ACE. */
361 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
362 if (!child_container) {
365 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
369 /* The INHERIT_ONLY_ACE is not used by the se_access_check()
370 function for the parent container, but is inherited by
371 all child objects as a normal ACE. */
373 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
374 /* Move along, nothing to see here */
377 /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
378 is inherited by child objects but not grandchildren
379 objects. We clear the object inherit and container
380 inherit flags in the inherited ACE. */
382 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
383 new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
384 SEC_ACE_FLAG_CONTAINER_INHERIT);
387 /* Add ACE to ACE list */
392 init_sec_access(&new_ace->info, ace->info.mask);
393 init_sec_ace(new_ace, &ace->sid, ace->type,
394 new_ace->info, new_flags);
396 sid_to_string(sid_str, &ace->sid);
398 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
399 " inherited as %s:%d/0x%02x/0x%08x\n", sid_str,
400 ace->type, ace->flags, ace->info.mask,
401 sid_str, new_ace->type, new_ace->flags,
402 new_ace->info.mask));
407 /* Create child security descriptor to return */
409 new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
411 /* Use the existing user and group sids. I don't think this is
412 correct. Perhaps the user and group should be passed in as
413 parameters by the caller? */
415 sd = make_sec_desc(ctx, SEC_DESC_REVISION,
416 parent_ctr->owner_sid,
421 sdb = make_sec_desc_buf(ctx, size, sd);