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 /**********************************************************************************
28 Check if this ACE has a SID in common with the token.
29 **********************************************************************************/
31 static BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace)
35 for (i = 0; i < token->num_sids; i++) {
36 if (sid_equal(&ace->trustee, &token->user_sids[i]))
43 /*********************************************************************************
44 Check an ACE against a SID. We return the remaining needed permission
45 bits not yet granted. Zero means permission allowed (no more needed bits).
46 **********************************************************************************/
48 static uint32 check_ace(SEC_ACE *ace, NT_USER_TOKEN *token, uint32 acc_desired,
51 uint32 mask = ace->info.mask;
54 * Inherit only is ignored.
57 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
62 * If this ACE has no SID in common with the token,
63 * ignore it as it cannot be used to make an access
67 if (!token_sid_in_ace( token, ace))
71 case SEC_ACE_TYPE_ACCESS_ALLOWED:
73 * This is explicitly allowed.
74 * Remove the bits from the remaining
75 * access required. Return the remaining
80 case SEC_ACE_TYPE_ACCESS_DENIED:
82 * This is explicitly denied.
83 * If any bits match terminate here,
86 if (acc_desired & mask) {
87 *status = NT_STATUS_ACCESS_DENIED;
91 case SEC_ACE_TYPE_SYSTEM_ALARM:
92 case SEC_ACE_TYPE_SYSTEM_AUDIT:
93 *status = NT_STATUS_NOT_IMPLEMENTED;
96 *status = NT_STATUS_INVALID_PARAMETER;
103 /*********************************************************************************
104 Maximum access was requested. Calculate the max possible. Fail if it doesn't
105 include other bits requested.
106 **********************************************************************************/
108 static BOOL get_max_access( SEC_ACL *the_acl, NT_USER_TOKEN *token, uint32 *granted,
112 uint32 acc_denied = 0;
113 uint32 acc_granted = 0;
116 for ( i = 0 ; i < the_acl->num_aces; i++) {
117 SEC_ACE *ace = &the_acl->ace[i];
118 uint32 mask = ace->info.mask;
120 if (!token_sid_in_ace( token, ace))
124 case SEC_ACE_TYPE_ACCESS_ALLOWED:
125 acc_granted |= (mask & ~acc_denied);
127 case SEC_ACE_TYPE_ACCESS_DENIED:
128 acc_denied |= (mask & ~acc_granted);
130 case SEC_ACE_TYPE_SYSTEM_ALARM:
131 case SEC_ACE_TYPE_SYSTEM_AUDIT:
132 *status = NT_STATUS_NOT_IMPLEMENTED;
136 *status = NT_STATUS_INVALID_PARAMETER;
143 * If we were granted no access, or we desired bits that we
144 * didn't get, then deny.
147 if ((acc_granted == 0) || ((acc_granted & desired) != desired)) {
148 *status = NT_STATUS_ACCESS_DENIED;
154 * Return the access we did get.
157 *granted = acc_granted;
158 *status = NT_STATUS_OK;
162 /* Map generic access rights to object specific rights. This technique is
163 used to give meaning to assigning read, write, execute and all access to
164 objects. Each type of object has its own mapping of generic to object
165 specific access rights. */
167 void se_map_generic(uint32 *access_mask, struct generic_mapping *mapping)
169 uint32 old_mask = *access_mask;
171 if (*access_mask & GENERIC_READ_ACCESS) {
172 *access_mask &= ~GENERIC_READ_ACCESS;
173 *access_mask |= mapping->generic_read;
176 if (*access_mask & GENERIC_WRITE_ACCESS) {
177 *access_mask &= ~GENERIC_WRITE_ACCESS;
178 *access_mask |= mapping->generic_write;
181 if (*access_mask & GENERIC_EXECUTE_ACCESS) {
182 *access_mask &= ~GENERIC_EXECUTE_ACCESS;
183 *access_mask |= mapping->generic_execute;
186 if (*access_mask & GENERIC_ALL_ACCESS) {
187 *access_mask &= ~GENERIC_ALL_ACCESS;
188 *access_mask |= mapping->generic_all;
191 if (old_mask != *access_mask) {
192 DEBUG(10, ("se_map_generic(): mapped mask 0x%08x to 0x%08x\n",
193 old_mask, *access_mask));
197 /*****************************************************************************
198 Check access rights of a user against a security descriptor. Look at
199 each ACE in the security descriptor until an access denied ACE denies
200 any of the desired rights to the user or any of the users groups, or one
201 or more ACEs explicitly grant all requested access rights. See
202 "Access-Checking" document in MSDN.
203 *****************************************************************************/
205 BOOL se_access_check(SEC_DESC *sd, NT_USER_TOKEN *token,
206 uint32 acc_desired, uint32 *acc_granted,
209 extern NT_USER_TOKEN anonymous_token;
213 uint32 tmp_acc_desired = acc_desired;
215 if (!status || !acc_granted)
219 token = &anonymous_token;
221 *status = NT_STATUS_OK;
224 DEBUG(10,("se_access_check: requested access 0x%08x, for NT token with %u entries and first sid %s.\n",
225 (unsigned int)acc_desired, (unsigned int)token->num_sids,
226 sid_to_string(sid_str, &token->user_sids[0])));
229 * No security descriptor or security descriptor with no DACL
230 * present allows all access.
233 /* ACL must have something in it */
235 if (!sd || (sd && (!(sd->type & SEC_DESC_DACL_PRESENT) || sd->dacl == NULL))) {
236 *status = NT_STATUS_OK;
237 *acc_granted = acc_desired;
238 DEBUG(5, ("se_access_check: no sd or blank DACL, access allowed\n"));
242 /* The user sid is the first in the token */
244 DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &token->user_sids[PRIMARY_USER_SID_INDEX]) ));
246 for (i = 1; i < token->num_sids; i++) {
247 DEBUG(3, ("se_access_check: also %s\n",
248 sid_to_string(sid_str, &token->user_sids[i])));
251 /* Is the token the owner of the SID ? */
254 for (i = 0; i < token->num_sids; i++) {
255 if (sid_equal(&token->user_sids[i], sd->owner_sid)) {
257 * The owner always has SEC_RIGHTS_WRITE_DAC & READ_CONTROL.
259 if (tmp_acc_desired & WRITE_DAC_ACCESS)
260 tmp_acc_desired &= ~WRITE_DAC_ACCESS;
261 if (tmp_acc_desired & READ_CONTROL_ACCESS)
262 tmp_acc_desired &= ~READ_CONTROL_ACCESS;
269 if (tmp_acc_desired & MAXIMUM_ALLOWED_ACCESS) {
270 tmp_acc_desired &= ~MAXIMUM_ALLOWED_ACCESS;
271 return get_max_access( the_acl, token, acc_granted, tmp_acc_desired,
275 for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) {
276 SEC_ACE *ace = &the_acl->ace[i];
278 DEBUG(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n",
279 (unsigned int)i, ace->type, ace->flags,
280 sid_to_string(sid_str, &ace->trustee),
281 (unsigned int) ace->info.mask,
282 (unsigned int)tmp_acc_desired ));
284 tmp_acc_desired = check_ace( ace, token, tmp_acc_desired, status);
285 if (NT_STATUS_V(*status)) {
287 DEBUG(5,("se_access_check: ACE %u denied with status %s.\n", (unsigned int)i, get_nt_error_msg(*status)));
293 * If there are no more desired permissions left then
294 * access was allowed.
297 if (tmp_acc_desired == 0) {
298 *acc_granted = acc_desired;
299 *status = NT_STATUS_OK;
300 DEBUG(5,("se_access_check: access (%x) granted.\n", (unsigned int)acc_desired ));
305 *status = NT_STATUS_ACCESS_DENIED;
306 DEBUG(5,("se_access_check: access (%x) denied.\n", (unsigned int)acc_desired ));
310 /* Create a child security descriptor using another security descriptor as
311 the parent container. This child object can either be a container or
312 non-container object. */
314 SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
315 BOOL child_container)
319 SEC_ACL *new_dacl, *the_acl;
320 SEC_ACE *new_ace_list = NULL;
321 int new_ace_list_ndx = 0, i;
324 /* Currently we only process the dacl when creating the child. The
325 sacl should also be processed but this is left out as sacls are
326 not implemented in Samba at the moment.*/
328 the_acl = parent_ctr->dacl;
330 if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces)))
333 for (i = 0; the_acl && i < the_acl->num_aces; i++) {
334 SEC_ACE *ace = &the_acl->ace[i];
335 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
337 BOOL inherit = False;
340 /* The OBJECT_INHERIT_ACE flag causes the ACE to be
341 inherited by non-container children objects. Container
342 children objects will inherit it as an INHERIT_ONLY
345 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
347 if (!child_container) {
348 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
350 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
356 /* The CONAINER_INHERIT_ACE flag means all child container
357 objects will inherit and use the ACE. */
359 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
360 if (!child_container) {
363 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
367 /* The INHERIT_ONLY_ACE is not used by the se_access_check()
368 function for the parent container, but is inherited by
369 all child objects as a normal ACE. */
371 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
372 /* Move along, nothing to see here */
375 /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
376 is inherited by child objects but not grandchildren
377 objects. We clear the object inherit and container
378 inherit flags in the inherited ACE. */
380 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
381 new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
382 SEC_ACE_FLAG_CONTAINER_INHERIT);
385 /* Add ACE to ACE list */
390 init_sec_access(&new_ace->info, ace->info.mask);
391 init_sec_ace(new_ace, &ace->trustee, ace->type,
392 new_ace->info, new_flags);
394 sid_to_string(sid_str, &ace->trustee);
396 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
397 " inherited as %s:%d/0x%02x/0x%08x\n", sid_str,
398 ace->type, ace->flags, ace->info.mask,
399 sid_str, new_ace->type, new_ace->flags,
400 new_ace->info.mask));
405 /* Create child security descriptor to return */
407 new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
409 /* Use the existing user and group sids. I don't think this is
410 correct. Perhaps the user and group should be passed in as
411 parameters by the caller? */
413 sd = make_sec_desc(ctx, SEC_DESC_REVISION,
414 parent_ctr->owner_sid,
419 sdb = make_sec_desc_buf(ctx, size, sd);