Added Elrond patch to make se_access_check use NT datastructures, not Samba.
[abartlet/samba.git/.git] / source3 / lib / util_seaccess.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 2.0
4    Copyright (C) Luke Kenneth Casson Leighton 1996-2000.
5    Copyright (C) Tim Potter 2000.
6    Copyright (C) Re-written by Jeremy Allison 2000.
7
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.
12
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.
17
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.
21 */
22
23 #include "includes.h"
24 #include "nterr.h"
25 #include "sids.h"
26
27 extern int DEBUGLEVEL;
28
29 /**********************************************************************************
30  Check if this ACE has a SID in common with the token.
31 **********************************************************************************/
32
33 static BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace)
34 {
35         size_t i;
36
37         for (i = 0; i < token->num_sids; i++) {
38                 if (sid_equal(&ace->sid, &token->user_sids[i]))
39                         return True;
40         }
41
42         return False;
43 }
44
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 **********************************************************************************/
49
50 static uint32 check_ace(SEC_ACE *ace, NT_USER_TOKEN *token, uint32 acc_desired, 
51                         NTSTATUS *status)
52 {
53         uint32 mask = ace->info.mask;
54
55         /*
56          * Inherit only is ignored.
57          */
58
59         if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
60                 return acc_desired;
61         }
62
63         /*
64          * If this ACE has no SID in common with the token,
65          * ignore it as it cannot be used to make an access
66          * determination.
67          */
68
69         if (!token_sid_in_ace( token, ace))
70                 return acc_desired;     
71
72         switch (ace->type) {
73                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
74                         /*
75                          * This is explicitly allowed.
76                          * Remove the bits from the remaining
77                          * access required. Return the remaining
78                          * bits needed.
79                          */
80                         acc_desired &= ~mask;
81                         break;
82                 case SEC_ACE_TYPE_ACCESS_DENIED:
83                         /*
84                          * This is explicitly denied.
85                          * If any bits match terminate here,
86                          * we are denied.
87                          */
88                         if (acc_desired & mask) {
89                                 *status = NT_STATUS_ACCESS_DENIED;
90                                 return 0xFFFFFFFF;
91                         }
92                         break;
93                 case SEC_ACE_TYPE_SYSTEM_ALARM:
94                 case SEC_ACE_TYPE_SYSTEM_AUDIT:
95                         *status = NT_STATUS_NOT_IMPLEMENTED;
96                         return 0xFFFFFFFF;
97                 default:
98                         *status = NT_STATUS_INVALID_PARAMETER;
99                         return 0xFFFFFFFF;
100         }
101
102         return acc_desired;
103 }
104
105 /*********************************************************************************
106  Maximum access was requested. Calculate the max possible. Fail if it doesn't
107  include other bits requested.
108 **********************************************************************************/ 
109
110 static BOOL get_max_access( SEC_ACL *the_acl, NT_USER_TOKEN *token, uint32 *granted, 
111                             uint32 desired, 
112                             NTSTATUS *status)
113 {
114         uint32 acc_denied = 0;
115         uint32 acc_granted = 0;
116         size_t i;
117         
118         for ( i = 0 ; i < the_acl->num_aces; i++) {
119                 SEC_ACE *ace = &the_acl->ace[i];
120                 uint32 mask = ace->info.mask;
121
122                 if (!token_sid_in_ace( token, ace))
123                         continue;
124
125                 switch (ace->type) {
126                         case SEC_ACE_TYPE_ACCESS_ALLOWED:
127                                 acc_granted |= (mask & ~acc_denied);
128                                 break;
129                         case SEC_ACE_TYPE_ACCESS_DENIED:
130                                 acc_denied |= (mask & ~acc_granted);
131                                 break;
132                         case SEC_ACE_TYPE_SYSTEM_ALARM:
133                         case SEC_ACE_TYPE_SYSTEM_AUDIT:
134                                 *status = NT_STATUS_NOT_IMPLEMENTED;
135                                 *granted = 0;
136                                 return False;
137                         default:
138                                 *status = NT_STATUS_INVALID_PARAMETER;
139                                 *granted = 0;
140                                 return False;
141                 }                           
142         }
143
144         /*
145          * If we were granted no access, or we desired bits that we
146          * didn't get, then deny.
147          */
148
149         if ((acc_granted == 0) || ((acc_granted & desired) != desired)) {
150                 *status = NT_STATUS_ACCESS_DENIED;
151                 *granted = 0;
152                 return False;
153         }
154
155         /*
156          * Return the access we did get.
157          */
158
159         *granted = acc_granted;
160         *status = NT_STATUS_OK;
161         return True;
162 }
163
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. */
168
169 void se_map_generic(uint32 *access_mask, struct generic_mapping *mapping)
170 {
171         uint32 old_mask = *access_mask;
172
173         if (*access_mask & GENERIC_READ_ACCESS) {
174                 *access_mask &= ~GENERIC_READ_ACCESS;
175                 *access_mask |= mapping->generic_read;
176         }
177
178         if (*access_mask & GENERIC_WRITE_ACCESS) {
179                 *access_mask &= ~GENERIC_WRITE_ACCESS;
180                 *access_mask |= mapping->generic_write;
181         }
182
183         if (*access_mask & GENERIC_EXECUTE_ACCESS) {
184                 *access_mask &= ~GENERIC_EXECUTE_ACCESS;
185                 *access_mask |= mapping->generic_execute;
186         }
187
188         if (*access_mask & GENERIC_ALL_ACCESS) {
189                 *access_mask &= ~GENERIC_ALL_ACCESS;
190                 *access_mask |= mapping->generic_all;
191         }
192
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));
196         }
197 }
198
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 *****************************************************************************/ 
206
207 BOOL se_access_check(SEC_DESC *sd, NT_USER_TOKEN *token,
208                      uint32 acc_desired, uint32 *acc_granted, 
209                      NTSTATUS *status)
210 {
211         extern NT_USER_TOKEN anonymous_token;
212         size_t i;
213         SEC_ACL *the_acl;
214         fstring sid_str;
215         uint32 tmp_acc_desired = acc_desired;
216
217         if (!status || !acc_granted)
218                 return False;
219
220         if (!token)
221                 token = &anonymous_token;
222
223         *status = NT_STATUS_OK;
224         *acc_granted = 0;
225
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])));
229
230         /*
231          * No security descriptor or security descriptor with no DACL
232          * present allows all access.
233          */
234
235         /* ACL must have something in it */
236
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"));
241                 return True;
242         }
243
244         /* The user sid is the first in the token */
245
246         DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &token->user_sids[0]) ));
247
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])));
251         }
252
253         /* Is the token the owner of the SID ? */
254
255         if (sd->owner_sid) {
256                 for (i = 0; i < token->num_sids; i++) {
257                         if (sid_equal(&token->user_sids[i], sd->owner_sid)) {
258                                 /*
259                                  * The owner always has SEC_RIGHTS_WRITE_DAC & READ_CONTROL.
260                                  */
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;
265                         }
266                 }
267         }
268
269         the_acl = sd->dacl;
270
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, 
274                                        status);
275         }
276
277         for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) {
278                 SEC_ACE *ace = &the_acl->ace[i];
279
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 ));
285
286                 tmp_acc_desired = check_ace( ace, token, tmp_acc_desired, status);
287                 if (NT_STATUS_V(*status)) {
288                         *acc_granted = 0;
289                         DEBUG(5,("se_access_check: ACE %u denied with status %s.\n", (unsigned int)i, get_nt_error_msg(*status)));
290                         return False;
291                 }
292         }
293
294         /*
295          * If there are no more desired permissions left then
296          * access was allowed.
297          */
298
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 ));
303                 return True;
304         }
305                 
306         *acc_granted = 0;
307         *status = NT_STATUS_ACCESS_DENIED;
308         DEBUG(5,("se_access_check: access (%x) denied.\n", (unsigned int)acc_desired ));
309         return False;
310 }
311
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. */
315
316 SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
317                                       BOOL child_container)
318 {
319         SEC_DESC_BUF *sdb;
320         SEC_DESC *sd;
321         SEC_ACL *new_dacl, *the_acl;
322         SEC_ACE *new_ace_list = NULL;
323         int new_ace_list_ndx = 0, i;
324         size_t size;
325
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.*/
329
330         the_acl = parent_ctr->dacl;
331
332         if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) 
333                 return NULL;
334
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];
338                 uint8 new_flags = 0;
339                 BOOL inherit = False;
340                 fstring sid_str;
341
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
345                    ACE. */
346
347                 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
348
349                         if (!child_container) {
350                                 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
351                         } else {
352                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
353                         }
354
355                         inherit = True;
356                 }
357
358                 /* The CONAINER_INHERIT_ACE flag means all child container
359                    objects will inherit and use the ACE. */
360
361                 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
362                         if (!child_container) {
363                                 inherit = False;
364                         } else {
365                                 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
366                         }
367                 }
368
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. */
372
373                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
374                         /* Move along, nothing to see here */
375                 }
376
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. */
381
382                 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
383                         new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
384                                        SEC_ACE_FLAG_CONTAINER_INHERIT);
385                 }
386
387                 /* Add ACE to ACE list */
388
389                 if (!inherit)
390                         continue;
391
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);
395
396                 sid_to_string(sid_str, &ace->sid);
397
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));
403
404                 new_ace_list_ndx++;
405         }
406
407         /* Create child security descriptor to return */
408         
409         new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
410
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? */
414
415         sd = make_sec_desc(ctx, SEC_DESC_REVISION,
416                            parent_ctr->owner_sid,
417                            parent_ctr->grp_sid,
418                            parent_ctr->sacl,
419                            new_dacl, &size);
420
421         sdb = make_sec_desc_buf(ctx, size, sd);
422
423         return sdb;
424 }