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( NT_USER_TOKEN
*token
, 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
, uint32
*status
)
52 uint32 mask
= ace
->info
.mask
;
55 * Inherit only is ignored.
58 if (ace
->flags
& SEC_ACE_FLAG_INHERIT_ONLY
) {
63 * If this ACE has no SID in common with the token,
64 * ignore it as it cannot be used to make an access
68 if (!token_sid_in_ace( token
, ace
))
72 case SEC_ACE_TYPE_ACCESS_ALLOWED
:
74 * This is explicitly allowed.
75 * Remove the bits from the remaining
76 * access required. Return the remaining
81 case SEC_ACE_TYPE_ACCESS_DENIED
:
83 * This is explicitly denied.
84 * If any bits match terminate here,
87 if (acc_desired
& mask
) {
88 *status
= NT_STATUS_ACCESS_DENIED
;
92 case SEC_ACE_TYPE_SYSTEM_ALARM
:
93 case SEC_ACE_TYPE_SYSTEM_AUDIT
:
94 *status
= NT_STATUS_NOT_IMPLEMENTED
;
97 *status
= NT_STATUS_INVALID_PARAMETER
;
104 /*********************************************************************************
105 Maximum access was requested. Calculate the max possible. Fail if it doesn't
106 include other bits requested.
107 **********************************************************************************/
109 static BOOL
get_max_access( SEC_ACL
*the_acl
, NT_USER_TOKEN
*token
, uint32
*granted
, uint32 desired
, uint32
*status
)
111 uint32 acc_denied
= 0;
112 uint32 acc_granted
= 0;
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
))
123 case SEC_ACE_TYPE_ACCESS_ALLOWED
:
124 acc_granted
|= (mask
& ~acc_denied
);
126 case SEC_ACE_TYPE_ACCESS_DENIED
:
127 acc_denied
|= (mask
& ~acc_granted
);
129 case SEC_ACE_TYPE_SYSTEM_ALARM
:
130 case SEC_ACE_TYPE_SYSTEM_AUDIT
:
131 *status
= NT_STATUS_NOT_IMPLEMENTED
;
135 *status
= NT_STATUS_INVALID_PARAMETER
;
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
;
153 * Return the access we did get.
156 *granted
= acc_granted
;
157 *status
= NT_STATUS_NOPROBLEMO
;
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 /*****************************************************************************
197 Check access rights of a user against a security descriptor. Look at
198 each ACE in the security descriptor until an access denied ACE denies
199 any of the desired rights to the user or any of the users groups, or one
200 or more ACEs explicitly grant all requested access rights. See
201 "Access-Checking" document in MSDN.
202 *****************************************************************************/
204 BOOL
se_access_check(SEC_DESC
*sd
, struct current_user
*user
,
205 uint32 acc_desired
, uint32
*acc_granted
, uint32
*status
)
207 extern NT_USER_TOKEN anonymous_token
;
211 NT_USER_TOKEN
*token
= user
->nt_user_token
? user
->nt_user_token
: &anonymous_token
;
212 uint32 tmp_acc_desired
= acc_desired
;
214 if (!status
|| !acc_granted
)
217 *status
= NT_STATUS_NOPROBLEMO
;
220 DEBUG(10,("se_access_check: requested access %x, for uid %u\n",
221 (unsigned int)acc_desired
, (unsigned int)user
->uid
));
224 * No security descriptor or security descriptor with no DACL
225 * present allows all access.
228 /* ACL must have something in it */
230 if (!sd
|| (sd
&& (!(sd
->type
& SEC_DESC_DACL_PRESENT
) || sd
->dacl
== NULL
))) {
231 *status
= NT_STATUS_NOPROBLEMO
;
232 *acc_granted
= acc_desired
;
233 DEBUG(5, ("se_access_check: no sd or blank DACL, access allowed\n"));
237 /* The user sid is the first in the token */
239 DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str
, &token
->user_sids
[0]) ));
241 for (i
= 1; i
< token
->num_sids
; i
++) {
242 DEBUG(3, ("se_access_check: also %s\n",
243 sid_to_string(sid_str
, &token
->user_sids
[i
])));
246 /* Is the token the owner of the SID ? */
249 for (i
= 0; i
< token
->num_sids
; i
++) {
250 if (sid_equal(&token
->user_sids
[i
], sd
->owner_sid
)) {
252 * The owner always has SEC_RIGHTS_WRITE_DAC & READ_CONTROL.
254 if (tmp_acc_desired
& WRITE_DAC_ACCESS
)
255 tmp_acc_desired
&= ~WRITE_DAC_ACCESS
;
256 if (tmp_acc_desired
& READ_CONTROL_ACCESS
)
257 tmp_acc_desired
&= ~READ_CONTROL_ACCESS
;
264 if (tmp_acc_desired
& MAXIMUM_ALLOWED_ACCESS
) {
265 tmp_acc_desired
&= ~MAXIMUM_ALLOWED_ACCESS
;
266 return get_max_access( the_acl
, token
, acc_granted
, tmp_acc_desired
, status
);
269 for ( i
= 0 ; i
< the_acl
->num_aces
&& tmp_acc_desired
!= 0; i
++) {
270 SEC_ACE
*ace
= &the_acl
->ace
[i
];
272 DEBUG(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n",
273 (unsigned int)i
, ace
->type
, ace
->flags
,
274 sid_to_string(sid_str
, &ace
->sid
),
275 (unsigned int) ace
->info
.mask
,
276 (unsigned int)tmp_acc_desired
));
278 tmp_acc_desired
= check_ace( ace
, token
, tmp_acc_desired
, status
);
279 if (*status
!= NT_STATUS_NOPROBLEMO
) {
281 DEBUG(5,("se_access_check: ACE %u denied with status %x.\n", (unsigned int)i
, (unsigned int)*status
));
287 * If there are no more desired permissions left then
288 * access was allowed.
291 if (tmp_acc_desired
== 0) {
292 *acc_granted
= acc_desired
;
293 *status
= NT_STATUS_NOPROBLEMO
;
294 DEBUG(5,("se_access_check: access (%x) granted.\n", (unsigned int)acc_desired
));
299 *status
= NT_STATUS_ACCESS_DENIED
;
300 DEBUG(5,("se_access_check: access (%x) denied.\n", (unsigned int)acc_desired
));
304 /* Create a child security descriptor using another security descriptor as
305 the parent container. This child object can either be a container or
306 non-container object. */
308 SEC_DESC_BUF
*se_create_child_secdesc(TALLOC_CTX
*ctx
, SEC_DESC
*parent_ctr
,
309 BOOL child_container
)
313 SEC_ACL
*new_dacl
, *the_acl
;
314 SEC_ACE
*new_ace_list
= NULL
;
315 int new_ace_list_ndx
= 0, i
;
318 /* Currently we only process the dacl when creating the child. The
319 sacl should also be processed but this is left out as sacls are
320 not implemented in Samba at the moment.*/
322 the_acl
= parent_ctr
->dacl
;
324 if (!(new_ace_list
= talloc(ctx
, sizeof(SEC_ACE
) * the_acl
->num_aces
)))
327 for (i
= 0; the_acl
&& i
< the_acl
->num_aces
; i
++) {
328 SEC_ACE
*ace
= &the_acl
->ace
[i
];
329 SEC_ACE
*new_ace
= &new_ace_list
[new_ace_list_ndx
];
331 BOOL inherit
= False
;
334 /* The OBJECT_INHERIT_ACE flag causes the ACE to be
335 inherited by non-container children objects. Container
336 children objects will inherit it as an INHERIT_ONLY
339 if (ace
->flags
& SEC_ACE_FLAG_OBJECT_INHERIT
) {
341 if (!child_container
) {
342 new_flags
|= SEC_ACE_FLAG_OBJECT_INHERIT
;
344 new_flags
|= SEC_ACE_FLAG_INHERIT_ONLY
;
350 /* The CONAINER_INHERIT_ACE flag means all child container
351 objects will inherit and use the ACE. */
353 if (ace
->flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) {
354 if (!child_container
) {
357 new_flags
|= SEC_ACE_FLAG_CONTAINER_INHERIT
;
361 /* The INHERIT_ONLY_ACE is not used by the se_access_check()
362 function for the parent container, but is inherited by
363 all child objects as a normal ACE. */
365 if (ace
->flags
& SEC_ACE_FLAG_INHERIT_ONLY
) {
366 /* Move along, nothing to see here */
369 /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
370 is inherited by child objects but not grandchildren
371 objects. We clear the object inherit and container
372 inherit flags in the inherited ACE. */
374 if (ace
->flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
) {
375 new_flags
&= ~(SEC_ACE_FLAG_OBJECT_INHERIT
|
376 SEC_ACE_FLAG_CONTAINER_INHERIT
);
379 /* Add ACE to ACE list */
384 init_sec_access(&new_ace
->info
, ace
->info
.mask
);
385 init_sec_ace(new_ace
, &ace
->sid
, ace
->type
,
386 new_ace
->info
, new_flags
);
388 sid_to_string(sid_str
, &ace
->sid
);
390 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
391 " inherited as %s:%d/0x%02x/0x%08x\n", sid_str
,
392 ace
->type
, ace
->flags
, ace
->info
.mask
,
393 sid_str
, new_ace
->type
, new_ace
->flags
,
394 new_ace
->info
.mask
));
399 /* Create child security descriptor to return */
401 new_dacl
= make_sec_acl(ctx
, ACL_REVISION
, new_ace_list_ndx
, new_ace_list
);
403 /* Use the existing user and group sids. I don't think this is
404 correct. Perhaps the user and group should be passed in as
405 parameters by the caller? */
407 sd
= make_sec_desc(ctx
, SEC_DESC_REVISION
,
408 parent_ctr
->owner_sid
,
413 sdb
= make_sec_desc_buf(ctx
, size
, sd
);