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