updated the 3.0 branch from the head branch - ready for alpha18
[abartlet/samba.git/.git] / source3 / lib / util_seaccess.c
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.
6
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.
11
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.
16
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.
20 */
21
22 #include "includes.h"
23
24 /**********************************************************************************
25  Check if this ACE has a SID in common with the token.
26 **********************************************************************************/
27
28 static BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace)
29 {
30         size_t i;
31
32         for (i = 0; i < token->num_sids; i++) {
33                 if (sid_equal(&ace->trustee, &token->user_sids[i]))
34                         return True;
35         }
36
37         return False;
38 }
39
40 /*********************************************************************************
41  Check an ACE against a SID.  We return the remaining needed permission
42  bits not yet granted. Zero means permission allowed (no more needed bits).
43 **********************************************************************************/
44
45 static uint32 check_ace(SEC_ACE *ace, NT_USER_TOKEN *token, uint32 acc_desired, 
46                         NTSTATUS *status)
47 {
48         uint32 mask = ace->info.mask;
49
50         /*
51          * Inherit only is ignored.
52          */
53
54         if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
55                 return acc_desired;
56         }
57
58         /*
59          * If this ACE has no SID in common with the token,
60          * ignore it as it cannot be used to make an access
61          * determination.
62          */
63
64         if (!token_sid_in_ace( token, ace))
65                 return acc_desired;     
66
67         switch (ace->type) {
68                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
69                         /*
70                          * This is explicitly allowed.
71                          * Remove the bits from the remaining
72                          * access required. Return the remaining
73                          * bits needed.
74                          */
75                         acc_desired &= ~mask;
76                         break;
77                 case SEC_ACE_TYPE_ACCESS_DENIED:
78                         /*
79                          * This is explicitly denied.
80                          * If any bits match terminate here,
81                          * we are denied.
82                          */
83                         if (acc_desired & mask) {
84                                 *status = NT_STATUS_ACCESS_DENIED;
85                                 return 0xFFFFFFFF;
86                         }
87                         break;
88                 case SEC_ACE_TYPE_SYSTEM_ALARM:
89                 case SEC_ACE_TYPE_SYSTEM_AUDIT:
90                         *status = NT_STATUS_NOT_IMPLEMENTED;
91                         return 0xFFFFFFFF;
92                 default:
93                         *status = NT_STATUS_INVALID_PARAMETER;
94                         return 0xFFFFFFFF;
95         }
96
97         return acc_desired;
98 }
99
100 /*********************************************************************************
101  Maximum access was requested. Calculate the max possible. Fail if it doesn't
102  include other bits requested.
103 **********************************************************************************/ 
104
105 static BOOL get_max_access( SEC_ACL *the_acl, NT_USER_TOKEN *token, uint32 *granted, 
106                             uint32 desired, 
107                             NTSTATUS *status)
108 {
109         uint32 acc_denied = 0;
110         uint32 acc_granted = 0;
111         size_t i;
112         
113         for ( i = 0 ; i < the_acl->num_aces; i++) {
114                 SEC_ACE *ace = &the_acl->ace[i];
115                 uint32 mask = ace->info.mask;
116
117                 if (!token_sid_in_ace( token, ace))
118                         continue;
119
120                 switch (ace->type) {
121                         case SEC_ACE_TYPE_ACCESS_ALLOWED:
122                                 acc_granted |= (mask & ~acc_denied);
123                                 break;
124                         case SEC_ACE_TYPE_ACCESS_DENIED:
125                                 acc_denied |= (mask & ~acc_granted);
126                                 break;
127                         case SEC_ACE_TYPE_SYSTEM_ALARM:
128                         case SEC_ACE_TYPE_SYSTEM_AUDIT:
129                                 *status = NT_STATUS_NOT_IMPLEMENTED;
130                                 *granted = 0;
131                                 return False;
132                         default:
133                                 *status = NT_STATUS_INVALID_PARAMETER;
134                                 *granted = 0;
135                                 return False;
136                 }                           
137         }
138
139         /*
140          * If we were granted no access, or we desired bits that we
141          * didn't get, then deny.
142          */
143
144         if ((acc_granted == 0) || ((acc_granted & desired) != desired)) {
145                 *status = NT_STATUS_ACCESS_DENIED;
146                 *granted = 0;
147                 return False;
148         }
149
150         /*
151          * Return the access we did get.
152          */
153
154         *granted = acc_granted;
155         *status = NT_STATUS_OK;
156         return True;
157 }
158
159 /* Map generic access rights to object specific rights.  This technique is
160    used to give meaning to assigning read, write, execute and all access to
161    objects.  Each type of object has its own mapping of generic to object
162    specific access rights. */
163
164 void se_map_generic(uint32 *access_mask, struct generic_mapping *mapping)
165 {
166         uint32 old_mask = *access_mask;
167
168         if (*access_mask & GENERIC_READ_ACCESS) {
169                 *access_mask &= ~GENERIC_READ_ACCESS;
170                 *access_mask |= mapping->generic_read;
171         }
172
173         if (*access_mask & GENERIC_WRITE_ACCESS) {
174                 *access_mask &= ~GENERIC_WRITE_ACCESS;
175                 *access_mask |= mapping->generic_write;
176         }
177
178         if (*access_mask & GENERIC_EXECUTE_ACCESS) {
179                 *access_mask &= ~GENERIC_EXECUTE_ACCESS;
180                 *access_mask |= mapping->generic_execute;
181         }
182
183         if (*access_mask & GENERIC_ALL_ACCESS) {
184                 *access_mask &= ~GENERIC_ALL_ACCESS;
185                 *access_mask |= mapping->generic_all;
186         }
187
188         if (old_mask != *access_mask) {
189                 DEBUG(10, ("se_map_generic(): mapped mask 0x%08x to 0x%08x\n",
190                            old_mask, *access_mask));
191         }
192 }
193
194 /* Map standard access rights to object specific rights.  This technique is
195    used to give meaning to assigning read, write, execute and all access to
196    objects.  Each type of object has its own mapping of standard to object
197    specific access rights. */
198
199 void se_map_standard(uint32 *access_mask, struct standard_mapping *mapping)
200 {
201         uint32 old_mask = *access_mask;
202
203         if (*access_mask & READ_CONTROL_ACCESS) {
204                 *access_mask &= ~READ_CONTROL_ACCESS;
205                 *access_mask |= mapping->std_read;
206         }
207
208         if (*access_mask & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS)) {
209                 *access_mask &= ~(DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS);
210                 *access_mask |= mapping->std_all;
211         }
212
213         if (old_mask != *access_mask) {
214                 DEBUG(10, ("se_map_standard(): mapped mask 0x%08x to 0x%08x\n",
215                            old_mask, *access_mask));
216         }
217 }
218
219 /*****************************************************************************
220  Check access rights of a user against a security descriptor.  Look at
221  each ACE in the security descriptor until an access denied ACE denies
222  any of the desired rights to the user or any of the users groups, or one
223  or more ACEs explicitly grant all requested access rights.  See
224  "Access-Checking" document in MSDN.
225 *****************************************************************************/ 
226
227 BOOL se_access_check(SEC_DESC *sd, NT_USER_TOKEN *token,
228                      uint32 acc_desired, uint32 *acc_granted, 
229                      NTSTATUS *status)
230 {
231         extern NT_USER_TOKEN anonymous_token;
232         size_t i;
233         SEC_ACL *the_acl;
234         fstring sid_str;
235         uint32 tmp_acc_desired = acc_desired;
236
237         if (!status || !acc_granted)
238                 return False;
239
240         if (!token)
241                 token = &anonymous_token;
242
243         *status = NT_STATUS_OK;
244         *acc_granted = 0;
245
246         DEBUG(10,("se_access_check: requested access 0x%08x, for NT token with %u entries and first sid %s.\n",
247                  (unsigned int)acc_desired, (unsigned int)token->num_sids,
248                 sid_to_string(sid_str, &token->user_sids[0])));
249
250         /*
251          * No security descriptor or security descriptor with no DACL
252          * present allows all access.
253          */
254
255         /* ACL must have something in it */
256
257         if (!sd || (sd && (!(sd->type & SEC_DESC_DACL_PRESENT) || sd->dacl == NULL))) {
258                 *status = NT_STATUS_OK;
259                 *acc_granted = acc_desired;
260                 DEBUG(5, ("se_access_check: no sd or blank DACL, access allowed\n"));
261                 return True;
262         }
263
264         /* The user sid is the first in the token */
265
266         DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &token->user_sids[PRIMARY_USER_SID_INDEX]) ));
267
268         for (i = 1; i < token->num_sids; i++) {
269                 DEBUG(3, ("se_access_check: also %s\n",
270                           sid_to_string(sid_str, &token->user_sids[i])));
271         }
272
273         /* Is the token the owner of the SID ? */
274
275         if (sd->owner_sid) {
276                 for (i = 0; i < token->num_sids; i++) {
277                         if (sid_equal(&token->user_sids[i], sd->owner_sid)) {
278                                 /*
279                                  * The owner always has SEC_RIGHTS_WRITE_DAC & READ_CONTROL.
280                                  */
281                                 if (tmp_acc_desired & WRITE_DAC_ACCESS)
282                                         tmp_acc_desired &= ~WRITE_DAC_ACCESS;
283                                 if (tmp_acc_desired & READ_CONTROL_ACCESS)
284                                         tmp_acc_desired &= ~READ_CONTROL_ACCESS;
285                         }
286                 }
287         }
288
289         the_acl = sd->dacl;
290
291         if (tmp_acc_desired & MAXIMUM_ALLOWED_ACCESS) {
292                 tmp_acc_desired &= ~MAXIMUM_ALLOWED_ACCESS;
293                 return get_max_access( the_acl, token, acc_granted, tmp_acc_desired, 
294                                        status);
295         }
296
297         for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) {
298                 SEC_ACE *ace = &the_acl->ace[i];
299
300                 DEBUG(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n",
301                           (unsigned int)i, ace->type, ace->flags,
302                           sid_to_string(sid_str, &ace->trustee),
303                           (unsigned int) ace->info.mask, 
304                           (unsigned int)tmp_acc_desired ));
305
306                 tmp_acc_desired = check_ace( ace, token, tmp_acc_desired, status);
307                 if (NT_STATUS_V(*status)) {
308                         *acc_granted = 0;
309                         DEBUG(5,("se_access_check: ACE %u denied with status %s.\n", (unsigned int)i, nt_errstr(*status)));
310                         return False;
311                 }
312         }
313
314         /*
315          * If there are no more desired permissions left then
316          * access was allowed.
317          */
318
319         if (tmp_acc_desired == 0) {
320                 *acc_granted = acc_desired;
321                 *status = NT_STATUS_OK;
322                 DEBUG(5,("se_access_check: access (%x) granted.\n", (unsigned int)acc_desired ));
323                 return True;
324         }
325                 
326         *acc_granted = 0;
327         *status = NT_STATUS_ACCESS_DENIED;
328         DEBUG(5,("se_access_check: access (%x) denied.\n", (unsigned int)acc_desired ));
329         return False;
330 }
331
332 /* Create a child security descriptor using another security descriptor as
333    the parent container.  This child object can either be a container or
334    non-container object. */
335
336 SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
337                                       BOOL child_container)
338 {
339         SEC_DESC_BUF *sdb;
340         SEC_DESC *sd;
341         SEC_ACL *new_dacl, *the_acl;
342         SEC_ACE *new_ace_list = NULL;
343         int new_ace_list_ndx = 0, i;
344         size_t size;
345
346         /* Currently we only process the dacl when creating the child.  The
347            sacl should also be processed but this is left out as sacls are
348            not implemented in Samba at the moment.*/
349
350         the_acl = parent_ctr->dacl;
351
352         if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) 
353                 return NULL;
354
355         for (i = 0; the_acl && i < the_acl->num_aces; i++) {
356                 SEC_ACE *ace = &the_acl->ace[i];
357                 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
358                 uint8 new_flags = 0;
359                 BOOL inherit = False;
360                 fstring sid_str;
361
362                 /* The OBJECT_INHERIT_ACE flag causes the ACE to be
363                    inherited by non-container children objects.  Container
364                    children objects will inherit it as an INHERIT_ONLY
365                    ACE. */
366
367                 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
368
369                         if (!child_container) {
370                                 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
371                         } else {
372                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
373                         }
374
375                         inherit = True;
376                 }
377
378                 /* The CONAINER_INHERIT_ACE flag means all child container
379                    objects will inherit and use the ACE. */
380
381                 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
382                         if (!child_container) {
383                                 inherit = False;
384                         } else {
385                                 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
386                         }
387                 }
388
389                 /* The INHERIT_ONLY_ACE is not used by the se_access_check()
390                    function for the parent container, but is inherited by
391                    all child objects as a normal ACE. */
392
393                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
394                         /* Move along, nothing to see here */
395                 }
396
397                 /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
398                    is inherited by child objects but not grandchildren
399                    objects.  We clear the object inherit and container
400                    inherit flags in the inherited ACE. */
401
402                 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
403                         new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
404                                        SEC_ACE_FLAG_CONTAINER_INHERIT);
405                 }
406
407                 /* Add ACE to ACE list */
408
409                 if (!inherit)
410                         continue;
411
412                 init_sec_access(&new_ace->info, ace->info.mask);
413                 init_sec_ace(new_ace, &ace->trustee, ace->type,
414                              new_ace->info, new_flags);
415
416                 sid_to_string(sid_str, &ace->trustee);
417
418                 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
419                           " inherited as %s:%d/0x%02x/0x%08x\n", sid_str,
420                           ace->type, ace->flags, ace->info.mask,
421                           sid_str, new_ace->type, new_ace->flags,
422                           new_ace->info.mask));
423
424                 new_ace_list_ndx++;
425         }
426
427         /* Create child security descriptor to return */
428         
429         new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
430
431         /* Use the existing user and group sids.  I don't think this is
432            correct.  Perhaps the user and group should be passed in as
433            parameters by the caller? */
434
435         sd = make_sec_desc(ctx, SEC_DESC_REVISION,
436                            parent_ctr->owner_sid,
437                            parent_ctr->grp_sid,
438                            parent_ctr->sacl,
439                            new_dacl, &size);
440
441         sdb = make_sec_desc_buf(ctx, size, sd);
442
443         return sdb;
444 }